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

View File

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