зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1664617 - Support calling DOM getters in CacheIR r=jandem
Differential Revision: https://phabricator.services.mozilla.com/D90011
This commit is contained in:
Родитель
88d3f70ab7
Коммит
a58b9699aa
|
@ -38,6 +38,9 @@ class JSJitGetterCallArgs : protected JS::MutableHandle<JS::Value> {
|
|||
explicit JSJitGetterCallArgs(JS::Rooted<JS::Value>* rooted)
|
||||
: JS::MutableHandle<JS::Value>(rooted) {}
|
||||
|
||||
explicit JSJitGetterCallArgs(JS::MutableHandle<JS::Value> handle)
|
||||
: JS::MutableHandle<JS::Value>(handle) {}
|
||||
|
||||
JS::MutableHandle<JS::Value> rval() { return *this; }
|
||||
};
|
||||
|
||||
|
|
|
@ -609,6 +609,34 @@ bool BaselineCacheIRCompiler::emitCallNativeGetterResult(
|
|||
return true;
|
||||
}
|
||||
|
||||
bool BaselineCacheIRCompiler::emitCallDOMGetterResult(ObjOperandId objId,
|
||||
uint32_t jitInfoOffset) {
|
||||
JitSpew(JitSpew_Codegen, "%s", __FUNCTION__);
|
||||
|
||||
Register obj = allocator.useRegister(masm, objId);
|
||||
Address jitInfoAddr(stubAddress(jitInfoOffset));
|
||||
|
||||
AutoScratchRegister scratch(allocator, masm);
|
||||
|
||||
allocator.discardStack(masm);
|
||||
|
||||
AutoStubFrame stubFrame(*this);
|
||||
stubFrame.enter(masm, scratch);
|
||||
|
||||
// Load the JSJitInfo in the scratch register.
|
||||
masm.loadPtr(jitInfoAddr, scratch);
|
||||
|
||||
masm.Push(obj);
|
||||
masm.Push(scratch);
|
||||
|
||||
using Fn =
|
||||
bool (*)(JSContext*, const JSJitInfo*, HandleObject, MutableHandleValue);
|
||||
callVM<Fn, CallDOMGetter>(masm);
|
||||
|
||||
stubFrame.leave(masm);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BaselineCacheIRCompiler::emitProxyGetResult(ObjOperandId objId,
|
||||
uint32_t idOffset) {
|
||||
JitSpew(JitSpew_Codegen, "%s", __FUNCTION__);
|
||||
|
|
|
@ -225,15 +225,15 @@ GetPropIRGenerator::GetPropIRGenerator(JSContext* cx, HandleScript script,
|
|||
resultFlags_(resultFlags),
|
||||
preliminaryObjectAction_(PreliminaryObjectAction::None) {}
|
||||
|
||||
static void EmitLoadSlotResult(CacheIRWriter& writer, ObjOperandId holderOp,
|
||||
static void EmitLoadSlotResult(CacheIRWriter& writer, ObjOperandId holderId,
|
||||
NativeObject* holder, Shape* shape) {
|
||||
if (holder->isFixedSlot(shape->slot())) {
|
||||
writer.loadFixedSlotResult(holderOp,
|
||||
writer.loadFixedSlotResult(holderId,
|
||||
NativeObject::getFixedSlotOffset(shape->slot()));
|
||||
} else {
|
||||
size_t dynamicSlotOffset =
|
||||
holder->dynamicSlotIndex(shape->slot()) * sizeof(Value);
|
||||
writer.loadDynamicSlotResult(holderOp, dynamicSlotOffset);
|
||||
writer.loadDynamicSlotResult(holderId, dynamicSlotOffset);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1065,6 +1065,54 @@ static void EmitCallGetterResult(JSContext* cx, CacheIRWriter& writer,
|
|||
EmitCallGetterResultNoGuards(cx, writer, obj, holder, shape, receiverId);
|
||||
}
|
||||
|
||||
static bool CanAttachDOMGetter(JSContext* cx, HandleObject obj,
|
||||
HandleShape shape, ICState::Mode mode) {
|
||||
if (!JitOptions.warpBuilder) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mode != ICState::Mode::Specialized) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JSFunction* getter = &shape->getterValue().toObject().as<JSFunction>();
|
||||
if (!getter->hasJitInfo()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cx->realm() != getter->realm()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const JSJitInfo* jitInfo = getter->jitInfo();
|
||||
if (jitInfo->type() != JSJitInfo::Getter) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const JSClass* clasp = obj->getClass();
|
||||
if (!clasp->isDOMClass() || clasp->isProxy()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DOMInstanceClassHasProtoAtDepth instanceChecker =
|
||||
cx->runtime()->DOMcallbacks->instanceClassMatchesProto;
|
||||
return instanceChecker(clasp, jitInfo->protoID, jitInfo->depth);
|
||||
}
|
||||
|
||||
static void EmitCallDOMGetterResult(JSContext* cx, CacheIRWriter& writer,
|
||||
JSObject* obj, JSObject* holder,
|
||||
Shape* shape, ObjOperandId objId) {
|
||||
// Note: this relies on EmitCallGetterResultGuards emitting a shape guard
|
||||
// for specialized stubs.
|
||||
// The shape guard ensures the receiver's Class is valid for this DOM getter.
|
||||
EmitCallGetterResultGuards(writer, obj, holder, shape, objId,
|
||||
ICState::Mode::Specialized);
|
||||
|
||||
JSFunction* getter = &shape->getterValue().toObject().as<JSFunction>();
|
||||
writer.callDOMGetterResult(objId, getter->jitInfo());
|
||||
writer.typeMonitorResult();
|
||||
}
|
||||
|
||||
void GetPropIRGenerator::attachMegamorphicNativeSlot(ObjOperandId objId,
|
||||
jsid id,
|
||||
bool handleMissing) {
|
||||
|
@ -1130,6 +1178,14 @@ AttachDecision GetPropIRGenerator::tryAttachNative(HandleObject obj,
|
|||
case CanAttachNativeGetter: {
|
||||
MOZ_ASSERT(!idempotent());
|
||||
maybeEmitIdGuard(id);
|
||||
|
||||
if (!isSuper() && CanAttachDOMGetter(cx_, obj, shape, mode_)) {
|
||||
EmitCallDOMGetterResult(cx_, writer, obj, holder, shape, objId);
|
||||
|
||||
trackAttached("DOMGetter");
|
||||
return AttachDecision::Attach;
|
||||
}
|
||||
|
||||
EmitCallGetterResult(cx_, writer, obj, holder, shape, objId, receiverId,
|
||||
mode_);
|
||||
|
||||
|
|
|
@ -1860,6 +1860,14 @@
|
|||
sameRealm: BoolImm
|
||||
nargsAndFlags: RawWordField
|
||||
|
||||
- name: CallDOMGetterResult
|
||||
shared: false
|
||||
transpile: false
|
||||
cost_estimate: 4
|
||||
args:
|
||||
obj: ObjId
|
||||
jitInfo: RawPointerField
|
||||
|
||||
- name: ProxyGetResult
|
||||
shared: false
|
||||
transpile: true
|
||||
|
|
|
@ -1069,6 +1069,30 @@ bool IonCacheIRCompiler::emitCallNativeGetterResult(
|
|||
return true;
|
||||
}
|
||||
|
||||
bool IonCacheIRCompiler::emitCallDOMGetterResult(ObjOperandId objId,
|
||||
uint32_t jitInfoOffset) {
|
||||
JitSpew(JitSpew_Codegen, "%s", __FUNCTION__);
|
||||
AutoSaveLiveRegisters save(*this);
|
||||
AutoOutputRegister output(*this);
|
||||
|
||||
Register obj = allocator.useRegister(masm, objId);
|
||||
|
||||
const JSJitInfo* info = rawWordStubField<const JSJitInfo*>(jitInfoOffset);
|
||||
|
||||
allocator.discardStack(masm);
|
||||
prepareVMCall(masm, save);
|
||||
|
||||
masm.Push(obj);
|
||||
masm.Push(ImmPtr(info));
|
||||
|
||||
using Fn =
|
||||
bool (*)(JSContext*, const JSJitInfo*, HandleObject, MutableHandleValue);
|
||||
callVM<Fn, jit::CallDOMGetter>(masm);
|
||||
|
||||
masm.storeCallResultValue(output);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IonCacheIRCompiler::emitProxyGetResult(ObjOperandId objId,
|
||||
uint32_t idOffset) {
|
||||
JitSpew(JitSpew_Codegen, "%s", __FUNCTION__);
|
||||
|
|
|
@ -76,6 +76,7 @@ namespace jit {
|
|||
_(BoxBoxableValue, js::wasm::BoxBoxableValue) \
|
||||
_(BoxNonStrictThis, js::BoxNonStrictThis) \
|
||||
_(BuiltinObjectOperation, js::BuiltinObjectOperation) \
|
||||
_(CallDOMGetter, js::jit::CallDOMGetter) \
|
||||
_(CallNativeGetter, js::jit::CallNativeGetter) \
|
||||
_(CallNativeSetter, js::jit::CallNativeSetter) \
|
||||
_(CharCodeAt, js::jit::CharCodeAt) \
|
||||
|
|
|
@ -1498,6 +1498,24 @@ bool CallNativeGetter(JSContext* cx, HandleFunction callee,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool CallDOMGetter(JSContext* cx, const JSJitInfo* info, HandleObject obj,
|
||||
MutableHandleValue result) {
|
||||
MOZ_ASSERT(info->type() == JSJitInfo::Getter);
|
||||
MOZ_ASSERT(obj->isNative());
|
||||
MOZ_ASSERT(obj->getClass()->isDOMClass());
|
||||
|
||||
#ifdef DEBUG
|
||||
DOMInstanceClassHasProtoAtDepth instanceChecker =
|
||||
cx->runtime()->DOMcallbacks->instanceClassMatchesProto;
|
||||
MOZ_ASSERT(instanceChecker(obj->getClass(), info->protoID, info->depth));
|
||||
#endif
|
||||
|
||||
// Loading DOM_OBJECT_SLOT, which must be the first slot.
|
||||
JS::Value val = JS::GetReservedSlot(obj, 0);
|
||||
JSJitGetterOp getter = info->getter;
|
||||
return getter(cx, obj, val.toPrivate(), JSJitGetterCallArgs(result));
|
||||
}
|
||||
|
||||
bool CallNativeSetter(JSContext* cx, HandleFunction callee, HandleObject obj,
|
||||
HandleValue rhs) {
|
||||
AutoRealm ar(cx, callee);
|
||||
|
|
|
@ -1078,6 +1078,9 @@ MOZ_MUST_USE bool CallNativeGetter(JSContext* cx, HandleFunction callee,
|
|||
HandleValue receiver,
|
||||
MutableHandleValue result);
|
||||
|
||||
bool CallDOMGetter(JSContext* cx, const JSJitInfo* jitInfo, HandleObject obj,
|
||||
MutableHandleValue result);
|
||||
|
||||
MOZ_MUST_USE bool CallNativeSetter(JSContext* cx, HandleFunction callee,
|
||||
HandleObject obj, HandleValue rhs);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче