зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1665396 - Support calling DOM setters in CacheIR. r=jandem
Differential Revision: https://phabricator.services.mozilla.com/D90422
This commit is contained in:
Родитель
c4fd01303a
Коммит
07459af75f
|
@ -53,6 +53,9 @@ class JSJitSetterCallArgs : protected JS::MutableHandle<JS::Value> {
|
|||
explicit JSJitSetterCallArgs(const JS::CallArgs& args)
|
||||
: JS::MutableHandle<JS::Value>(args[0]) {}
|
||||
|
||||
explicit JSJitSetterCallArgs(JS::Rooted<JS::Value>* rooted)
|
||||
: JS::MutableHandle<JS::Value>(rooted) {}
|
||||
|
||||
JS::MutableHandle<JS::Value> operator[](unsigned i) {
|
||||
MOZ_ASSERT(i == 0);
|
||||
return *this;
|
||||
|
|
|
@ -2012,6 +2012,35 @@ bool BaselineCacheIRCompiler::emitCallScriptedSetter(
|
|||
return true;
|
||||
}
|
||||
|
||||
bool BaselineCacheIRCompiler::emitCallDOMSetter(ObjOperandId objId,
|
||||
uint32_t jitInfoOffset,
|
||||
ValOperandId rhsId) {
|
||||
JitSpew(JitSpew_Codegen, "%s", __FUNCTION__);
|
||||
Register obj = allocator.useRegister(masm, objId);
|
||||
ValueOperand val = allocator.useValueRegister(masm, rhsId);
|
||||
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(val);
|
||||
masm.Push(obj);
|
||||
masm.Push(scratch);
|
||||
|
||||
using Fn = bool (*)(JSContext*, const JSJitInfo*, HandleObject, HandleValue);
|
||||
callVM<Fn, CallDOMSetter>(masm);
|
||||
|
||||
stubFrame.leave(masm);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BaselineCacheIRCompiler::emitCallSetArrayLength(ObjOperandId objId,
|
||||
bool strict,
|
||||
ValOperandId rhsId) {
|
||||
|
|
|
@ -1065,8 +1065,10 @@ 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) {
|
||||
static bool CanAttachDOMGetterSetter(JSContext* cx, JSJitInfo::OpType type,
|
||||
HandleObject obj, HandleShape shape,
|
||||
ICState::Mode mode) {
|
||||
MOZ_ASSERT(type == JSJitInfo::Getter || type == JSJitInfo::Setter);
|
||||
if (!JitOptions.warpBuilder) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1075,17 +1077,19 @@ static bool CanAttachDOMGetter(JSContext* cx, HandleObject obj,
|
|||
return false;
|
||||
}
|
||||
|
||||
JSFunction* getter = &shape->getterValue().toObject().as<JSFunction>();
|
||||
if (!getter->hasJitInfo()) {
|
||||
Value v =
|
||||
type == JSJitInfo::Getter ? shape->getterValue() : shape->setterValue();
|
||||
JSFunction* fun = &v.toObject().as<JSFunction>();
|
||||
if (!fun->hasJitInfo()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cx->realm() != getter->realm()) {
|
||||
if (cx->realm() != fun->realm()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const JSJitInfo* jitInfo = getter->jitInfo();
|
||||
if (jitInfo->type() != JSJitInfo::Getter) {
|
||||
const JSJitInfo* jitInfo = fun->jitInfo();
|
||||
if (jitInfo->type() != type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1179,7 +1183,8 @@ AttachDecision GetPropIRGenerator::tryAttachNative(HandleObject obj,
|
|||
MOZ_ASSERT(!idempotent());
|
||||
maybeEmitIdGuard(id);
|
||||
|
||||
if (!isSuper() && CanAttachDOMGetter(cx_, obj, shape, mode_)) {
|
||||
if (!isSuper() &&
|
||||
CanAttachDOMGetterSetter(cx_, JSJitInfo::Getter, obj, shape, mode_)) {
|
||||
EmitCallDOMGetterResult(cx_, writer, obj, holder, shape, objId);
|
||||
|
||||
trackAttached("DOMGetter");
|
||||
|
@ -3916,6 +3921,16 @@ static void EmitCallSetterNoGuards(JSContext* cx, CacheIRWriter& writer,
|
|||
writer.returnFromIC();
|
||||
}
|
||||
|
||||
static void EmitCallDOMSetterNoGuards(JSContext* cx, CacheIRWriter& writer,
|
||||
Shape* shape, ObjOperandId objId,
|
||||
ValOperandId rhsId) {
|
||||
JSFunction* setter = &shape->setterValue().toObject().as<JSFunction>();
|
||||
MOZ_ASSERT(cx->realm() == setter->realm());
|
||||
|
||||
writer.callDOMSetter(objId, setter->jitInfo(), rhsId);
|
||||
writer.returnFromIC();
|
||||
}
|
||||
|
||||
AttachDecision SetPropIRGenerator::tryAttachSetter(HandleObject obj,
|
||||
ObjOperandId objId,
|
||||
HandleId id,
|
||||
|
@ -3945,6 +3960,13 @@ AttachDecision SetPropIRGenerator::tryAttachSetter(HandleObject obj,
|
|||
writer.guardHasGetterSetter(objId, propShape);
|
||||
}
|
||||
|
||||
if (CanAttachDOMGetterSetter(cx_, JSJitInfo::Setter, obj, propShape, mode_)) {
|
||||
EmitCallDOMSetterNoGuards(cx_, writer, propShape, objId, rhsId);
|
||||
|
||||
trackAttached("DOMSetter");
|
||||
return AttachDecision::Attach;
|
||||
}
|
||||
|
||||
EmitCallSetterNoGuards(cx_, writer, obj, holder, propShape, objId, rhsId);
|
||||
|
||||
trackAttached("Setter");
|
||||
|
|
|
@ -1440,6 +1440,15 @@
|
|||
sameRealm: BoolImm
|
||||
nargsAndFlags: RawWordField
|
||||
|
||||
- name: CallDOMSetter
|
||||
shared: false
|
||||
transpile: false
|
||||
cost_estimate: 4
|
||||
args:
|
||||
obj: ObjId
|
||||
jitInfo: RawPointerField
|
||||
rhs: ValId
|
||||
|
||||
- name: CallSetArrayLength
|
||||
shared: false
|
||||
transpile: true
|
||||
|
|
|
@ -1093,6 +1093,29 @@ bool IonCacheIRCompiler::emitCallDOMGetterResult(ObjOperandId objId,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool IonCacheIRCompiler::emitCallDOMSetter(ObjOperandId objId,
|
||||
uint32_t jitInfoOffset,
|
||||
ValOperandId rhsId) {
|
||||
JitSpew(JitSpew_Codegen, "%s", __FUNCTION__);
|
||||
AutoSaveLiveRegisters save(*this);
|
||||
|
||||
Register obj = allocator.useRegister(masm, objId);
|
||||
ValueOperand val = allocator.useValueRegister(masm, rhsId);
|
||||
|
||||
const JSJitInfo* info = rawWordStubField<const JSJitInfo*>(jitInfoOffset);
|
||||
|
||||
allocator.discardStack(masm);
|
||||
prepareVMCall(masm, save);
|
||||
|
||||
masm.Push(val);
|
||||
masm.Push(obj);
|
||||
masm.Push(ImmPtr(info));
|
||||
|
||||
using Fn = bool (*)(JSContext*, const JSJitInfo*, HandleObject, HandleValue);
|
||||
callVM<Fn, jit::CallDOMSetter>(masm);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IonCacheIRCompiler::emitProxyGetResult(ObjOperandId objId,
|
||||
uint32_t idOffset) {
|
||||
JitSpew(JitSpew_Codegen, "%s", __FUNCTION__);
|
||||
|
|
|
@ -77,6 +77,7 @@ namespace jit {
|
|||
_(BoxNonStrictThis, js::BoxNonStrictThis) \
|
||||
_(BuiltinObjectOperation, js::BuiltinObjectOperation) \
|
||||
_(CallDOMGetter, js::jit::CallDOMGetter) \
|
||||
_(CallDOMSetter, js::jit::CallDOMSetter) \
|
||||
_(CallNativeGetter, js::jit::CallNativeGetter) \
|
||||
_(CallNativeSetter, js::jit::CallNativeSetter) \
|
||||
_(CharCodeAt, js::jit::CharCodeAt) \
|
||||
|
|
|
@ -1531,6 +1531,26 @@ bool CallNativeSetter(JSContext* cx, HandleFunction callee, HandleObject obj,
|
|||
return natfun(cx, 1, vp.begin());
|
||||
}
|
||||
|
||||
bool CallDOMSetter(JSContext* cx, const JSJitInfo* info, HandleObject obj,
|
||||
HandleValue value) {
|
||||
MOZ_ASSERT(info->type() == JSJitInfo::Setter);
|
||||
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);
|
||||
JSJitSetterOp setter = info->setter;
|
||||
|
||||
RootedValue v(cx, value);
|
||||
return setter(cx, obj, val.toPrivate(), JSJitSetterCallArgs(&v));
|
||||
}
|
||||
|
||||
bool EqualStringsHelperPure(JSString* str1, JSString* str2) {
|
||||
// IC code calls this directly so we shouldn't GC.
|
||||
AutoUnsafeCallWithABI unsafe;
|
||||
|
|
|
@ -1081,6 +1081,9 @@ MOZ_MUST_USE bool CallNativeGetter(JSContext* cx, HandleFunction callee,
|
|||
bool CallDOMGetter(JSContext* cx, const JSJitInfo* jitInfo, HandleObject obj,
|
||||
MutableHandleValue result);
|
||||
|
||||
bool CallDOMSetter(JSContext* cx, const JSJitInfo* jitInfo, HandleObject obj,
|
||||
HandleValue value);
|
||||
|
||||
MOZ_MUST_USE bool CallNativeSetter(JSContext* cx, HandleFunction callee,
|
||||
HandleObject obj, HandleValue rhs);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче