Bug 807047 - Only use missing property cache on non-idempotent IC. r=jandem

This commit is contained in:
Nicolas B. Pierron 2012-11-05 16:40:41 -08:00
parent e6ce95979f
commit b9bd532656
4 changed files with 42 additions and 13 deletions

View File

@ -182,17 +182,22 @@ IsCacheableNoProperty(JSObject *obj, JSObject *holder, const Shape *shape, jsbyt
obj2 = obj2->getProto();
}
// The pc is NULL if the cache is idempotent. We cannot share missing
// properties between caches because TI can only try to prove that a type is
// contained, but does not attempts to check if something does not exists.
// So the infered type of getprop would be missing and would not contain
// undefined, as expected for missing properties.
if (!pc)
return false;
#if JS_HAS_NO_SUCH_METHOD
// This case cannot appear with an idempotent cache.
if (pc) {
// The __noSuchMethod__ hook may substitute in a valid method. Since,
// if o.m is missing, o.m() will probably be an error, just mark all
// missing callprops as uncacheable.
if (JSOp(*pc) == JSOP_CALLPROP ||
JSOp(*pc) == JSOP_CALLELEM)
{
return false;
}
// The __noSuchMethod__ hook may substitute in a valid method. Since,
// if o.m is missing, o.m() will probably be an error, just mark all
// missing callprops as uncacheable.
if (JSOp(*pc) == JSOP_CALLPROP ||
JSOp(*pc) == JSOP_CALLELEM)
{
return false;
}
#endif
@ -1852,7 +1857,7 @@ IonCacheName::attach(JSContext *cx, IonScript *ion, HandleObject scopeChain, Han
static bool
IsCacheableName(JSContext *cx, HandleObject scopeChain, HandleObject obj, HandleObject holder,
HandleShape shape, const TypedOrValueRegister &output)
HandleShape shape, jsbytecode *pc, const TypedOrValueRegister &output)
{
if (!shape)
return false;
@ -1864,7 +1869,7 @@ IsCacheableName(JSContext *cx, HandleObject scopeChain, HandleObject obj, Handle
if (obj->isGlobal()) {
// Support only simple property lookups.
if (!IsCacheableGetPropReadSlot(obj, holder, shape) &&
!IsCacheableNoProperty(obj, holder, shape, NULL, output))
!IsCacheableNoProperty(obj, holder, shape, pc, output))
return false;
} else if (obj->isCall()) {
if (!shape->hasDefaultGetter())
@ -1910,7 +1915,7 @@ js::ion::GetNameCache(JSContext *cx, size_t cacheIndex, HandleObject scopeChain,
return false;
if (cache.stubCount() < MAX_STUBS &&
IsCacheableName(cx, scopeChain, obj, holder, shape, cache.outputReg()))
IsCacheableName(cx, scopeChain, obj, holder, shape, pc, cache.outputReg()))
{
if (!cache.attach(cx, ion, scopeChain, obj, shape))
return false;

View File

@ -0,0 +1,10 @@
// |jit-test| error: TypeError
function f(code) {
eval(code)
}
f("\
function h({x}) {\
print(x)\
}\
h(/x/);\
")

View File

@ -0,0 +1,7 @@
// |jit-test| error: TypeError
t = ""
function f(code) {
eval("(function(){" + code + "})")()
}
evalcx("")
f("var r=({a:1})[\"\"];t(r)")

View File

@ -1512,6 +1512,13 @@ class GetPropCompiler : public PICStubCompiler
MarkNotIdempotent(script, f.pc());
}
// The property is missing, Mark as not idempotent to avoid
// recompilation in Ion Monkey GetPropertyCache.
if (!getprop.holder) {
RawScript script = f.script().unsafeGet();
MarkNotIdempotent(script, f.pc());
}
if (hadGC())
return Lookup_Uncacheable;