Use JS_GetGlobalForObject to get the global object. Walking back the call chain is not equivalent and not safe.
authorAndreas Gal <gal@mozilla.com>
Mon, 14 Jul 2008 16:40:38 -0700
changeset 17657 14f0ea38fac42068e461932ef0c704b5e83bfb83
parent 17656 be90e8cf66b74f998ecf02015b13015f1587555b
child 17658 ee36097ea0b5071301bdd8dc6d3b08a184991c90
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone1.9.1a1pre
Use JS_GetGlobalForObject to get the global object. Walking back the call chain is not equivalent and not safe.
js/src/jstracer.cpp
js/src/jstracer.h
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -320,43 +320,39 @@ public:
 
 /* This macro can be used to iterate over all slots in currently pending
    frames that make up the native frame, including global variables and
    frames consisting of rval, args, vars, and stack (except for the top-
    level frame which does not have args or vars. */
 #define FORALL_SLOTS_IN_PENDING_FRAMES(cx, entryFrame, currentFrame, code)    \
     JS_BEGIN_MACRO                                                            \
         DEF_VPNAME;                                                           \
-        /* find the global frame */                                           \
-        JSStackFrame* global = entryFrame;                                    \
-        while (global->down)                                                  \
-            global = global->down;                                            \
-        JSObject* gvarobj = global->varobj;                                   \
+        JSObject* globalObj = JS_GetGlobalForObject(cx, cx->fp->scopeChain);  \
         unsigned n;                                                           \
         jsval* vp;                                                            \
         JSAtom** atoms = entryFrame->script->atomMap.vector;                  \
         unsigned natoms = entryFrame->script->atomMap.length;                 \
         SET_VPNAME("global");                                                 \
         for (n = 0; n < natoms; ++n) {                                        \
             JSAtom* atom = atoms[n];                                          \
             if (!ATOM_IS_STRING(atom))                                        \
                 continue;                                                     \
             jsid id = ATOM_TO_JSID(atom);                                     \
             JSObject* pobj;                                                   \
             JSProperty *prop;                                                 \
             JSScopeProperty* sprop;                                           \
-            if (!js_LookupProperty(cx, gvarobj, id, &pobj, &prop))            \
+            if (!js_LookupProperty(cx, globalObj, id, &pobj, &prop))          \
                 continue; /* XXX need to signal real error! */                \
             if (!prop)                                                        \
                 continue; /* property not found -- string constant? */        \
-            if (pobj == gvarobj) {                                            \
+            if (pobj == globalObj) {                                          \
                 sprop = (JSScopeProperty*) prop;                              \
                 if (SPROP_HAS_STUB_GETTER(sprop) &&                           \
                     SPROP_HAS_STUB_SETTER(sprop)) {                           \
-                    vp = &STOBJ_GET_SLOT(gvarobj, sprop->slot);               \
+                    vp = &STOBJ_GET_SLOT(globalObj, sprop->slot);             \
                     { code; }                                                 \
                     INC_VPNUM();                                              \
                 }                                                             \
             }                                                                 \
             JS_UNLOCK_OBJ(cx, pobj);                                          \
         }                                                                     \
         /* count the number of pending frames */                              \
         unsigned frames = 0;                                                  \
@@ -437,20 +433,17 @@ public:
             value = demote(out, value);
         return out->insStorei(value, base, d);
     }
 };
 
 TraceRecorder::TraceRecorder(JSContext* cx, Fragmento* fragmento, Fragment* _fragment)
 {
     this->cx = cx;
-    JSStackFrame* global = cx->fp;
-    while (global->down)
-        global = global->down;
-    this->global = global;
+    this->globalObj = JS_GetGlobalForObject(cx, cx->fp->scopeChain);
     this->fragment = _fragment;
     entryFrame = cx->fp;
     entryRegs.pc = entryFrame->regs->pc;
     entryRegs.sp = entryFrame->regs->sp;
     this->atoms = cx->fp->script->atomMap.vector;
 
 #ifdef DEBUG
     printf("recording starting from %s:%u\n", cx->fp->script->filename, 
@@ -561,45 +554,42 @@ TraceRecorder::onFrame(jsval* p) const
 {
     return isGlobal(p) || findFrame(p) != NULL;
 }
 
 /* Determine whether an address points to a global variable (gvar). */
 bool
 TraceRecorder::isGlobal(jsval* p) const
 {
-    JSObject* varobj = global->varobj;
-
     /* has to be in either one of the fslots or dslots of varobj */
-    if (size_t(p - varobj->fslots) < JS_INITIAL_NSLOTS)
+    if (size_t(p - globalObj->fslots) < JS_INITIAL_NSLOTS)
         return true;
-    return varobj->dslots &&
-           size_t(p - varobj->dslots) < size_t(varobj->dslots[-1] - JS_INITIAL_NSLOTS);
+    return globalObj->dslots &&
+           size_t(p - globalObj->dslots) < size_t(globalObj->dslots[-1] - JS_INITIAL_NSLOTS);
 }
 
 /* Calculate the total number of native frame slots we need from this frame
    all the way back to the entry frame, including the current stack usage. */
 unsigned
 TraceRecorder::nativeFrameSlots(JSStackFrame* fp, JSFrameRegs& regs) const
 {
     unsigned slots = 0;
-    JSObject* gvarobj = global->varobj;
     unsigned n;
     JSAtom** atoms = entryFrame->script->atomMap.vector;
     unsigned natoms = entryFrame->script->atomMap.length;
     for (n = 0; n < natoms; ++n) {
         JSAtom* atom = atoms[n];
         if (!ATOM_IS_STRING(atom))
             continue;
         jsid id = ATOM_TO_JSID(atom);
         JSObject* obj2;
         JSScopeProperty* sprop;
-        if (!js_LookupProperty(cx, gvarobj, id, &obj2, (JSProperty**)&sprop))
+        if (!js_LookupProperty(cx, globalObj, id, &obj2, (JSProperty**)&sprop))
             continue; /* XXX need to signal real error */
-        if (obj2 != gvarobj)
+        if (obj2 != globalObj)
             continue;
         JS_ASSERT(sprop);
         if (SPROP_HAS_STUB_GETTER(sprop) && SPROP_HAS_STUB_SETTER(sprop))
             ++slots;
         JS_UNLOCK_OBJ(cx, obj2);
     }
     for (;;) {
         slots += 1/*rval*/ + (regs.sp - fp->spbase);
@@ -849,22 +839,16 @@ TraceRecorder::get(jsval* p)
 
 JSContext*
 TraceRecorder::getContext() const
 {
     return cx;
 }
 
 JSStackFrame*
-TraceRecorder::getGlobalFrame() const
-{
-    return global;
-}
-
-JSStackFrame*
 TraceRecorder::getEntryFrame() const
 {
     return entryFrame;
 }
 
 JSStackFrame*
 TraceRecorder::getFp() const
 {
@@ -1105,17 +1089,17 @@ bool
 js_LoopEdge(JSContext* cx)
 {
     JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
 
     /* is the recorder currently active? */
     if (tm->recorder) {
 #ifdef JS_THREADSAFE
         /* XXX should this test not be earlier, to avoid even recording? */
-        if (OBJ_SCOPE(tm->recorder->getGlobalFrame()->varobj)->title.ownercx != cx) {
+        if (OBJ_SCOPE(JS_GetGlobalForObject(cx, cx->fp->scopeChain))->title.ownercx != cx) {
 #ifdef DEBUG
             printf("Global object not owned by this context.\n");
 #endif
             return false; /* we stay away from shared global objects */
         }
 #endif
 
         if (tm->recorder->loopEdge())
@@ -1990,17 +1974,17 @@ bool TraceRecorder::record_JSOP_CALL()
 
     /* Didn't find it. */
     ABORT_TRACE("unknown native");
 }
 
 bool TraceRecorder::record_JSOP_NAME()
 {
     JSObject* obj = cx->fp->scopeChain;
-    if (obj != global->varobj)
+    if (obj != globalObj)
         return false;
 
     LIns* obj_ins = lir->insLoadi(lir->insLoadi(cx_ins, offsetof(JSContext, fp)),
                                   offsetof(JSStackFrame, scopeChain));
     uint32 slot;
     if (!test_property_cache_direct_slot(obj, obj_ins, slot))
         return false;
 
@@ -2218,17 +2202,17 @@ bool TraceRecorder::record_JSOP_FORELEM(
 }
 bool TraceRecorder::record_JSOP_POPN()
 {
     return true;
 }
 bool TraceRecorder::record_JSOP_BINDNAME()
 {
     JSObject* obj = cx->fp->scopeChain;
-    if (obj != global->varobj)
+    if (obj != globalObj)
         return false;
 
     LIns* obj_ins = lir->insLoadi(lir->insLoadi(cx_ins, offsetof(JSContext, fp)),
                                   offsetof(JSStackFrame, scopeChain));
     JSObject* obj2;
     JSPropCacheEntry* entry;
     if (!test_property_cache(obj, obj_ins, obj2, entry))
         return false;
@@ -2245,17 +2229,17 @@ bool TraceRecorder::record_JSOP_SETNAME(
     if (JSVAL_IS_PRIMITIVE(l))
         return false;
 
     /*
      * Trace cases that are global code or in lightweight functions scoped by
      * the global object only.
      */
     JSObject* obj = JSVAL_TO_OBJECT(l);
-    if (obj != cx->fp->scopeChain || obj != global->varobj)
+    if (obj != cx->fp->scopeChain || obj != globalObj)
         return false;
 
     LIns* obj_ins = get(&l);
     uint32 slot;
     if (!test_property_cache_direct_slot(obj, obj_ins, slot))
         return false;
 
     LIns* r_ins = get(&r);
--- a/js/src/jstracer.h
+++ b/js/src/jstracer.h
@@ -102,17 +102,17 @@ extern struct nanojit::CallInfo builtins
 
 #define TYPEMAP_TYPE_ANY            7
 
 #define TYPEMAP_FLAG_DEMOTE 0x10 /* try to record as int */
 #define TYPEMAP_FLAG_DONT_DEMOTE 0x20 /* do not try to record as int */
 
 class TraceRecorder {
     JSContext*              cx;
-    JSStackFrame*           global;
+    JSObject*               globalObj;
     Tracker                 tracker;
     char*                   entryTypeMap;
     struct JSStackFrame*    entryFrame;
     struct JSFrameRegs      entryRegs;
     JSAtom**                atoms;
     nanojit::Fragment*      fragment;
     VMFragmentInfo*         fragmentInfo;
     nanojit::LirBuffer*     lirbuf;
@@ -190,17 +190,16 @@ class TraceRecorder {
                                      nanojit::LIns*& dslots_ins);
     bool guardDenseArrayIndexWithinBounds(JSObject* obj, jsint idx, nanojit::LIns* obj_ins,
                                           nanojit::LIns*& dslots_ins, nanojit::LIns* idx_ins);
 public:
     TraceRecorder(JSContext* cx, nanojit::Fragmento*, nanojit::Fragment*);
     ~TraceRecorder();
 
     JSContext* getContext() const;
-    JSStackFrame* getGlobalFrame() const;
     JSStackFrame* getEntryFrame() const;
     JSStackFrame* getFp() const;
     JSFrameRegs& getRegs() const;
     nanojit::Fragment* getFragment() const;
     nanojit::SideExit* snapshot();
 
     nanojit::LIns* get(jsval* p);