From 872a0e6b97762414cbdfeb1bf2fd2b16d241d520 Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Mon, 27 Aug 2012 09:13:44 -0700 Subject: [PATCH] Bug 749371 - Remove now-unnecessary JS_ClearScope defense (r=bhackett) --- js/src/jsapi.h | 2 +- js/src/jsinfer.cpp | 34 ++++++--------------- js/src/jsinferinlines.h | 2 +- js/src/jsinterp.cpp | 15 --------- js/src/jsscript.h | 3 -- js/src/jsscriptinlines.h | 18 ----------- js/src/methodjit/Compiler.cpp | 9 ++---- js/src/methodjit/PolyIC.cpp | 2 +- js/src/vm/Debugger.cpp | 2 +- js/src/vm/GlobalObject-inl.h | 12 -------- js/src/vm/GlobalObject.cpp | 57 +---------------------------------- js/src/vm/GlobalObject.h | 14 +-------- 12 files changed, 18 insertions(+), 152 deletions(-) diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 8f0511196aa..7e03356b994 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -4193,7 +4193,7 @@ struct JSClass { * 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 \ diff --git a/js/src/jsinfer.cpp b/js/src/jsinfer.cpp index bf429196f7c..8821273fda3 100644 --- a/js/src/jsinfer.cpp +++ b/js/src/jsinfer.cpp @@ -1135,7 +1135,7 @@ UnknownPropertyAccess(JSScript *script, Type type) { return type.isUnknown() || type.isAnyObject() - || (!type.isObject() && !script->hasGlobal()); + || (!type.isObject() && !script->compileAndGo); } template @@ -1448,7 +1448,7 @@ TypeConstraintTransformThis::newType(JSContext *cx, TypeSet *source, Type type) * 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()); @@ -2141,7 +2141,7 @@ types::UseNewTypeForInitializer(JSContext *cx, JSScript *script, jsbytecode *pc, 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); @@ -3320,7 +3320,7 @@ CheckNextTest(jsbytecode *pc) static inline TypeObject * GetInitializerType(JSContext *cx, JSScript *script, jsbytecode *pc) { - if (!script->hasGlobal()) + if (!script->compileAndGo) return NULL; JSOp op = JSOp(*pc); @@ -3503,7 +3503,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset, break; case JSOP_REGEXP: - if (script->hasGlobal()) { + if (script->compileAndGo) { TypeObject *object = TypeScript::StandardType(cx, script, JSProto_RegExp); if (!object) return false; @@ -3715,7 +3715,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset, 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; @@ -3850,7 +3850,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset, 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()); @@ -3916,7 +3916,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset, } TypeObject *initializer = GetInitializerType(cx, script, pc); - if (script->hasGlobal()) { + if (script->compileAndGo) { if (!initializer) return false; types->addType(cx, Type::ObjectType(initializer)); @@ -4100,7 +4100,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset, case JSOP_GENERATOR: if (script->function()) { - if (script->hasGlobal()) { + if (script->compileAndGo) { JSObject *proto = script->global().getOrCreateGeneratorPrototype(cx); if (!proto) return false; @@ -4153,7 +4153,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset, 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()); @@ -4179,17 +4179,6 @@ ScriptAnalysis::analyzeTypes(JSContext *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()) @@ -4414,9 +4403,6 @@ AnalyzeNewScriptProperties(JSContext *cx, TypeObject *type, JSFunction *fun, JSO return false; } - if (script->hasClearedGlobal()) - return false; - ScriptAnalysis *analysis = script->analysis(); /* diff --git a/js/src/jsinferinlines.h b/js/src/jsinferinlines.h index 8d0f8da2856..e816710cd97 100644 --- a/js/src/jsinferinlines.h +++ b/js/src/jsinferinlines.h @@ -683,7 +683,7 @@ TypeScript::InitObject(JSContext *cx, JSScript *script, jsbytecode *pc, JSProtoK /* :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; diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 68a9cd87cac..66dc95f3d37 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -270,14 +270,6 @@ js::RunScript(JSContext *cx, JSScript *script, StackFrame *fp) 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; @@ -2424,16 +2416,9 @@ BEGIN_CASE(JSOP_FUNCALL) 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; diff --git a/js/src/jsscript.h b/js/src/jsscript.h index 7e572fdc883..3c58756b21c 100644 --- a/js/src/jsscript.h +++ b/js/src/jsscript.h @@ -580,9 +580,6 @@ struct JSScript : public js::gc::Cell inline void clearPropertyReadTypes(); - inline bool hasGlobal() const; - inline bool hasClearedGlobal() const; - inline js::GlobalObject &global() const; /* See StaticScopeIter comment. */ diff --git a/js/src/jsscriptinlines.h b/js/src/jsscriptinlines.h index 72a15c8e735..f99055cf491 100644 --- a/js/src/jsscriptinlines.h +++ b/js/src/jsscriptinlines.h @@ -120,17 +120,6 @@ JSScript::isEmpty() const 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 { @@ -141,13 +130,6 @@ JSScript::global() const return *compartment()->maybeGlobal(); } -inline bool -JSScript::hasClearedGlobal() const -{ - JS_ASSERT(types); - return global().isCleared(); -} - #ifdef JS_METHODJIT inline bool JSScript::ensureHasMJITInfo(JSContext *cx) diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index ae1cedb7d3a..a6ba0592111 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -59,7 +59,7 @@ mjit::Compiler::Compiler(JSContext *cx, JSScript *outerScript, 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), @@ -134,11 +134,6 @@ mjit::Compiler::compile() 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; @@ -193,7 +188,7 @@ mjit::Compiler::scanInlineCalls(uint32_t index, uint32_t depth) 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()) || diff --git a/js/src/methodjit/PolyIC.cpp b/js/src/methodjit/PolyIC.cpp index 4aecb078e2f..ec88862ac1d 100644 --- a/js/src/methodjit/PolyIC.cpp +++ b/js/src/methodjit/PolyIC.cpp @@ -881,7 +881,7 @@ class GetPropCompiler : public PICStubCompiler 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); diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index 96e975028b9..8d8ee388513 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -2092,7 +2092,7 @@ class Debugger::ScriptQuery { 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(); - if (script->hasGlobal() && !script->isForEval()) { + if (script->compileAndGo && !script->isForEval()) { if (!consider(script, &script->global(), vector)) return false; } diff --git a/js/src/vm/GlobalObject-inl.h b/js/src/vm/GlobalObject-inl.h index ef014c7a3de..c28437b681b 100644 --- a/js/src/vm/GlobalObject-inl.h +++ b/js/src/vm/GlobalObject-inl.h @@ -10,18 +10,6 @@ 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) { diff --git a/js/src/vm/GlobalObject.cpp b/js/src/vm/GlobalObject.cpp index a6a28cfb789..a9fdd29892d 100644 --- a/js/src/vm/GlobalObject.cpp +++ b/js/src/vm/GlobalObject.cpp @@ -488,9 +488,8 @@ GlobalObject::create(JSContext *cx, Class *clasp) JSObject *res = RegExpStatics::create(cx, global); if (!res) return NULL; - global->initSlot(REGEXP_STATICS, ObjectValue(*res)); - global->initFlags(0); + global->initSlot(REGEXP_STATICS, ObjectValue(*res)); return global; } @@ -533,60 +532,6 @@ GlobalObject::initStandardClasses(JSContext *cx, Handle 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(); - 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) { diff --git a/js/src/vm/GlobalObject.h b/js/src/vm/GlobalObject.h index 7141bcef0de..fef055cee4e 100644 --- a/js/src/vm/GlobalObject.h +++ b/js/src/vm/GlobalObject.h @@ -98,8 +98,7 @@ class GlobalObject : public JSObject 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. */ @@ -114,11 +113,6 @@ class GlobalObject : public JSObject 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 * @@ -413,12 +407,6 @@ class GlobalObject : public JSObject 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 {