зеркало из 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)
|
explicit JSJitGetterCallArgs(JS::Rooted<JS::Value>* rooted)
|
||||||
: JS::MutableHandle<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; }
|
JS::MutableHandle<JS::Value> rval() { return *this; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -609,6 +609,34 @@ bool BaselineCacheIRCompiler::emitCallNativeGetterResult(
|
||||||
return true;
|
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,
|
bool BaselineCacheIRCompiler::emitProxyGetResult(ObjOperandId objId,
|
||||||
uint32_t idOffset) {
|
uint32_t idOffset) {
|
||||||
JitSpew(JitSpew_Codegen, "%s", __FUNCTION__);
|
JitSpew(JitSpew_Codegen, "%s", __FUNCTION__);
|
||||||
|
|
|
@ -225,15 +225,15 @@ GetPropIRGenerator::GetPropIRGenerator(JSContext* cx, HandleScript script,
|
||||||
resultFlags_(resultFlags),
|
resultFlags_(resultFlags),
|
||||||
preliminaryObjectAction_(PreliminaryObjectAction::None) {}
|
preliminaryObjectAction_(PreliminaryObjectAction::None) {}
|
||||||
|
|
||||||
static void EmitLoadSlotResult(CacheIRWriter& writer, ObjOperandId holderOp,
|
static void EmitLoadSlotResult(CacheIRWriter& writer, ObjOperandId holderId,
|
||||||
NativeObject* holder, Shape* shape) {
|
NativeObject* holder, Shape* shape) {
|
||||||
if (holder->isFixedSlot(shape->slot())) {
|
if (holder->isFixedSlot(shape->slot())) {
|
||||||
writer.loadFixedSlotResult(holderOp,
|
writer.loadFixedSlotResult(holderId,
|
||||||
NativeObject::getFixedSlotOffset(shape->slot()));
|
NativeObject::getFixedSlotOffset(shape->slot()));
|
||||||
} else {
|
} else {
|
||||||
size_t dynamicSlotOffset =
|
size_t dynamicSlotOffset =
|
||||||
holder->dynamicSlotIndex(shape->slot()) * sizeof(Value);
|
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);
|
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,
|
void GetPropIRGenerator::attachMegamorphicNativeSlot(ObjOperandId objId,
|
||||||
jsid id,
|
jsid id,
|
||||||
bool handleMissing) {
|
bool handleMissing) {
|
||||||
|
@ -1130,6 +1178,14 @@ AttachDecision GetPropIRGenerator::tryAttachNative(HandleObject obj,
|
||||||
case CanAttachNativeGetter: {
|
case CanAttachNativeGetter: {
|
||||||
MOZ_ASSERT(!idempotent());
|
MOZ_ASSERT(!idempotent());
|
||||||
maybeEmitIdGuard(id);
|
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,
|
EmitCallGetterResult(cx_, writer, obj, holder, shape, objId, receiverId,
|
||||||
mode_);
|
mode_);
|
||||||
|
|
||||||
|
|
|
@ -1860,6 +1860,14 @@
|
||||||
sameRealm: BoolImm
|
sameRealm: BoolImm
|
||||||
nargsAndFlags: RawWordField
|
nargsAndFlags: RawWordField
|
||||||
|
|
||||||
|
- name: CallDOMGetterResult
|
||||||
|
shared: false
|
||||||
|
transpile: false
|
||||||
|
cost_estimate: 4
|
||||||
|
args:
|
||||||
|
obj: ObjId
|
||||||
|
jitInfo: RawPointerField
|
||||||
|
|
||||||
- name: ProxyGetResult
|
- name: ProxyGetResult
|
||||||
shared: false
|
shared: false
|
||||||
transpile: true
|
transpile: true
|
||||||
|
|
|
@ -1069,6 +1069,30 @@ bool IonCacheIRCompiler::emitCallNativeGetterResult(
|
||||||
return true;
|
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,
|
bool IonCacheIRCompiler::emitProxyGetResult(ObjOperandId objId,
|
||||||
uint32_t idOffset) {
|
uint32_t idOffset) {
|
||||||
JitSpew(JitSpew_Codegen, "%s", __FUNCTION__);
|
JitSpew(JitSpew_Codegen, "%s", __FUNCTION__);
|
||||||
|
|
|
@ -76,6 +76,7 @@ namespace jit {
|
||||||
_(BoxBoxableValue, js::wasm::BoxBoxableValue) \
|
_(BoxBoxableValue, js::wasm::BoxBoxableValue) \
|
||||||
_(BoxNonStrictThis, js::BoxNonStrictThis) \
|
_(BoxNonStrictThis, js::BoxNonStrictThis) \
|
||||||
_(BuiltinObjectOperation, js::BuiltinObjectOperation) \
|
_(BuiltinObjectOperation, js::BuiltinObjectOperation) \
|
||||||
|
_(CallDOMGetter, js::jit::CallDOMGetter) \
|
||||||
_(CallNativeGetter, js::jit::CallNativeGetter) \
|
_(CallNativeGetter, js::jit::CallNativeGetter) \
|
||||||
_(CallNativeSetter, js::jit::CallNativeSetter) \
|
_(CallNativeSetter, js::jit::CallNativeSetter) \
|
||||||
_(CharCodeAt, js::jit::CharCodeAt) \
|
_(CharCodeAt, js::jit::CharCodeAt) \
|
||||||
|
|
|
@ -1498,6 +1498,24 @@ bool CallNativeGetter(JSContext* cx, HandleFunction callee,
|
||||||
return true;
|
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,
|
bool CallNativeSetter(JSContext* cx, HandleFunction callee, HandleObject obj,
|
||||||
HandleValue rhs) {
|
HandleValue rhs) {
|
||||||
AutoRealm ar(cx, callee);
|
AutoRealm ar(cx, callee);
|
||||||
|
|
|
@ -1078,6 +1078,9 @@ MOZ_MUST_USE bool CallNativeGetter(JSContext* cx, HandleFunction callee,
|
||||||
HandleValue receiver,
|
HandleValue receiver,
|
||||||
MutableHandleValue result);
|
MutableHandleValue result);
|
||||||
|
|
||||||
|
bool CallDOMGetter(JSContext* cx, const JSJitInfo* jitInfo, HandleObject obj,
|
||||||
|
MutableHandleValue result);
|
||||||
|
|
||||||
MOZ_MUST_USE bool CallNativeSetter(JSContext* cx, HandleFunction callee,
|
MOZ_MUST_USE bool CallNativeSetter(JSContext* cx, HandleFunction callee,
|
||||||
HandleObject obj, HandleValue rhs);
|
HandleObject obj, HandleValue rhs);
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче