Bug 1007631 - Enable the innerize-window optimization for getters; r=jandem

This commit is contained in:
Johannes Schulte 2014-11-14 17:53:11 +01:00
Родитель 2201b8a64d
Коммит c7cd5daae9
3 изменённых файлов: 103 добавлений и 43 удалений

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

@ -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(),