Bug 918593 - Part 1: Allow caching of global object prototypal name sets in NameIC. (r=djvj)

This commit is contained in:
Eric Faust 2013-09-23 15:36:19 -07:00
parent 9dff5bab8a
commit 525b3811ac
2 changed files with 19 additions and 25 deletions

View File

@ -3660,7 +3660,7 @@ GenerateScopeChainGuard(MacroAssembler &masm, JSObject *scopeObj,
static void
GenerateScopeChainGuards(MacroAssembler &masm, JSObject *scopeChain, JSObject *holder,
Register outputReg, Label *failures)
Register outputReg, Label *failures, bool skipLastGuard = false)
{
JSObject *tobj = scopeChain;
@ -3669,7 +3669,11 @@ GenerateScopeChainGuards(MacroAssembler &masm, JSObject *scopeChain, JSObject *h
while (true) {
JS_ASSERT(IsCacheableNonGlobalScope(tobj) || tobj->is<GlobalObject>());
if (skipLastGuard && tobj == holder)
break;
GenerateScopeChainGuard(masm, tobj, outputReg, NULL, failures);
if (tobj == holder)
break;
@ -3773,7 +3777,8 @@ BindNameIC::update(JSContext *cx, size_t cacheIndex, HandleObject scopeChain)
}
bool
NameIC::attachReadSlot(JSContext *cx, IonScript *ion, HandleObject scopeChain, HandleObject holder,
NameIC::attachReadSlot(JSContext *cx, IonScript *ion, HandleObject scopeChain,
HandleObject holderBase, HandleObject holder,
HandleShape shape)
{
MacroAssembler masm(cx);
@ -3782,26 +3787,16 @@ NameIC::attachReadSlot(JSContext *cx, IonScript *ion, HandleObject scopeChain, H
Register scratchReg = outputReg().valueReg().scratchReg();
// Don't guard the base of the proto chain the name was found on. It will be guarded
// by GenerateReadSlot().
masm.mov(scopeChainReg(), scratchReg);
GenerateScopeChainGuards(masm, scopeChain, holder, scratchReg, &failures);
GenerateScopeChainGuards(masm, scopeChain, holderBase, scratchReg, &failures,
/* skipLastGuard = */true);
unsigned slot = shape->slot();
if (holder->isFixedSlot(slot)) {
Address addr(scratchReg, JSObject::getFixedSlotOffset(slot));
masm.loadTypedOrValue(addr, outputReg());
} else {
masm.loadPtr(Address(scratchReg, JSObject::offsetOfSlots()), scratchReg);
Address addr(scratchReg, holder->dynamicSlotIndex(slot) * sizeof(Value));
masm.loadTypedOrValue(addr, outputReg());
}
attacher.jumpRejoin(masm);
if (failures.used()) {
masm.bind(&failures);
attacher.jumpNextStub(masm);
}
// GenerateScopeChain leaves the last scope chain in scrachReg, even though it
// doesn't generate the extra guard.
GenerateReadSlot(cx, ion, masm, attacher, holderBase, holder, shape, scratchReg,
outputReg(), failures.used() ? &failures : NULL);
return linkAndAttachStub(cx, masm, attacher, ion, "generic");
}
@ -3815,8 +3810,6 @@ IsCacheableNameReadSlot(JSContext *cx, HandleObject scopeChain, HandleObject obj
return false;
if (!obj->isNative())
return false;
if (obj != holder)
return false;
if (obj->is<GlobalObject>()) {
// Support only simple property lookups.
@ -3824,6 +3817,7 @@ IsCacheableNameReadSlot(JSContext *cx, HandleObject scopeChain, HandleObject obj
!IsCacheableNoProperty(obj, holder, shape, pc, output))
return false;
} else if (obj->is<CallObject>()) {
JS_ASSERT(obj == holder);
if (!shape->hasDefaultGetter())
return false;
} else {
@ -3904,7 +3898,7 @@ NameIC::update(JSContext *cx, size_t cacheIndex, HandleObject scopeChain,
if (cache.canAttachStub()) {
if (IsCacheableNameReadSlot(cx, scopeChain, obj, holder, shape, pc, cache.outputReg())) {
if (!cache.attachReadSlot(cx, ion, scopeChain, obj, shape))
if (!cache.attachReadSlot(cx, ion, scopeChain, obj, holder, shape))
return false;
} else if (IsCacheableNameCallGetter(scopeChain, obj, holder, shape)) {
if (!cache.attachCallGetter(cx, ion, obj, holder, shape, returnAddr))

View File

@ -932,8 +932,8 @@ class NameIC : public RepatchIonCache
return typeOf_;
}
bool attachReadSlot(JSContext *cx, IonScript *ion, HandleObject scopeChain, HandleObject obj,
HandleShape shape);
bool attachReadSlot(JSContext *cx, IonScript *ion, HandleObject scopeChain,
HandleObject holderBase, HandleObject holder, HandleShape shape);
bool attachCallGetter(JSContext *cx, IonScript *ion, JSObject *obj, JSObject *holder,
HandleShape shape, void *returnAddr);