зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1007631 - Enable the innerize-window optimization for getters; r=jandem
This commit is contained in:
Родитель
2201b8a64d
Коммит
c7cd5daae9
|
@ -6009,6 +6009,7 @@ TryAttachGlobalNameStub(JSContext *cx, HandleScript script, jsbytecode *pc,
|
|||
}
|
||||
ICGetProp_CallNative::Compiler compiler(cx, monitorStub, current,
|
||||
getter, script->pcToOffset(pc),
|
||||
/* outerClass = */ nullptr,
|
||||
/* inputDefinitelyObject = */ true);
|
||||
newStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
} else {
|
||||
|
@ -6019,6 +6020,7 @@ TryAttachGlobalNameStub(JSContext *cx, HandleScript script, jsbytecode *pc,
|
|||
}
|
||||
ICGetProp_CallNativePrototype::Compiler compiler(cx, monitorStub, global, current,
|
||||
getter, script->pcToOffset(pc),
|
||||
/* outerClass = */ nullptr,
|
||||
/* inputDefinitelyObject = */ true);
|
||||
newStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
}
|
||||
|
@ -6582,13 +6584,10 @@ TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc,
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!isDOMProxy && !obj->isNative())
|
||||
return true;
|
||||
|
||||
bool isCallProp = (JSOp(*pc) == JSOP_CALLPROP);
|
||||
|
||||
ICStub *monitorStub = stub->fallbackMonitorStub()->firstMonitorStub();
|
||||
if (!isDOMProxy && IsCacheableGetPropReadSlot(obj, holder, shape)) {
|
||||
if (!isDOMProxy && obj->isNative() && IsCacheableGetPropReadSlot(obj, holder, shape)) {
|
||||
bool isFixedSlot;
|
||||
uint32_t offset;
|
||||
GetFixedOrDynamicSlotOffset(&holder->as<NativeObject>(), shape->slot(), &isFixedSlot, &offset);
|
||||
|
@ -6620,8 +6619,8 @@ TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc,
|
|||
}
|
||||
|
||||
bool isScripted = false;
|
||||
bool cacheableCall = IsCacheableGetPropCall(cx, obj, holder, shape, &isScripted,
|
||||
isTemporarilyUnoptimizable, isDOMProxy);
|
||||
bool cacheableCall = obj->isNative() && IsCacheableGetPropCall(cx, obj, holder, shape, &isScripted,
|
||||
isTemporarilyUnoptimizable);
|
||||
|
||||
// Try handling scripted getters.
|
||||
if (cacheableCall && isScripted && !isDOMProxy) {
|
||||
|
@ -6661,6 +6660,56 @@ TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc,
|
|||
return true;
|
||||
}
|
||||
|
||||
// If it's a shadowed listbase proxy property, attach stub to call Proxy::get instead.
|
||||
if (isDOMProxy && domProxyShadowsResult == Shadows) {
|
||||
MOZ_ASSERT(obj == holder);
|
||||
#if JS_HAS_NO_SUCH_METHOD
|
||||
if (isCallProp)
|
||||
return true;
|
||||
#endif
|
||||
|
||||
JitSpew(JitSpew_BaselineIC, " Generating GetProp(DOMProxyProxy) stub");
|
||||
Rooted<ProxyObject*> proxy(cx, &obj->as<ProxyObject>());
|
||||
ICGetProp_DOMProxyShadowed::Compiler compiler(cx, monitorStub, proxy, name,
|
||||
script->pcToOffset(pc));
|
||||
ICStub *newStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
if (!newStub)
|
||||
return false;
|
||||
stub->addNewStub(newStub);
|
||||
*attached = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
const Class *outerClass = nullptr;
|
||||
if (!isDOMProxy && !obj->isNative()) {
|
||||
outerClass = obj->getClass();
|
||||
DebugOnly<JSObject *> outer = obj.get();
|
||||
obj = GetInnerObject(obj);
|
||||
MOZ_ASSERT(script->global().isNative());
|
||||
if (obj != &script->global())
|
||||
return true;
|
||||
// ICGetProp_CallNative*::Compiler::generateStubCode depends on this.
|
||||
MOZ_ASSERT(&((GetProxyDataLayout(outer)->values->privateSlot).toObject()) == obj);
|
||||
if (!EffectlesslyLookupProperty(cx, obj, name, &holder, &shape, &isDOMProxy,
|
||||
&domProxyShadowsResult, &domProxyHasGeneration))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
cacheableCall = IsCacheableGetPropCall(cx, obj, holder, shape, &isScripted,
|
||||
isTemporarilyUnoptimizable, isDOMProxy);
|
||||
}
|
||||
|
||||
if (!shape || !shape->hasGetterValue() || !shape->getterValue().isObject() ||
|
||||
!shape->getterObject()->is<JSFunction>())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
RootedFunction callee(cx, &shape->getterObject()->as<JSFunction>());
|
||||
|
||||
if (outerClass && (!callee->jitInfo() || callee->jitInfo()->needsOuterizedThisObject()))
|
||||
return true;
|
||||
|
||||
// Try handling JSNative getters.
|
||||
if (cacheableCall && !isScripted) {
|
||||
#if JS_HAS_NO_SUCH_METHOD
|
||||
|
@ -6671,7 +6720,6 @@ TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc,
|
|||
return true;
|
||||
#endif
|
||||
|
||||
RootedFunction callee(cx, &shape->getterObject()->as<JSFunction>());
|
||||
MOZ_ASSERT(callee->isNative());
|
||||
|
||||
JitSpew(JitSpew_BaselineIC, " Generating GetProp(%s%s/NativeGetter %p) stub",
|
||||
|
@ -6704,7 +6752,7 @@ TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc,
|
|||
}
|
||||
|
||||
ICGetProp_CallNative::Compiler compiler(cx, monitorStub, obj, callee,
|
||||
script->pcToOffset(pc));
|
||||
script->pcToOffset(pc), outerClass);
|
||||
newStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
} else {
|
||||
if (UpdateExistingGetPropCallStubs(stub, ICStub::GetProp_CallNativePrototype,
|
||||
|
@ -6714,7 +6762,7 @@ TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc,
|
|||
}
|
||||
|
||||
ICGetProp_CallNativePrototype::Compiler compiler(cx, monitorStub, obj, holder, callee,
|
||||
script->pcToOffset(pc));
|
||||
script->pcToOffset(pc), outerClass);
|
||||
newStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
}
|
||||
if (!newStub)
|
||||
|
@ -6724,26 +6772,6 @@ TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc,
|
|||
return true;
|
||||
}
|
||||
|
||||
// If it's a shadowed listbase proxy property, attach stub to call Proxy::get instead.
|
||||
if (isDOMProxy && domProxyShadowsResult == Shadows) {
|
||||
MOZ_ASSERT(obj == holder);
|
||||
#if JS_HAS_NO_SUCH_METHOD
|
||||
if (isCallProp)
|
||||
return true;
|
||||
#endif
|
||||
|
||||
JitSpew(JitSpew_BaselineIC, " Generating GetProp(DOMProxyProxy) stub");
|
||||
Rooted<ProxyObject*> proxy(cx, &obj->as<ProxyObject>());
|
||||
ICGetProp_DOMProxyShadowed::Compiler compiler(cx, monitorStub, proxy, name,
|
||||
script->pcToOffset(pc));
|
||||
ICStub *newStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
if (!newStub)
|
||||
return false;
|
||||
stub->addNewStub(newStub);
|
||||
*attached = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -7460,12 +7488,24 @@ ICGetProp_CallNative::Compiler::generateStubCode(MacroAssembler &masm)
|
|||
|
||||
GeneralRegisterSet regs(availableGeneralRegs(0));
|
||||
Register obj = InvalidReg;
|
||||
|
||||
MOZ_ASSERT(!(inputDefinitelyObject_ && outerClass_));
|
||||
if (inputDefinitelyObject_) {
|
||||
obj = R0.scratchReg();
|
||||
} else {
|
||||
regs.take(R0);
|
||||
masm.branchTestObject(Assembler::NotEqual, R0, &failure);
|
||||
obj = masm.extractObject(R0, ExtractTemp0);
|
||||
if (outerClass_) {
|
||||
ValueOperand val = regs.takeAnyValue();
|
||||
Register tmp = regs.takeAny();
|
||||
masm.branchTestObjClass(Assembler::NotEqual, obj, tmp, outerClass_, &failure);
|
||||
masm.loadPtr(Address(obj, ProxyDataOffset + offsetof(ProxyDataLayout, values)), tmp);
|
||||
masm.loadValue(Address(tmp, offsetof(ProxyValueArray, privateSlot)), val);
|
||||
obj = masm.extractObject(val, ExtractTemp0);
|
||||
regs.add(val);
|
||||
regs.add(tmp);
|
||||
}
|
||||
}
|
||||
regs.takeUnchecked(obj);
|
||||
|
||||
|
@ -7508,6 +7548,7 @@ ICGetProp_CallNativePrototype::Compiler::generateStubCode(MacroAssembler &masm)
|
|||
GeneralRegisterSet regs(availableGeneralRegs(0));
|
||||
Register objReg = InvalidReg;
|
||||
|
||||
MOZ_ASSERT(!(inputDefinitelyObject_ && outerClass_));
|
||||
if (inputDefinitelyObject_) {
|
||||
objReg = R0.scratchReg();
|
||||
} else {
|
||||
|
@ -7515,6 +7556,16 @@ ICGetProp_CallNativePrototype::Compiler::generateStubCode(MacroAssembler &masm)
|
|||
// Guard input is an object and unbox.
|
||||
masm.branchTestObject(Assembler::NotEqual, R0, &failure);
|
||||
objReg = masm.extractObject(R0, ExtractTemp0);
|
||||
if (outerClass_) {
|
||||
ValueOperand val = regs.takeAnyValue();
|
||||
Register tmp = regs.takeAny();
|
||||
masm.branchTestObjClass(Assembler::NotEqual, objReg, tmp, outerClass_, &failure);
|
||||
masm.loadPtr(Address(objReg, ProxyDataOffset + offsetof(ProxyDataLayout, values)), tmp);
|
||||
masm.loadValue(Address(tmp, offsetof(ProxyValueArray, privateSlot)), val);
|
||||
objReg = masm.extractObject(val, ExtractTemp0);
|
||||
regs.add(val);
|
||||
regs.add(tmp);
|
||||
}
|
||||
}
|
||||
regs.takeUnchecked(objReg);
|
||||
|
||||
|
|
|
@ -4737,15 +4737,23 @@ class ICGetPropCallGetter : public ICMonitoredStub
|
|||
RootedObject holder_;
|
||||
RootedFunction getter_;
|
||||
uint32_t pcOffset_;
|
||||
const Class *outerClass_;
|
||||
|
||||
virtual int32_t getKey() const {
|
||||
return static_cast<int32_t>(kind) |
|
||||
(static_cast<int32_t>(!!outerClass_) << 16);
|
||||
}
|
||||
|
||||
public:
|
||||
Compiler(JSContext *cx, ICStub::Kind kind, ICStub *firstMonitorStub,
|
||||
HandleObject holder, HandleFunction getter, uint32_t pcOffset)
|
||||
HandleObject holder, HandleFunction getter, uint32_t pcOffset,
|
||||
const Class *outerClass)
|
||||
: ICStubCompiler(cx, kind),
|
||||
firstMonitorStub_(firstMonitorStub),
|
||||
holder_(cx, holder),
|
||||
getter_(cx, getter),
|
||||
pcOffset_(pcOffset)
|
||||
pcOffset_(pcOffset),
|
||||
outerClass_(outerClass)
|
||||
{
|
||||
MOZ_ASSERT(kind == ICStub::GetProp_CallScripted ||
|
||||
kind == ICStub::GetProp_CallNative ||
|
||||
|
@ -4784,8 +4792,10 @@ class ICGetPropCallPrototypeGetter : public ICGetPropCallGetter
|
|||
|
||||
public:
|
||||
Compiler(JSContext *cx, ICStub::Kind kind, ICStub *firstMonitorStub,
|
||||
HandleObject obj, HandleObject holder, HandleFunction getter, uint32_t pcOffset)
|
||||
: ICGetPropCallGetter::Compiler(cx, kind, firstMonitorStub, holder, getter, pcOffset),
|
||||
HandleObject obj, HandleObject holder, HandleFunction getter, uint32_t pcOffset,
|
||||
const Class *outerClass)
|
||||
: ICGetPropCallGetter::Compiler(cx, kind, firstMonitorStub, holder, getter, pcOffset,
|
||||
outerClass),
|
||||
receiver_(cx, obj)
|
||||
{
|
||||
MOZ_ASSERT(kind == ICStub::GetProp_CallScripted ||
|
||||
|
@ -4833,7 +4843,7 @@ class ICGetProp_CallScripted : public ICGetPropCallPrototypeGetter
|
|||
HandleObject holder, HandleFunction getter, uint32_t pcOffset)
|
||||
: ICGetPropCallPrototypeGetter::Compiler(cx, ICStub::GetProp_CallScripted,
|
||||
firstMonitorStub, obj, holder,
|
||||
getter, pcOffset)
|
||||
getter, pcOffset, /* outerClass = */ nullptr)
|
||||
{}
|
||||
|
||||
ICStub *getStub(ICStubSpace *space) {
|
||||
|
@ -4886,9 +4896,10 @@ class ICGetProp_CallNative : public ICGetPropCallGetter
|
|||
|
||||
public:
|
||||
Compiler(JSContext *cx, ICStub *firstMonitorStub, HandleObject obj,
|
||||
HandleFunction getter, uint32_t pcOffset, bool inputDefinitelyObject = false)
|
||||
HandleFunction getter, uint32_t pcOffset, const Class *outerClass,
|
||||
bool inputDefinitelyObject = false)
|
||||
: ICGetPropCallGetter::Compiler(cx, ICStub::GetProp_CallNative, firstMonitorStub,
|
||||
obj, getter, pcOffset),
|
||||
obj, getter, pcOffset, outerClass),
|
||||
inputDefinitelyObject_(inputDefinitelyObject)
|
||||
{}
|
||||
|
||||
|
@ -4943,10 +4954,10 @@ class ICGetProp_CallNativePrototype : public ICGetPropCallPrototypeGetter
|
|||
public:
|
||||
Compiler(JSContext *cx, ICStub *firstMonitorStub, HandleObject obj,
|
||||
HandleObject holder, HandleFunction getter, uint32_t pcOffset,
|
||||
bool inputDefinitelyObject = false)
|
||||
const Class *outerClass, bool inputDefinitelyObject = false)
|
||||
: ICGetPropCallPrototypeGetter::Compiler(cx, ICStub::GetProp_CallNativePrototype,
|
||||
firstMonitorStub, obj, holder,
|
||||
getter, pcOffset),
|
||||
getter, pcOffset, outerClass),
|
||||
inputDefinitelyObject_(inputDefinitelyObject)
|
||||
{}
|
||||
|
||||
|
|
|
@ -10086,11 +10086,6 @@ IonBuilder::getPropTryInnerize(bool *emitted, MDefinition *obj, PropertyName *na
|
|||
// Note: the Baseline ICs don't know about this optimization, so it's
|
||||
// possible the global property's HeapTypeSet has not been initialized
|
||||
// yet. In this case we'll fall back to getPropTryCache for now.
|
||||
//
|
||||
// Also note that we don't call getPropTryCommonGetter below, because
|
||||
// (a) it requires a Baseline getter stub, which we don't have for outer
|
||||
// window proxies and (b) we have to be careful not to pass the inner
|
||||
// object to scripted getters etc. See bug 1007631.
|
||||
|
||||
if (!getPropTryConstant(emitted, inner, name, types) || *emitted)
|
||||
return *emitted;
|
||||
|
@ -10098,6 +10093,9 @@ IonBuilder::getPropTryInnerize(bool *emitted, MDefinition *obj, PropertyName *na
|
|||
if (!getStaticName(&script()->global(), name, emitted) || *emitted)
|
||||
return *emitted;
|
||||
|
||||
if (!getPropTryCommonGetter(emitted, inner, name, types) || *emitted)
|
||||
return *emitted;
|
||||
|
||||
// Passing the inner object to GetProperty IC is safe, see the
|
||||
// needsOuterizedThisObject check in IsCacheableGetPropCallNative.
|
||||
BarrierKind barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(),
|
||||
|
|
Загрузка…
Ссылка в новой задаче