From fd8a117e2f59b74d653265f23c9f2af6e5920480 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 6 Aug 2009 12:40:51 -0700 Subject: [PATCH] Bug 503694 - TM: Code run off an event handler is never traced, r=brendan. --HG-- extra : rebase_source : da2e900baac68f88f06eaa8554b245f7d403153f --- js/src/jsinterp.cpp | 35 ----------------------------------- js/src/jsobj.cpp | 23 ++--------------------- js/src/jsobj.h | 22 ++++++++++++++++++++++ js/src/jstracer.cpp | 34 +++++++++++++++++++++++++++++++++- 4 files changed, 57 insertions(+), 57 deletions(-) diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index b3f738a0860..8adc2b221cf 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -1423,17 +1423,6 @@ js_InternalInvoke(JSContext *cx, JSObject *obj, jsval fval, uintN flags, JSBool ok; js_LeaveTrace(cx); - -#ifdef JS_TRACER - /* - * The JIT requires that the scope chain here is equal to its global - * object. Disable the JIT for this call if this condition is not true. - */ - uint32 oldOptions = cx->options; - if ((oldOptions & JSOPTION_JIT) && obj != JS_GetGlobalForObject(cx, obj)) - cx->options &= ~JSOPTION_JIT; -#endif - invokevp = js_AllocStack(cx, 2 + argc, &mark); if (!invokevp) return JS_FALSE; @@ -1463,13 +1452,6 @@ js_InternalInvoke(JSContext *cx, JSObject *obj, jsval fval, uintN flags, } js_FreeStack(cx, mark); - -#ifdef JS_TRACER - /* Possibly re-enable JIT, if disabled above. */ - if (oldOptions & JSOPTION_JIT) - cx->options |= JSOPTION_JIT; -#endif - return ok; } @@ -1527,16 +1509,6 @@ js_Execute(JSContext *cx, JSObject *chain, JSScript *script, js_LeaveTrace(cx); -#ifdef JS_TRACER - /* - * The JIT requires that the scope chain here is equal to its global - * object. Disable the JIT for this call if this condition is not true. - */ - uint32 oldOptions = cx->options; - if ((oldOptions & JSOPTION_JIT) && chain != JS_GetGlobalForObject(cx, chain)) - cx->options &= ~JSOPTION_JIT; -#endif - #ifdef INCLUDE_MOZILLA_DTRACE if (JAVASCRIPT_EXECUTE_START_ENABLED()) jsdtrace_execute_start(script); @@ -1661,13 +1633,6 @@ out: if (JAVASCRIPT_EXECUTE_DONE_ENABLED()) jsdtrace_execute_done(script); #endif - -#ifdef JS_TRACER - /* Possibly re-enable JIT, if disabled above. */ - if (oldOptions & JSOPTION_JIT) - cx->options |= JSOPTION_JIT; -#endif - return ok; } diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index bb7ba260807..c8dfca2587a 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -3942,25 +3942,6 @@ out: return protoIndex; } -/* - * We cache name lookup results only for the global object or for native - * non-global objects without prototype or with prototype that never mutates, - * see bug 462734 and bug 487039. - */ -static inline bool -IsCacheableNonGlobalScope(JSObject *obj) -{ - JS_ASSERT(STOBJ_GET_PARENT(obj)); - - JSClass *clasp = STOBJ_GET_CLASS(obj); - bool cacheable = (clasp == &js_CallClass || - clasp == &js_BlockClass || - clasp == &js_DeclEnvClass); - - JS_ASSERT_IF(cacheable, obj->map->ops->lookupProperty == js_LookupProperty); - return cacheable; -} - JSPropCacheEntry * js_FindPropertyHelper(JSContext *cx, jsid id, JSBool cacheResult, JSObject **objp, JSObject **pobjp, JSProperty **propp) @@ -3979,7 +3960,7 @@ js_FindPropertyHelper(JSContext *cx, jsid id, JSBool cacheResult, parent = OBJ_GET_PARENT(cx, obj); for (scopeIndex = 0; parent - ? IsCacheableNonGlobalScope(obj) + ? js_IsCacheableNonGlobalScope(obj) : obj->map->ops->lookupProperty == js_LookupProperty; ++scopeIndex) { protoIndex = @@ -4078,7 +4059,7 @@ js_FindIdentifierBase(JSContext *cx, JSObject *scopeChain, jsid id) * farther checks or lookups. For details see the JSOP_BINDNAME case of * js_Interpret. */ - for (int scopeIndex = 0; IsCacheableNonGlobalScope(obj); scopeIndex++) { + for (int scopeIndex = 0; js_IsCacheableNonGlobalScope(obj); scopeIndex++) { JSObject *pobj; JSProperty *prop; int protoIndex = js_LookupPropertyWithFlags(cx, obj, id, diff --git a/js/src/jsobj.h b/js/src/jsobj.h index a29d964b1d7..0a798d43d16 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -719,6 +719,28 @@ extern int js_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, uintN flags, JSObject **objp, JSProperty **propp); + +/* + * We cache name lookup results only for the global object or for native + * non-global objects without prototype or with prototype that never mutates, + * see bug 462734 and bug 487039. + */ +static inline bool +js_IsCacheableNonGlobalScope(JSObject *obj) +{ + extern JS_FRIEND_DATA(JSClass) js_CallClass; + extern JS_FRIEND_DATA(JSClass) js_DeclEnvClass; + JS_ASSERT(STOBJ_GET_PARENT(obj)); + + JSClass *clasp = STOBJ_GET_CLASS(obj); + bool cacheable = (clasp == &js_CallClass || + clasp == &js_BlockClass || + clasp == &js_DeclEnvClass); + + JS_ASSERT_IF(cacheable, obj->map->ops->lookupProperty == js_LookupProperty); + return cacheable; +} + /* * If cacheResult is false, return JS_NO_PROP_CACHE_FILL on success. */ diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 1f471c5c051..bc53de6ea1f 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -5407,8 +5407,40 @@ ExecuteTree(JSContext* cx, Fragment* f, uintN& inlineCallCount, JS_ASSERT(f->root == f && f->code() && f->vmprivate); + /* + * The JIT records and expects to execute with two scope-chain + * assumptions baked-in: + * + * 1. That the bottom of the scope chain is global, in the sense of + * JSCLASS_IS_GLOBAL. + * + * 2. That the scope chain between fp and the global is free of + * "unusual" native objects such as HTML forms or other funny + * things. + * + * #2 is checked here while following the scope-chain links, via + * js_IsCacheableNonGlobalScope, which consults a whitelist of known + * class types; once a global is found, it's checked for #1. Failing + * either check causes an early return from execution. + */ + JSObject* parent; + JSObject* child = cx->fp->scopeChain; + while ((parent = OBJ_GET_PARENT(cx, child)) != NULL) { + if (!js_IsCacheableNonGlobalScope(child)) { + debug_only_print0(LC_TMTracer,"Blacklist: non-cacheable object on scope chain.\n"); + Blacklist((jsbytecode*) f->root->ip); + return NULL; + } + child = parent; + } + JSObject* globalObj = child; + if (!(OBJ_GET_CLASS(cx, globalObj)->flags & JSCLASS_IS_GLOBAL)) { + debug_only_print0(LC_TMTracer, "Blacklist: non-global at root of scope chain.\n"); + Blacklist((jsbytecode*) f->root->ip); + return NULL; + } + JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx); - JSObject* globalObj = JS_GetGlobalForObject(cx, cx->fp->scopeChain); TreeInfo* ti = (TreeInfo*)f->vmprivate; unsigned ngslots = ti->globalSlots->length(); uint16* gslots = ti->globalSlots->data();