Bug 749371 - Remove now-unnecessary JS_ClearScope defense (r=bhackett)
authorLuke Wagner <luke@mozilla.com>
Mon, 27 Aug 2012 09:13:44 -0700
changeset 105641 e208bf8354c950401a9b2457e80d32921eb75478
parent 105640 104671eaadb84738adcb5b5b4a03379367ad9367
child 105642 a7f0beb4637490aef47f653e429b4fe653829cde
push id55
push usershu@rfrn.org
push dateThu, 30 Aug 2012 01:33:09 +0000
reviewersbhackett
bugs749371
milestone17.0a1
Bug 749371 - Remove now-unnecessary JS_ClearScope defense (r=bhackett)
js/src/jsapi.h
js/src/jsinfer.cpp
js/src/jsinferinlines.h
js/src/jsinterp.cpp
js/src/jsscript.h
js/src/jsscriptinlines.h
js/src/methodjit/Compiler.cpp
js/src/methodjit/PolyIC.cpp
js/src/vm/Debugger.cpp
js/src/vm/GlobalObject-inl.h
js/src/vm/GlobalObject.cpp
js/src/vm/GlobalObject.h
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -4188,17 +4188,17 @@ struct JSClass {
  * member initial value.  The "original ... value" verbiage is there because
  * in ECMA-262, global properties naming class objects are read/write and
  * deleteable, for the most part.
  *
  * Implementing this efficiently requires that global objects have classes
  * with the following flags. Failure to use JSCLASS_GLOBAL_FLAGS was
  * prevously allowed, but is now an ES5 violation and thus unsupported.
  */
-#define JSCLASS_GLOBAL_SLOT_COUNT      (JSProto_LIMIT * 3 + 24)
+#define JSCLASS_GLOBAL_SLOT_COUNT      (JSProto_LIMIT * 3 + 23)
 #define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n)                                    \
     (JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n)))
 #define JSCLASS_GLOBAL_FLAGS                                                  \
     JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(0)
 #define JSCLASS_HAS_GLOBAL_FLAG_AND_SLOTS(clasp)                              \
   (((clasp)->flags & JSCLASS_IS_GLOBAL)                                       \
    && JSCLASS_RESERVED_SLOTS(clasp) >= JSCLASS_GLOBAL_SLOT_COUNT)
 
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -1130,17 +1130,17 @@ PropertyAccess(JSContext *cx, JSScript *
 }
 
 /* Whether the JSObject/TypeObject referent of an access on type cannot be determined. */
 static inline bool
 UnknownPropertyAccess(JSScript *script, Type type)
 {
     return type.isUnknown()
         || type.isAnyObject()
-        || (!type.isObject() && !script->hasGlobal());
+        || (!type.isObject() && !script->compileAndGo);
 }
 
 template <PropertyAccessKind access>
 void
 TypeConstraintProp<access>::newType(JSContext *cx, TypeSet *source, Type type)
 {
     if (UnknownPropertyAccess(script, type)) {
         /*
@@ -1443,17 +1443,17 @@ TypeConstraintTransformThis::newType(JSC
         target->addType(cx, type);
         return;
     }
 
     /*
      * Note: if |this| is null or undefined, the pushed value is the outer window. We
      * can't use script->getGlobalType() here because it refers to the inner window.
      */
-    if (!script->hasGlobal() ||
+    if (!script->compileAndGo ||
         type.isPrimitive(JSVAL_TYPE_NULL) ||
         type.isPrimitive(JSVAL_TYPE_UNDEFINED)) {
         target->addType(cx, Type::UnknownType());
         return;
     }
 
     TypeObject *object = NULL;
     switch (type.primitive()) {
@@ -2136,17 +2136,17 @@ types::UseNewTypeForInitializer(JSContex
         return false;
 
     return !script->analysis()->getCode(pc).inLoop;
 }
 
 bool
 types::ArrayPrototypeHasIndexedProperty(JSContext *cx, JSScript *script)
 {
-    if (!cx->typeInferenceEnabled() || !script->hasGlobal())
+    if (!cx->typeInferenceEnabled() || !script->compileAndGo)
         return true;
 
     JSObject *proto = script->global().getOrCreateArrayPrototype(cx);
     if (!proto)
         return true;
 
     do {
         TypeObject *type = proto->getType(cx);
@@ -3315,17 +3315,17 @@ CheckNextTest(jsbytecode *pc)
         /* TRAP ok here */
         return false;
     }
 }
 
 static inline TypeObject *
 GetInitializerType(JSContext *cx, JSScript *script, jsbytecode *pc)
 {
-    if (!script->hasGlobal())
+    if (!script->compileAndGo)
         return NULL;
 
     JSOp op = JSOp(*pc);
     JS_ASSERT(op == JSOP_NEWARRAY || op == JSOP_NEWOBJECT || op == JSOP_NEWINIT);
 
     bool isArray = (op == JSOP_NEWARRAY || (op == JSOP_NEWINIT && GET_UINT8(pc) == JSProto_Array));
     JSProtoKey key = isArray ? JSProto_Array : JSProto_Object;
 
@@ -3498,17 +3498,17 @@ ScriptAnalysis::analyzeTypesBytecode(JSC
       case JSOP_XMLELTEXPR:
         pushed[0].addType(cx, Type::StringType());
         break;
       case JSOP_NULL:
         pushed[0].addType(cx, Type::NullType());
         break;
 
       case JSOP_REGEXP:
-        if (script->hasGlobal()) {
+        if (script->compileAndGo) {
             TypeObject *object = TypeScript::StandardType(cx, script, JSProto_RegExp);
             if (!object)
                 return false;
             pushed[0].addType(cx, Type::ObjectType(object));
         } else {
             pushed[0].addType(cx, Type::UnknownType());
         }
         break;
@@ -3710,17 +3710,17 @@ ScriptAnalysis::analyzeTypesBytecode(JSC
         if (script->needsArgsObj())
             pushed[0].addType(cx, Type::UnknownType());
         else
             pushed[0].addType(cx, Type::MagicArgType());
         break;
 
       case JSOP_REST: {
         StackTypeSet *types = script->analysis()->bytecodeTypes(pc);
-        if (script->hasGlobal()) {
+        if (script->compileAndGo) {
             TypeObject *rest = TypeScript::InitObject(cx, script, pc, JSProto_Array);
             if (!rest)
                 return false;
             types->addType(cx, Type::ObjectType(rest));
 
             // Simulate setting a element.
             HeapTypeSet *propTypes = rest->getProperty(cx, JSID_VOID, true);
             if (!propTypes)
@@ -3845,17 +3845,17 @@ ScriptAnalysis::analyzeTypesBytecode(JSC
       case JSOP_DEFFUN: {
         JSObject *obj = script->getObject(GET_UINT32_INDEX(pc));
 
         TypeSet *res = NULL;
         if (op == JSOP_LAMBDA)
             res = &pushed[0];
 
         if (res) {
-            if (script->hasGlobal() && !UseNewTypeForClone(obj->toFunction()))
+            if (script->compileAndGo && !UseNewTypeForClone(obj->toFunction()))
                 res->addType(cx, Type::ObjectType(obj));
             else
                 res->addType(cx, Type::UnknownType());
         } else {
             cx->compartment->types.monitorBytecode(cx, script, offset);
         }
         break;
       }
@@ -3911,17 +3911,17 @@ ScriptAnalysis::analyzeTypesBytecode(JSC
         JSProtoKey key = isArray ? JSProto_Array : JSProto_Object;
 
         if (UseNewTypeForInitializer(cx, script, pc, key)) {
             /* Defer types pushed by this bytecode until runtime. */
             break;
         }
 
         TypeObject *initializer = GetInitializerType(cx, script, pc);
-        if (script->hasGlobal()) {
+        if (script->compileAndGo) {
             if (!initializer)
                 return false;
             types->addType(cx, Type::ObjectType(initializer));
         } else {
             JS_ASSERT(!initializer);
             types->addType(cx, Type::UnknownType());
         }
         break;
@@ -4095,17 +4095,17 @@ ScriptAnalysis::analyzeTypesBytecode(JSC
         break;
 
       case JSOP_CASE:
         poppedTypes(pc, 1)->addSubset(cx, &pushed[0]);
         break;
 
       case JSOP_GENERATOR:
           if (script->function()) {
-            if (script->hasGlobal()) {
+            if (script->compileAndGo) {
                 JSObject *proto = script->global().getOrCreateGeneratorPrototype(cx);
                 if (!proto)
                     return false;
                 TypeObject *object = proto->getNewType(cx);
                 if (!object)
                     return false;
                 TypeScript::ReturnTypes(script)->addType(cx, Type::ObjectType(object));
             } else {
@@ -4148,17 +4148,17 @@ ScriptAnalysis::analyzeTypesBytecode(JSC
       case JSOP_FILTER:
         /* Note: the second value pushed by filter is a hole, and not modelled. */
       case JSOP_ENDFILTER:
         pushed[0].addType(cx, Type::UnknownType());
         break;
 
       case JSOP_CALLEE: {
         JSFunction *fun = script->function();
-        if (script->hasGlobal() && !UseNewTypeForClone(fun))
+        if (script->compileAndGo && !UseNewTypeForClone(fun))
             pushed[0].addType(cx, Type::ObjectType(fun));
         else
             pushed[0].addType(cx, Type::UnknownType());
         break;
       }
 
       default:
         /* Display fine-grained debug information first */
@@ -4174,27 +4174,16 @@ ScriptAnalysis::analyzeTypes(JSContext *
 {
     JS_ASSERT(!ranInference());
 
     if (OOM()) {
         cx->compartment->types.setPendingNukeTypes(cx);
         return;
     }
 
-    /*
-     * Refuse to analyze the types in a script which is compileAndGo but is
-     * running against a global with a cleared scope. Per GlobalObject::clear,
-     * we won't be running anymore compileAndGo code against the global
-     * (moreover, after clearing our analysis results will be wrong for the
-     * script and trying to reanalyze here can cause reentrance problems if we
-     * try to reinitialize standard classes that were cleared).
-     */
-    if (script->hasClearedGlobal())
-        return;
-
     if (!ranSSA()) {
         analyzeSSA(cx);
         if (failed())
             return;
     }
 
     /*
      * Set this early to avoid reentrance. Any failures are OOMs, and will nuke
@@ -4409,19 +4398,16 @@ AnalyzeNewScriptProperties(JSContext *cx
 
     JSScript *script = fun->script();
     if (!script->ensureRanAnalysis(cx) || !script->ensureRanInference(cx)) {
         *pbaseobj = NULL;
         cx->compartment->types.setPendingNukeTypes(cx);
         return false;
     }
 
-    if (script->hasClearedGlobal())
-        return false;
-
     ScriptAnalysis *analysis = script->analysis();
 
     /*
      * Offset of the last bytecode which popped 'this' and which we have
      * processed. To support compound inline assignments to properties like
      * 'this.f = (this.g = ...)'  where multiple 'this' values are pushed
      * and popped en masse, we keep a stack of 'this' values that have yet to
      * be processed. If a 'this' is pushed before the previous 'this' value
--- a/js/src/jsinferinlines.h
+++ b/js/src/jsinferinlines.h
@@ -678,17 +678,17 @@ struct AllocationSiteKey {
 /* static */ inline TypeObject *
 TypeScript::InitObject(JSContext *cx, JSScript *script, jsbytecode *pc, JSProtoKey kind)
 {
     JS_ASSERT(!UseNewTypeForInitializer(cx, script, pc, kind));
 
     /* :XXX: Limit script->length so we don't need to check the offset up front? */
     uint32_t offset = pc - script->code;
 
-    if (!cx->typeInferenceEnabled() || !script->hasGlobal() || offset >= AllocationSiteKey::OFFSET_LIMIT)
+    if (!cx->typeInferenceEnabled() || !script->compileAndGo || offset >= AllocationSiteKey::OFFSET_LIMIT)
         return GetTypeNewObject(cx, kind);
 
     AllocationSiteKey key;
     key.script = script;
     key.offset = offset;
     key.kind = kind;
 
     if (!cx->compartment->types.allocationSiteTable)
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -265,24 +265,16 @@ js::RunScript(JSContext *cx, JSScript *s
     JS_ASSERT_IF(!fp->isGeneratorFrame(), cx->regs().pc == script->code);
     JS_ASSERT_IF(fp->isEvalFrame(), script->isActiveEval);
 #ifdef JS_METHODJIT_SPEW
     JMCheckLogging();
 #endif
 
     JS_CHECK_RECURSION(cx, return false);
 
-    /* FIXME: Once bug 470510 is fixed, make this an assert. */
-    if (script->compileAndGo) {
-        if (fp->global().isCleared()) {
-            JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CLEARED_SCOPE);
-            return false;
-        }
-    }
-
 #ifdef DEBUG
     struct CheckStackBalance {
         JSContext *cx;
         StackFrame *fp;
         RootedObject enumerators;
         CheckStackBalance(JSContext *cx)
           : cx(cx), fp(cx->fp()), enumerators(cx, cx->enumerators)
         {}
@@ -2419,26 +2411,19 @@ BEGIN_CASE(JSOP_FUNCALL)
         len = JSOP_CALL_LENGTH;
         DO_NEXT_OP(len);
     }
 
     if (!TypeMonitorCall(cx, args, construct))
         goto error;
 
     InitialFrameFlags initial = construct ? INITIAL_CONSTRUCT : INITIAL_NONE;
-
     bool newType = cx->typeInferenceEnabled() && UseNewType(cx, script, regs.pc);
-
     JSScript *newScript = fun->script();
 
-    if (newScript->compileAndGo && newScript->hasClearedGlobal()) {
-        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CLEARED_SCOPE);
-        goto error;
-    }
-
     if (!cx->stack.pushInlineFrame(cx, regs, args, *fun, newScript, initial))
         goto error;
 
     SET_SCRIPT(regs.fp()->script());
     RESET_USE_METHODJIT();
 
 #ifdef JS_METHODJIT
     if (!newType) {
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -575,19 +575,16 @@ struct JSScript : public js::gc::Cell
     inline bool ensureRanInference(JSContext *cx);
 
     inline bool hasAnalysis();
     inline void clearAnalysis();
     inline js::analyze::ScriptAnalysis *analysis();
 
     inline void clearPropertyReadTypes();
 
-    inline bool hasGlobal() const;
-    inline bool hasClearedGlobal() const;
-
     inline js::GlobalObject &global() const;
 
     /* See StaticScopeIter comment. */
     JSObject *enclosingStaticScope() const {
         JS_ASSERT(enclosingScriptsCompiledSuccessfully());
         return enclosingScope_;
     }
 
--- a/js/src/jsscriptinlines.h
+++ b/js/src/jsscriptinlines.h
@@ -115,44 +115,26 @@ JSScript::isEmpty() const
         return false;
 
     jsbytecode *pc = code;
     if (noScriptRval && JSOp(*pc) == JSOP_FALSE)
         ++pc;
     return JSOp(*pc) == JSOP_STOP;
 }
 
-inline bool
-JSScript::hasGlobal() const
-{
-    /*
-     * Make sure that we don't try to query information about global objects
-     * which have had their scopes cleared. compileAndGo code should not run
-     * anymore against such globals.
-     */
-    return compileAndGo && !global().isCleared();
-}
-
 inline js::GlobalObject &
 JSScript::global() const
 {
     /*
      * A JSScript always marks its compartment's global (via bindings) so we
      * can assert that maybeGlobal is non-null here.
      */
     return *compartment()->maybeGlobal();
 }
 
-inline bool
-JSScript::hasClearedGlobal() const
-{
-    JS_ASSERT(types);
-    return global().isCleared();
-}
-
 #ifdef JS_METHODJIT
 inline bool
 JSScript::ensureHasMJITInfo(JSContext *cx)
 {
     if (mJITInfo)
         return true;
     mJITInfo = cx->new_<JITScriptSet>();
     return mJITInfo != NULL;
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -54,17 +54,17 @@ static const size_t USES_BEFORE_INLINING
 mjit::Compiler::Compiler(JSContext *cx, JSScript *outerScript,
                          unsigned chunkIndex, bool isConstructing)
   : BaseCompiler(cx),
     outerScript(cx, outerScript),
     chunkIndex(chunkIndex),
     isConstructing(isConstructing),
     outerChunk(outerJIT()->chunkDescriptor(chunkIndex)),
     ssa(cx, outerScript),
-    globalObj(cx, outerScript->hasGlobal() ? &outerScript->global() : NULL),
+    globalObj(cx, outerScript->compileAndGo ? &outerScript->global() : NULL),
     globalSlots(globalObj ? globalObj->getRawSlots() : NULL),
     sps(&cx->runtime->spsProfiler, &script, &PC),
     masm(&sps),
     frame(cx, *thisFromCtor(), masm, stubcc),
     a(NULL), outer(NULL), script(NULL), PC(NULL), loop(NULL),
     inlineFrames(CompilerAllocPolicy(cx, *thisFromCtor())),
     branchPatches(CompilerAllocPolicy(cx, *thisFromCtor())),
 #if defined JS_MONOIC
@@ -129,21 +129,16 @@ mjit::Compiler::compile()
     }
 
     return status;
 }
 
 CompileStatus
 mjit::Compiler::checkAnalysis(HandleScript script)
 {
-    if (script->hasClearedGlobal()) {
-        JaegerSpew(JSpew_Abort, "script has a cleared global\n");
-        return Compile_Abort;
-    }
-
     if (!script->ensureRanAnalysis(cx))
         return Compile_Error;
 
     if (!script->analysis()->jaegerCompileable()) {
         JaegerSpew(JSpew_Abort, "script has uncompileable opcodes\n");
         return Compile_Abort;
     }
 
@@ -188,17 +183,17 @@ mjit::Compiler::scanInlineCalls(uint32_t
     /* Not inlining yet from 'new' scripts. */
     if (isConstructing)
         return Compile_Okay;
 
     JSScript *script = ssa.getFrame(index).script;
     ScriptAnalysis *analysis = script->analysis();
 
     /* Don't inline from functions which could have a non-global scope object. */
-    if (!script->hasGlobal() ||
+    if (!script->compileAndGo ||
         &script->global() != globalObj ||
         (script->function() && script->function()->getParent() != globalObj) ||
         (script->function() && script->function()->isHeavyweight()) ||
         script->isActiveEval) {
         return Compile_Okay;
     }
 
     uint32_t nextOffset = 0;
--- a/js/src/methodjit/PolyIC.cpp
+++ b/js/src/methodjit/PolyIC.cpp
@@ -876,17 +876,17 @@ class GetPropCompiler : public PICStubCo
 
         disable("string object length done");
 
         return Lookup_Cacheable;
     }
 
     LookupStatus generateStringPropertyStub()
     {
-        if (!f.fp()->script()->hasGlobal())
+        if (!f.fp()->script()->compileAndGo)
             return disable("String.prototype without compile-and-go global");
 
         RecompilationMonitor monitor(f.cx);
 
         RootedObject obj(f.cx, f.fp()->global().getOrCreateStringPrototype(f.cx));
         if (!obj)
             return error();
 
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -2087,17 +2087,17 @@ class Debugger::ScriptQuery {
     bool findScripts(AutoScriptVector *vector) {
         if (!prepareQuery())
             return false;
 
         /* Search each compartment for debuggee scripts. */
         for (CompartmentSet::Range r = compartments.all(); !r.empty(); r.popFront()) {
             for (gc::CellIter i(r.front(), gc::FINALIZE_SCRIPT); !i.done(); i.next()) {
                 JSScript *script = i.get<JSScript>();
-                if (script->hasGlobal() && !script->isForEval()) {
+                if (script->compileAndGo && !script->isForEval()) {
                     if (!consider(script, &script->global(), vector))
                         return false;
                 }
             }
         }
 
         /*
          * Since eval scripts have no global, we need to find them via the call
--- a/js/src/vm/GlobalObject-inl.h
+++ b/js/src/vm/GlobalObject-inl.h
@@ -6,28 +6,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef GlobalObject_inl_h___
 #define GlobalObject_inl_h___
 
 namespace js {
 
 inline void
-GlobalObject::setFlags(int32_t flags)
-{
-    setSlot(FLAGS, Int32Value(flags));
-}
-
-inline void
-GlobalObject::initFlags(int32_t flags)
-{
-    initSlot(FLAGS, Int32Value(flags));
-}
-
-inline void
 GlobalObject::setDetailsForKey(JSProtoKey key, JSObject *ctor, JSObject *proto)
 {
     JS_ASSERT(getSlotRef(key).isUndefined());
     JS_ASSERT(getSlotRef(JSProto_LIMIT + key).isUndefined());
     JS_ASSERT(getSlotRef(2 * JSProto_LIMIT + key).isUndefined());
     setSlot(key, ObjectValue(*ctor));
     setSlot(JSProto_LIMIT + key, ObjectValue(*proto));
     setSlot(2 * JSProto_LIMIT + key, ObjectValue(*ctor));
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -483,19 +483,18 @@ GlobalObject::create(JSContext *cx, Clas
 
     if (!JSObject::setSingletonType(cx, global) || !global->setVarObj(cx))
         return NULL;
 
     /* Construct a regexp statics object for this global object. */
     JSObject *res = RegExpStatics::create(cx, global);
     if (!res)
         return NULL;
+
     global->initSlot(REGEXP_STATICS, ObjectValue(*res));
-    global->initFlags(0);
-
     return global;
 }
 
 /* static */ bool
 GlobalObject::initStandardClasses(JSContext *cx, Handle<GlobalObject*> global)
 {
     JSAtomState &state = cx->runtime->atomState;
 
@@ -528,70 +527,16 @@ GlobalObject::initStandardClasses(JSCont
            js_InitWeakMapClass(cx, global) &&
            js_InitProxyClass(cx, global) &&
            js_InitMapClass(cx, global) &&
            GlobalObject::initMapIteratorProto(cx, global) &&
            js_InitSetClass(cx, global) &&
            GlobalObject::initSetIteratorProto(cx, global);
 }
 
-void
-GlobalObject::clear(JSContext *cx)
-{
-    for (int key = JSProto_Null; key < JSProto_LIMIT * 3; key++)
-        setSlot(key, UndefinedValue());
-
-    /* Clear regexp statics. */
-    getRegExpStatics()->clear();
-
-    /* Clear the runtime-codegen-enabled cache. */
-    setSlot(RUNTIME_CODEGEN_ENABLED, UndefinedValue());
-
-    /*
-     * Clear all slots storing values in case throwing trying to execute a
-     * script for this global must reinitialize standard classes.  See
-     * bug 470150.
-     */
-    setSlot(BOOLEAN_VALUEOF, UndefinedValue());
-    setSlot(EVAL, UndefinedValue());
-    setSlot(CREATE_DATAVIEW_FOR_THIS, UndefinedValue());
-    setSlot(THROWTYPEERROR, UndefinedValue());
-    setSlot(INTRINSICS, UndefinedValue());
-    setSlot(PROTO_GETTER, UndefinedValue());
-
-    /*
-     * Mark global as cleared. If we try to execute any compile-and-go
-     * scripts from here on, we will throw.
-     */
-    int32_t flags = getSlot(FLAGS).toInt32();
-    flags |= FLAGS_CLEARED;
-    setSlot(FLAGS, Int32Value(flags));
-
-    /*
-     * Reset the new object cache in the compartment, which assumes that
-     * prototypes cached on the global object are immutable.
-     */
-    cx->runtime->newObjectCache.purge();
-
-#ifdef JS_METHODJIT
-    /*
-     * Destroy compiled code for any scripts parented to this global. Call ICs
-     * can directly call scripts which have associated JIT code, and do so
-     * without checking whether the script's global has been cleared.
-     */
-    for (gc::CellIter i(cx->compartment, gc::FINALIZE_SCRIPT); !i.done(); i.next()) {
-        JSScript *script = i.get<JSScript>();
-        if (script->compileAndGo && script->hasMJITInfo() && script->hasClearedGlobal()) {
-            mjit::Recompiler::clearStackReferences(cx->runtime->defaultFreeOp(), script);
-            mjit::ReleaseScriptCode(cx->runtime->defaultFreeOp(), script);
-        }
-    }
-#endif
-}
-
 bool
 GlobalObject::isRuntimeCodeGenEnabled(JSContext *cx)
 {
     HeapSlot &v = getSlotRef(RUNTIME_CODEGEN_ENABLED);
     if (v.isUndefined()) {
         /*
          * If there are callbacks, make sure that the CSP callback is installed
          * and that it permits runtime code generation, then cache the result.
--- a/js/src/vm/GlobalObject.h
+++ b/js/src/vm/GlobalObject.h
@@ -93,37 +93,31 @@ class GlobalObject : public JSObject
     /* One-off properties stored after slots for built-ins. */
     static const unsigned ELEMENT_ITERATOR_PROTO  = FROM_BUFFER_UINT8CLAMPED + 1;
     static const unsigned GENERATOR_PROTO         = ELEMENT_ITERATOR_PROTO + 1;
     static const unsigned MAP_ITERATOR_PROTO      = GENERATOR_PROTO + 1;
     static const unsigned SET_ITERATOR_PROTO      = MAP_ITERATOR_PROTO + 1;
     static const unsigned REGEXP_STATICS          = SET_ITERATOR_PROTO + 1;
     static const unsigned FUNCTION_NS             = REGEXP_STATICS + 1;
     static const unsigned RUNTIME_CODEGEN_ENABLED = FUNCTION_NS + 1;
-    static const unsigned FLAGS                   = RUNTIME_CODEGEN_ENABLED + 1;
-    static const unsigned DEBUGGERS               = FLAGS + 1;
+    static const unsigned DEBUGGERS               = RUNTIME_CODEGEN_ENABLED + 1;
     static const unsigned INTRINSICS              = DEBUGGERS + 1;
 
     /* Total reserved-slot count for global objects. */
     static const unsigned RESERVED_SLOTS = INTRINSICS + 1;
 
     void staticAsserts() {
         /*
          * The slot count must be in the public API for JSCLASS_GLOBAL_FLAGS,
          * and we aren't going to expose GlobalObject, so just assert that the
          * two values are synchronized.
          */
         JS_STATIC_ASSERT(JSCLASS_GLOBAL_SLOT_COUNT == RESERVED_SLOTS);
     }
 
-    static const int32_t FLAGS_CLEARED = 0x1;
-
-    inline void setFlags(int32_t flags);
-    inline void initFlags(int32_t flags);
-
     friend JSObject *
     ::js_InitObjectClass(JSContext *cx, JSObject *obj);
     friend JSObject *
     ::js_InitFunctionClass(JSContext *cx, JSObject *obj);
 
     /* Initialize the Function and Object classes.  Must only be called once! */
     JSObject *
     initFunctionAndObjectClasses(JSContext *cx);
@@ -408,22 +402,16 @@ class GlobalObject : public JSObject
     template<typename T>
     inline Value createArrayFromBuffer() const;
 
     Value protoGetter() const {
         JS_ASSERT(functionObjectClassesInitialized());
         return getSlot(PROTO_GETTER);
     }
 
-    void clear(JSContext *cx);
-
-    bool isCleared() const {
-        return getSlot(FLAGS).toInt32() & FLAGS_CLEARED;
-    }
-
     bool isRuntimeCodeGenEnabled(JSContext *cx);
 
     const Value &getOriginalEval() const {
         JS_ASSERT(getSlot(EVAL).isObject());
         return getSlot(EVAL);
     }
 
     bool getFunctionNamespace(JSContext *cx, Value *vp);