Bug 1664617 - Support calling DOM getters in CacheIR r=jandem

Differential Revision: https://phabricator.services.mozilla.com/D90011
This commit is contained in:
Tom Schuster 2020-09-16 14:38:06 +00:00
Родитель 88d3f70ab7
Коммит a58b9699aa
8 изменённых файлов: 144 добавлений и 3 удалений

Просмотреть файл

@ -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);