author | Terrence Cole <terrence@mozilla.com> |
Thu, 29 Nov 2012 10:22:12 -0800 | |
changeset 116088 | eb53ab86f515ba239e4ec604cfce3991c14154ef |
parent 116087 | 0852e5efadac7f597cb772ceb9f8c2976377e3d1 |
child 116089 | 0723845d095e2cb3eb5ee968b45bce40cc00f1a7 |
push id | 24043 |
push user | ryanvm@gmail.com |
push date | Sat, 15 Dec 2012 21:18:16 +0000 |
treeherder | mozilla-central@c8a1314aa449 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | bhackett |
bugs | 816779 |
milestone | 20.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/js/src/builtin/Eval.cpp +++ b/js/src/builtin/Eval.cpp @@ -30,17 +30,17 @@ AssertInnerizedScopeChain(JSContext *cx, Rooted<JSObject*> obj(cx, o); JS_ASSERT(op(cx, obj) == o); } } #endif } static bool -IsEvalCacheCandidate(JSScript *script) +IsEvalCacheCandidate(UnrootedScript script) { // Make sure there are no inner objects which might use the wrong parent // and/or call scope by reusing the previous eval's script. Skip the // script's first object, which entrains the eval's scope. return script->savedCallerFun && !script->hasSingletons && script->objects()->length == 1 && !script->hasRegexps(); @@ -52,17 +52,17 @@ EvalCacheHashPolicy::hash(const EvalCach return AddToHash(HashString(l.str->chars(), l.str->length()), l.caller, l.staticLevel, l.version, l.compartment); } /* static */ bool -EvalCacheHashPolicy::match(JSScript *script, const EvalCacheLookup &l) +EvalCacheHashPolicy::match(UnrootedScript script, const EvalCacheLookup &l) { JS_ASSERT(IsEvalCacheCandidate(script)); // Get the source string passed for safekeeping in the atom map // by the prior eval to frontend::CompileScript. JSAtom *keyStr = script->atoms[0]; return EqualStrings(keyStr, l.str) && @@ -116,23 +116,23 @@ class EvalScriptGuard lookup_.caller = caller; lookup_.staticLevel = staticLevel; lookup_.version = cx_->findVersion(); lookup_.compartment = cx_->compartment; p_ = cx_->runtime->evalCache.lookupForAdd(lookup_); if (p_) { script_ = *p_; cx_->runtime->evalCache.remove(p_); - js_CallNewScriptHook(cx_, script_, NULL); + CallNewScriptHook(cx_, script_, NullPtr()); script_->isCachedEval = false; script_->isActiveEval = true; } } - void setNewScript(JSScript *script) { + void setNewScript(UnrootedScript script) { // JSScript::initFromEmitter has already called js_CallNewScriptHook. JS_ASSERT(!script_ && script); script_ = script; script_->isActiveEval = true; } bool foundScript() { return !!script_; @@ -269,18 +269,18 @@ EvalKernel(JSContext *cx, const CallArgs : NOT_CALLED_FROM_JSOP_EVAL); CompileOptions options(cx); options.setFileAndLine(filename, lineno) .setCompileAndGo(true) .setNoScriptRval(false) .setPrincipals(principals) .setOriginPrincipals(originPrincipals); - JSScript *compiled = frontend::CompileScript(cx, scopeobj, caller, options, - chars, length, stableStr, staticLevel); + UnrootedScript compiled = frontend::CompileScript(cx, scopeobj, caller, options, + chars, length, stableStr, staticLevel); if (!compiled) return false; esg.setNewScript(compiled); } return ExecuteKernel(cx, esg.script(), *scopeobj, thisv, ExecuteType(evalType), NULL /* evalInFrame */, args.rval().address());
--- a/js/src/frontend/BytecodeCompiler.cpp +++ b/js/src/frontend/BytecodeCompiler.cpp @@ -32,26 +32,26 @@ CheckLength(JSContext *cx, size_t length if (length > UINT32_MAX) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_SOURCE_TOO_LONG); return false; } return true; } static bool -SetSourceMap(JSContext *cx, TokenStream &tokenStream, ScriptSource *ss, JSScript *script) +SetSourceMap(JSContext *cx, TokenStream &tokenStream, ScriptSource *ss, UnrootedScript script) { if (tokenStream.hasSourceMap()) { if (!ss->setSourceMap(cx, tokenStream.releaseSourceMap(), script->filename)) return false; } return true; } -JSScript * +UnrootedScript frontend::CompileScript(JSContext *cx, HandleObject scopeChain, StackFrame *callerFrame, const CompileOptions &options, StableCharPtr chars, size_t length, JSString *source_ /* = NULL */, unsigned staticLevel /* = 0 */) { RootedString source(cx, source_); @@ -71,94 +71,94 @@ frontend::CompileScript(JSContext *cx, H /* * The scripted callerFrame can only be given for compile-and-go scripts * and non-zero static level requires callerFrame. */ JS_ASSERT_IF(callerFrame, options.compileAndGo); JS_ASSERT_IF(staticLevel != 0, callerFrame); if (!CheckLength(cx, length)) - return NULL; + return UnrootedScript(NULL); JS_ASSERT_IF(staticLevel != 0, options.sourcePolicy != CompileOptions::LAZY_SOURCE); ScriptSource *ss = cx->new_<ScriptSource>(); if (!ss) - return NULL; + return UnrootedScript(NULL); ScriptSourceHolder ssh(cx->runtime, ss); SourceCompressionToken sct(cx); switch (options.sourcePolicy) { case CompileOptions::SAVE_SOURCE: if (!ss->setSourceCopy(cx, chars, length, false, &sct)) - return NULL; + return UnrootedScript(NULL); break; case CompileOptions::LAZY_SOURCE: ss->setSourceRetrievable(); break; case CompileOptions::NO_SOURCE: break; } Parser parser(cx, options, chars, length, /* foldConstants = */ true); if (!parser.init()) - return NULL; + return UnrootedScript(NULL); parser.sct = &sct; GlobalSharedContext globalsc(cx, scopeChain, StrictModeFromContext(cx)); ParseContext pc(&parser, &globalsc, staticLevel, /* bodyid = */ 0); if (!pc.init()) - return NULL; + return UnrootedScript(NULL); bool savedCallerFun = options.compileAndGo && callerFrame && callerFrame->isFunctionFrame(); Rooted<JSScript*> script(cx, JSScript::Create(cx, NullPtr(), savedCallerFun, options, staticLevel, ss, 0, length)); if (!script) - return NULL; + return UnrootedScript(NULL); // Global/eval script bindings are always empty (all names are added to the // scope dynamically via JSOP_DEFFUN/VAR). InternalHandle<Bindings*> bindings(script, &script->bindings); if (!Bindings::initWithTemporaryStorage(cx, bindings, 0, 0, NULL)) - return NULL; + return UnrootedScript(NULL); // We can specialize a bit for the given scope chain if that scope chain is the global object. JSObject *globalScope = scopeChain && scopeChain == &scopeChain->global() ? (JSObject*) scopeChain : NULL; JS_ASSERT_IF(globalScope, globalScope->isNative()); JS_ASSERT_IF(globalScope, JSCLASS_HAS_GLOBAL_FLAG_AND_SLOTS(globalScope->getClass())); BytecodeEmitter bce(/* parent = */ NULL, &parser, &globalsc, script, callerFrame, !!globalScope, options.lineno, options.selfHostingMode); if (!bce.init()) - return NULL; + return UnrootedScript(NULL); /* If this is a direct call to eval, inherit the caller's strictness. */ if (callerFrame && callerFrame->script()->strict) globalsc.strict = true; if (options.compileAndGo) { if (source) { /* * Save eval program source in script->atoms[0] for the * eval cache (see EvalCacheLookup in jsobj.cpp). */ JSAtom *atom = AtomizeString(cx, source); jsatomid _; if (!atom || !bce.makeAtomIndex(atom, &_)) - return NULL; + return UnrootedScript(NULL); } if (callerFrame && callerFrame->isFunctionFrame()) { /* * An eval script in a caller frame needs to have its enclosing * function captured in case it refers to an upvar, and someone * wishes to decompile it while it's running. */ JSFunction *fun = callerFrame->fun(); ObjectBox *funbox = parser.newFunctionBox(fun, &pc, fun->strict()); if (!funbox) - return NULL; + return UnrootedScript(NULL); bce.objectList.add(funbox); } } ParseNode *pn; #if JS_HAS_XML_SUPPORT pn = NULL; bool onlyXML; @@ -168,84 +168,84 @@ frontend::CompileScript(JSContext *cx, H TokenStream &tokenStream = parser.tokenStream; bool canHaveDirectives = true; for (;;) { TokenKind tt = tokenStream.peekToken(TSF_OPERAND); if (tt <= TOK_EOF) { if (tt == TOK_EOF) break; JS_ASSERT(tt == TOK_ERROR); - return NULL; + return UnrootedScript(NULL); } pn = parser.statement(); if (!pn) - return NULL; + return UnrootedScript(NULL); if (canHaveDirectives) { if (!parser.maybeParseDirective(pn, &canHaveDirectives)) - return NULL; + return UnrootedScript(NULL); } if (!FoldConstants(cx, pn, &parser)) - return NULL; + return UnrootedScript(NULL); if (!NameFunctions(cx, pn)) - return NULL; + return UnrootedScript(NULL); if (!EmitTree(cx, &bce, pn)) - return NULL; + return UnrootedScript(NULL); #if JS_HAS_XML_SUPPORT if (!pn->isKind(PNK_SEMI) || !pn->pn_kid || !pn->pn_kid->isXMLItem()) onlyXML = false; #endif parser.freeTree(pn); } if (!SetSourceMap(cx, tokenStream, ss, script)) - return NULL; + return UnrootedScript(NULL); #if JS_HAS_XML_SUPPORT /* * Prevent XML data theft via <script src="http://victim.com/foo.xml">. * For background, see: * * https://bugzilla.mozilla.org/show_bug.cgi?id=336551 */ if (pn && onlyXML && !callerFrame) { parser.reportError(NULL, JSMSG_XML_WHOLE_PROGRAM); - return NULL; + return UnrootedScript(NULL); } #endif // It's an error to use |arguments| in a function that has a rest parameter. if (callerFrame && callerFrame->isFunctionFrame() && callerFrame->fun()->hasRest()) { HandlePropertyName arguments = cx->names().arguments; for (AtomDefnRange r = pc.lexdeps->all(); !r.empty(); r.popFront()) { if (r.front().key() == arguments) { parser.reportError(NULL, JSMSG_ARGUMENTS_AND_REST); - return NULL; + return UnrootedScript(NULL); } } } /* * Nowadays the threaded interpreter needs a stop instruction, so we * do have to emit that here. */ if (Emit1(cx, &bce, JSOP_STOP) < 0) - return NULL; + return UnrootedScript(NULL); if (!JSScript::fullyInitFromEmitter(cx, script, &bce)) - return NULL; + return UnrootedScript(NULL); bce.tellDebuggerAboutCompiledScript(cx); if (!sct.complete()) - return NULL; + return UnrootedScript(NULL); return script; } // Compile a JS function body, which might appear as the value of an event // handler attribute in an HTML <INPUT> tag, or in a Function() constructor. bool frontend::CompileFunctionBody(JSContext *cx, HandleFunction fun, CompileOptions options,
--- a/js/src/frontend/BytecodeCompiler.h +++ b/js/src/frontend/BytecodeCompiler.h @@ -8,17 +8,17 @@ #ifndef BytecodeCompiler_h__ #define BytecodeCompiler_h__ #include "frontend/Parser.h" namespace js { namespace frontend { -JSScript * +UnrootedScript CompileScript(JSContext *cx, HandleObject scopeChain, StackFrame *callerFrame, const CompileOptions &options, StableCharPtr chars, size_t length, JSString *source_ = NULL, unsigned staticLevel = 0); bool CompileFunctionBody(JSContext *cx, HandleFunction fun, CompileOptions options, const AutoNameVector &formals, StableCharPtr chars, size_t length);
--- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -1683,17 +1683,18 @@ BytecodeEmitter::needsImplicitThis() return true; } return false; } void BytecodeEmitter::tellDebuggerAboutCompiledScript(JSContext *cx) { - js_CallNewScriptHook(cx, script, script->function()); + RootedFunction function(cx, script->function()); + CallNewScriptHook(cx, script, function); if (!parent) { GlobalObject *compileAndGoGlobal = NULL; if (script->compileAndGo) compileAndGoGlobal = &script->global(); Debugger::onNewScript(cx, script, compileAndGoGlobal); } }
--- a/js/src/gc/Marking.cpp +++ b/js/src/gc/Marking.cpp @@ -63,32 +63,32 @@ PushMarkStack(GCMarker *gcmarker, JSXML static inline void PushMarkStack(GCMarker *gcmarker, JSObject *thing); static inline void PushMarkStack(GCMarker *gcmarker, JSFunction *thing); static inline void -PushMarkStack(GCMarker *gcmarker, JSScript *thing); +PushMarkStack(GCMarker *gcmarker, UnrootedScript thing); static inline void PushMarkStack(GCMarker *gcmarker, UnrootedShape thing); static inline void PushMarkStack(GCMarker *gcmarker, JSString *thing); static inline void PushMarkStack(GCMarker *gcmarker, types::TypeObject *thing); namespace js { namespace gc { static void MarkChildren(JSTracer *trc, JSString *str); -static void MarkChildren(JSTracer *trc, JSScript *script); +static void MarkChildren(JSTracer *trc, UnrootedScript script); static void MarkChildren(JSTracer *trc, UnrootedShape shape); static void MarkChildren(JSTracer *trc, UnrootedBaseShape base); static void MarkChildren(JSTracer *trc, types::TypeObject *type); static void MarkChildren(JSTracer *trc, ion::IonCode *code); #if JS_HAS_XML_SUPPORT static void MarkChildren(JSTracer *trc, JSXML *xml); #endif @@ -641,17 +641,17 @@ gc::MarkCrossCompartmentSlot(JSTracer *t { if (dst->isMarkable() && ShouldMarkCrossCompartment(trc, src, (Cell *)dst->toGCThing())) MarkSlot(trc, dst, name); } /*** Special Marking ***/ void -gc::MarkObject(JSTracer *trc, HeapPtr<GlobalObject, JSScript *> *thingp, const char *name) +gc::MarkObject(JSTracer *trc, HeapPtr<GlobalObject, RawScript> *thingp, const char *name) { JS_SET_TRACING_NAME(trc, name); MarkInternal(trc, thingp->unsafeGet()); } void gc::MarkValueUnbarriered(JSTracer *trc, Value *v, const char *name) { @@ -714,17 +714,17 @@ PushMarkStack(GCMarker *gcmarker, types: { JS_COMPARTMENT_ASSERT(gcmarker->runtime, thing); if (thing->markIfUnmarked(gcmarker->getMarkColor())) gcmarker->pushType(thing); } static void -PushMarkStack(GCMarker *gcmarker, JSScript *thing) +PushMarkStack(GCMarker *gcmarker, UnrootedScript thing) { JS_COMPARTMENT_ASSERT(gcmarker->runtime, thing); /* * We mark scripts directly rather than pushing on the stack as they can * refer to other scripts only indirectly (like via nested functions) and * we cannot get to deep recursion. */ @@ -921,17 +921,17 @@ gc::MarkChildren(JSTracer *trc, JSString { if (str->hasBase()) str->markBase(trc); else if (str->isRope()) str->asRope().markChildren(trc); } static void -gc::MarkChildren(JSTracer *trc, JSScript *script) +gc::MarkChildren(JSTracer *trc, UnrootedScript script) { script->markChildren(trc); } static void gc::MarkChildren(JSTracer *trc, UnrootedShape shape) { shape->markChildren(trc);
--- a/js/src/gc/Root.h +++ b/js/src/gc/Root.h @@ -8,16 +8,17 @@ #ifndef jsgc_root_h__ #define jsgc_root_h__ #ifdef __cplusplus #include "mozilla/TypeTraits.h" #include "mozilla/GuardObjects.h" +#include "js/Utility.h" #include "js/TemplateLib.h" #include "jspubtd.h" /* * Moving GC Stack Rooting * * A moving GC may change the physical location of GC allocated things, even @@ -238,16 +239,18 @@ class Handle : public js::HandleBase<T> typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0); const T *address() const { return ptr; } T get() const { return *ptr; } operator T() const { return get(); } T operator->() const { return get(); } + bool operator!=(const T &other) { return *ptr != other; } + private: Handle() {} const T *ptr; template <typename S> void operator=(S v) MOZ_DELETE; }; @@ -333,17 +336,17 @@ namespace js { * Raw pointer used as documentation that a parameter does not need to be * rooted. */ typedef JSObject * RawObject; typedef JSFunction * RawFunction; typedef JSScript * RawScript; typedef JSString * RawString; typedef jsid RawId; -typedef Value RawValue; +typedef JS::Value RawValue; /* * InternalHandle is a handle to an internal pointer into a gcthing. Use * InternalHandle when you have a pointer to a direct field of a gcthing, or * when you need a parameter type for something that *may* be a pointer to a * direct field of a gcthing. */ template <typename T> @@ -388,17 +391,17 @@ class InternalHandle<T*> * gcthing, and so does not need to be rooted in the first place. Use these * InternalHandles to pass pointers into functions that also need to accept * regular InternalHandles to gcthing fields. * * Make this private to prevent accidental misuse; this is only for * fromMarkedLocation(). */ InternalHandle(T *field) - : holder(reinterpret_cast<void * const *>(&NullPtr::constNullValue)), + : holder(reinterpret_cast<void * const *>(&JS::NullPtr::constNullValue)), offset(uintptr_t(field)) {} }; #ifdef DEBUG /* * |Unrooted<T>| acts as an AutoAssertNoGC after it is initialized. It otherwise * acts like as a normal pointer of type T. @@ -423,72 +426,72 @@ class Unrooted typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0); template <typename S> Unrooted(const JS::Handle<S> &root, typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0) : ptr_(root.get()) { JS_ASSERT(ptr_ != UninitializedTag()); - EnterAssertNoGCScope(); + JS::EnterAssertNoGCScope(); } /* * |Unrooted<T>| can initialize by copying from a convertible type * |Unrooted<S>|. This enables usage such as: * * Unrooted<BaseShape*> base = js_NewBaseShape(cx); * Unrooted<UnownedBaseShape*> ubase = static_cast<UnrootedUnownedBaseShape>(ubase); */ template <typename S> Unrooted(const Unrooted<S> &other) /* Note: |static_cast<S>| acquires other.ptr_ in DEBUG builds. */ : ptr_(static_cast<T>(static_cast<S>(other))) { if (ptr_ != UninitializedTag()) - EnterAssertNoGCScope(); + JS::EnterAssertNoGCScope(); } Unrooted(const Unrooted &other) : ptr_(other.ptr_) { if (ptr_ != UninitializedTag()) - EnterAssertNoGCScope(); + JS::EnterAssertNoGCScope(); } Unrooted(const T &p) : ptr_(p) { JS_ASSERT(ptr_ != UninitializedTag()); - EnterAssertNoGCScope(); + JS::EnterAssertNoGCScope(); } Unrooted(const JS::NullPtr &) : ptr_(NULL) { - EnterAssertNoGCScope(); + JS::EnterAssertNoGCScope(); } ~Unrooted() { if (ptr_ != UninitializedTag()) - LeaveAssertNoGCScope(); + JS::LeaveAssertNoGCScope(); } void drop() { if (ptr_ != UninitializedTag()) - LeaveAssertNoGCScope(); + JS::LeaveAssertNoGCScope(); ptr_ = UninitializedTag(); } /* See notes for Unrooted::Unrooted(const T &) */ Unrooted &operator=(T other) { JS_ASSERT(other != UninitializedTag()); if (ptr_ == UninitializedTag()) - EnterAssertNoGCScope(); + JS::EnterAssertNoGCScope(); ptr_ = other; return *this; } Unrooted &operator=(Unrooted other) { JS_ASSERT(other.ptr_ != UninitializedTag()); if (ptr_ == UninitializedTag()) - EnterAssertNoGCScope(); + JS::EnterAssertNoGCScope(); ptr_ = other.ptr_; return *this; } operator T() const { return (ptr_ == UninitializedTag()) ? NULL : ptr_; } T *operator&() { return &ptr_; } const T operator->() const { JS_ASSERT(ptr_ != UninitializedTag()); return ptr_; } bool operator==(const T &other) { return ptr_ == other; } @@ -766,26 +769,26 @@ class Rooted<JSStableString *>; #ifdef DEBUG template <typename T> template <typename S> inline Unrooted<T>::Unrooted(const Rooted<S> &root, typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy) : ptr_(root.get()) { JS_ASSERT(ptr_ != UninitializedTag()); - EnterAssertNoGCScope(); + JS::EnterAssertNoGCScope(); } #endif /* DEBUG */ typedef Rooted<JSObject*> RootedObject; typedef Rooted<JSFunction*> RootedFunction; typedef Rooted<JSScript*> RootedScript; typedef Rooted<JSString*> RootedString; typedef Rooted<jsid> RootedId; -typedef Rooted<Value> RootedValue; +typedef Rooted<JS::Value> RootedValue; /* * Mark a stack location as a root for the rooting analysis, without actually * rooting it in release builds. This should only be used for stack locations * of GC things that cannot be relocated by a garbage collection, and that * are definitely reachable via another path. */ class SkipRoot @@ -920,17 +923,17 @@ JS_FRIEND_API(bool) NeedRelaxedRootCheck namespace js { /* * Hook for dynamic root analysis. Checks the native stack and poisons * references to GC things which have not been rooted. */ inline void MaybeCheckStackRoots(JSContext *cx, bool relax = true) { - AssertCanGC(); + JS::AssertCanGC(); #if defined(DEBUG) && defined(JS_GC_ZEAL) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE) if (relax && NeedRelaxedRootChecks()) return; CheckStackRoots(cx); #endif } namespace gc {
--- a/js/src/ion/Bailouts.cpp +++ b/js/src/ion/Bailouts.cpp @@ -531,17 +531,17 @@ ion::EnsureHasScopeObjects(JSContext *cx } return true; } uint32_t ion::BoundsCheckFailure() { JSContext *cx = GetIonContext()->cx; - JSScript *script = GetBailedJSScript(cx); + UnrootedScript script = GetBailedJSScript(cx); IonSpew(IonSpew_Bailouts, "Bounds check failure %s:%d", script->filename, script->lineno); if (!script->failedBoundsCheck) { script->failedBoundsCheck = true; // Invalidate the script to force a recompile. @@ -552,33 +552,33 @@ ion::BoundsCheckFailure() return true; } uint32_t ion::ShapeGuardFailure() { JSContext *cx = GetIonContext()->cx; - JSScript *script = GetBailedJSScript(cx); + UnrootedScript script = GetBailedJSScript(cx); JS_ASSERT(script->hasIonScript()); JS_ASSERT(!script->ion->invalidated()); script->failedShapeGuard = true; IonSpew(IonSpew_Invalidate, "Invalidating due to shape guard failure"); return Invalidate(cx, script); } uint32_t ion::CachedShapeGuardFailure() { JSContext *cx = GetIonContext()->cx; - JSScript *script = GetBailedJSScript(cx); + UnrootedScript script = GetBailedJSScript(cx); JS_ASSERT(script->hasIonScript()); JS_ASSERT(!script->ion->invalidated()); script->failedShapeGuard = true; // Purge JM caches in the script and all inlined script, to avoid baking in // the same shape guard next time. @@ -617,17 +617,17 @@ ion::ThunkToInterpreter(Value *vp) // in order to create an arguments object for them. However, there is an // invariant that script->needsArgsObj() implies fp->hasArgsObj() (after the // prologue), so we must create one now for each inlined frame which needs // one. { br->entryfp()->clearRunningInIon(); ScriptFrameIter iter(cx); StackFrame *fp = NULL; - Rooted<JSScript*> script(cx, NULL); + Rooted<JSScript*> script(cx); do { fp = iter.interpFrame(); script = iter.script(); if (script->needsArgsObj()) { // Currently IonMonkey does not compile if the script needs an // arguments object, so the frame should not have any argument // object yet. JS_ASSERT(!fp->hasArgsObj());
--- a/js/src/ion/C1Spewer.cpp +++ b/js/src/ion/C1Spewer.cpp @@ -22,17 +22,17 @@ using namespace js::ion; bool C1Spewer::init(const char *path) { spewout_ = fopen(path, "w"); return (spewout_ != NULL); } void -C1Spewer::beginFunction(MIRGraph *graph, JSScript *script) +C1Spewer::beginFunction(MIRGraph *graph, HandleScript script) { if (!spewout_) return; this->graph = graph; this->script = script; fprintf(spewout_, "begin_compilation\n"); @@ -73,17 +73,16 @@ C1Spewer::spewIntervals(const char *pass fprintf(spewout_, "end_intervals\n"); fflush(spewout_); } void C1Spewer::endFunction() { - return; } void C1Spewer::finish() { if (spewout_) fclose(spewout_); }
--- a/js/src/ion/C1Spewer.h +++ b/js/src/ion/C1Spewer.h @@ -5,39 +5,42 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifdef DEBUG #ifndef jsion_c1spewer_h__ #define jsion_c1spewer_h__ +#include "gc/Root.h" +#include "jsscript.h" + namespace js { namespace ion { class MDefinition; class MInstruction; class MBasicBlock; class MIRGraph; class LinearScanAllocator; class LInstruction; class C1Spewer { MIRGraph *graph; - JSScript *script; + HandleScript script; FILE *spewout_; public: C1Spewer() - : graph(NULL), script(NULL), spewout_(NULL) + : graph(NULL), script(NullPtr()), spewout_(NULL) { } bool init(const char *path); - void beginFunction(MIRGraph *graph, JSScript *script); + void beginFunction(MIRGraph *graph, HandleScript script); void spewPass(const char *pass); void spewIntervals(const char *pass, LinearScanAllocator *regalloc); void endFunction(); void finish(); private: void spewPass(FILE *fp, MBasicBlock *block); void spewIntervals(FILE *fp, LinearScanAllocator *regalloc, LInstruction *ins, size_t &nextId);
--- a/js/src/ion/CompileInfo.h +++ b/js/src/ion/CompileInfo.h @@ -25,26 +25,26 @@ enum ExecutionMode { // e.g. by ParallelArray ParallelExecution }; // Contains information about the compilation source for IR being generated. class CompileInfo { public: - CompileInfo(JSScript *script, JSFunction *fun, jsbytecode *osrPc, bool constructing, + CompileInfo(UnrootedScript script, JSFunction *fun, jsbytecode *osrPc, bool constructing, ExecutionMode executionMode) : script_(script), fun_(fun), osrPc_(osrPc), constructing_(constructing), executionMode_(executionMode) { JS_ASSERT_IF(osrPc, JSOp(*osrPc) == JSOP_LOOPENTRY); nslots_ = script->nslots + CountArgSlots(fun); } - JSScript *script() const { + UnrootedScript script() const { return script_; } JSFunction *fun() const { return fun_; } bool constructing() const { return constructing_; }
--- a/js/src/ion/ExecutionModeInlines.h +++ b/js/src/ion/ExecutionModeInlines.h @@ -6,37 +6,37 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef jsion_compilemode_h__ #define jsion_compilemode_h__ namespace js { namespace ion { -static inline bool HasIonScript(JSScript *script, ExecutionMode cmode) +static inline bool HasIonScript(UnrootedScript script, ExecutionMode cmode) { switch (cmode) { case SequentialExecution: return script->hasIonScript(); case ParallelExecution: return script->hasParallelIonScript(); } JS_NOT_REACHED("No such execution mode"); return false; } -static inline IonScript *GetIonScript(JSScript *script, ExecutionMode cmode) +static inline IonScript *GetIonScript(UnrootedScript script, ExecutionMode cmode) { switch (cmode) { case SequentialExecution: return script->ion; case ParallelExecution: return script->parallelIon; } JS_NOT_REACHED("No such execution mode"); return NULL; } -static inline void SetIonScript(JSScript *script, ExecutionMode cmode, IonScript *ionScript) +static inline void SetIonScript(UnrootedScript script, ExecutionMode cmode, IonScript *ionScript) { switch (cmode) { case SequentialExecution: script->ion = ionScript; return; case ParallelExecution: script->parallelIon = ionScript; return; } JS_NOT_REACHED("No such execution mode"); } @@ -53,17 +53,17 @@ static inline bool CanIonCompile(HandleS static inline bool CanIonCompile(JSContext *cx, HandleFunction fun, ExecutionMode cmode) { if (!fun->isInterpreted()) return false; RootedScript script(cx, fun->nonLazyScript()); return CanIonCompile(script, cmode); } -static inline bool CompilingOffThread(JSScript *script, ExecutionMode cmode) +static inline bool CompilingOffThread(UnrootedScript script, ExecutionMode cmode) { switch (cmode) { case SequentialExecution: return script->isIonCompilingOffThread(); case ParallelExecution: return script->isParallelIonCompilingOffThread(); } JS_NOT_REACHED("No such execution mode"); return false; } @@ -73,17 +73,17 @@ static inline bool CompilingOffThread(Ha switch (cmode) { case SequentialExecution: return script->isIonCompilingOffThread(); case ParallelExecution: return script->isParallelIonCompilingOffThread(); } JS_NOT_REACHED("No such execution mode"); return false; } -static inline bool Disabled(JSScript *script, ExecutionMode cmode) { +static inline bool Disabled(UnrootedScript script, ExecutionMode cmode) { switch (cmode) { case SequentialExecution: return script->isIonCompilingOffThread(); case ParallelExecution: return script->isParallelIonCompilingOffThread(); } JS_NOT_REACHED("No such execution mode"); return false; }
--- a/js/src/ion/Ion.cpp +++ b/js/src/ion/Ion.cpp @@ -474,17 +474,17 @@ IonScript::New(JSContext *cx, uint32_t f size_t paddedBailoutSize = AlignBytes(bailoutEntries * sizeof(uint32_t), DataAlignment); size_t paddedConstantsSize = AlignBytes(constants * sizeof(Value), DataAlignment); size_t paddedSafepointIndicesSize = AlignBytes(safepointIndices * sizeof(SafepointIndex), DataAlignment); size_t paddedOsiIndicesSize = AlignBytes(osiIndices * sizeof(OsiIndex), DataAlignment); size_t paddedCacheEntriesSize = AlignBytes(cacheEntries * sizeof(IonCache), DataAlignment); size_t paddedPrebarrierEntriesSize = AlignBytes(prebarrierEntries * sizeof(CodeOffsetLabel), DataAlignment); size_t paddedSafepointSize = AlignBytes(safepointsSize, DataAlignment); - size_t paddedScriptSize = AlignBytes(scriptEntries * sizeof(JSScript *), DataAlignment); + size_t paddedScriptSize = AlignBytes(scriptEntries * sizeof(RawScript), DataAlignment); size_t bytes = paddedSnapshotsSize + paddedBailoutSize + paddedConstantsSize + paddedSafepointIndicesSize+ paddedOsiIndicesSize + paddedCacheEntriesSize + paddedPrebarrierEntriesSize + paddedSafepointSize + @@ -765,17 +765,17 @@ IonScript::purgeCaches(JSCompartment *c) } void ion::ToggleBarriers(JSCompartment *comp, bool needs) { IonContext ictx(NULL, comp, NULL); AutoFlushCache afc("ToggleBarriers"); for (gc::CellIterUnderGC i(comp, gc::FINALIZE_SCRIPT); !i.done(); i.next()) { - JSScript *script = i.get<JSScript>(); + UnrootedScript script = i.get<JSScript>(); if (script->hasIonScript()) script->ion->toggleBarriers(needs); } } namespace js { namespace ion { @@ -1117,17 +1117,17 @@ AttachFinishedCompilations(JSContext *cx compilations.clear(); #endif } static const size_t BUILDER_LIFO_ALLOC_PRIMARY_CHUNK_SIZE = 1 << 12; template <typename CompileContext> static bool -IonCompile(JSContext *cx, JSScript *script, JSFunction *fun, jsbytecode *osrPc, bool constructing, +IonCompile(JSContext *cx, HandleScript script, HandleFunction fun, jsbytecode *osrPc, bool constructing, CompileContext &compileContext) { AssertCanGC(); #if JS_TRACE_LOGGING AutoTraceLog logger(TraceLogging::defaultLogger(), TraceLogging::ION_COMPILE_START, TraceLogging::ION_COMPILE_STOP, script); @@ -1179,17 +1179,18 @@ IonCompile(JSContext *cx, JSScript *scri bool SequentialCompileContext::compile(IonBuilder *builder, MIRGraph *graph, AutoDestroyAllocator &autoDestroy) { JS_ASSERT(!builder->script()->ion); JSContext *cx = GetIonContext()->cx; - IonSpewNewFunction(graph, builder->script()); + RootedScript builderScript(cx, builder->script()); + IonSpewNewFunction(graph, builderScript); if (!builder->build()) { IonSpew(IonSpew_Abort, "Builder failed to build."); return false; } builder->clearForBackEnd(); // Try to compile the script off thread, if possible. Compilation cannot be @@ -1223,17 +1224,17 @@ SequentialCompileContext::compile(IonBui js_delete(codegen); IonSpewEndFunction(); return success; } bool -TestIonCompile(JSContext *cx, JSScript *script, JSFunction *fun, jsbytecode *osrPc, bool constructing) +TestIonCompile(JSContext *cx, HandleScript script, HandleFunction fun, jsbytecode *osrPc, bool constructing) { SequentialCompileContext compileContext; if (!IonCompile(cx, script, fun, osrPc, constructing, compileContext)) { if (!cx->isExceptionPending()) ForbidCompilation(cx, script); return false; } return true; @@ -1275,34 +1276,34 @@ CheckFrame(StackFrame *fp) IonSpew(IonSpew_Abort, "too many actual args"); return false; } return true; } static bool -CheckScript(JSScript *script) +CheckScript(UnrootedScript script) { if (script->needsArgsObj()) { // Functions with arguments objects, are not supported yet. IonSpew(IonSpew_Abort, "script has argsobj"); return false; } if (!script->compileAndGo) { IonSpew(IonSpew_Abort, "not compile-and-go"); return false; } return true; } static bool -CheckScriptSize(JSScript *script) +CheckScriptSize(UnrootedScript script) { if (!js_IonOptions.limitScriptSize) return true; static const uint32_t MAX_SCRIPT_SIZE = 2000; static const uint32_t MAX_LOCALS_AND_ARGS = 256; if (script->length > MAX_SCRIPT_SIZE) { @@ -1315,17 +1316,17 @@ CheckScriptSize(JSScript *script) IonSpew(IonSpew_Abort, "Too many locals and arguments (%u)", numLocalsAndArgs); return false; } return true; } static MethodStatus -Compile(JSContext *cx, JSScript *script, JSFunction *fun, jsbytecode *osrPc, bool constructing) +Compile(JSContext *cx, HandleScript script, HandleFunction fun, jsbytecode *osrPc, bool constructing) { JS_ASSERT(ion::IsEnabled(cx)); JS_ASSERT_IF(osrPc != NULL, (JSOp)*osrPc == JSOP_LOOPENTRY); if (cx->compartment->debugMode()) { IonSpew(IonSpew_Abort, "debugging"); return Method_CantCompile; } @@ -1388,17 +1389,17 @@ ion::CanEnterAtBranch(JSContext *cx, Han // Mark as forbidden if frame can't be handled. if (!CheckFrame(fp)) { ForbidCompilation(cx, script); return Method_CantCompile; } // Attempt compilation. Returns Method_Compiled if already compiled. - JSFunction *fun = fp->isFunctionFrame() ? fp->fun() : NULL; + RootedFunction fun(cx, fp->isFunctionFrame() ? fp->fun() : NULL); MethodStatus status = Compile(cx, script, fun, pc, fp->isConstructing()); if (status != Method_Compiled) { if (status == Method_CantCompile) ForbidCompilation(cx, script); return status; } if (script->ion->osrPc() != pc) @@ -1437,17 +1438,17 @@ ion::CanEnter(JSContext *cx, HandleScrip // Mark as forbidden if frame can't be handled. if (!CheckFrame(fp)) { ForbidCompilation(cx, script); return Method_CantCompile; } // Attempt compilation. Returns Method_Compiled if already compiled. - JSFunction *fun = fp->isFunctionFrame() ? fp->fun() : NULL; + RootedFunction fun(cx, fp->isFunctionFrame() ? fp->fun() : NULL); MethodStatus status = Compile(cx, script, fun, NULL, fp->isConstructing()); if (status != Method_Compiled) { if (status == Method_CantCompile) ForbidCompilation(cx, script); return status; } return Method_Compiled; @@ -1702,17 +1703,17 @@ InvalidateActivation(FreeOp *fop, uint8_ case IonFrame_Exit: IonSpew(IonSpew_Invalidate, "#%d exit frame @ %p", frameno, it.fp()); break; case IonFrame_OptimizedJS: { JS_ASSERT(it.isScripted()); IonSpew(IonSpew_Invalidate, "#%d JS frame @ %p, %s:%d (fun: %p, script: %p, pc %p)", frameno, it.fp(), it.script()->filename, it.script()->lineno, - it.maybeCallee(), it.script(), it.returnAddressToFp()); + it.maybeCallee(), (RawScript)it.script(), it.returnAddressToFp()); break; } case IonFrame_Rectifier: IonSpew(IonSpew_Invalidate, "#%d rectifier frame @ %p", frameno, it.fp()); break; case IonFrame_Bailed_JS: JS_NOT_REACHED("invalid"); break; @@ -1876,17 +1877,17 @@ ion::Invalidate(types::TypeCompartment & continue; case types::CompilerOutput::Ion: break; case types::CompilerOutput::ParallelIon: executionMode = ParallelExecution; break; } JS_ASSERT(co.isValid()); - JSScript *script = co.script; + UnrootedScript script = co.script; IonScript *ionScript = GetIonScript(script, executionMode); JSCompartment *compartment = script->compartment(); if (compartment->needsBarrier()) { // We're about to remove edges from the JSScript to gcthings // embedded in the IonScript. Perform one final trace of the // IonScript for the incremental GC, as it must know about // those edges. @@ -1902,34 +1903,36 @@ ion::Invalidate(types::TypeCompartment & if (resetUses) script->resetUseCount(); } } void ion::Invalidate(JSContext *cx, const Vector<types::RecompileInfo> &invalid, bool resetUses) { + AutoAssertNoGC nogc; ion::Invalidate(cx->compartment->types, cx->runtime->defaultFreeOp(), invalid, resetUses); } bool -ion::Invalidate(JSContext *cx, JSScript *script, bool resetUses) +ion::Invalidate(JSContext *cx, UnrootedScript script, bool resetUses) { + AutoAssertNoGC nogc; JS_ASSERT(script->hasIonScript()); Vector<types::RecompileInfo> scripts(cx); if (!scripts.append(script->ionScript()->recompileInfo())) return false; Invalidate(cx, scripts, resetUses); return true; } void -ion::FinishInvalidation(FreeOp *fop, JSScript *script) +ion::FinishInvalidation(FreeOp *fop, UnrootedScript script) { if (!script->hasIonScript()) return; /* * If this script has Ion code on the stack, invalidation() will return * true. In this case we have to wait until destroying it. */ @@ -1952,17 +1955,17 @@ ion::MarkValueFromIon(JSRuntime *rt, Val void ion::MarkShapeFromIon(JSRuntime *rt, Shape **shapep) { gc::MarkShapeUnbarriered(&rt->gcMarker, shapep, "write barrier"); } void -ion::ForbidCompilation(JSContext *cx, JSScript *script) +ion::ForbidCompilation(JSContext *cx, UnrootedScript script) { IonSpew(IonSpew_Abort, "Disabling Ion compilation of script %s:%d", script->filename, script->lineno); CancelOffThreadIonCompile(cx->compartment, script); if (script->hasIonScript()) { // It is only safe to modify script->ion if the script is not currently @@ -1973,17 +1976,17 @@ ion::ForbidCompilation(JSContext *cx, JS if (!Invalidate(cx, script, false)) return; } script->ion = ION_DISABLED_SCRIPT; } uint32_t -ion::UsesBeforeIonRecompile(JSScript *script, jsbytecode *pc) +ion::UsesBeforeIonRecompile(UnrootedScript script, jsbytecode *pc) { JS_ASSERT(pc == script->code || JSOp(*pc) == JSOP_LOOPENTRY); uint32_t minUses = js_IonOptions.usesBeforeCompile; if (JSOp(*pc) != JSOP_LOOPENTRY || !script->hasAnalysis() || js_IonOptions.eagerCompilation) return minUses; analyze::LoopAnalysis *loop = script->analysis()->getLoop(pc); @@ -2048,46 +2051,46 @@ AutoFlushInhibitor::~AutoFlushInhibitor( ic_->setFlusher(afc); if (afc) IonSpewCont(IonSpew_CacheFlush, "{"); } int js::ion::LabelBase::id_count = 0; void -ion::PurgeCaches(JSScript *script, JSCompartment *c) { +ion::PurgeCaches(UnrootedScript script, JSCompartment *c) { if (script->hasIonScript()) script->ion->purgeCaches(c); if (script->hasParallelIonScript()) script->ion->purgeCaches(c); } size_t -ion::MemoryUsed(JSScript *script, JSMallocSizeOfFun mallocSizeOf) { +ion::MemoryUsed(UnrootedScript script, JSMallocSizeOfFun mallocSizeOf) { size_t result = 0; if (script->hasIonScript()) result += script->ion->sizeOfIncludingThis(mallocSizeOf); if (script->hasParallelIonScript()) result += script->parallelIon->sizeOfIncludingThis(mallocSizeOf); return result; } void -ion::DestroyIonScripts(FreeOp *fop, JSScript *script) { +ion::DestroyIonScripts(FreeOp *fop, UnrootedScript script) { if (script->hasIonScript()) ion::IonScript::Destroy(fop, script->ion); if (script->hasParallelIonScript()) ion::IonScript::Destroy(fop, script->parallelIon); } void -ion::TraceIonScripts(JSTracer* trc, JSScript *script) { +ion::TraceIonScripts(JSTracer* trc, UnrootedScript script) { if (script->hasIonScript()) ion::IonScript::Trace(trc, script->ion); if (script->hasParallelIonScript()) ion::IonScript::Trace(trc, script->parallelIon); }
--- a/js/src/ion/Ion.h +++ b/js/src/ion/Ion.h @@ -276,42 +276,42 @@ IonExecStatus SideCannon(JSContext *cx, // Used to enter Ion from C++ natives like Array.map. Called from FastInvokeGuard. IonExecStatus FastInvoke(JSContext *cx, HandleFunction fun, CallArgsList &args); // Walk the stack and invalidate active Ion frames for the invalid scripts. void Invalidate(types::TypeCompartment &types, FreeOp *fop, const Vector<types::RecompileInfo> &invalid, bool resetUses = true); void Invalidate(JSContext *cx, const Vector<types::RecompileInfo> &invalid, bool resetUses = true); -bool Invalidate(JSContext *cx, JSScript *script, bool resetUses = true); +bool Invalidate(JSContext *cx, UnrootedScript script, bool resetUses = true); void MarkValueFromIon(JSRuntime *rt, Value *vp); void MarkShapeFromIon(JSRuntime *rt, Shape **shapep); void ToggleBarriers(JSCompartment *comp, bool needs); class IonBuilder; class MIRGenerator; class CodeGenerator; CodeGenerator *CompileBackEnd(MIRGenerator *mir); void AttachFinishedCompilations(JSContext *cx); void FinishOffThreadBuilder(IonBuilder *builder); -bool TestIonCompile(JSContext *cx, JSScript *script, JSFunction *fun, jsbytecode *osrPc, bool constructing); +bool TestIonCompile(JSContext *cx, HandleScript script, HandleFunction fun, jsbytecode *osrPc, bool constructing); static inline bool IsEnabled(JSContext *cx) { return cx->hasRunOption(JSOPTION_ION) && cx->typeInferenceEnabled(); } -void ForbidCompilation(JSContext *cx, JSScript *script); -uint32_t UsesBeforeIonRecompile(JSScript *script, jsbytecode *pc); +void ForbidCompilation(JSContext *cx, UnrootedScript script); +uint32_t UsesBeforeIonRecompile(UnrootedScript script, jsbytecode *pc); -void PurgeCaches(JSScript *script, JSCompartment *c); -size_t MemoryUsed(JSScript *script, JSMallocSizeOfFun mallocSizeOf); -void DestroyIonScripts(FreeOp *fop, JSScript *script); -void TraceIonScripts(JSTracer* trc, JSScript *script); +void PurgeCaches(UnrootedScript script, JSCompartment *c); +size_t MemoryUsed(UnrootedScript script, JSMallocSizeOfFun mallocSizeOf); +void DestroyIonScripts(FreeOp *fop, UnrootedScript script); +void TraceIonScripts(JSTracer* trc, UnrootedScript script); } // namespace ion } // namespace js #endif // jsion_ion_h__
--- a/js/src/ion/IonCaches.cpp +++ b/js/src/ion/IonCaches.cpp @@ -790,17 +790,17 @@ TryAttachNativeGetPropStub(JSContext *cx } bool js::ion::GetPropertyCache(JSContext *cx, size_t cacheIndex, HandleObject obj, MutableHandleValue vp) { AutoFlushCache afc ("GetPropertyCache"); const SafepointIndex *safepointIndex; void *returnAddr; - JSScript *topScript = GetTopIonJSScript(cx, &safepointIndex, &returnAddr); + RootedScript topScript(cx, GetTopIonJSScript(cx, &safepointIndex, &returnAddr)); IonScript *ion = topScript->ionScript(); IonCacheGetProperty &cache = ion->getCache(cacheIndex).toGetProperty(); RootedPropertyName name(cx, cache.name()); RootedScript script(cx); jsbytecode *pc; cache.getScriptedLocation(&script, &pc); @@ -1343,17 +1343,17 @@ IsPropertyAddInlineable(JSContext *cx, H bool js::ion::SetPropertyCache(JSContext *cx, size_t cacheIndex, HandleObject obj, HandleValue value, bool isSetName) { AutoFlushCache afc ("SetPropertyCache"); void *returnAddr; const SafepointIndex *safepointIndex; - JSScript *script = GetTopIonJSScript(cx, &safepointIndex, &returnAddr); + RootedScript script(cx, GetTopIonJSScript(cx, &safepointIndex, &returnAddr)); IonScript *ion = script->ion; IonCacheSetProperty &cache = ion->getCache(cacheIndex).toSetProperty(); RootedPropertyName name(cx, cache.name()); RootedId id(cx, AtomToId(name)); RootedShape shape(cx); RootedObject holder(cx); bool inlinable = IsPropertyInlineable(obj, cache);
--- a/js/src/ion/IonCaches.h +++ b/js/src/ion/IonCaches.h @@ -223,17 +223,17 @@ class IonCache JS_ASSERT(kind_ == BindName); return *(IonCacheBindName *)this; } IonCacheName &toName() { JS_ASSERT(kind_ == Name || kind_ == NameTypeOf); return *(IonCacheName *)this; } - void setScriptedLocation(JSScript *script, jsbytecode *pc) { + void setScriptedLocation(UnrootedScript script, jsbytecode *pc) { JS_ASSERT(!idempotent_); this->script = script; this->pc = pc; } void getScriptedLocation(MutableHandleScript pscript, jsbytecode **ppc) { pscript.set(script); *ppc = pc;
--- a/js/src/ion/IonCode.h +++ b/js/src/ion/IonCode.h @@ -323,17 +323,17 @@ struct IonScript return snapshotsSize_; } const uint8_t *safepoints() const { return reinterpret_cast<const uint8_t *>(this) + safepointsStart_; } size_t safepointsSize() const { return safepointsSize_; } - JSScript *getScript(size_t i) const { + UnrootedScript getScript(size_t i) const { JS_ASSERT(i < scriptEntries_); return scriptList()[i]; } size_t scriptEntries() const { return scriptEntries_; } size_t sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf) const { return mallocSizeOf(this);
--- a/js/src/ion/IonCompartment.h +++ b/js/src/ion/IonCompartment.h @@ -220,15 +220,15 @@ class IonActivation } static inline size_t offsetOfEntryFp() { return offsetof(IonActivation, entryfp_); } }; // Called from JSCompartment::discardJitCode(). void InvalidateAll(FreeOp *fop, JSCompartment *comp); -void FinishInvalidation(FreeOp *fop, JSScript *script); +void FinishInvalidation(FreeOp *fop, UnrootedScript script); } // namespace ion } // namespace js #endif // jsion_ion_compartment_h__
--- a/js/src/ion/IonFrameIterator.h +++ b/js/src/ion/IonFrameIterator.h @@ -124,17 +124,17 @@ class IonFrameIterator bool isConstructing() const; bool isEntryJSFrame() const; void *calleeToken() const; JSFunction *callee() const; JSFunction *maybeCallee() const; unsigned numActualArgs() const; - JSScript *script() const; + UnrootedScript script() const; Value *nativeVp() const; Value *actualArgs() const; // Returns the return address of the frame above this one (that is, the // return address that returns back to the current frame). uint8_t *returnAddressToFp() const { return returnAddressToFp_; } @@ -286,18 +286,18 @@ class InlineFrameIterator JSFunction *maybeCallee() const { return callee_; } unsigned numActualArgs() const; template <class Op> inline void forEachCanonicalActualArg(Op op, unsigned start, unsigned count) const; - JSScript *script() const { - return script_; + UnrootedScript script() const { + return script_.get(); } jsbytecode *pc() const { return pc_; } SnapshotIterator snapshotIterator() const { return si_; } bool isFunctionFrame() const;
--- a/js/src/ion/IonFrames.cpp +++ b/js/src/ion/IonFrames.cpp @@ -150,17 +150,17 @@ IonFrameIterator::isEntryJSFrame() const ++iter; for (; !iter.done(); ++iter) { if (iter.isScripted()) return false; } return true; } -JSScript * +UnrootedScript IonFrameIterator::script() const { AutoAssertNoGC nogc; JS_ASSERT(isScripted()); RawScript script = ScriptFromCalleeToken(calleeToken()); JS_ASSERT(script); return script; } @@ -396,17 +396,17 @@ MarkCalleeToken(JSTracer *trc, CalleeTok { JSFunction *fun = CalleeTokenToFunction(token); MarkObjectRoot(trc, &fun, "ion-callee"); JS_ASSERT(fun == CalleeTokenToFunction(token)); break; } case CalleeToken_Script: { - JSScript *script = CalleeTokenToScript(token); + UnrootedScript script = CalleeTokenToScript(token); MarkScriptRoot(trc, &script, "ion-entry"); JS_ASSERT(script == CalleeTokenToScript(token)); break; } default: JS_NOT_REACHED("unknown callee token type"); } }
--- a/js/src/ion/IonMacroAssembler.h +++ b/js/src/ion/IonMacroAssembler.h @@ -642,17 +642,17 @@ class MacroAssembler : public MacroAssem void spsUpdatePCIdx(SPSProfiler *p, int32_t idx, Register temp) { Label stackFull; spsProfileEntryAddress(p, -1, temp, &stackFull); store32(Imm32(idx), Address(temp, ProfileEntry::offsetOfPCIdx())); bind(&stackFull); } - void spsPushFrame(SPSProfiler *p, const char *str, JSScript *s, Register temp) { + void spsPushFrame(SPSProfiler *p, const char *str, UnrootedScript s, Register temp) { Label stackFull; spsProfileEntryAddress(p, 0, temp, &stackFull); storePtr(ImmWord(str), Address(temp, ProfileEntry::offsetOfString())); storePtr(ImmGCPtr(s), Address(temp, ProfileEntry::offsetOfScript())); storePtr(ImmWord((void*) NULL), Address(temp, ProfileEntry::offsetOfStackAddress())); store32(Imm32(ProfileEntry::NullPCIndex),
--- a/js/src/ion/IonSpewer.cpp +++ b/js/src/ion/IonSpewer.cpp @@ -36,17 +36,17 @@ static const char *ChannelNames[] = void ion::EnableIonDebugLogging() { ionspewer.init(); } void -ion::IonSpewNewFunction(MIRGraph *graph, JSScript *function) +ion::IonSpewNewFunction(MIRGraph *graph, HandleScript function) { if (!js_IonOptions.parallelCompilation) ionspewer.beginFunction(graph, function); } void ion::IonSpewPass(const char *pass) { @@ -89,17 +89,17 @@ IonSpewer::init() if (!jsonSpewer.init(ION_SPEW_DIR "ion.json")) return false; inited_ = true; return true; } void -IonSpewer::beginFunction(MIRGraph *graph, JSScript *function) +IonSpewer::beginFunction(MIRGraph *graph, HandleScript function) { if (!inited_) return; this->graph = graph; this->function = function; c1Spewer.beginFunction(graph, function);
--- a/js/src/ion/IonSpewer.h +++ b/js/src/ion/IonSpewer.h @@ -67,37 +67,38 @@ enum IonSpewChannel { static const int NULL_ID = -1; #ifdef DEBUG class IonSpewer { private: MIRGraph *graph; - JSScript *function; + HandleScript function; C1Spewer c1Spewer; JSONSpewer jsonSpewer; bool inited_; + public: IonSpewer() - : graph(NULL), function(NULL), inited_(false) + : graph(NULL), function(NullPtr()), inited_(false) { } // File output is terminated safely upon destruction. ~IonSpewer(); bool init(); - void beginFunction(MIRGraph *graph, JSScript *); + void beginFunction(MIRGraph *graph, HandleScript); void spewPass(const char *pass); void spewPass(const char *pass, LinearScanAllocator *ra); void endFunction(); }; -void IonSpewNewFunction(MIRGraph *graph, JSScript *function); +void IonSpewNewFunction(MIRGraph *graph, HandleScript function); void IonSpewPass(const char *pass); void IonSpewPass(const char *pass, LinearScanAllocator *ra); void IonSpewEndFunction(); void CheckLogging(); extern FILE *IonSpewFile; void IonSpew(IonSpewChannel channel, const char *fmt, ...); void IonSpewStart(IonSpewChannel channel, const char *fmt, ...); @@ -110,17 +111,17 @@ void IonSpewStartVA(IonSpewChannel chann void IonSpewContVA(IonSpewChannel channel, const char *fmt, va_list ap); void EnableChannel(IonSpewChannel channel); void DisableChannel(IonSpewChannel channel); void EnableIonDebugLogging(); #else -static inline void IonSpewNewFunction(MIRGraph *graph, JSScript *function) +static inline void IonSpewNewFunction(MIRGraph *graph, HandleScript function) { } static inline void IonSpewPass(const char *pass) { } static inline void IonSpewPass(const char *pass, LinearScanAllocator *ra) { } static inline void IonSpewEndFunction() { }
--- a/js/src/ion/JSONSpewer.cpp +++ b/js/src/ion/JSONSpewer.cpp @@ -173,17 +173,17 @@ JSONSpewer::init(const char *path) return false; beginObject(); beginListProperty("functions"); return true; } void -JSONSpewer::beginFunction(JSScript *script) +JSONSpewer::beginFunction(UnrootedScript script) { if (inFunction_) endFunction(); beginObject(); stringProperty("name", "%s:%d", script->filename, script->lineno); beginListProperty("passes");
--- a/js/src/ion/JSONSpewer.h +++ b/js/src/ion/JSONSpewer.h @@ -5,16 +5,19 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef js_ion_jsonspewer_h__ #define js_ion_jsonspewer_h__ #include <stdio.h> +#include "gc/Root.h" +#include "jsscript.h" + struct JSScript; namespace js { namespace ion { class MDefinition; class MInstruction; class MBasicBlock; @@ -52,17 +55,17 @@ class JSONSpewer : inFunction_(false), indentLevel_(0), first_(true), fp_(NULL) { } ~JSONSpewer(); bool init(const char *path); - void beginFunction(JSScript *script); + void beginFunction(UnrootedScript script); void beginPass(const char * pass); void spewMDef(MDefinition *def); void spewMResumePoint(MResumePoint *rp); void spewMIR(MIRGraph *mir); void spewLIns(LInstruction *ins); void spewLIR(MIRGraph *mir); void spewIntervals(LinearScanAllocator *regalloc); void endPass();
--- a/js/src/ion/LIR-Common.h +++ b/js/src/ion/LIR-Common.h @@ -3259,17 +3259,17 @@ class LFunctionBoundary : public LInstru LFunctionBoundary(const LDefinition &temp) { setTemp(0, temp); } const LDefinition *temp() { return getTemp(0); } - JSScript *script() { + UnrootedScript script() { return mir_->toFunctionBoundary()->script(); } MFunctionBoundary::Type type() { return mir_->toFunctionBoundary()->type(); } unsigned inlineLevel() {
--- a/js/src/ion/MIR.h +++ b/js/src/ion/MIR.h @@ -4468,40 +4468,40 @@ class MGetElementCache class MBindNameCache : public MUnaryInstruction, public SingleObjectPolicy { CompilerRootPropertyName name_; CompilerRootScript script_; jsbytecode *pc_; - MBindNameCache(MDefinition *scopeChain, PropertyName *name, JSScript *script, jsbytecode *pc) + MBindNameCache(MDefinition *scopeChain, PropertyName *name, UnrootedScript script, jsbytecode *pc) : MUnaryInstruction(scopeChain), name_(name), script_(script), pc_(pc) { setResultType(MIRType_Object); } public: INSTRUCTION_HEADER(BindNameCache) - static MBindNameCache *New(MDefinition *scopeChain, PropertyName *name, JSScript *script, + static MBindNameCache *New(MDefinition *scopeChain, PropertyName *name, UnrootedScript script, jsbytecode *pc) { return new MBindNameCache(scopeChain, name, script, pc); } TypePolicy *typePolicy() { return this; } MDefinition *scopeChain() const { return getOperand(0); } PropertyName *name() const { return name_; } - JSScript *script() const { + UnrootedScript script() const { return script_; } jsbytecode *pc() const { return pc_; } }; // Guard on an object's shape. @@ -5670,33 +5670,33 @@ class MFunctionBoundary : public MNullar // before this boundary }; private: JSScript *script_; Type type_; unsigned inlineLevel_; - MFunctionBoundary(JSScript *script, Type type, unsigned inlineLevel) + MFunctionBoundary(UnrootedScript script, Type type, unsigned inlineLevel) : script_(script), type_(type), inlineLevel_(inlineLevel) { JS_ASSERT_IF(type != Inline_Exit, script != NULL); JS_ASSERT_IF(type == Inline_Enter, inlineLevel != 0); setGuard(); } public: INSTRUCTION_HEADER(FunctionBoundary) - static MFunctionBoundary *New(JSScript *script, Type type, + static MFunctionBoundary *New(UnrootedScript script, Type type, unsigned inlineLevel = 0) { return new MFunctionBoundary(script, type, inlineLevel); } - JSScript *script() { + UnrootedScript script() { return script_; } Type type() { return type_; } unsigned inlineLevel() {
--- a/js/src/ion/MIRGraph.h +++ b/js/src/ion/MIRGraph.h @@ -463,17 +463,17 @@ class MIRGraph TempAllocator *alloc_; MIRGraphExits *exitAccumulator_; uint32_t blockIdGen_; uint32_t idGen_; MBasicBlock *osrBlock_; MStart *osrStart_; // List of compiled/inlined scripts. - Vector<JSScript *, 4, IonAllocPolicy> scripts_; + Vector<RawScript, 4, IonAllocPolicy> scripts_; size_t numBlocks_; public: MIRGraph(TempAllocator *alloc) : alloc_(alloc), exitAccumulator_(NULL), blockIdGen_(0), @@ -582,17 +582,17 @@ class MIRGraph return osrBlock_; } void setOsrStart(MStart *osrStart) { osrStart_ = osrStart; } MStart *osrStart() { return osrStart_; } - bool addScript(JSScript *script) { + bool addScript(UnrootedScript script) { // The same script may be inlined multiple times, add it only once. for (size_t i = 0; i < scripts_.length(); i++) { if (scripts_[i] == script) return true; } return scripts_.append(script); } size_t numScripts() const {
--- a/js/src/ion/PcScriptCache.h +++ b/js/src/ion/PcScriptCache.h @@ -15,17 +15,17 @@ struct JSRuntime; namespace js { namespace ion { struct PcScriptCacheEntry { uint8_t *returnAddress; // Key into the hash table. jsbytecode *pc; // Cached PC. - JSScript *script; // Cached script. + RawScript script; // Cached script. }; struct PcScriptCache { static const uint32_t Length = 73; // GC number at the time the cache was filled or created. // Storing and checking against this number allows us to not bother @@ -41,17 +41,17 @@ struct PcScriptCache this->gcNumber = gcNumber; } // Get a value from the cache. May perform lazy allocation. // Defined in PcScriptCache-inl.h. bool get(JSRuntime *rt, uint32_t hash, uint8_t *addr, MutableHandleScript scriptRes, jsbytecode **pcRes); - void add(uint32_t hash, uint8_t *addr, jsbytecode *pc, JSScript *script) { + void add(uint32_t hash, uint8_t *addr, jsbytecode *pc, UnrootedScript script) { entries[hash].returnAddress = addr; entries[hash].pc = pc; entries[hash].script = script; } static uint32_t Hash(uint8_t *addr) { uint32_t key = (uint32_t)((uintptr_t)addr); return ((key >> 3) * 2654435761u) % Length;
--- a/js/src/ion/SnapshotWriter.h +++ b/js/src/ion/SnapshotWriter.h @@ -29,17 +29,17 @@ class SnapshotWriter uint32_t nframes_; uint32_t framesWritten_; SnapshotOffset lastStart_; void writeSlotHeader(JSValueType type, uint32_t regCode); public: SnapshotOffset startSnapshot(uint32_t frameCount, BailoutKind kind, bool resumeAfter); - void startFrame(JSFunction *fun, JSScript *script, jsbytecode *pc, uint32_t exprStack); + void startFrame(JSFunction *fun, UnrootedScript script, jsbytecode *pc, uint32_t exprStack); #ifdef TRACK_SNAPSHOTS void trackFrame(uint32_t pcOpcode, uint32_t mirOpcode, uint32_t mirId, uint32_t lirOpcode, uint32_t lirId); #endif void endFrame(); void addSlot(const FloatRegister ®); void addSlot(JSValueType type, const Register ®);
--- a/js/src/ion/Snapshots.cpp +++ b/js/src/ion/Snapshots.cpp @@ -26,17 +26,17 @@ using namespace js::ion; // Snapshot header: // // [vwu] bits (n-31]: frame count // bits [0,n): bailout kind (n = BAILOUT_KIND_BITS) // // Snapshot body, repeated "frame count" times, from oldest frame to newest frame. // Note that the first frame doesn't have the "parent PC" field. // -// [ptr] Debug only: JSScript * +// [ptr] Debug only: RawScript // [vwu] pc offset // [vwu] # of slots, including nargs // [slot*] N slot entries, where N = nargs + nfixed + stackDepth // // Encodings: // [ptr] A fixed-size pointer. // [vwu] A variable-width unsigned integer. // [vws] A variable-width signed integer. @@ -131,20 +131,20 @@ SnapshotReader::readSnapshotHeader() void SnapshotReader::readFrameHeader() { JS_ASSERT(moreFrames()); JS_ASSERT(slotsRead_ == slotCount_); #ifdef DEBUG union { - JSScript *script; - uint8_t bytes[sizeof(JSScript *)]; + RawScript script; + uint8_t bytes[sizeof(RawScript)]; } u; - for (size_t i = 0; i < sizeof(JSScript *); i++) + for (size_t i = 0; i < sizeof(RawScript); i++) u.bytes[i] = reader_.readByte(); script_ = u.script; #endif pcOffset_ = reader_.readUnsigned(); slotCount_ = reader_.readUnsigned(); IonSpew(IonSpew_Snapshots, "Read pc offset %u, nslots %u", pcOffset_, slotCount_); @@ -302,36 +302,36 @@ SnapshotWriter::startSnapshot(uint32_t f if (resumeAfter) bits |= (1 << BAILOUT_RESUME_SHIFT); writer_.writeUnsigned(bits); return lastStart_; } void -SnapshotWriter::startFrame(JSFunction *fun, JSScript *script, jsbytecode *pc, uint32_t exprStack) +SnapshotWriter::startFrame(JSFunction *fun, UnrootedScript script, jsbytecode *pc, uint32_t exprStack) { JS_ASSERT(CountArgSlots(fun) < SNAPSHOT_MAX_NARGS); JS_ASSERT(exprStack < SNAPSHOT_MAX_STACK); uint32_t formalArgs = CountArgSlots(fun); nslots_ = formalArgs + script->nfixed + exprStack; slotsWritten_ = 0; IonSpew(IonSpew_Snapshots, "Starting frame; formals %u, fixed %u, exprs %u", formalArgs, script->nfixed, exprStack); #ifdef DEBUG union { - JSScript *script; - uint8_t bytes[sizeof(JSScript *)]; + RawScript script; + uint8_t bytes[sizeof(RawScript)]; } u; u.script = script; - for (size_t i = 0; i < sizeof(JSScript *); i++) + for (size_t i = 0; i < sizeof(RawScript); i++) writer_.writeByte(u.bytes[i]); #endif JS_ASSERT(script->code <= pc && pc <= script->code + script->length); uint32_t pcoff = uint32_t(pc - script->code); IonSpew(IonSpew_Snapshots, "Writing pc offset %u, nslots %u", pcoff, nslots_); writer_.writeUnsigned(pcoff);
--- a/js/src/ion/TypeOracle.cpp +++ b/js/src/ion/TypeOracle.cpp @@ -13,21 +13,21 @@ #include "jsanalyze.h" using namespace js; using namespace js::ion; using namespace js::types; using namespace js::analyze; bool -TypeInferenceOracle::init(JSContext *cx, JSScript *script) +TypeInferenceOracle::init(JSContext *cx, HandleScript script) { this->cx = cx; this->script_.init(script); - return script->ensureRanInference(cx); + return JSScript::ensureRanInference(cx, script); } MIRType GetMIRType(JSValueType type) { /* Get the suggested representation to use for values in a given type set. */ switch (type) { case JSVAL_TYPE_UNDEFINED: @@ -59,28 +59,28 @@ TypeInferenceOracle::getMIRType(StackTyp MIRType TypeInferenceOracle::getMIRType(HeapTypeSet *types) { return GetMIRType(types->getKnownTypeTag(cx)); } TypeOracle::UnaryTypes -TypeInferenceOracle::unaryTypes(JSScript *script, jsbytecode *pc) +TypeInferenceOracle::unaryTypes(UnrootedScript script, jsbytecode *pc) { JS_ASSERT(script == this->script()); UnaryTypes res; res.inTypes = script->analysis()->poppedTypes(pc, 0); res.outTypes = script->analysis()->pushedTypes(pc, 0); return res; } TypeOracle::BinaryTypes -TypeInferenceOracle::binaryTypes(JSScript *script, jsbytecode *pc) +TypeInferenceOracle::binaryTypes(UnrootedScript script, jsbytecode *pc) { JS_ASSERT(script == this->script()); JSOp op = (JSOp)*pc; BinaryTypes res; if (op == JSOP_NEG || op == JSOP_POS) { res.lhsTypes = script->analysis()->poppedTypes(pc, 0); @@ -90,28 +90,28 @@ TypeInferenceOracle::binaryTypes(JSScrip res.lhsTypes = script->analysis()->poppedTypes(pc, 1); res.rhsTypes = script->analysis()->poppedTypes(pc, 0); res.outTypes = script->analysis()->pushedTypes(pc, 0); } return res; } TypeOracle::Unary -TypeInferenceOracle::unaryOp(JSScript *script, jsbytecode *pc) +TypeInferenceOracle::unaryOp(UnrootedScript script, jsbytecode *pc) { JS_ASSERT(script == this->script()); Unary res; res.ival = getMIRType(script->analysis()->poppedTypes(pc, 0)); res.rval = getMIRType(script->analysis()->pushedTypes(pc, 0)); return res; } TypeOracle::Binary -TypeInferenceOracle::binaryOp(JSScript *script, jsbytecode *pc) +TypeInferenceOracle::binaryOp(UnrootedScript script, jsbytecode *pc) { JS_ASSERT(script == this->script()); JSOp op = (JSOp)*pc; Binary res; if (op == JSOP_NEG || op == JSOP_POS) { res.lhs = getMIRType(script->analysis()->poppedTypes(pc, 0)); @@ -121,17 +121,17 @@ TypeInferenceOracle::binaryOp(JSScript * res.lhs = getMIRType(script->analysis()->poppedTypes(pc, 1)); res.rhs = getMIRType(script->analysis()->poppedTypes(pc, 0)); res.rval = getMIRType(script->analysis()->pushedTypes(pc, 0)); } return res; } StackTypeSet * -TypeInferenceOracle::thisTypeSet(JSScript *script) +TypeInferenceOracle::thisTypeSet(UnrootedScript script) { JS_ASSERT(script == this->script()); return TypeScript::ThisTypes(script); } bool TypeInferenceOracle::getOsrTypes(jsbytecode *osrPc, Vector<MIRType> &slotTypes) { @@ -200,43 +200,43 @@ TypeInferenceOracle::getOsrTypes(jsbytec for (size_t i = ArgSlot(0); i < TotalSlots(script()); i++) slotTypes[i - 1] = getMIRType(slotTypeSets[i]); } return true; } StackTypeSet * -TypeInferenceOracle::parameterTypeSet(JSScript *script, size_t index) +TypeInferenceOracle::parameterTypeSet(UnrootedScript script, size_t index) { JS_ASSERT(script == this->script()); return TypeScript::ArgTypes(script, index); } StackTypeSet * -TypeInferenceOracle::propertyRead(JSScript *script, jsbytecode *pc) +TypeInferenceOracle::propertyRead(UnrootedScript script, jsbytecode *pc) { return script->analysis()->pushedTypes(pc, 0); } StackTypeSet * -TypeInferenceOracle::propertyReadBarrier(JSScript *script, jsbytecode *pc) +TypeInferenceOracle::propertyReadBarrier(HandleScript script, jsbytecode *pc) { if (script->analysis()->typeBarriers(cx, pc)) return script->analysis()->bytecodeTypes(pc); return NULL; } bool -TypeInferenceOracle::propertyReadIdempotent(JSScript *script, jsbytecode *pc, HandleId id) +TypeInferenceOracle::propertyReadIdempotent(HandleScript script, jsbytecode *pc, HandleId id) { if (script->analysis()->getCode(pc).notIdempotent) return false; - if (id.get() != MakeTypeId(cx, id)) + if (id != MakeTypeId(cx, id)) return false; StackTypeSet *types = script->analysis()->poppedTypes(pc, 0); if (!types || types->unknownObject()) return false; for (unsigned i = 0; i < types->getObjectCount(); i++) { if (types->getSingleObject(i)) @@ -252,17 +252,17 @@ TypeInferenceOracle::propertyReadIdempot return false; } } return true; } bool -TypeInferenceOracle::propertyReadAccessGetter(JSScript *script, jsbytecode *pc) +TypeInferenceOracle::propertyReadAccessGetter(UnrootedScript script, jsbytecode *pc) { return script->analysis()->getCode(pc).accessGetter; } bool TypeInferenceOracle::inObjectIsDenseArray(HandleScript script, jsbytecode *pc) { // Check whether the object is a dense array and index is int32 or double. @@ -276,24 +276,24 @@ TypeInferenceOracle::inObjectIsDenseArra JSValueType objType = obj->getKnownTypeTag(); if (objType != JSVAL_TYPE_OBJECT) return false; return !obj->hasObjectFlags(cx, types::OBJECT_FLAG_NON_DENSE_ARRAY); } bool -TypeInferenceOracle::inArrayIsPacked(JSScript *script, jsbytecode *pc) +TypeInferenceOracle::inArrayIsPacked(UnrootedScript script, jsbytecode *pc) { StackTypeSet *types = script->analysis()->poppedTypes(pc, 0); return !types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_PACKED_ARRAY); } bool -TypeInferenceOracle::elementReadIsDenseArray(JSScript *script, jsbytecode *pc) +TypeInferenceOracle::elementReadIsDenseArray(UnrootedScript script, jsbytecode *pc) { // Check whether the object is a dense array and index is int32 or double. StackTypeSet *obj = script->analysis()->poppedTypes(pc, 1); StackTypeSet *id = script->analysis()->poppedTypes(pc, 0); JSValueType objType = obj->getKnownTypeTag(); if (objType != JSVAL_TYPE_OBJECT) return false; @@ -301,17 +301,17 @@ TypeInferenceOracle::elementReadIsDenseA JSValueType idType = id->getKnownTypeTag(); if (idType != JSVAL_TYPE_INT32 && idType != JSVAL_TYPE_DOUBLE) return false; return !obj->hasObjectFlags(cx, types::OBJECT_FLAG_NON_DENSE_ARRAY); } bool -TypeInferenceOracle::elementReadIsTypedArray(JSScript *script, jsbytecode *pc, int *arrayType) +TypeInferenceOracle::elementReadIsTypedArray(UnrootedScript script, jsbytecode *pc, int *arrayType) { // Check whether the object is a typed array and index is int32 or double. StackTypeSet *obj = script->analysis()->poppedTypes(pc, 1); StackTypeSet *id = script->analysis()->poppedTypes(pc, 0); JSValueType objType = obj->getKnownTypeTag(); if (objType != JSVAL_TYPE_OBJECT) return false; @@ -341,17 +341,17 @@ TypeInferenceOracle::elementReadIsTypedA if (!result->hasType(types::Type::Int32Type())) return false; } return true; } bool -TypeInferenceOracle::elementReadIsString(JSScript *script, jsbytecode *pc) +TypeInferenceOracle::elementReadIsString(UnrootedScript script, jsbytecode *pc) { // Check for string[index]. StackTypeSet *value = script->analysis()->poppedTypes(pc, 1); StackTypeSet *id = script->analysis()->poppedTypes(pc, 0); if (value->getKnownTypeTag() != JSVAL_TYPE_STRING) return false; @@ -365,24 +365,24 @@ TypeInferenceOracle::elementReadIsString StackTypeSet *pushed = script->analysis()->pushedTypes(pc, 0); if (pushed->getKnownTypeTag() != JSVAL_TYPE_STRING) return false; return true; } bool -TypeInferenceOracle::elementReadIsPacked(JSScript *script, jsbytecode *pc) +TypeInferenceOracle::elementReadIsPacked(UnrootedScript script, jsbytecode *pc) { StackTypeSet *types = script->analysis()->poppedTypes(pc, 1); return !types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_PACKED_ARRAY); } void -TypeInferenceOracle::elementReadGeneric(JSScript *script, jsbytecode *pc, bool *cacheable, bool *monitorResult) +TypeInferenceOracle::elementReadGeneric(UnrootedScript script, jsbytecode *pc, bool *cacheable, bool *monitorResult) { MIRType obj = getMIRType(script->analysis()->poppedTypes(pc, 1)); MIRType id = getMIRType(script->analysis()->poppedTypes(pc, 0)); *cacheable = (obj == MIRType_Object && (id == MIRType_Value || id == MIRType_Int32 || id == MIRType_String)); // Turn off cacheing if the element is int32 and we've seen non-native objects as the target @@ -410,17 +410,17 @@ TypeInferenceOracle::elementWriteIsDense JSValueType idType = id->getKnownTypeTag(); if (idType != JSVAL_TYPE_INT32 && idType != JSVAL_TYPE_DOUBLE) return false; return !obj->hasObjectFlags(cx, types::OBJECT_FLAG_NON_DENSE_ARRAY); } bool -TypeInferenceOracle::elementWriteIsTypedArray(JSScript *script, jsbytecode *pc, int *arrayType) +TypeInferenceOracle::elementWriteIsTypedArray(UnrootedScript script, jsbytecode *pc, int *arrayType) { // Check whether the object is a dense array and index is int32 or double. StackTypeSet *obj = script->analysis()->poppedTypes(pc, 2); StackTypeSet *id = script->analysis()->poppedTypes(pc, 1); JSValueType objType = obj->getKnownTypeTag(); if (objType != JSVAL_TYPE_OBJECT) return false; @@ -435,30 +435,30 @@ TypeInferenceOracle::elementWriteIsTyped *arrayType = obj->getTypedArrayType(); if (*arrayType == TypedArray::TYPE_MAX) return false; return true; } bool -TypeInferenceOracle::elementWriteIsPacked(JSScript *script, jsbytecode *pc) +TypeInferenceOracle::elementWriteIsPacked(UnrootedScript script, jsbytecode *pc) { StackTypeSet *types = script->analysis()->poppedTypes(pc, 2); return !types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_PACKED_ARRAY); } bool -TypeInferenceOracle::setElementHasWrittenHoles(JSScript *script, jsbytecode *pc) +TypeInferenceOracle::setElementHasWrittenHoles(UnrootedScript script, jsbytecode *pc) { return script->analysis()->getCode(pc).arrayWriteHole; } MIRType -TypeInferenceOracle::elementWrite(JSScript *script, jsbytecode *pc) +TypeInferenceOracle::elementWrite(UnrootedScript script, jsbytecode *pc) { StackTypeSet *objTypes = script->analysis()->poppedTypes(pc, 2); MIRType elementType = MIRType_None; unsigned count = objTypes->getObjectCount(); for (unsigned i = 0; i < count; i++) { if (objTypes->getSingleObject(i)) return MIRType_None; @@ -497,58 +497,58 @@ TypeInferenceOracle::canInlineCalls() bool TypeInferenceOracle::propertyWriteCanSpecialize(UnrootedScript script, jsbytecode *pc) { return !script->analysis()->getCode(pc).monitoredTypes; } bool -TypeInferenceOracle::propertyWriteNeedsBarrier(JSScript *script, jsbytecode *pc, jsid id) +TypeInferenceOracle::propertyWriteNeedsBarrier(UnrootedScript script, jsbytecode *pc, jsid id) { StackTypeSet *types = script->analysis()->poppedTypes(pc, 1); return types->propertyNeedsBarrier(cx, id); } bool -TypeInferenceOracle::elementWriteNeedsBarrier(JSScript *script, jsbytecode *pc) +TypeInferenceOracle::elementWriteNeedsBarrier(UnrootedScript script, jsbytecode *pc) { // Return true if SETELEM-like instructions need a write barrier before modifying // a property. The object is the third value popped by SETELEM. StackTypeSet *types = script->analysis()->poppedTypes(pc, 2); return types->propertyNeedsBarrier(cx, JSID_VOID); } StackTypeSet * -TypeInferenceOracle::getCallTarget(JSScript *caller, uint32_t argc, jsbytecode *pc) +TypeInferenceOracle::getCallTarget(UnrootedScript caller, uint32_t argc, jsbytecode *pc) { JS_ASSERT(caller == this->script()); JS_ASSERT(js_CodeSpec[*pc].format & JOF_INVOKE && JSOp(*pc) != JSOP_EVAL); ScriptAnalysis *analysis = script()->analysis(); return analysis->poppedTypes(pc, argc + 1); } StackTypeSet * -TypeInferenceOracle::getCallArg(JSScript *script, uint32_t argc, uint32_t arg, jsbytecode *pc) +TypeInferenceOracle::getCallArg(UnrootedScript script, uint32_t argc, uint32_t arg, jsbytecode *pc) { JS_ASSERT(argc >= arg); // Bytecode order: Function, This, Arg0, Arg1, ..., ArgN, Call. // |argc| does not include |this|. return script->analysis()->poppedTypes(pc, argc - arg); } StackTypeSet * -TypeInferenceOracle::getCallReturn(JSScript *script, jsbytecode *pc) +TypeInferenceOracle::getCallReturn(UnrootedScript script, jsbytecode *pc) { return script->analysis()->pushedTypes(pc, 0); } bool -TypeInferenceOracle::canInlineCall(JSScript *caller, jsbytecode *pc) +TypeInferenceOracle::canInlineCall(HandleScript caller, jsbytecode *pc) { JS_ASSERT(types::IsInlinableCall(pc)); Bytecode *code = caller->analysis()->maybeCode(pc); if (code->monitoredTypes || code->monitoredTypesReturn || caller->analysis()->typeBarriers(cx, pc)) return false; return true; } @@ -571,45 +571,45 @@ TypeInferenceOracle::canEnterInlinedFunc return false; // TI calls ObjectStateChange to trigger invalidation of the caller. HeapTypeSet::WatchObjectStateChange(cx, target->getType(cx)); return true; } HeapTypeSet * -TypeInferenceOracle::globalPropertyWrite(JSScript *script, jsbytecode *pc, jsid id, +TypeInferenceOracle::globalPropertyWrite(UnrootedScript script, jsbytecode *pc, jsid id, bool *canSpecialize) { *canSpecialize = !script->analysis()->getCode(pc).monitoredTypes; if (!*canSpecialize) return NULL; return globalPropertyTypeSet(script, pc, id); } StackTypeSet * -TypeInferenceOracle::returnTypeSet(JSScript *script, jsbytecode *pc, types::StackTypeSet **barrier) +TypeInferenceOracle::returnTypeSet(UnrootedScript script, jsbytecode *pc, types::StackTypeSet **barrier) { if (script->analysis()->getCode(pc).monitoredTypesReturn) *barrier = script->analysis()->bytecodeTypes(pc); else *barrier = NULL; return script->analysis()->pushedTypes(pc, 0); } StackTypeSet * -TypeInferenceOracle::aliasedVarBarrier(JSScript *script, jsbytecode *pc, types::StackTypeSet **barrier) +TypeInferenceOracle::aliasedVarBarrier(UnrootedScript script, jsbytecode *pc, types::StackTypeSet **barrier) { *barrier = script->analysis()->bytecodeTypes(pc); return script->analysis()->pushedTypes(pc, 0); } HeapTypeSet * -TypeInferenceOracle::globalPropertyTypeSet(JSScript *script, jsbytecode *pc, jsid id) +TypeInferenceOracle::globalPropertyTypeSet(UnrootedScript script, jsbytecode *pc, jsid id) { TypeObject *type = script->global().getType(cx); if (type->unknownProperties()) return NULL; return type->getProperty(cx, id, false); } @@ -619,27 +619,27 @@ TypeInferenceOracle::isArgumentObject(ty if (obj->isMagicArguments()) return DefinitelyArguments; if (obj->hasAnyFlag(TYPE_FLAG_LAZYARGS)) return MaybeArguments; return NotArguments; } LazyArgumentsType -TypeInferenceOracle::propertyReadMagicArguments(JSScript *script, jsbytecode *pc) +TypeInferenceOracle::propertyReadMagicArguments(UnrootedScript script, jsbytecode *pc) { StackTypeSet *obj = script->analysis()->poppedTypes(pc, 0); return isArgumentObject(obj); } LazyArgumentsType -TypeInferenceOracle::elementReadMagicArguments(JSScript *script, jsbytecode *pc) +TypeInferenceOracle::elementReadMagicArguments(UnrootedScript script, jsbytecode *pc) { StackTypeSet *obj = script->analysis()->poppedTypes(pc, 1); return isArgumentObject(obj); } LazyArgumentsType -TypeInferenceOracle::elementWriteMagicArguments(JSScript *script, jsbytecode *pc) +TypeInferenceOracle::elementWriteMagicArguments(UnrootedScript script, jsbytecode *pc) { StackTypeSet *obj = script->analysis()->poppedTypes(pc, 2); return isArgumentObject(obj); }
--- a/js/src/ion/TypeOracle.h +++ b/js/src/ion/TypeOracle.h @@ -39,159 +39,161 @@ class TypeOracle }; struct Binary { MIRType lhs; MIRType rhs; MIRType rval; }; public: - virtual UnaryTypes unaryTypes(JSScript *script, jsbytecode *pc) = 0; - virtual BinaryTypes binaryTypes(JSScript *script, jsbytecode *pc) = 0; - virtual Unary unaryOp(JSScript *script, jsbytecode *pc) = 0; - virtual Binary binaryOp(JSScript *script, jsbytecode *pc) = 0; - virtual types::StackTypeSet *thisTypeSet(JSScript *script) { return NULL; } + virtual UnaryTypes unaryTypes(UnrootedScript script, jsbytecode *pc) = 0; + virtual BinaryTypes binaryTypes(UnrootedScript script, jsbytecode *pc) = 0; + virtual Unary unaryOp(UnrootedScript script, jsbytecode *pc) = 0; + virtual Binary binaryOp(UnrootedScript script, jsbytecode *pc) = 0; + virtual types::StackTypeSet *thisTypeSet(UnrootedScript script) { return NULL; } virtual bool getOsrTypes(jsbytecode *osrPc, Vector<MIRType> &slotTypes) { return true; } - virtual types::StackTypeSet *parameterTypeSet(JSScript *script, size_t index) { return NULL; } - virtual types::HeapTypeSet *globalPropertyTypeSet(JSScript *script, jsbytecode *pc, jsid id) { + virtual types::StackTypeSet *parameterTypeSet(UnrootedScript script, size_t index) { return NULL; } + virtual types::HeapTypeSet *globalPropertyTypeSet(UnrootedScript script, jsbytecode *pc, jsid id) { return NULL; } - virtual types::StackTypeSet *propertyRead(JSScript *script, jsbytecode *pc) { + virtual types::StackTypeSet *propertyRead(UnrootedScript script, jsbytecode *pc) { return NULL; } - virtual types::StackTypeSet *propertyReadBarrier(JSScript *script, jsbytecode *pc) { + virtual types::StackTypeSet *propertyReadBarrier(HandleScript script, jsbytecode *pc) { return NULL; } - virtual bool propertyReadIdempotent(JSScript *script, jsbytecode *pc, HandleId id) { + virtual bool propertyReadIdempotent(HandleScript script, jsbytecode *pc, HandleId id) { return false; } - virtual bool propertyReadAccessGetter(JSScript *script, jsbytecode *pc) { + virtual bool propertyReadAccessGetter(UnrootedScript script, jsbytecode *pc) { return false; } - virtual types::HeapTypeSet *globalPropertyWrite(JSScript *script, jsbytecode *pc, + virtual types::HeapTypeSet *globalPropertyWrite(UnrootedScript script, jsbytecode *pc, jsid id, bool *canSpecialize) { *canSpecialize = true; return NULL; } - virtual types::StackTypeSet *returnTypeSet(JSScript *script, jsbytecode *pc, types::StackTypeSet **barrier) { + virtual types::StackTypeSet *returnTypeSet(UnrootedScript script, jsbytecode *pc, types::StackTypeSet **barrier) { *barrier = NULL; return NULL; } virtual bool inObjectIsDenseArray(HandleScript script, jsbytecode *pc) { return false; } - virtual bool inArrayIsPacked(JSScript *script, jsbytecode *pc) { + virtual bool inArrayIsPacked(UnrootedScript script, jsbytecode *pc) { return false; } - virtual bool elementReadIsDenseArray(JSScript *script, jsbytecode *pc) { + virtual bool elementReadIsDenseArray(UnrootedScript script, jsbytecode *pc) { return false; } - virtual bool elementReadIsTypedArray(JSScript *script, jsbytecode *pc, int *arrayType) { + virtual bool elementReadIsTypedArray(UnrootedScript script, jsbytecode *pc, int *arrayType) { return false; } - virtual bool elementReadIsString(JSScript *script, jsbytecode *pc) { + virtual bool elementReadIsString(UnrootedScript script, jsbytecode *pc) { return false; } - virtual bool elementReadIsPacked(JSScript *script, jsbytecode *pc) { + virtual bool elementReadIsPacked(UnrootedScript script, jsbytecode *pc) { return false; } - virtual void elementReadGeneric(JSScript *script, jsbytecode *pc, bool *cacheable, bool *monitorResult) { + virtual void elementReadGeneric(UnrootedScript script, jsbytecode *pc, bool *cacheable, bool *monitorResult) { *cacheable = false; *monitorResult = true; } - virtual bool setElementHasWrittenHoles(JSScript *script, jsbytecode *pc) { + virtual bool setElementHasWrittenHoles(UnrootedScript script, jsbytecode *pc) { return true; } virtual bool elementWriteIsDenseArray(HandleScript script, jsbytecode *pc) { return false; } - virtual bool elementWriteIsTypedArray(JSScript *script, jsbytecode *pc, int *arrayType) { + virtual bool elementWriteIsTypedArray(UnrootedScript script, jsbytecode *pc, int *arrayType) { return false; } - virtual bool elementWriteIsPacked(JSScript *script, jsbytecode *pc) { + virtual bool elementWriteIsPacked(UnrootedScript script, jsbytecode *pc) { return false; } virtual bool propertyWriteCanSpecialize(UnrootedScript script, jsbytecode *pc) { return true; } - virtual bool propertyWriteNeedsBarrier(JSScript *script, jsbytecode *pc, jsid id) { + virtual bool propertyWriteNeedsBarrier(UnrootedScript script, jsbytecode *pc, jsid id) { return true; } - virtual bool elementWriteNeedsBarrier(JSScript *script, jsbytecode *pc) { + virtual bool elementWriteNeedsBarrier(UnrootedScript script, jsbytecode *pc) { return true; } - virtual MIRType elementWrite(JSScript *script, jsbytecode *pc) { + virtual MIRType elementWrite(UnrootedScript script, jsbytecode *pc) { return MIRType_None; } virtual bool arrayPrototypeHasIndexedProperty() { return true; } virtual bool canInlineCalls() { return false; } /* |pc| must be a |JSOP_CALL|. */ - virtual types::StackTypeSet *getCallTarget(JSScript *caller, uint32_t argc, jsbytecode *pc) { + virtual types::StackTypeSet *getCallTarget(UnrootedScript caller, uint32_t argc, jsbytecode *pc) { // Same assertion as TypeInferenceOracle::getCallTarget. JS_ASSERT(js_CodeSpec[*pc].format & JOF_INVOKE && JSOp(*pc) != JSOP_EVAL); return NULL; } - virtual types::StackTypeSet *getCallArg(JSScript *script, uint32_t argc, uint32_t arg, jsbytecode *pc) { + virtual types::StackTypeSet *getCallArg(UnrootedScript script, uint32_t argc, uint32_t arg, jsbytecode *pc) { return NULL; } - virtual types::StackTypeSet *getCallReturn(JSScript *script, jsbytecode *pc) { + virtual types::StackTypeSet *getCallReturn(UnrootedScript script, jsbytecode *pc) { return NULL; } - virtual bool canInlineCall(JSScript *caller, jsbytecode *pc) { + virtual bool canInlineCall(HandleScript caller, jsbytecode *pc) { return false; } virtual bool canEnterInlinedFunction(JSFunction *callee) { return false; } virtual LazyArgumentsType isArgumentObject(types::StackTypeSet *obj) { return MaybeArguments; } - virtual LazyArgumentsType propertyReadMagicArguments(JSScript *script, jsbytecode *pc) { + virtual LazyArgumentsType propertyReadMagicArguments(UnrootedScript script, jsbytecode *pc) { + return MaybeArguments; + } + virtual LazyArgumentsType elementReadMagicArguments(UnrootedScript script, jsbytecode *pc) { return MaybeArguments; } - virtual LazyArgumentsType elementReadMagicArguments(JSScript *script, jsbytecode *pc) { + virtual LazyArgumentsType elementWriteMagicArguments(UnrootedScript script, jsbytecode *pc) { return MaybeArguments; } - virtual LazyArgumentsType elementWriteMagicArguments(JSScript *script, jsbytecode *pc) { - return MaybeArguments; - } - virtual types::StackTypeSet *aliasedVarBarrier(JSScript *script, jsbytecode *pc, types::StackTypeSet **barrier) { + virtual types::StackTypeSet *aliasedVarBarrier(UnrootedScript script, jsbytecode *pc, + types::StackTypeSet **barrier) + { return NULL; } }; class DummyOracle : public TypeOracle { public: - UnaryTypes unaryTypes(JSScript *script, jsbytecode *pc) { + UnaryTypes unaryTypes(UnrootedScript script, jsbytecode *pc) { UnaryTypes u; u.inTypes = NULL; u.outTypes = NULL; return u; } - BinaryTypes binaryTypes(JSScript *script, jsbytecode *pc) { + BinaryTypes binaryTypes(UnrootedScript script, jsbytecode *pc) { BinaryTypes b; b.lhsTypes = NULL; b.rhsTypes = NULL; b.outTypes = NULL; return b; } - Unary unaryOp(JSScript *script, jsbytecode *pc) { + Unary unaryOp(UnrootedScript script, jsbytecode *pc) { Unary u; u.ival = MIRType_Int32; u.rval = MIRType_Int32; return u; } - Binary binaryOp(JSScript *script, jsbytecode *pc) { + Binary binaryOp(UnrootedScript script, jsbytecode *pc) { Binary b; b.lhs = MIRType_Int32; b.rhs = MIRType_Int32; b.rval = MIRType_Int32; return b; } }; @@ -201,62 +203,62 @@ class TypeInferenceOracle : public TypeO HeapPtrScript script_; MIRType getMIRType(types::StackTypeSet *types); MIRType getMIRType(types::HeapTypeSet *types); public: TypeInferenceOracle() : cx(NULL), script_(NULL) {} - bool init(JSContext *cx, JSScript *script); + bool init(JSContext *cx, HandleScript script); UnrootedScript script() { return script_.get(); } - UnaryTypes unaryTypes(JSScript *script, jsbytecode *pc); - BinaryTypes binaryTypes(JSScript *script, jsbytecode *pc); - Unary unaryOp(JSScript *script, jsbytecode *pc); - Binary binaryOp(JSScript *script, jsbytecode *pc); - types::StackTypeSet *thisTypeSet(JSScript *script); + UnaryTypes unaryTypes(UnrootedScript script, jsbytecode *pc); + BinaryTypes binaryTypes(UnrootedScript script, jsbytecode *pc); + Unary unaryOp(UnrootedScript script, jsbytecode *pc); + Binary binaryOp(UnrootedScript script, jsbytecode *pc); + types::StackTypeSet *thisTypeSet(UnrootedScript script); bool getOsrTypes(jsbytecode *osrPc, Vector<MIRType> &slotTypes); - types::StackTypeSet *parameterTypeSet(JSScript *script, size_t index); - types::HeapTypeSet *globalPropertyTypeSet(JSScript *script, jsbytecode *pc, jsid id); - types::StackTypeSet *propertyRead(JSScript *script, jsbytecode *pc); - types::StackTypeSet *propertyReadBarrier(JSScript *script, jsbytecode *pc); - bool propertyReadIdempotent(JSScript *script, jsbytecode *pc, HandleId id); - bool propertyReadAccessGetter(JSScript *script, jsbytecode *pc); - types::HeapTypeSet *globalPropertyWrite(JSScript *script, jsbytecode *pc, jsid id, bool *canSpecialize); - types::StackTypeSet *returnTypeSet(JSScript *script, jsbytecode *pc, types::StackTypeSet **barrier); - types::StackTypeSet *getCallTarget(JSScript *caller, uint32_t argc, jsbytecode *pc); - types::StackTypeSet *getCallArg(JSScript *caller, uint32_t argc, uint32_t arg, jsbytecode *pc); - types::StackTypeSet *getCallReturn(JSScript *caller, jsbytecode *pc); + types::StackTypeSet *parameterTypeSet(UnrootedScript script, size_t index); + types::HeapTypeSet *globalPropertyTypeSet(UnrootedScript script, jsbytecode *pc, jsid id); + types::StackTypeSet *propertyRead(UnrootedScript script, jsbytecode *pc); + types::StackTypeSet *propertyReadBarrier(HandleScript script, jsbytecode *pc); + bool propertyReadIdempotent(HandleScript script, jsbytecode *pc, HandleId id); + bool propertyReadAccessGetter(UnrootedScript script, jsbytecode *pc); + types::HeapTypeSet *globalPropertyWrite(UnrootedScript script, jsbytecode *pc, jsid id, bool *canSpecialize); + types::StackTypeSet *returnTypeSet(UnrootedScript script, jsbytecode *pc, types::StackTypeSet **barrier); + types::StackTypeSet *getCallTarget(UnrootedScript caller, uint32_t argc, jsbytecode *pc); + types::StackTypeSet *getCallArg(UnrootedScript caller, uint32_t argc, uint32_t arg, jsbytecode *pc); + types::StackTypeSet *getCallReturn(UnrootedScript caller, jsbytecode *pc); bool inObjectIsDenseArray(HandleScript script, jsbytecode *pc); - bool inArrayIsPacked(JSScript *script, jsbytecode *pc); - bool elementReadIsDenseArray(JSScript *script, jsbytecode *pc); - bool elementReadIsTypedArray(JSScript *script, jsbytecode *pc, int *atype); - bool elementReadIsString(JSScript *script, jsbytecode *pc); - bool elementReadIsPacked(JSScript *script, jsbytecode *pc); - void elementReadGeneric(JSScript *script, jsbytecode *pc, bool *cacheable, bool *monitorResult); + bool inArrayIsPacked(UnrootedScript script, jsbytecode *pc); + bool elementReadIsDenseArray(UnrootedScript script, jsbytecode *pc); + bool elementReadIsTypedArray(UnrootedScript script, jsbytecode *pc, int *atype); + bool elementReadIsString(UnrootedScript script, jsbytecode *pc); + bool elementReadIsPacked(UnrootedScript script, jsbytecode *pc); + void elementReadGeneric(UnrootedScript script, jsbytecode *pc, bool *cacheable, bool *monitorResult); bool elementWriteIsDenseArray(HandleScript script, jsbytecode *pc); - bool elementWriteIsTypedArray(JSScript *script, jsbytecode *pc, int *arrayType); - bool elementWriteIsPacked(JSScript *script, jsbytecode *pc); - bool setElementHasWrittenHoles(JSScript *script, jsbytecode *pc); + bool elementWriteIsTypedArray(UnrootedScript script, jsbytecode *pc, int *arrayType); + bool elementWriteIsPacked(UnrootedScript script, jsbytecode *pc); + bool setElementHasWrittenHoles(UnrootedScript script, jsbytecode *pc); bool propertyWriteCanSpecialize(UnrootedScript script, jsbytecode *pc); - bool propertyWriteNeedsBarrier(JSScript *script, jsbytecode *pc, jsid id); - bool elementWriteNeedsBarrier(JSScript *script, jsbytecode *pc); - MIRType elementWrite(JSScript *script, jsbytecode *pc); + bool propertyWriteNeedsBarrier(UnrootedScript script, jsbytecode *pc, jsid id); + bool elementWriteNeedsBarrier(UnrootedScript script, jsbytecode *pc); + MIRType elementWrite(UnrootedScript script, jsbytecode *pc); bool arrayPrototypeHasIndexedProperty(); bool canInlineCalls(); - bool canInlineCall(JSScript *caller, jsbytecode *pc); + bool canInlineCall(HandleScript caller, jsbytecode *pc); bool canEnterInlinedFunction(JSFunction *callee); - types::StackTypeSet *aliasedVarBarrier(JSScript *script, jsbytecode *pc, types::StackTypeSet **barrier); + types::StackTypeSet *aliasedVarBarrier(UnrootedScript script, jsbytecode *pc, types::StackTypeSet **barrier); LazyArgumentsType isArgumentObject(types::StackTypeSet *obj); - LazyArgumentsType propertyReadMagicArguments(JSScript *script, jsbytecode *pc); - LazyArgumentsType elementReadMagicArguments(JSScript *script, jsbytecode *pc); - LazyArgumentsType elementWriteMagicArguments(JSScript *script, jsbytecode *pc); + LazyArgumentsType propertyReadMagicArguments(UnrootedScript script, jsbytecode *pc); + LazyArgumentsType elementReadMagicArguments(UnrootedScript script, jsbytecode *pc); + LazyArgumentsType elementWriteMagicArguments(UnrootedScript script, jsbytecode *pc); }; static inline MIRType MIRTypeFromValueType(JSValueType type) { switch (type) { case JSVAL_TYPE_DOUBLE: return MIRType_Double;
--- a/js/src/ion/VMFunctions.cpp +++ b/js/src/ion/VMFunctions.cpp @@ -51,17 +51,17 @@ InvokeFunction(JSContext *cx, JSFunction Value fval = ObjectValue(*fun); // In order to prevent massive bouncing between Ion and JM, see if we keep // hitting functions that are uncompilable. if (fun->isInterpreted()) { if (fun->isInterpretedLazy() && !fun->getOrCreateScript(cx)) return false; if (!fun->nonLazyScript()->canIonCompile()) { - JSScript *script = GetTopIonJSScript(cx); + UnrootedScript script = GetTopIonJSScript(cx); if (script->hasIonScript() && ++script->ion->slowCallCount >= js_IonOptions.slowCallLimit) { AutoFlushCache afc("InvokeFunction"); // Poison the script so we don't try to run it again. This will // trigger invalidation. ForbidCompilation(cx, script);
--- a/js/src/ion/VMFunctions.h +++ b/js/src/ion/VMFunctions.h @@ -214,17 +214,17 @@ template <> struct TypeToArgProperties<H }; template <> struct TypeToArgProperties<HandlePropertyName> { static const uint32_t result = TypeToArgProperties<PropertyName *>::result | VMFunction::ByRef; }; template <> struct TypeToArgProperties<HandleFunction> { static const uint32_t result = TypeToArgProperties<JSFunction *>::result | VMFunction::ByRef; }; template <> struct TypeToArgProperties<HandleScript> { - static const uint32_t result = TypeToArgProperties<JSScript *>::result | VMFunction::ByRef; + static const uint32_t result = TypeToArgProperties<RawScript>::result | VMFunction::ByRef; }; template <> struct TypeToArgProperties<HandleValue> { static const uint32_t result = TypeToArgProperties<Value>::result | VMFunction::ByRef; }; template <> struct TypeToArgProperties<MutableHandleValue> { static const uint32_t result = TypeToArgProperties<Value>::result | VMFunction::ByRef; }; template <> struct TypeToArgProperties<HandleShape> {
--- a/js/src/ion/arm/CodeGenerator-arm.cpp +++ b/js/src/ion/arm/CodeGenerator-arm.cpp @@ -1100,17 +1100,17 @@ void CodeGeneratorARM::linkAbsoluteLabels() { // arm doesn't have deferred doubles, so this whole thing should be a NOP (right?) // deferred doubles are an x86 mechanism for loading doubles into registers by storing // them after the function body, then referring to them by their absolute address. // On arm, everything should just go in a pool. # if 0 JS_NOT_REACHED("Absolute Labels NYI"); - JSScript *script = gen->info().script(); + UnrootedScript script = gen->info().script(); IonCode *method = script->ion->method(); for (size_t i = 0; i < deferredDoubles_.length(); i++) { DeferredDouble *d = deferredDoubles_[i]; const Value &v = script->ion->getConstant(d->index()); MacroAssembler::Bind(method, d->label(), &v); } #endif
--- a/js/src/ion/shared/CodeGenerator-shared.h +++ b/js/src/ion/shared/CodeGenerator-shared.h @@ -328,24 +328,24 @@ class OutOfLineCode : public TempObject return &rejoin_; } void setFramePushed(uint32_t framePushed) { framePushed_ = framePushed; } uint32_t framePushed() const { return framePushed_; } - void setSource(JSScript *script, jsbytecode *pc) { + void setSource(UnrootedScript script, jsbytecode *pc) { script_ = script; pc_ = pc; } jsbytecode *pc() { return pc_; } - JSScript *script() { + UnrootedScript script() { return script_; } }; // For OOL paths that want a specific-typed code generator. template <typename T> class OutOfLineCodeBase : public OutOfLineCode {
--- a/js/src/ion/x86/CodeGenerator-x86.cpp +++ b/js/src/ion/x86/CodeGenerator-x86.cpp @@ -132,17 +132,17 @@ CodeGeneratorX86::visitUnbox(LUnbox *unb return false; } return true; } void CodeGeneratorX86::linkAbsoluteLabels() { - JSScript *script = gen->info().script(); + UnrootedScript script = gen->info().script(); IonCode *method = script->ion->method(); for (size_t i = 0; i < deferredDoubles_.length(); i++) { DeferredDouble *d = deferredDoubles_[i]; const Value &v = script->ion->getConstant(d->index()); MacroAssembler::Bind(method, d->label(), &v); } }
--- a/js/src/jsalloc.h +++ b/js/src/jsalloc.h @@ -3,17 +3,16 @@ * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef jsalloc_h_ #define jsalloc_h_ -#include "jspubtd.h" #include "jsutil.h" namespace js { /* * Allocation policies. These model the concept: * - public copy constructor, assignment, destructor * - void *malloc_(size_t)
--- a/js/src/jsanalyze.cpp +++ b/js/src/jsanalyze.cpp @@ -17,20 +17,19 @@ using namespace js; using namespace js::analyze; ///////////////////////////////////////////////////////////////////// // Bytecode ///////////////////////////////////////////////////////////////////// #ifdef DEBUG void -analyze::PrintBytecode(JSContext *cx, JSScript *scriptArg, jsbytecode *pc) +analyze::PrintBytecode(JSContext *cx, HandleScript script, jsbytecode *pc) { - RootedScript script(cx, scriptArg); - + AssertCanGC(); printf("#%u:", script->id()); Sprinter sprinter(cx); if (!sprinter.init()) return; js_Disassemble1(cx, script, pc, pc - script->code, true, &sprinter); fprintf(stdout, "%s", sprinter.string()); } #endif @@ -1960,17 +1959,17 @@ ScriptAnalysis::needsArgsObj(JSContext * } CrossSSAValue CrossScriptSSA::foldValue(const CrossSSAValue &cv) { const Frame &frame = getFrame(cv.frame); const SSAValue &v = cv.v; - JSScript *parentScript = NULL; + UnrootedScript parentScript = NULL; ScriptAnalysis *parentAnalysis = NULL; if (frame.parent != INVALID_FRAME) { parentScript = getFrame(frame.parent).script; parentAnalysis = parentScript->analysis(); } if (v.kind() == SSAValue::VAR && v.varInitial() && parentScript) { uint32_t slot = v.varSlot(); @@ -1993,17 +1992,17 @@ CrossScriptSSA::foldValue(const CrossSSA } break; case JSOP_CALL: { /* * If there is a single inline callee with a single return site, * propagate back to that. */ - JSScript *callee = NULL; + UnrootedScript callee = NULL; uint32_t calleeFrame = INVALID_FRAME; for (unsigned i = 0; i < numFrames(); i++) { if (iterFrame(i).parent == cv.frame && iterFrame(i).parentpc == pc) { if (callee) return cv; /* Multiple callees */ callee = iterFrame(i).script; calleeFrame = iterFrame(i).index; } @@ -2045,24 +2044,25 @@ CrossScriptSSA::foldValue(const CrossSSA void ScriptAnalysis::printSSA(JSContext *cx) { AutoEnterAnalysis enter(cx); printf("\n"); + RootedScript script(cx, script_); for (unsigned offset = 0; offset < script_->length; offset++) { Bytecode *code = maybeCode(offset); if (!code) continue; jsbytecode *pc = script_->code + offset; - PrintBytecode(cx, script_, pc); + PrintBytecode(cx, script, pc); SlotValue *newv = code->newValues; if (newv) { while (newv->slot) { if (newv->value.kind() != SSAValue::PHI || newv->value.phiOffset() != offset) { newv++; continue; }
--- a/js/src/jsanalyze.h +++ b/js/src/jsanalyze.h @@ -168,17 +168,17 @@ class Bytecode /* Types for all values pushed by this bytecode. */ types::StackTypeSet *pushedTypes; /* Any type barriers in place at this bytecode. */ types::TypeBarrier *typeBarriers; }; static inline unsigned -GetDefCount(JSScript *script, unsigned offset) +GetDefCount(UnrootedScript script, unsigned offset) { JS_ASSERT(offset < script->length); jsbytecode *pc = script->code + offset; /* * Add an extra pushed value for OR/AND opcodes, so that they are included * in the pushed array of stack values for type inference. */ @@ -197,17 +197,17 @@ GetDefCount(JSScript *script, unsigned o */ return (pc[1] + 1); default: return StackDefs(script, pc); } } static inline unsigned -GetUseCount(JSScript *script, unsigned offset) +GetUseCount(UnrootedScript script, unsigned offset) { JS_ASSERT(offset < script->length); jsbytecode *pc = script->code + offset; if (JSOp(*pc) == JSOP_PICK) return (pc[1] + 1); if (js_CodeSpec[*pc].nuses == -1) return StackUses(script, pc); @@ -326,17 +326,17 @@ NegateCompareOp(JSOp op) return JSOP_STRICTNE; default: JS_NOT_REACHED("unrecognized op"); return op; } } static inline unsigned -FollowBranch(JSContext *cx, JSScript *script, unsigned offset) +FollowBranch(JSContext *cx, UnrootedScript script, unsigned offset) { /* * Get the target offset of a branch. For GOTO opcodes implementing * 'continue' statements, short circuit any artificial backwards jump * inserted by the emitter. */ jsbytecode *pc = script->code + offset; unsigned targetOffset = offset + GET_JUMP_OFFSET(pc); @@ -354,28 +354,28 @@ static inline uint32_t CalleeSlot() { return 0; } static inline uint32_t ThisSlot() { return 1; } static inline uint32_t ArgSlot(uint32_t arg) { return 2 + arg; } -static inline uint32_t LocalSlot(JSScript *script, uint32_t local) { +static inline uint32_t LocalSlot(UnrootedScript script, uint32_t local) { return 2 + (script->function() ? script->function()->nargs : 0) + local; } -static inline uint32_t TotalSlots(JSScript *script) { +static inline uint32_t TotalSlots(UnrootedScript script) { return LocalSlot(script, 0) + script->nfixed; } -static inline uint32_t StackSlot(JSScript *script, uint32_t index) { +static inline uint32_t StackSlot(UnrootedScript script, uint32_t index) { return TotalSlots(script) + index; } -static inline uint32_t GetBytecodeSlot(JSScript *script, jsbytecode *pc) +static inline uint32_t GetBytecodeSlot(UnrootedScript script, jsbytecode *pc) { switch (JSOp(*pc)) { case JSOP_GETARG: case JSOP_CALLARG: case JSOP_SETARG: return ArgSlot(GET_SLOTNO(pc)); @@ -541,17 +541,17 @@ struct LifetimeVariable } return UINT32_MAX; } uint32_t firstWrite(LoopAnalysis *loop) const { return firstWrite(loop->head, loop->backedge); } /* Return true if the variable cannot decrease during the body of a loop. */ - bool nonDecreasing(JSScript *script, LoopAnalysis *loop) const { + bool nonDecreasing(UnrootedScript script, LoopAnalysis *loop) const { Lifetime *segment = lifetime ? lifetime : saved; while (segment && segment->start <= loop->backedge) { if (segment->start >= loop->head && segment->write) { switch (JSOp(script->code[segment->start])) { case JSOP_INCLOCAL: case JSOP_LOCALINC: case JSOP_INCARG: case JSOP_ARGINC: @@ -857,17 +857,17 @@ class ScriptAnalysis uint32_t numReturnSites_; /* --------- Lifetime analysis --------- */ LifetimeVariable *lifetimes; public: - ScriptAnalysis(JSScript *script) { + ScriptAnalysis(UnrootedScript script) { PodZero(this); this->script_ = script; #ifdef DEBUG this->originalDebugMode_ = script_->compartment()->debugMode(); #endif } bool ranBytecode() { return ranBytecode_; } @@ -1259,69 +1259,71 @@ class CrossScriptSSA struct Frame { uint32_t index; JSScript *script; uint32_t depth; /* Distance from outer frame to this frame, in sizeof(Value) */ uint32_t parent; jsbytecode *parentpc; - Frame(uint32_t index, JSScript *script, uint32_t depth, uint32_t parent, jsbytecode *parentpc) - : index(index), script(script), depth(depth), parent(parent), parentpc(parentpc) + Frame(uint32_t index, UnrootedScript script, uint32_t depth, uint32_t parent, + jsbytecode *parentpc) + : index(index), script(script), depth(depth), parent(parent), parentpc(parentpc) {} }; const Frame &getFrame(uint32_t index) { if (index == OUTER_FRAME) return outerFrame; return inlineFrames[index]; } unsigned numFrames() { return 1 + inlineFrames.length(); } const Frame &iterFrame(unsigned i) { if (i == 0) return outerFrame; return inlineFrames[i - 1]; } - JSScript *outerScript() { return outerFrame.script; } + UnrootedScript outerScript() { return outerFrame.script; } /* Total length of scripts preceding a frame. */ size_t frameLength(uint32_t index) { if (index == OUTER_FRAME) return 0; size_t res = outerFrame.script->length; for (unsigned i = 0; i < index; i++) res += inlineFrames[i].script->length; return res; } types::StackTypeSet *getValueTypes(const CrossSSAValue &cv) { return getFrame(cv.frame).script->analysis()->getValueTypes(cv.v); } - bool addInlineFrame(JSScript *script, uint32_t depth, uint32_t parent, jsbytecode *parentpc) + bool addInlineFrame(UnrootedScript script, uint32_t depth, uint32_t parent, + jsbytecode *parentpc) { uint32_t index = inlineFrames.length(); return inlineFrames.append(Frame(index, script, depth, parent, parentpc)); } - CrossScriptSSA(JSContext *cx, JSScript *outer) + CrossScriptSSA(JSContext *cx, UnrootedScript outer) : outerFrame(OUTER_FRAME, outer, 0, INVALID_FRAME, NULL), inlineFrames(cx) {} CrossSSAValue foldValue(const CrossSSAValue &cv); private: Frame outerFrame; Vector<Frame> inlineFrames; }; #ifdef DEBUG -void PrintBytecode(JSContext *cx, JSScript *script, jsbytecode *pc); +void PrintBytecode(JSContext *cx, HandleScript script, jsbytecode *pc); #endif } /* namespace analyze */ } /* namespace js */ namespace js { namespace tl {
--- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -7136,17 +7136,17 @@ JS::AssertArgumentsAreSane(JSContext *cx { AssertHeapIsIdle(cx); CHECK_REQUEST(cx); assertSameCompartment(cx, value); } #endif /* DEBUG */ JS_PUBLIC_API(void *) -JS_EncodeScript(JSContext *cx, JSRawScript scriptArg, uint32_t *lengthp) +JS_EncodeScript(JSContext *cx, RawScript scriptArg, uint32_t *lengthp) { XDREncoder encoder(cx); RootedScript script(cx, scriptArg); if (!encoder.codeScript(&script)) return NULL; return encoder.forgetData(lengthp); }
--- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -511,17 +511,17 @@ static bool checkReportFlags(JSContext *cx, unsigned *flags) { if (JSREPORT_IS_STRICT_MODE_ERROR(*flags)) { /* * Error in strict code; warning with strict option; okay otherwise. * We assume that if the top frame is a native, then it is strict if * the nearest scripted frame is strict, see bug 536306. */ - JSScript *script = cx->stack.currentScript(); + UnrootedScript script = cx->stack.currentScript(); if (script && script->strict) *flags &= ~JSREPORT_WARNING; else if (cx->hasStrictOption()) *flags |= JSREPORT_WARNING; else return true; } else if (JSREPORT_IS_STRICT(*flags)) { /* Warning/error only when JSOPTION_STRICT is set. */
--- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -199,20 +199,20 @@ struct EvalCacheLookup JSCompartment *compartment; }; struct EvalCacheHashPolicy { typedef EvalCacheLookup Lookup; static HashNumber hash(const Lookup &l); - static bool match(JSScript *script, const EvalCacheLookup &l); + static bool match(UnrootedScript script, const EvalCacheLookup &l); }; -typedef HashSet<JSScript *, EvalCacheHashPolicy, SystemAllocPolicy> EvalCache; +typedef HashSet<RawScript, EvalCacheHashPolicy, SystemAllocPolicy> EvalCache; class NativeIterCache { static const size_t SIZE = size_t(1) << 8; /* Cached native iterators. */ PropertyIteratorObject *data[SIZE];
--- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -420,17 +420,17 @@ js::XDRInterpretedFunction(XDRState<mode fun->flags = uint16_t(flagsword); fun->initAtom(atom); fun->initScript(script); script->setFunction(fun); if (!JSFunction::setTypeForScriptedFunction(cx, fun)) return false; JS_ASSERT(fun->nargs == fun->nonLazyScript()->bindings.numArgs()); RootedScript script(cx, fun->nonLazyScript()); - js_CallNewScriptHook(cx, script, fun); + CallNewScriptHook(cx, script, fun); objp.set(fun); } return true; } template bool js::XDRInterpretedFunction(XDRState<XDR_ENCODE> *, HandleObject, HandleScript, MutableHandleObject); @@ -446,30 +446,30 @@ js::CloneInterpretedFunction(JSContext * /* NB: Keep this in sync with XDRInterpretedFunction. */ RootedFunction clone(cx, js_NewFunction(cx, NullPtr(), NULL, 0, JSFunction::INTERPRETED, NullPtr(), NullPtr())); if (!clone) return NULL; RootedScript srcScript(cx, srcFun->nonLazyScript()); - RawScript clonedScript = CloneScript(cx, enclosingScope, clone, srcScript); + RootedScript clonedScript(cx, CloneScript(cx, enclosingScope, clone, srcScript)); if (!clonedScript) return NULL; clone->nargs = srcFun->nargs; clone->flags = srcFun->flags; clone->initAtom(srcFun->displayAtom()); clone->initScript(clonedScript); clonedScript->setFunction(clone); if (!JSFunction::setTypeForScriptedFunction(cx, clone)) return NULL; RootedScript cloneScript(cx, clone->nonLazyScript()); - js_CallNewScriptHook(cx, cloneScript, clone); + CallNewScriptHook(cx, cloneScript, clone); return clone; } /* * [[HasInstance]] internal method for Function objects: fetch the .prototype * property of its 'this' parameter, and walks the prototype chain of v (only * if v is an object) returning true if .prototype is found. */ @@ -1515,27 +1515,27 @@ js_CloneFunctionObject(JSContext *cx, Ha JS_ASSERT(script->compartment() == fun->compartment()); JS_ASSERT_IF(script->compartment() != cx->compartment, !script->enclosingStaticScope()); RootedObject scope(cx, script->enclosingStaticScope()); clone->mutableScript().init(NULL); - RawScript cscript = CloneScript(cx, scope, clone, script); + RootedScript cscript(cx, CloneScript(cx, scope, clone, script)); if (!cscript) return NULL; clone->setScript(cscript); cscript->setFunction(clone); GlobalObject *global = script->compileAndGo ? &script->global() : NULL; script = clone->nonLazyScript(); - js_CallNewScriptHook(cx, script, clone); + CallNewScriptHook(cx, script, clone); Debugger::onNewScript(cx, script, global); } } return clone; } JSFunction * js_DefineFunction(JSContext *cx, HandleObject obj, HandleId id, Native native,
--- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -4566,17 +4566,17 @@ js::StopPCCountProfiling(JSContext *cx) ReleaseAllJITCode(rt->defaultFreeOp()); ScriptAndCountsVector *vec = cx->new_<ScriptAndCountsVector>(SystemAllocPolicy()); if (!vec) return; for (CompartmentsIter c(rt); !c.done(); c.next()) { for (CellIter i(c, FINALIZE_SCRIPT); !i.done(); i.next()) { - JSScript *script = i.get<JSScript>(); + RawScript script = i.get<JSScript>(); if (script->hasScriptCounts && script->types) { ScriptAndCounts sac; sac.script = script; sac.scriptCounts.set(script->releaseScriptCounts()); if (!vec->append(sac)) sac.scriptCounts.destroy(rt->defaultFreeOp()); } }
--- a/js/src/jsinfer.cpp +++ b/js/src/jsinfer.cpp @@ -523,31 +523,31 @@ enum PropertyAccessKind { PROPERTY_READ, PROPERTY_READ_EXISTING }; /* Constraints for reads/writes on object properties. */ template <PropertyAccessKind access> class TypeConstraintProp : public TypeConstraint { - JSScript *script_; + RawScript script_; public: jsbytecode *pc; /* * If assign is true, the target is used to update a property of the object. * If assign is false, the target is assigned the value of the property. */ StackTypeSet *target; /* Property being accessed. */ jsid id; - TypeConstraintProp(JSScript *script, jsbytecode *pc, StackTypeSet *target, jsid id) + TypeConstraintProp(UnrootedScript script, jsbytecode *pc, StackTypeSet *target, jsid id) : script_(script), pc(pc), target(target), id(id) { JS_ASSERT(script && pc && target); } const char *kind() { return "prop"; } void newType(JSContext *cx, TypeSet *source, Type type); @@ -590,25 +590,25 @@ HeapTypeSet::addGetProperty(JSContext *c * These are derived from the types on the properties themselves, rather than * those pushed in the 'this' slot at the call site, which allows us to retain * correlations between the type of the 'this' object and the associated * callee scripts at polymorphic call sites. */ template <PropertyAccessKind access> class TypeConstraintCallProp : public TypeConstraint { - JSScript *script_; + RawScript script_; public: jsbytecode *callpc; /* Property being accessed. */ jsid id; - TypeConstraintCallProp(JSScript *script, jsbytecode *callpc, jsid id) + TypeConstraintCallProp(UnrootedScript script, jsbytecode *callpc, jsid id) : script_(script), callpc(callpc), id(id) { JS_ASSERT(script && callpc); } const char *kind() { return "callprop"; } void newType(JSContext *cx, TypeSet *source, Type type); @@ -635,25 +635,25 @@ HeapTypeSet::addCallProperty(JSContext * /* * Constraints for generating 'set' property constraints on a SETELEM only if * the element type may be a number. For SETELEM we only account for integer * indexes, and if the element cannot be an integer (e.g. it must be a string) * then we lose precision by treating it like one. */ class TypeConstraintSetElement : public TypeConstraint { - JSScript *script_; + RawScript script_; public: jsbytecode *pc; StackTypeSet *objectTypes; StackTypeSet *valueTypes; - TypeConstraintSetElement(JSScript *script, jsbytecode *pc, + TypeConstraintSetElement(UnrootedScript script, jsbytecode *pc, StackTypeSet *objectTypes, StackTypeSet *valueTypes) : script_(script), pc(pc), objectTypes(objectTypes), valueTypes(valueTypes) { JS_ASSERT(script && pc); } const char *kind() { return "setelement"; } @@ -693,28 +693,28 @@ void StackTypeSet::addCall(JSContext *cx, TypeCallsite *site) { add(cx, cx->analysisLifoAlloc().new_<TypeConstraintCall>(site)); } /* Constraints for arithmetic operations. */ class TypeConstraintArith : public TypeConstraint { - JSScript *script_; + RawScript script_; public: jsbytecode *pc; /* Type set receiving the result of the arithmetic. */ TypeSet *target; /* For addition operations, the other operand. */ TypeSet *other; - TypeConstraintArith(JSScript *script, jsbytecode *pc, TypeSet *target, TypeSet *other) + TypeConstraintArith(UnrootedScript script, jsbytecode *pc, TypeSet *target, TypeSet *other) : script_(script), pc(pc), target(target), other(other) { JS_ASSERT(target); } const char *kind() { return "arith"; } void newType(JSContext *cx, TypeSet *source, Type type); @@ -725,22 +725,22 @@ StackTypeSet::addArith(JSContext *cx, Ha TypeSet *other) { add(cx, cx->analysisLifoAlloc().new_<TypeConstraintArith>(script, pc, target, other)); } /* Subset constraint which transforms primitive values into appropriate objects. */ class TypeConstraintTransformThis : public TypeConstraint { - JSScript *script_; + RawScript script_; public: TypeSet *target; - TypeConstraintTransformThis(JSScript *script, TypeSet *target) + TypeConstraintTransformThis(UnrootedScript script, TypeSet *target) : script_(script), target(target) {} const char *kind() { return "transformthis"; } void newType(JSContext *cx, TypeSet *source, Type type); }; @@ -751,24 +751,24 @@ StackTypeSet::addTransformThis(JSContext } /* * Constraint which adds a particular type to the 'this' types of all * discovered scripted functions. */ class TypeConstraintPropagateThis : public TypeConstraint { - JSScript *script_; + RawScript script_; public: jsbytecode *callpc; Type type; StackTypeSet *types; - TypeConstraintPropagateThis(JSScript *script, jsbytecode *callpc, Type type, StackTypeSet *types) + TypeConstraintPropagateThis(UnrootedScript script, jsbytecode *callpc, Type type, StackTypeSet *types) : script_(script), callpc(callpc), type(type), types(types) {} const char *kind() { return "propagatethis"; } void newType(JSContext *cx, TypeSet *source, Type type); }; @@ -913,30 +913,31 @@ void ScriptAnalysis::breakTypeBarriersSS /* * Subset constraint for property reads and argument passing which can add type * barriers on the read instead of passing types along. */ class TypeConstraintSubsetBarrier : public TypeConstraint { public: - JSScript *script; + RawScript script; jsbytecode *pc; TypeSet *target; - TypeConstraintSubsetBarrier(JSScript *script, jsbytecode *pc, TypeSet *target) + TypeConstraintSubsetBarrier(UnrootedScript script, jsbytecode *pc, TypeSet *target) : script(script), pc(pc), target(target) {} const char *kind() { return "subsetBarrier"; } void newType(JSContext *cx, TypeSet *source, Type type) { if (!target->hasType(type)) { - if (!script->ensureRanAnalysis(cx)) + RootedScript scriptRoot(cx, script); + if (!JSScript::ensureRanAnalysis(cx, scriptRoot)) return; script->analysis()->addTypeBarrier(cx, pc, target, type); } } }; void StackTypeSet::addSubsetBarrier(JSContext *cx, HandleScript script, jsbytecode *pc, TypeSet *target) @@ -2085,20 +2086,20 @@ AddPendingRecompile(JSContext *cx, Handl /* * As for TypeConstraintFreeze, but describes an implicit freeze constraint * added for stack types within a script. Applies to all compilations of the * script, not just a single one. */ class TypeConstraintFreezeStack : public TypeConstraint { - JSScript *script_; + RawScript script_; public: - TypeConstraintFreezeStack(JSScript *script) + TypeConstraintFreezeStack(UnrootedScript script) : script_(script) {} const char *kind() { return "freezeStack"; } void newType(JSContext *cx, TypeSet *source, Type type) { /* @@ -2392,17 +2393,17 @@ types::UseNewTypeForInitializer(JSContex if (!cx->typeInferenceEnabled() || script->function()) return false; if (key != JSProto_Object && !(key >= JSProto_Int8Array && key <= JSProto_Uint8ClampedArray)) return false; AutoEnterTypeInference enter(cx); - if (!script->ensureRanAnalysis(cx)) + if (!JSScript::ensureRanAnalysis(cx, script)) return false; return !script->analysis()->getCode(pc).inLoop; } bool types::ArrayPrototypeHasIndexedProperty(JSContext *cx, HandleScript script) { @@ -2642,19 +2643,19 @@ TypeCompartment::addPendingRecompile(JSC # endif #endif } void TypeCompartment::monitorBytecode(JSContext *cx, HandleScript script, uint32_t offset, bool returnOnly) { - AutoAssertNoGC nogc; - - if (!script->ensureRanInference(cx)) + AssertCanGC(); + + if (!JSScript::ensureRanInference(cx, script)) return; ScriptAnalysis *analysis = script->analysis(); jsbytecode *pc = script->code + offset; JS_ASSERT_IF(returnOnly, js_CodeSpec[*pc].format & JOF_INVOKE); Bytecode &code = analysis->getCode(pc); @@ -4637,16 +4638,18 @@ AnalyzePoppedThis(JSContext *cx, Vector< TypeObject *type, JSFunction *fun, MutableHandleObject pbaseobj, Vector<TypeNewScript::Initializer> *initializerList); static bool AnalyzeNewScriptProperties(JSContext *cx, TypeObject *type, JSFunction *fun, MutableHandleObject pbaseobj, Vector<TypeNewScript::Initializer> *initializerList) { + AssertCanGC(); + /* * When invoking 'new' on the specified script, try to find some properties * which will definitely be added to the created object before it has a * chance to escape and be accessed elsewhere. * * Returns true if the entire script was analyzed (pbaseobj has been * preserved), false if we had to bail out part way through (pbaseobj may * have been cleared). @@ -4656,17 +4659,17 @@ AnalyzeNewScriptProperties(JSContext *cx /* * Bail out on really long initializer lists (far longer than maximum * number of properties we can track), we may be recursing. */ return false; } RootedScript script(cx, fun->nonLazyScript()); - if (!script->ensureRanAnalysis(cx) || !script->ensureRanInference(cx)) { + if (!JSScript::ensureRanAnalysis(cx, script) || !JSScript::ensureRanInference(cx, script)) { pbaseobj.set(NULL); cx->compartment->types.setPendingNukeTypes(cx); return false; } ScriptAnalysis *analysis = script->analysis(); /* @@ -5126,23 +5129,24 @@ ScriptAnalysis::printTypes(JSContext *cx for (unsigned i = 0; i < script_->nfixed; i++) { if (!trackSlot(LocalSlot(script_, i))) { printf("\n local%u:", i); TypeScript::LocalTypes(script_, i)->print(); } } printf("\n"); + RootedScript script(cx, script_); for (unsigned offset = 0; offset < script_->length; offset++) { if (!maybeCode(offset)) continue; jsbytecode *pc = script_->code + offset; - PrintBytecode(cx, script_, pc); + PrintBytecode(cx, script, pc); if (js_CodeSpec[*pc].format & JOF_DECOMPOSE) continue; if (js_CodeSpec[*pc].format & JOF_TYPESET) { TypeSet *types = script_->analysis()->bytecodeTypes(pc); printf(" typeset %d:", (int) (types - script_->types->typeArray())); types->print(); @@ -5277,17 +5281,17 @@ IsAboutToBeFinalized(TypeObjectKey *key) void types::TypeDynamicResult(JSContext *cx, HandleScript script, jsbytecode *pc, Type type) { JS_ASSERT(cx->typeInferenceEnabled()); AutoEnterTypeInference enter(cx); /* Directly update associated type sets for applicable bytecodes. */ if (js_CodeSpec[*pc].format & JOF_TYPESET) { - if (!script->ensureRanAnalysis(cx)) { + if (!JSScript::ensureRanAnalysis(cx, script)) { cx->compartment->types.setPendingNukeTypes(cx); return; } TypeSet *types = script->analysis()->bytecodeTypes(pc); if (!types->hasType(type)) { InferSpew(ISpewOps, "externalType: monitorResult #%u:%05u: %s", script->id(), pc - script->code, TypeString(type)); types->addType(cx, type); @@ -5380,17 +5384,17 @@ void types::TypeMonitorResult(JSContext *cx, HandleScript script, jsbytecode *pc, const js::Value &rval) { /* Allow the non-TYPESET scenario to simplify stubs used in compound opcodes. */ if (!(js_CodeSpec[*pc].format & JOF_TYPESET)) return; AutoEnterTypeInference enter(cx); - if (!script->ensureRanAnalysis(cx)) { + if (!JSScript::ensureRanAnalysis(cx, script)) { cx->compartment->types.setPendingNukeTypes(cx); return; } Type type = GetValueType(cx, rval); TypeSet *types = script->analysis()->bytecodeTypes(pc); if (types->hasType(type)) return;
--- a/js/src/jsinfer.h +++ b/js/src/jsinfer.h @@ -8,24 +8,25 @@ #ifndef jsinfer_h___ #define jsinfer_h___ #include "mozilla/Attributes.h" #include "jsalloc.h" #include "jsfriendapi.h" -#include "jsprvtd.h" #include "ds/LifoAlloc.h" #include "gc/Barrier.h" #include "gc/Heap.h" #include "js/HashTable.h" #include "js/Vector.h" +ForwardDeclareJS(Script); + namespace JS { struct TypeInferenceSizes; } namespace js { class TaggedProto { @@ -1100,17 +1101,17 @@ struct TypeCallsite StackTypeSet **argumentTypes; /* Types of the this variable. */ StackTypeSet *thisTypes; /* Type set receiving the return value of this call. */ StackTypeSet *returnTypes; - inline TypeCallsite(JSContext *cx, JSScript *script, jsbytecode *pc, + inline TypeCallsite(JSContext *cx, UnrootedScript script, jsbytecode *pc, bool isNew, unsigned argumentCount); }; /* Persistent type information for a script, retained across GCs. */ class TypeScript { friend struct ::JSScript; @@ -1126,17 +1127,17 @@ class TypeScript * Generated the first time the script is analyzed by inference and kept * after analysis purges. */ HeapTypeSet *propertyReadTypes; /* Array of type type sets for variables and JOF_TYPESET ops. */ TypeSet *typeArray() { return (TypeSet *) (uintptr_t(this) + sizeof(TypeScript)); } - static inline unsigned NumTypeSets(RawScript script); + static inline unsigned NumTypeSets(UnrootedScript script); static inline HeapTypeSet *ReturnTypes(RawScript script); static inline StackTypeSet *ThisTypes(RawScript script); static inline StackTypeSet *ArgTypes(RawScript script, unsigned i); static inline StackTypeSet *LocalTypes(RawScript script, unsigned i); /* Follows slot layout in jsanalyze.h, can get this/arg/local type sets. */ static inline StackTypeSet *SlotTypes(RawScript script, unsigned slot);
--- a/js/src/jsinferinlines.h +++ b/js/src/jsinferinlines.h @@ -410,17 +410,17 @@ struct AutoEnterCompilation : cx(cx), info(cx->compartment->types.compiledInfo), kind(kind) { JS_ASSERT(cx->compartment->activeAnalysis); JS_ASSERT(info.outputIndex == RecompileInfo::NoCompilerRunning); } - bool init(JSScript *script, bool constructing, unsigned chunkIndex) + bool init(UnrootedScript script, bool constructing, unsigned chunkIndex) { CompilerOutput co; co.script = script; co.setKind(kind); co.constructing = constructing; co.barriers = cx->compartment->compileBarriers(); co.chunkIndex = chunkIndex; @@ -529,17 +529,17 @@ void TypeMonitorCallSlow(JSContext *cx, inline bool TypeMonitorCall(JSContext *cx, const js::CallArgs &args, bool constructing) { js::RootedObject callee(cx, &args.callee()); if (callee->isFunction()) { JSFunction *fun = callee->toFunction(); if (fun->isInterpreted()) { js::RootedScript script(cx, fun->nonLazyScript()); - if (!script->ensureRanAnalysis(cx)) + if (!JSScript::ensureRanAnalysis(cx, script)) return false; if (cx->typeInferenceEnabled()) TypeMonitorCallSlow(cx, callee, args, constructing); } } return true; } @@ -657,17 +657,17 @@ FixArrayType(JSContext *cx, HandleObject inline void FixObjectType(JSContext *cx, HandleObject obj) { if (cx->typeInferenceEnabled()) cx->compartment->types.fixObjectType(cx, obj); } -/* Interface helpers for JSScript */ +/* Interface helpers for RawScript */ extern void TypeMonitorResult(JSContext *cx, HandleScript script, jsbytecode *pc, const js::Value &rval); extern void TypeDynamicResult(JSContext *cx, HandleScript script, jsbytecode *pc, js::types::Type type); inline bool UseNewTypeAtEntry(JSContext *cx, StackFrame *fp) { @@ -735,68 +735,74 @@ UseNewTypeForClone(JSFunction *fun) return hasArguments && hasApply; } ///////////////////////////////////////////////////////////////////// // Script interface functions ///////////////////////////////////////////////////////////////////// /* static */ inline unsigned -TypeScript::NumTypeSets(RawScript script) +TypeScript::NumTypeSets(UnrootedScript script) { return script->nTypeSets + analyze::TotalSlots(script); } /* static */ inline HeapTypeSet * TypeScript::ReturnTypes(RawScript script) { + AutoAssertNoGC nogc; TypeSet *types = script->types->typeArray() + script->nTypeSets + js::analyze::CalleeSlot(); return types->toHeapTypeSet(); } /* static */ inline StackTypeSet * TypeScript::ThisTypes(RawScript script) { + AutoAssertNoGC nogc; TypeSet *types = script->types->typeArray() + script->nTypeSets + js::analyze::ThisSlot(); return types->toStackTypeSet(); } /* * Note: for non-escaping arguments and locals, argTypes/localTypes reflect * only the initial type of the variable (e.g. passed values for argTypes, * or undefined for localTypes) and not types from subsequent assignments. */ /* static */ inline StackTypeSet * TypeScript::ArgTypes(RawScript script, unsigned i) { + AutoAssertNoGC nogc; JS_ASSERT(i < script->function()->nargs); TypeSet *types = script->types->typeArray() + script->nTypeSets + js::analyze::ArgSlot(i); return types->toStackTypeSet(); } /* static */ inline StackTypeSet * TypeScript::LocalTypes(RawScript script, unsigned i) { + AutoAssertNoGC nogc; JS_ASSERT(i < script->nfixed); TypeSet *types = script->types->typeArray() + script->nTypeSets + js::analyze::LocalSlot(script, i); return types->toStackTypeSet(); } /* static */ inline StackTypeSet * TypeScript::SlotTypes(RawScript script, unsigned slot) { + AutoAssertNoGC nogc; JS_ASSERT(slot < js::analyze::TotalSlots(script)); TypeSet *types = script->types->typeArray() + script->nTypeSets + slot; return types->toStackTypeSet(); } /* static */ inline TypeObject * TypeScript::StandardType(JSContext *cx, HandleScript script, JSProtoKey key) { + AssertCanGC(); js::RootedObject proto(cx); if (!js_GetClassPrototype(cx, key, &proto, NULL)) return NULL; return proto->getNewType(cx); } struct AllocationSiteKey { JSScript *script; @@ -985,17 +991,17 @@ TypeScript::SetThis(JSContext *cx, Handl if (!ThisTypes(script)->hasType(type) || analyze) { AutoEnterTypeInference enter(cx); InferSpew(ISpewOps, "externalType: setThis #%u: %s", script->id(), TypeString(type)); ThisTypes(script)->addType(cx, type); if (analyze) - script->ensureRanInference(cx); + JSScript::ensureRanInference(cx, script); } } /* static */ inline void TypeScript::SetThis(JSContext *cx, HandleScript script, const js::Value &value) { if (cx->typeInferenceEnabled()) SetThis(cx, script, GetValueType(cx, value)); @@ -1473,17 +1479,17 @@ TypeSet::getTypeObject(unsigned i) const return (key && !(uintptr_t(key) & 1)) ? (TypeObject *) key : NULL; } ///////////////////////////////////////////////////////////////////// // TypeCallsite ///////////////////////////////////////////////////////////////////// inline -TypeCallsite::TypeCallsite(JSContext *cx, JSScript *script, jsbytecode *pc, +TypeCallsite::TypeCallsite(JSContext *cx, UnrootedScript script, jsbytecode *pc, bool isNew, unsigned argumentCount) : script(script), pc(pc), isNew(isNew), argumentCount(argumentCount), thisTypes(NULL), returnTypes(NULL) { /* Caller must check for failure. */ argumentTypes = cx->analysisLifoAlloc().newArray<StackTypeSet*>(argumentCount); } @@ -1710,41 +1716,41 @@ Property::Property(const Property &o) } } /* namespace js::types */ inline bool JSScript::ensureHasTypes(JSContext *cx) { return types || makeTypes(cx); } -inline bool -JSScript::ensureRanAnalysis(JSContext *cx) +/* static */ inline bool +JSScript::ensureRanAnalysis(JSContext *cx, JS::HandleScript script) { + AssertCanGC(); js::analyze::AutoEnterAnalysis aea(cx->compartment); - js::RootedScript self(cx, this); - if (!self->ensureHasTypes(cx)) + if (!script->ensureHasTypes(cx)) return false; - if (!self->hasAnalysis() && !self->makeAnalysis(cx)) + if (!script->hasAnalysis() && !script->makeAnalysis(cx)) return false; - JS_ASSERT(self->analysis()->ranBytecode()); + JS_ASSERT(script->analysis()->ranBytecode()); return true; } -inline bool -JSScript::ensureRanInference(JSContext *cx) +/* static */ inline bool +JSScript::ensureRanInference(JSContext *cx, JS::HandleScript script) { - js::RootedScript self(cx, this); - if (!ensureRanAnalysis(cx)) + AssertCanGC(); + if (!script->ensureRanAnalysis(cx, script)) return false; - if (!self->analysis()->ranInference()) { + if (!script->analysis()->ranInference()) { js::types::AutoEnterTypeInference enter(cx); - self->analysis()->analyzeTypes(cx); + script->analysis()->analyzeTypes(cx); } - return !self->analysis()->OOM() && + return !script->analysis()->OOM() && !cx->compartment->types.pendingNukeTypes; } inline bool JSScript::hasAnalysis() { return types && types->analysis; }
--- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -522,17 +522,17 @@ js::ExecuteKernel(JSContext *cx, HandleS result->setUndefined(); return true; } ExecuteFrameGuard efg; if (!cx->stack.pushExecuteFrame(cx, script, thisv, scopeChain, type, evalInFrame, &efg)) return false; - if (!script->ensureRanAnalysis(cx)) + if (!JSScript::ensureRanAnalysis(cx, script)) return false; TypeScript::SetThis(cx, script, efg.fp()->thisValue()); Probes::startExecution(script); bool ok = RunScript(cx, script, efg.fp()); Probes::stopExecution(script); /* Propgate the return value out. */ @@ -1169,16 +1169,17 @@ js::Interpret(JSContext *cx, StackFrame RootedValue rootValue0(cx), rootValue1(cx); RootedString rootString0(cx), rootString1(cx); RootedObject rootObject0(cx), rootObject1(cx), rootObject2(cx); RootedFunction rootFunction0(cx); RootedTypeObject rootType0(cx); RootedPropertyName rootName0(cx); RootedId rootId0(cx); RootedShape rootShape0(cx); + RootedScript rootScript0(cx); DebugOnly<uint32_t> blockDepth; if (!entryFrame) entryFrame = regs.fp(); #if JS_HAS_GENERATORS if (JS_UNLIKELY(regs.fp()->isGeneratorFrame())) { JS_ASSERT(size_t(regs.pc - script->code) <= script->length); @@ -2355,17 +2356,17 @@ BEGIN_CASE(JSOP_FUNCALL) 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); - RawScript funScript = fun->getOrCreateScript(cx); + RootedScript funScript(cx, fun->getOrCreateScript(cx)); if (!funScript) goto error; if (!cx->stack.pushInlineFrame(cx, regs, args, *fun, funScript, initial)) goto error; SET_SCRIPT(regs.fp()->script()); #ifdef JS_METHODJIT script->resetLoopCount();
--- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -2411,17 +2411,17 @@ js_CreateThisForFunction(JSContext *cx, } /* * Given pc pointing after a property accessing bytecode, return true if the * access is "object-detecting" in the sense used by web scripts, e.g., when * checking whether document.all is defined. */ static bool -Detecting(JSContext *cx, JSScript *script, jsbytecode *pc) +Detecting(JSContext *cx, UnrootedScript script, jsbytecode *pc) { /* General case: a branch or equality op follows the access. */ JSOp op = JSOp(*pc); if (js_CodeSpec[op].format & JOF_DETECTING) return true; jsbytecode *endpc = script->code + script->length; JS_ASSERT(script->code <= pc && pc < endpc); @@ -2462,17 +2462,17 @@ Detecting(JSContext *cx, JSScript *scrip unsigned js_InferFlags(JSContext *cx, unsigned defaultFlags) { /* * We intentionally want to look across compartment boundaries to correctly * handle the case of cross-compartment property access. */ jsbytecode *pc; - JSScript *script = cx->stack.currentScript(&pc, ContextStack::ALLOW_CROSS_COMPARTMENT); + UnrootedScript script = cx->stack.currentScript(&pc, ContextStack::ALLOW_CROSS_COMPARTMENT); if (!script) return defaultFlags; const JSCodeSpec *cs = &js_CodeSpec[*pc]; uint32_t format = cs->format; unsigned flags = 0; if (JOF_MODE(format) != JOF_NAME) flags |= JSRESOLVE_QUALIFIED; @@ -4064,16 +4064,18 @@ CallResolveOp(JSContext *cx, HandleObjec return true; } static JS_ALWAYS_INLINE bool LookupPropertyWithFlagsInline(JSContext *cx, HandleObject obj, HandleId id, unsigned flags, MutableHandleObject objp, MutableHandleShape propp) { + AssertCanGC(); + /* Search scopes starting with obj and following the prototype link. */ RootedObject current(cx, obj); while (true) { { UnrootedShape shape = current->nativeLookup(cx, id); if (shape) { objp.set(current); propp.set(shape); @@ -4196,22 +4198,24 @@ js_NativeGetInline(JSContext *cx, Handle JS_ASSERT_IF(!pobj->hasSingletonType() && shape->hasDefaultGetter(), js::types::TypeHasProperty(cx, pobj->type(), shape->propid(), vp)); } else { vp.setUndefined(); } if (shape->hasDefaultGetter()) return true; - jsbytecode *pc; - JSScript *script = cx->stack.currentScript(&pc); - if (script && script->hasAnalysis()) { - analyze::Bytecode *code = script->analysis()->maybeCode(pc); - if (code) - code->accessGetter = true; + { + jsbytecode *pc; + UnrootedScript script = cx->stack.currentScript(&pc); + if (script && script->hasAnalysis()) { + analyze::Bytecode *code = script->analysis()->maybeCode(pc); + if (code) + code->accessGetter = true; + } } if (!shape->get(cx, receiver, obj, pobj, vp)) return false; /* Update slotful shapes according to the value produced by the getter. */ if (shape->hasSlot() && pobj->nativeContains(cx, shape)) pobj->nativeSetSlot(shape->slot(), vp); @@ -4311,17 +4315,17 @@ js_GetPropertyHelperInline(JSContext *cx return false; } /* Don't warn if not strict or for random getprop operations. */ if (!cx->hasStrictOption() || (op != JSOP_GETPROP && op != JSOP_GETELEM)) return true; /* Don't warn repeatedly for the same script. */ - JSScript *script = cx->stack.currentScript(); + RootedScript script(cx, cx->stack.currentScript()); if (!script || script->warnedAboutUndefinedProp) return true; /* * XXX do not warn about missing __iterator__ as the function * may be called from JS_GetMethodById. See bug 355145. */ if (JSID_IS_ATOM(id, cx->names().iteratorIntrinsic)) @@ -4426,23 +4430,25 @@ js::GetMethod(JSContext *cx, HandleObjec return js_GetXMLMethod(cx, obj, id, vp); #endif return op(cx, obj, obj, id, vp); } JS_FRIEND_API(bool) js::CheckUndeclaredVarAssignment(JSContext *cx, JSString *propname) { - JSScript *script = cx->stack.currentScript(NULL, ContextStack::ALLOW_CROSS_COMPARTMENT); - if (!script) - return true; - - /* If neither cx nor the code is strict, then no check is needed. */ - if (!script->strict && !cx->hasStrictOption()) - return true; + { + UnrootedScript script = cx->stack.currentScript(NULL, ContextStack::ALLOW_CROSS_COMPARTMENT); + if (!script) + return true; + + /* If neither cx nor the code is strict, then no check is needed. */ + if (!script->strict && !cx->hasStrictOption()) + return true; + } JSAutoByteString bytes(cx, propname); return !!bytes && JS_ReportErrorFlagsAndNumber(cx, (JSREPORT_WARNING | JSREPORT_STRICT | JSREPORT_STRICT_MODE_ERROR), js_GetErrorMessage, NULL, JSMSG_UNDECLARED_VAR, bytes.ptr());
--- a/js/src/jsprobes.cpp +++ b/js/src/jsprobes.cpp @@ -68,17 +68,17 @@ void Probes::discardMJITCode(FreeOp *fop, mjit::JITScript *jscr, mjit::JITChunk *chunk, void* address) { if (fop->runtime()->spsProfiler.enabled()) fop->runtime()->spsProfiler.discardMJITCode(jscr, chunk, address); } bool Probes::registerICCode(JSContext *cx, - mjit::JITChunk *chunk, JSScript *script, jsbytecode* pc, + mjit::JITChunk *chunk, UnrootedScript script, jsbytecode* pc, void *start, size_t size) { if (cx->runtime->spsProfiler.enabled() && !cx->runtime->spsProfiler.registerICCode(chunk, script, pc, start, size)) { return false; } return true; @@ -144,17 +144,17 @@ Probes::shutdown() ok = false; #endif return ok; } #ifdef INCLUDE_MOZILLA_DTRACE static const char * -ScriptFilename(const JSScript *script) +ScriptFilename(const UnrootedScript script) { if (!script) return Probes::nullName; if (!script->filename) return Probes::anonymousName; return script->filename; } @@ -171,37 +171,37 @@ FunctionName(JSContext *cx, const JSFunc /* * These functions call the DTrace macros for the JavaScript USDT probes. * Originally this code was inlined in the JavaScript code; however since * a number of operations are called, these have been placed into functions * to reduce any negative compiler optimization effect that the addition of * a number of usually unused lines of code would cause. */ void -Probes::DTraceEnterJSFun(JSContext *cx, JSFunction *fun, JSScript *script) +Probes::DTraceEnterJSFun(JSContext *cx, JSFunction *fun, UnrootedScript script) { JSAutoByteString funNameBytes; JAVASCRIPT_FUNCTION_ENTRY(ScriptFilename(script), Probes::nullName, FunctionName(cx, fun, &funNameBytes)); } void -Probes::DTraceExitJSFun(JSContext *cx, JSFunction *fun, JSScript *script) +Probes::DTraceExitJSFun(JSContext *cx, JSFunction *fun, UnrootedScript script) { JSAutoByteString funNameBytes; JAVASCRIPT_FUNCTION_RETURN(ScriptFilename(script), Probes::nullName, FunctionName(cx, fun, &funNameBytes)); } #endif #ifdef MOZ_ETW static void current_location(JSContext *cx, int* lineno, char const **filename) { - JSScript *script = cx->stack.currentScript() + UnrootedScript script = cx->stack.currentScript() if (! script) { *lineno = -1; *filename = "(uninitialized)"; return; } *lineno = js_PCToLineNumber(cx, script, js_GetCurrentBytecodePC(cx)); *filename = ScriptFilename(script); } @@ -238,27 +238,27 @@ Probes::ETWDestroyRuntime(JSRuntime *rt) bool Probes::ETWShutdown() { EventUnregisterMozillaSpiderMonkey(); return true; } bool -Probes::ETWEnterJSFun(JSContext *cx, JSFunction *fun, JSScript *script, int counter) +Probes::ETWEnterJSFun(JSContext *cx, JSFunction *fun, UnrootedScript script, int counter) { int lineno = script ? script->lineno : -1; JSAutoByteString bytes; return (EventWriteEvtFunctionEntry(ScriptFilename(script), lineno, ObjectClassname((JSObject *)fun), FunctionName(cx, fun, &bytes)) == ERROR_SUCCESS); } bool -Probes::ETWExitJSFun(JSContext *cx, JSFunction *fun, JSScript *script, int counter) +Probes::ETWExitJSFun(JSContext *cx, JSFunction *fun, UnrootedScript script, int counter) { int lineno = script ? script->lineno : -1; JSAutoByteString bytes; return (EventWriteEvtFunctionExit(ScriptFilename(script), lineno, ObjectClassname((JSObject *)fun), FunctionName(cx, fun, &bytes)) == ERROR_SUCCESS); } @@ -420,24 +420,24 @@ Probes::ETWCustomMark(const char *string bool Probes::ETWCustomMark(int marker) { return EventWriteEvtCustomInt(marker) == ERROR_SUCCESS; } bool -Probes::ETWStartExecution(JSScript *script) +Probes::ETWStartExecution(UnrootedScript script) { int lineno = script ? script->lineno : -1; return EventWriteEvtExecuteStart(ScriptFilename(script), lineno) == ERROR_SUCCESS; } bool -Probes::ETWStopExecution(JSScript *script) +Probes::ETWStopExecution(UnrootedScript script) { int lineno = script ? script->lineno : -1; return EventWriteEvtExecuteDone(ScriptFilename(script), lineno) == ERROR_SUCCESS; } bool Probes::ETWResizeHeap(JSCompartment *compartment, size_t oldSize, size_t newSize) {
--- a/js/src/jsprobes.h +++ b/js/src/jsprobes.h @@ -87,26 +87,26 @@ bool callTrackingActive(JSContext *); /* * Test whether anything is looking for JIT native code registration events. * This information will not be collected otherwise. */ bool wantNativeAddressInfo(JSContext *); /* Entering a JS function */ -bool enterScript(JSContext *, JSScript *, JSFunction *, StackFrame *); +bool enterScript(JSContext *, UnrootedScript , JSFunction *, StackFrame *); /* About to leave a JS function */ -bool exitScript(JSContext *, JSScript *, JSFunction *, StackFrame *); +bool exitScript(JSContext *, UnrootedScript , JSFunction *, StackFrame *); /* Executing a script */ -bool startExecution(JSScript *script); +bool startExecution(UnrootedScript script); /* Script has completed execution */ -bool stopExecution(JSScript *script); +bool stopExecution(UnrootedScript script); /* Heap has been resized */ bool resizeHeap(JSCompartment *compartment, size_t oldSize, size_t newSize); /* * Object has been created. |obj| must exist (its class and size are read) */ bool createObject(JSContext *cx, JSObject *obj); @@ -218,47 +218,47 @@ registerMJITCode(JSContext *cx, js::mjit void discardMJITCode(FreeOp *fop, mjit::JITScript *jscr, mjit::JITChunk *chunk, void* address); /* * IC code has been allocated within the given JITChunk */ bool registerICCode(JSContext *cx, - mjit::JITChunk *chunk, JSScript *script, jsbytecode* pc, + mjit::JITChunk *chunk, UnrootedScript script, jsbytecode* pc, void *start, size_t size); #endif /* JS_METHODJIT */ /* * A whole region of code has been deallocated, containing any number of ICs. * (ICs are unregistered in a batch, so individual ICs are not registered.) */ void discardExecutableRegion(void *start, size_t size); /* * Internal: DTrace-specific functions to be called during Probes::enterScript * and Probes::exitScript. These will not be inlined, but the argument * marshalling required for these probe points is expensive enough that it * shouldn't really matter. */ -void DTraceEnterJSFun(JSContext *cx, JSFunction *fun, JSScript *script); -void DTraceExitJSFun(JSContext *cx, JSFunction *fun, JSScript *script); +void DTraceEnterJSFun(JSContext *cx, JSFunction *fun, UnrootedScript script); +void DTraceExitJSFun(JSContext *cx, JSFunction *fun, UnrootedScript script); /* * Internal: ETW-specific probe functions */ #ifdef MOZ_ETW // ETW Handlers bool ETWCreateRuntime(JSRuntime *rt); bool ETWDestroyRuntime(JSRuntime *rt); bool ETWShutdown(); bool ETWCallTrackingActive(); -bool ETWEnterJSFun(JSContext *cx, JSFunction *fun, JSScript *script, int counter); -bool ETWExitJSFun(JSContext *cx, JSFunction *fun, JSScript *script, int counter); +bool ETWEnterJSFun(JSContext *cx, JSFunction *fun, UnrootedScript script, int counter); +bool ETWExitJSFun(JSContext *cx, JSFunction *fun, UnrootedScript script, int counter); bool ETWCreateObject(JSContext *cx, JSObject *obj); bool ETWFinalizeObject(JSObject *obj); bool ETWResizeObject(JSContext *cx, JSObject *obj, size_t oldSize, size_t newSize); bool ETWCreateString(JSContext *cx, JSString *string, size_t length); bool ETWFinalizeString(JSString *string); bool ETWCompileScriptBegin(const char *filename, int lineno); bool ETWCompileScriptEnd(const char *filename, int lineno); bool ETWCalloutBegin(JSContext *cx, JSFunction *fun); @@ -269,18 +269,18 @@ bool ETWGCStart(); bool ETWGCEnd(); bool ETWGCStartMarkPhase(); bool ETWGCEndMarkPhase(); bool ETWGCStartSweepPhase(); bool ETWGCEndSweepPhase(); bool ETWCustomMark(JSString *string); bool ETWCustomMark(const char *string); bool ETWCustomMark(int marker); -bool ETWStartExecution(JSScript *script); -bool ETWStopExecution(JSContext *cx, JSScript *script); +bool ETWStartExecution(UnrootedScript script); +bool ETWStopExecution(JSContext *cx, UnrootedScript script); bool ETWResizeHeap(JSCompartment *compartment, size_t oldSize, size_t newSize); #endif } /* namespace Probes */ /* * Many probe handlers are implemented inline for minimal performance impact, * especially important when no backends are enabled. @@ -307,17 +307,17 @@ Probes::callTrackingActive(JSContext *cx inline bool Probes::wantNativeAddressInfo(JSContext *cx) { return (cx->reportGranularity >= JITREPORT_GRANULARITY_FUNCTION && JITGranularityRequested(cx) >= JITREPORT_GRANULARITY_FUNCTION); } inline bool -Probes::enterScript(JSContext *cx, JSScript *script, JSFunction *maybeFun, +Probes::enterScript(JSContext *cx, UnrootedScript script, JSFunction *maybeFun, StackFrame *fp) { bool ok = true; #ifdef INCLUDE_MOZILLA_DTRACE if (JAVASCRIPT_FUNCTION_ENTRY_ENABLED()) DTraceEnterJSFun(cx, maybeFun, script); #endif #ifdef MOZ_TRACE_JSCALLS @@ -334,17 +334,17 @@ Probes::enterScript(JSContext *cx, JSScr JS_ASSERT_IF(!fp->isGeneratorFrame(), !fp->hasPushedSPSFrame()); fp->setPushedSPSFrame(); } return ok; } inline bool -Probes::exitScript(JSContext *cx, JSScript *script, JSFunction *maybeFun, +Probes::exitScript(JSContext *cx, UnrootedScript script, JSFunction *maybeFun, StackFrame *fp) { bool ok = true; #ifdef INCLUDE_MOZILLA_DTRACE if (JAVASCRIPT_FUNCTION_RETURN_ENABLED()) DTraceExitJSFun(cx, maybeFun, script); #endif @@ -676,17 +676,17 @@ Probes::CustomMark(int marker) if (ProfilingActive && !ETWCustomMark(marker)) ok = false; #endif return ok; } inline bool -Probes::startExecution(JSScript *script) +Probes::startExecution(UnrootedScript script) { bool ok = true; #ifdef INCLUDE_MOZILLA_DTRACE if (JAVASCRIPT_EXECUTE_START_ENABLED()) JAVASCRIPT_EXECUTE_START((script->filename ? (char *)script->filename : nullName), script->lineno); #endif @@ -694,17 +694,17 @@ Probes::startExecution(JSScript *script) if (ProfilingActive && !ETWStartExecution(script)) ok = false; #endif return ok; } inline bool -Probes::stopExecution(JSScript *script) +Probes::stopExecution(UnrootedScript script) { bool ok = true; #ifdef INCLUDE_MOZILLA_DTRACE if (JAVASCRIPT_EXECUTE_DONE_ENABLED()) JAVASCRIPT_EXECUTE_DONE((script->filename ? (char *)script->filename : nullName), script->lineno); #endif
--- a/js/src/jspropertycache.cpp +++ b/js/src/jspropertycache.cpp @@ -103,17 +103,17 @@ PropertyCache::fill(JSContext *cx, JSObj return entry; } PropertyName * PropertyCache::fullTest(JSContext *cx, jsbytecode *pc, JSObject **objp, JSObject **pobjp, PropertyCacheEntry *entry) { JSObject *obj, *pobj; - JSScript *script = cx->stack.currentScript(); + RootedScript script(cx, cx->stack.currentScript()); JS_ASSERT(this == &cx->propertyCache()); JS_ASSERT(uint32_t(pc - script->code) < script->length); JSOp op = JSOp(*pc); obj = *objp;
--- a/js/src/jsprvtd.h +++ b/js/src/jsprvtd.h @@ -273,26 +273,26 @@ typedef JSTrapStatus typedef JSBool (* JSWatchPointHandler)(JSContext *cx, JSObject *obj, jsid id, jsval old, jsval *newp, void *closure); /* called just after script creation */ typedef void (* JSNewScriptHook)(JSContext *cx, const char *filename, /* URL of script */ - unsigned lineno, /* first line */ + unsigned lineno, /* first line */ JSScript *script, JSFunction *fun, void *callerdata); /* called just before script destruction */ typedef void (* JSDestroyScriptHook)(JSFreeOp *fop, - JSRawScript script, - void *callerdata); + JSScript *script, + void *callerdata); typedef void (* JSSourceHandler)(const char *filename, unsigned lineno, const jschar *str, size_t length, void **listenerTSData, void *closure); /* * This hook captures high level script execution and function calls (JS or * native). It is used by JS_SetExecuteHook to hook top level scripts and by
--- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -841,17 +841,17 @@ JSScript::initScriptCounts(JSContext *cx /* Enable interrupts in any interpreter frames running on this script. */ InterpreterFrames *frames; for (frames = cx->runtime->interpreterFrames; frames; frames = frames->older) frames->enableInterruptsIfRunning(this); return true; } -static inline ScriptCountsMap::Ptr GetScriptCountsMapEntry(JSScript *script) +static inline ScriptCountsMap::Ptr GetScriptCountsMapEntry(UnrootedScript script) { JS_ASSERT(script->hasScriptCounts); ScriptCountsMap *map = script->compartment()->scriptCountsMap; ScriptCountsMap::Ptr p = map->lookup(script); JS_ASSERT(p); return p; } @@ -1566,24 +1566,24 @@ ScriptDataSize(uint32_t length, uint32_t size += sizeof(TryNoteArray) + ntrynotes * sizeof(JSTryNote); size += nbindings * sizeof(Binding); size += length * sizeof(jsbytecode); size += nsrcnotes * sizeof(jssrcnote); return size; } -JSScript * +UnrootedScript JSScript::Create(JSContext *cx, HandleObject enclosingScope, bool savedCallerFun, const CompileOptions &options, unsigned staticLevel, ScriptSource *ss, uint32_t bufStart, uint32_t bufEnd) { RootedScript script(cx, js_NewGCScript(cx)); if (!script) - return NULL; + return UnrootedScript(NULL); PodZero(script.get()); new (&script->bindings) Bindings; script->enclosingScope_ = enclosingScope; script->savedCallerFun = savedCallerFun; /* Establish invariant: principals implies originPrincipals. */ @@ -1605,17 +1605,17 @@ JSScript::Create(JSContext *cx, HandleOb JS_ASSERT(script->getVersion() == options.version); // assert that no overflow occurred // This is an unsigned-to-uint16_t conversion, test for too-high values. // In practice, recursion in Parser and/or BytecodeEmitter will blow the // stack if we nest functions more than a few hundred deep, so this will // never trigger. Oh well. if (staticLevel > UINT16_MAX) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_TOO_DEEP, js_function_str); - return NULL; + return UnrootedScript(NULL); } script->staticLevel = uint16_t(staticLevel); script->setScriptSource(ss); script->sourceStart = bufStart; script->sourceEnd = bufEnd; script->userBit = options.userBit; @@ -1880,30 +1880,32 @@ JSScript::enclosingScriptsCompiledSucces enclosing = fun->nonLazyScript()->enclosingScope_; } else { enclosing = enclosing->asStaticBlock().enclosingStaticScope(); } } return true; } -JS_FRIEND_API(void) -js_CallNewScriptHook(JSContext *cx, JSScript *script, JSFunction *fun) +void +js::CallNewScriptHook(JSContext *cx, HandleScript script, HandleFunction fun) { + AssertCanGC(); JS_ASSERT(!script->isActiveEval); if (JSNewScriptHook hook = cx->runtime->debugHooks.newScriptHook) { AutoKeepAtoms keep(cx->runtime); hook(cx, script->filename, script->lineno, script, fun, cx->runtime->debugHooks.newScriptHookData); } } void js::CallDestroyScriptHook(FreeOp *fop, RawScript script) { + // The hook will only call into JS if a GC is not running. if (JSDestroyScriptHook hook = fop->runtime()->debugHooks.destroyScriptHook) hook(fop, script, fop->runtime()->debugHooks.destroyScriptHookData); script->clearTraps(fop); } void JSScript::finalize(FreeOp *fop) { @@ -2162,17 +2164,17 @@ js::CurrentScriptFileLineOriginSlow(JSCo template <class T> static inline T * Rebase(RawScript dst, RawScript src, T *srcp) { size_t off = reinterpret_cast<uint8_t *>(srcp) - src->data; return reinterpret_cast<T *>(dst->data + off); } -JSScript * +UnrootedScript js::CloneScript(JSContext *cx, HandleObject enclosingScope, HandleFunction fun, HandleScript src) { AssertCanGC(); /* NB: Keep this in sync with XDRScript. */ uint32_t nconsts = src->hasConsts() ? src->consts()->length : 0; uint32_t nobjects = src->hasObjects() ? src->objects()->length : 0; @@ -2181,25 +2183,25 @@ js::CloneScript(JSContext *cx, HandleObj /* Script data */ size_t size = ScriptDataSize(src->length, src->numNotes(), src->bindings.count(), src->natoms, nobjects, nregexps, ntrynotes, nconsts); uint8_t *data = AllocScriptData(cx, size); if (!data) - return NULL; + return UnrootedScript(NULL); /* Bindings */ Rooted<Bindings> bindings(cx); InternalHandle<Bindings*> bindingsHandle = InternalHandle<Bindings*>::fromMarkedLocation(bindings.address()); if (!Bindings::clone(cx, bindingsHandle, data, src)) - return NULL; + return UnrootedScript(NULL); /* Objects */ AutoObjectVector objects(cx); if (nobjects != 0) { HeapPtrObject *vector = src->objects()->vector; for (unsigned i = 0; i < nobjects; i++) { RootedObject obj(cx, vector[i]); @@ -2230,29 +2232,29 @@ js::CloneScript(JSContext *cx, HandleObj * Clone object literals emitted for the JSOP_NEWOBJECT opcode. We only emit that * instead of the less-optimized JSOP_NEWINIT for self-hosted code or code compiled * with JSOPTION_COMPILE_N_GO set. As we don't clone the latter type of code, this * case should only ever be hit when cloning objects from self-hosted code. */ clone = CloneObjectLiteral(cx, cx->global(), obj); } if (!clone || !objects.append(clone)) - return NULL; + return UnrootedScript(NULL); } } /* RegExps */ AutoObjectVector regexps(cx); for (unsigned i = 0; i < nregexps; i++) { HeapPtrObject *vector = src->regexps()->vector; for (unsigned i = 0; i < nregexps; i++) { RawObject clone = CloneScriptRegExpObject(cx, vector[i]->asRegExp()); if (!clone || !regexps.append(clone)) - return NULL; + return UnrootedScript(NULL); } } /* Now that all fallible allocation is complete, create the GC thing. */ CompileOptions options(cx); options.setPrincipals(cx->compartment->principals) .setOriginPrincipals(src->originPrincipals) @@ -2260,17 +2262,17 @@ js::CloneScript(JSContext *cx, HandleObj .setNoScriptRval(src->noScriptRval) .setVersion(src->getVersion()) .setUserBit(src->userBit); RootedScript dst(cx, JSScript::Create(cx, enclosingScope, src->savedCallerFun, options, src->staticLevel, src->scriptSource(), src->sourceStart, src->sourceEnd)); if (!dst) { js_free(data); - return NULL; + return UnrootedScript(NULL); } AutoAssertNoGC nogc; dst->bindings = bindings; /* This assignment must occur before all the Rebase calls. */ dst->data = data; memcpy(data, src->data, size);
--- a/js/src/jsscript.h +++ b/js/src/jsscript.h @@ -235,19 +235,19 @@ class ScriptCounts inline void destroy(FreeOp *fop); void set(js::ScriptCounts counts) { pcCountsVector = counts.pcCountsVector; ionCounts = counts.ionCounts; } }; -typedef HashMap<JSScript *, +typedef HashMap<RawScript, ScriptCounts, - DefaultHasher<JSScript *>, + DefaultHasher<RawScript>, SystemAllocPolicy> ScriptCountsMap; class DebugScript { friend struct ::JSScript; /* * When non-zero, compile script in single-step mode. The top bit is set and @@ -263,19 +263,19 @@ class DebugScript /* * Array with all breakpoints installed at opcodes in the script, indexed * by the offset of the opcode into the script. */ BreakpointSite *breakpoints[1]; }; -typedef HashMap<JSScript *, +typedef HashMap<RawScript, DebugScript *, - DefaultHasher<JSScript *>, + DefaultHasher<RawScript>, SystemAllocPolicy> DebugScriptMap; struct ScriptSource; } /* namespace js */ struct JSScript : public js::gc::Cell { @@ -507,19 +507,19 @@ struct JSScript : public js::gc::Cell bool needsArgsAnalysis_:1; bool needsArgsObj_:1; // // End of fields. Start methods. // public: - static JSScript *Create(JSContext *cx, js::HandleObject enclosingScope, bool savedCallerFun, - const JS::CompileOptions &options, unsigned staticLevel, - js::ScriptSource *ss, uint32_t sourceStart, uint32_t sourceEnd); + static js::UnrootedScript Create(JSContext *cx, js::HandleObject enclosingScope, bool savedCallerFun, + const JS::CompileOptions &options, unsigned staticLevel, + js::ScriptSource *ss, uint32_t sourceStart, uint32_t sourceEnd); // Three ways ways to initialize a JSScript. Callers of partiallyInit() // and fullyInitTrivial() are responsible for notifying the debugger after // successfully creating any kind (function or other) of new JSScript. // However, callers of fullyInitFromEmitter() do not need to do this. static bool partiallyInit(JSContext *cx, JS::Handle<JSScript*> script, uint32_t length, uint32_t nsrcnotes, uint32_t natoms, uint32_t nobjects, uint32_t nregexps, uint32_t ntrynotes, uint32_t nconsts, @@ -637,20 +637,20 @@ struct JSScript : public js::gc::Cell /* Ensure the script has a TypeScript. */ inline bool ensureHasTypes(JSContext *cx); /* * Ensure the script has bytecode analysis information. Performed when the * script first runs, or first runs after a TypeScript GC purge. */ - inline bool ensureRanAnalysis(JSContext *cx); + static inline bool ensureRanAnalysis(JSContext *cx, JS::HandleScript script); /* Ensure the script has type inference analysis information. */ - inline bool ensureRanInference(JSContext *cx); + static inline bool ensureRanInference(JSContext *cx, JS::HandleScript script); inline bool hasAnalysis(); inline void clearAnalysis(); inline js::analyze::ScriptAnalysis *analysis(); /* Heuristic to check if the function is expected to be "short running". */ bool isShortRunning(); @@ -767,17 +767,17 @@ struct JSScript : public js::gc::Cell uint32_t numNotes(); /* Number of srcnote slots in the srcnotes section */ /* Script notes are allocated right after the code. */ jssrcnote *notes() { return (jssrcnote *)(code + length); } bool hasArray(ArrayKind kind) { return (hasArrayBits & (1 << kind)); } void setHasArray(ArrayKind kind) { hasArrayBits |= (1 << kind); } - void cloneHasArray(JSScript *script) { hasArrayBits = script->hasArrayBits; } + void cloneHasArray(js::UnrootedScript script) { hasArrayBits = script->hasArrayBits; } bool hasConsts() { return hasArray(CONSTS); } bool hasObjects() { return hasArray(OBJECTS); } bool hasRegexps() { return hasArray(REGEXPS); } bool hasTrynotes() { return hasArray(TRYNOTES); } #define OFF(fooOff, hasFoo, t) (fooOff() + (hasFoo() ? sizeof(t) : 0)) @@ -915,18 +915,18 @@ struct JSScript : public js::gc::Cell bool stepModeEnabled() { return hasDebugScript && !!debugScript()->stepMode; } #ifdef DEBUG uint32_t stepModeCount() { return hasDebugScript ? (debugScript()->stepMode & stepCountMask) : 0; } #endif void finalize(js::FreeOp *fop); - static inline void writeBarrierPre(JSScript *script); - static inline void writeBarrierPost(JSScript *script, void *addr); + static inline void writeBarrierPre(js::UnrootedScript script); + static inline void writeBarrierPost(js::UnrootedScript script, void *addr); static inline js::ThingRootKind rootKind() { return js::THING_ROOT_SCRIPT; } static JSPrincipals *normalizeOriginPrincipals(JSPrincipals *principals, JSPrincipals *originPrincipals) { return originPrincipals ? originPrincipals : principals; } @@ -992,42 +992,28 @@ class AliasedFormalIter unsigned slot_; void settle() { while (p_ != end_ && !p_->aliased()) p_++; } public: - explicit inline AliasedFormalIter(JSScript *script); + explicit inline AliasedFormalIter(js::UnrootedScript script); bool done() const { return p_ == end_; } operator bool() const { return !done(); } void operator++(int) { JS_ASSERT(!done()); p_++; slot_++; settle(); } const Binding &operator*() const { JS_ASSERT(!done()); return *p_; } const Binding *operator->() const { JS_ASSERT(!done()); return p_; } unsigned frameIndex() const { JS_ASSERT(!done()); return p_ - begin_; } unsigned scopeSlot() const { JS_ASSERT(!done()); return slot_; } }; -} /* namespace js */ - -/* - * New-script-hook calling is factored from JSScript::fullyInitFromEmitter() so - * that it and callers of XDRScript() can share this code. In the case of - * callers of XDRScript(), the hook should be invoked only after successful - * decode of any owning function (the fun parameter) or script object (null - * fun). - */ -extern JS_FRIEND_API(void) -js_CallNewScriptHook(JSContext *cx, JSScript *script, JSFunction *fun); - -namespace js { - struct SourceCompressionToken; struct ScriptSource { friend class SourceCompressorThread; private: union { // Before setSourceCopy or setSource are successfully called, this union @@ -1208,16 +1194,26 @@ struct SourceCompressionToken complete(); } bool complete(); void abort(); bool active() const { return !!ss; } }; +/* + * New-script-hook calling is factored from JSScript::fullyInitFromEmitter() so + * that it and callers of XDRScript() can share this code. In the case of + * callers of XDRScript(), the hook should be invoked only after successful + * decode of any owning function (the fun parameter) or script object (null + * fun). + */ +extern void +CallNewScriptHook(JSContext *cx, JS::HandleScript script, JS::HandleFunction fun); + extern void CallDestroyScriptHook(FreeOp *fop, js::RawScript script); extern const char * SaveScriptFilename(JSContext *cx, const char *filename); struct ScriptFilenameEntry { @@ -1248,17 +1244,18 @@ MarkScriptFilename(JSRuntime *rt, const extern void SweepScriptFilenames(JSRuntime *rt); extern void FreeScriptFilenames(JSRuntime *rt); struct ScriptAndCounts { - JSScript *script; + /* This structure is stored and marked from the JSRuntime. */ + js::RawScript script; ScriptCounts scriptCounts; PCCounts &getPCCounts(jsbytecode *pc) const { JS_ASSERT(unsigned(pc - script->code) < script->length); return scriptCounts.pcCountsVector[pc - script->code]; } ion::IonScriptCounts *getIonCounts() const { @@ -1301,17 +1298,17 @@ CurrentLine(JSContext *cx); enum LineOption { CALLED_FROM_JSOP_EVAL, NOT_CALLED_FROM_JSOP_EVAL }; inline void CurrentScriptFileLineOrigin(JSContext *cx, unsigned *linenop, LineOption = NOT_CALLED_FROM_JSOP_EVAL); -extern JSScript * +extern UnrootedScript CloneScript(JSContext *cx, HandleObject enclosingScope, HandleFunction fun, HandleScript script); /* * NB: after a successful XDR_DECODE, XDRScript callers must do any required * subsequent set-up of owning function or script object and then call * js_CallNewScriptHook. */ template<XDRMode mode>
--- a/js/src/jsscriptinlines.h +++ b/js/src/jsscriptinlines.h @@ -23,17 +23,17 @@ namespace js { inline Bindings::Bindings() : callObjShape_(NULL), bindingArrayAndFlag_(TEMPORARY_STORAGE_BIT), numArgs_(0), numVars_(0) {} inline -AliasedFormalIter::AliasedFormalIter(JSScript *script) +AliasedFormalIter::AliasedFormalIter(js::UnrootedScript script) : begin_(script->bindings.bindingArray()), p_(begin_), end_(begin_ + (script->funHasAnyAliasedFormal ? script->bindings.numArgs() : 0)), slot_(CallObject::RESERVED_SLOTS) { settle(); } @@ -146,30 +146,30 @@ inline void JSScript::destroyMJITInfo(js::FreeOp *fop) { fop->delete_(mJITInfo); mJITInfo = NULL; } #endif /* JS_METHODJIT */ inline void -JSScript::writeBarrierPre(JSScript *script) +JSScript::writeBarrierPre(js::UnrootedScript script) { #ifdef JSGC_INCREMENTAL if (!script) return; JSCompartment *comp = script->compartment(); if (comp->needsBarrier()) { JS_ASSERT(!comp->rt->isHeapBusy()); - JSScript *tmp = script; + js::UnrootedScript tmp = script; MarkScriptUnbarriered(comp->barrierTracer(), &tmp, "write barrier"); JS_ASSERT(tmp == script); } #endif } inline void -JSScript::writeBarrierPost(JSScript *script, void *addr) +JSScript::writeBarrierPost(js::UnrootedScript script, void *addr) { } #endif /* jsscriptinlines_h___ */
--- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -156,25 +156,25 @@ mjit::Compiler::compile() } return status; } CompileStatus mjit::Compiler::checkAnalysis(HandleScript script) { - if (!script->ensureRanAnalysis(cx)) + if (!JSScript::ensureRanAnalysis(cx, script)) return Compile_Error; if (!script->analysis()->jaegerCompileable()) { JaegerSpew(JSpew_Abort, "script has uncompileable opcodes\n"); return Compile_Abort; } - if (cx->typeInferenceEnabled() && !script->ensureRanInference(cx)) + if (cx->typeInferenceEnabled() && !JSScript::ensureRanInference(cx, script)) return Compile_Error; ScriptAnalysis *analysis = script->analysis(); analysis->assertMatchingDebugMode(); if (analysis->failed()) { JaegerSpew(JSpew_Abort, "couldn't analyze bytecode; probably switchX or OOM\n"); return Compile_Abort; } @@ -667,34 +667,35 @@ static uint32_t CHUNK_LIMIT = 1500; void mjit::SetChunkLimit(uint32_t limit) { if (limit) CHUNK_LIMIT = limit; } JITScript * -MakeJITScript(JSContext *cx, JSScript *script) -{ - if (!script->ensureRanAnalysis(cx)) +MakeJITScript(JSContext *cx, HandleScript script) +{ + AssertCanGC(); + if (!JSScript::ensureRanAnalysis(cx, script)) return NULL; ScriptAnalysis *analysis = script->analysis(); Vector<ChunkDescriptor> chunks(cx); Vector<CrossChunkEdge> edges(cx); if (script->length < CHUNK_LIMIT || !cx->typeInferenceEnabled()) { ChunkDescriptor desc; desc.begin = 0; desc.end = script->length; if (!chunks.append(desc)) return NULL; } else { - if (!script->ensureRanInference(cx)) + if (!JSScript::ensureRanInference(cx, script)) return NULL; /* Outgoing edges within the current chunk. */ Vector<CrossChunkEdge> currentEdges(cx); uint32_t chunkStart = 0; bool preserveNextChunk = false; unsigned offset, nextOffset = 0; @@ -988,21 +989,20 @@ IonGetsFirstChance(JSContext *cx, JSScri return false; return true; #endif return false; } CompileStatus -mjit::CanMethodJIT(JSContext *cx, JSScript *scriptArg, jsbytecode *pc, +mjit::CanMethodJIT(JSContext *cx, HandleScript script, jsbytecode *pc, bool construct, CompileRequest request, StackFrame *frame) { bool compiledOnce = false; - RootedScript script(cx, scriptArg); checkOutput: if (!cx->methodJitEnabled) return Compile_Abort; /* * If SPS (profiling) is enabled, then the emitted instrumentation has to be * careful to not wildly write to random locations. This is relevant * whenever the status of profiling (on/off) is changed while JS is running. @@ -1015,17 +1015,17 @@ mjit::CanMethodJIT(JSContext *cx, JSScri * SPS frame has not been pushed, and SPS is not enabled, then we're still * good to go. If, however, the two are different, then we cannot emit JIT * code because the instrumentation will be wrong one way or another. */ if (frame->script() == script && pc != script->code) { if (frame->hasPushedSPSFrame() != cx->runtime->spsProfiler.enabled()) return Compile_Skipped; } - + if (IonGetsFirstChance(cx, script, request)) return Compile_Skipped; if (script->hasMJITInfo()) { JSScript::JITScriptHandle *jith = script->jitHandle(construct, cx->compartment->compileBarriers()); if (jith->isUnjittable()) return Compile_Abort; }
--- a/js/src/methodjit/InvokeHelpers.cpp +++ b/js/src/methodjit/InvokeHelpers.cpp @@ -608,17 +608,17 @@ js_InternalThrow(VMFrame &f) * Fall back to EnterMethodJIT and finish the frame in the interpreter. * With type inference enabled, we may wipe out all JIT code on the * stack without patching ncode values to jump to the interpreter, and * thus can only enter JIT code via EnterMethodJIT (which overwrites * its entry frame's ncode). See ClearAllFrames. */ cx->jaegerRuntime().setLastUnfinished(Jaeger_Unfinished); - if (!script->ensureRanAnalysis(cx)) { + if (!JSScript::ensureRanAnalysis(cx, script)) { js_ReportOutOfMemory(cx); return NULL; } analyze::AutoEnterAnalysis enter(cx); /* * Interpret the ENTERBLOCK and EXCEPTION opcodes, so that we don't go @@ -703,21 +703,21 @@ stubs::ScriptProbeOnlyEpilogue(VMFrame & void JS_FASTCALL stubs::CrossChunkShim(VMFrame &f, void *edge_) { AssertCanGC(); DebugOnly<CrossChunkEdge*> edge = (CrossChunkEdge *) edge_; mjit::ExpandInlineFrames(f.cx->compartment); - UnrootedScript script = f.script(); + RootedScript script(f.cx, f.script()); JS_ASSERT(edge->target < script->length); JS_ASSERT(script->code + edge->target == f.pc()); - CompileStatus status = CanMethodJIT(f.cx, DropUnrooted(script), f.pc(), + CompileStatus status = CanMethodJIT(f.cx, script, f.pc(), f.fp()->isConstructing(), CompileRequest_Interpreter, f.fp()); if (status == Compile_Error) THROW(); void **addr = f.returnAddressLocation(); *addr = JS_FUNC_TO_DATA_PTR(void *, JaegerInterpoline); @@ -753,17 +753,17 @@ js_InternalInterpret(void *returnData, v JSContext *cx = f.cx; StackFrame *fp = f.regs.fp(); RootedScript script(cx, fp->script()); jsbytecode *pc = f.regs.pc; JSOp op = JSOp(*pc); - if (!script->ensureRanAnalysis(cx)) { + if (!JSScript::ensureRanAnalysis(cx, script)) { js_ReportOutOfMemory(cx); return js_InternalThrow(f); } analyze::AutoEnterAnalysis enter(cx); analyze::ScriptAnalysis *analysis = script->analysis(); /*
--- a/js/src/methodjit/MethodJIT.h +++ b/js/src/methodjit/MethodJIT.h @@ -909,17 +909,17 @@ ProfileStubCall(VMFrame &f); enum CompileRequest { CompileRequest_Interpreter, CompileRequest_JIT }; CompileStatus -CanMethodJIT(JSContext *cx, JSScript *script, jsbytecode *pc, +CanMethodJIT(JSContext *cx, HandleScript script, jsbytecode *pc, bool construct, CompileRequest request, StackFrame *sp); inline void ReleaseScriptCode(FreeOp *fop, JSScript *script) { if (!script->hasMJITInfo()) return;
--- a/js/src/methodjit/PolyIC.cpp +++ b/js/src/methodjit/PolyIC.cpp @@ -414,19 +414,19 @@ class SetPropCompiler : public PICStubCo if (!type->unknownProperties()) { types::AutoEnterTypeInference enter(cx); types::TypeSet *types = type->getProperty(cx, types::MakeTypeId(cx, id), true); if (!types) return false; jsbytecode *pc; - JSScript *script = cx->stack.currentScript(&pc); - - if (!script->ensureRanInference(cx) || monitor.recompiled()) + RootedScript script(cx, cx->stack.currentScript(&pc)); + + if (!JSScript::ensureRanInference(cx, script) || monitor.recompiled()) return false; JS_ASSERT(*pc == JSOP_SETPROP || *pc == JSOP_SETNAME); types::StackTypeSet *rhsTypes = script->analysis()->poppedTypes(pc, 0); rhsTypes->addSubset(cx, types); } @@ -2214,17 +2214,17 @@ frameCountersOffset(VMFrame &f) offset += cx->fp()->script()->length; uint32_t index = cx->regs().inlined()->inlineIndex; InlineFrame *frames = f.chunk()->inlineFrames(); for (unsigned i = 0; i < index; i++) offset += frames[i].fun->nonLazyScript()->length; } jsbytecode *pc; - JSScript *script = cx->stack.currentScript(&pc); + UnrootedScript script = cx->stack.currentScript(&pc); offset += pc - script->code; return offset; } LookupStatus BaseIC::disable(VMFrame &f, const char *reason, void *stub) {
--- a/js/src/methodjit/StubCalls.cpp +++ b/js/src/methodjit/StubCalls.cpp @@ -829,17 +829,18 @@ stubs::TriggerIonCompile(VMFrame &f) */ if (!script->canIonCompile() || script->isIonCompilingOffThread()) return; jsbytecode *osrPC = f.regs.pc; if (*osrPC != JSOP_LOOPENTRY) osrPC = NULL; - if (!ion::TestIonCompile(f.cx, script, script->function(), osrPC, f.fp()->isConstructing())) { + RootedFunction scriptFunction(f.cx, script->function()); + if (!ion::TestIonCompile(f.cx, script, scriptFunction, osrPC, f.fp()->isConstructing())) { if (f.cx->isExceptionPending()) THROW(); } return; } ExpandInlineFrames(f.cx->compartment);
--- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -515,19 +515,19 @@ SkipUTF8BOM(FILE* file) if (ch1 != EOF) ungetc(ch1, file); } static void Process(JSContext *cx, JSObject *obj_, const char *filename, bool forceTTY) { bool ok, hitEOF; - JSScript *script; + RootedScript script(cx); jsval result; - JSString *str; + RootedString str(cx); char *buffer; size_t size; jschar *uc_buffer; size_t uc_len; int lineno; int startline; FILE *file; uint32_t oldopts; @@ -1050,17 +1050,17 @@ Evaluate(JSContext *cx, unsigned argc, j uint32_t saved = JS_GetOptions(cx); uint32_t options = saved & ~(JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL); if (compileAndGo) options |= JSOPTION_COMPILE_N_GO; if (noScriptRval) options |= JSOPTION_NO_SCRIPT_RVAL; JS_SetOptions(cx, options); - JSScript *script = JS_CompileUCScript(cx, global, codeChars, codeLength, fileName, lineNumber); + RootedScript script(cx, JS_CompileUCScript(cx, global, codeChars, codeLength, fileName, lineNumber)); JS_SetOptions(cx, saved); if (!script) return false; if (sourceMapURL && !script->scriptSource()->hasSourceMap()) { if (!script->scriptSource()->setSourceMap(cx, sourceMapURL, script->filename)) return false; } @@ -1196,17 +1196,17 @@ Run(JSContext *cx, unsigned argc, jsval if (!ucbuf) return false; JS::Anchor<JSString *> a_str(str); uint32_t oldopts = JS_GetOptions(cx); JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL); int64_t startClock = PRMJ_Now(); - JSScript *script = JS_CompileUCScript(cx, thisobj, ucbuf, buflen, filename.ptr(), 1); + RootedScript script(cx, JS_CompileUCScript(cx, thisobj, ucbuf, buflen, filename.ptr(), 1)); JS_SetOptions(cx, oldopts); if (!script || !JS_ExecuteScript(cx, thisobj, script, NULL)) return false; int64_t endClock = PRMJ_Now(); JS_SET_RVAL(cx, vp, DOUBLE_TO_JSVAL((endClock - startClock) / double(PRMJ_USEC_PER_MSEC))); return true; } @@ -1445,22 +1445,22 @@ AssertJit(JSContext *cx, unsigned argc, } } #endif JS_SET_RVAL(cx, vp, JSVAL_VOID); return true; } -static JSScript * +static UnrootedScript ValueToScript(JSContext *cx, jsval v, JSFunction **funp = NULL) { RootedFunction fun(cx, JS_ValueToFunction(cx, v)); if (!fun) - return NULL; + return UnrootedScript(NULL); RootedScript script(cx); fun->maybeGetOrCreateScript(cx, &script); if (!script) JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_SCRIPTS_ONLY); if (fun && funp) *funp = fun; @@ -1486,29 +1486,29 @@ SetDebug(JSContext *cx, unsigned argc, j */ bool ok = !!JS_SetDebugMode(cx, JSVAL_TO_BOOLEAN(argv[0])); if (ok) JS_SET_RVAL(cx, vp, JSVAL_TRUE); return ok; } -static JSScript * +static UnrootedScript GetTopScript(JSContext *cx) { - JSScript *script; - JS_DescribeScriptedCaller(cx, &script, NULL); + RootedScript script(cx); + JS_DescribeScriptedCaller(cx, script.address(), NULL); return script; } static JSBool -GetScriptAndPCArgs(JSContext *cx, unsigned argc, jsval *argv, JSScript **scriptp, +GetScriptAndPCArgs(JSContext *cx, unsigned argc, jsval *argv, MutableHandleScript scriptp, int32_t *ip) { - JSScript *script = GetTopScript(cx); + RootedScript script(cx, GetTopScript(cx)); *ip = 0; if (argc != 0) { jsval v = argv[0]; unsigned intarg = 0; if (!JSVAL_IS_PRIMITIVE(v) && JS_GetClass(JSVAL_TO_OBJECT(v)) == Jsvalify(&FunctionClass)) { script = ValueToScript(cx, v); if (!script) @@ -1520,23 +1520,23 @@ GetScriptAndPCArgs(JSContext *cx, unsign return false; if ((uint32_t)*ip >= script->length) { JS_ReportError(cx, "Invalid PC"); return false; } } } - *scriptp = script; + scriptp.set(script); return true; } static JSTrapStatus -TrapHandler(JSContext *cx, JSScript *, jsbytecode *pc, jsval *rval, +TrapHandler(JSContext *cx, RawScript, jsbytecode *pc, jsval *rval, jsval closure) { JSString *str = JSVAL_TO_STRING(closure); ScriptFrameIter iter(cx); JS_ASSERT(!iter.done()); /* Debug-mode currently disables Ion compilation. */ @@ -1558,17 +1558,17 @@ TrapHandler(JSContext *cx, JSScript *, j return JSTRAP_RETURN; return JSTRAP_CONTINUE; } static JSBool Trap(JSContext *cx, unsigned argc, jsval *vp) { JSString *str; - JSScript *script; + RootedScript script(cx); int32_t i; jsval *argv = JS_ARGV(cx, vp); if (argc == 0) { JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_TRAP_USAGE); return false; } argc--; @@ -1584,28 +1584,28 @@ Trap(JSContext *cx, unsigned argc, jsval } JS_SET_RVAL(cx, vp, JSVAL_VOID); return JS_SetTrap(cx, script, script->code + i, TrapHandler, STRING_TO_JSVAL(str)); } static JSBool Untrap(JSContext *cx, unsigned argc, jsval *vp) { - JSScript *script; + RootedScript script(cx); int32_t i; if (!GetScriptAndPCArgs(cx, argc, JS_ARGV(cx, vp), &script, &i)) return false; JS_ClearTrap(cx, script, script->code + i, NULL, NULL); JS_SET_RVAL(cx, vp, JSVAL_VOID); return true; } static JSTrapStatus -DebuggerAndThrowHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval, +DebuggerAndThrowHandler(JSContext *cx, RawScript script, jsbytecode *pc, jsval *rval, void *closure) { return TrapHandler(cx, script, pc, rval, STRING_TO_JSVAL((JSString *)closure)); } static JSBool SetDebuggerHandler(JSContext *cx, unsigned argc, jsval *vp) { @@ -1673,33 +1673,33 @@ LineToPC(JSContext *cx, unsigned argc, j return false; *vp = INT_TO_JSVAL(pc - script->code); return true; } static JSBool PCToLine(JSContext *cx, unsigned argc, jsval *vp) { - JSScript *script; + RootedScript script(cx); int32_t i; unsigned lineno; if (!GetScriptAndPCArgs(cx, argc, JS_ARGV(cx, vp), &script, &i)) return false; lineno = JS_PCToLineNumber(cx, script, script->code + i); if (!lineno) return false; *vp = INT_TO_JSVAL(lineno); return true; } #ifdef DEBUG static void -UpdateSwitchTableBounds(JSContext *cx, JSScript *script, unsigned offset, +UpdateSwitchTableBounds(JSContext *cx, HandleScript script, unsigned offset, unsigned *start, unsigned *end) { jsbytecode *pc; JSOp op; ptrdiff_t jmplen; int32_t low, high, n; pc = script->code + offset; @@ -1729,17 +1729,17 @@ UpdateSwitchTableBounds(JSContext *cx, J return; } *start = (unsigned)(pc - script->code); *end = *start + (unsigned)(n * jmplen); } static void -SrcNotes(JSContext *cx, JSScript *script, Sprinter *sp) +SrcNotes(JSContext *cx, HandleScript script, Sprinter *sp) { Sprint(sp, "\nSource notes:\n"); Sprint(sp, "%4s %4s %5s %6s %-8s %s\n", "ofs", "line", "pc", "delta", "desc", "args"); Sprint(sp, "---- ---- ----- ------ -------- ------\n"); unsigned offset = 0; unsigned colspan = 0; unsigned lineno = script->lineno; @@ -1846,17 +1846,17 @@ static JSBool Notes(JSContext *cx, unsigned argc, jsval *vp) { Sprinter sprinter(cx); if (!sprinter.init()) return false; jsval *argv = JS_ARGV(cx, vp); for (unsigned i = 0; i < argc; i++) { - JSScript *script = ValueToScript(cx, argv[i]); + RootedScript script (cx, ValueToScript(cx, argv[i])); if (!script) return false; SrcNotes(cx, script, &sprinter); } JSString *str = JS_NewStringCopyZ(cx, sprinter.string()); if (!str) @@ -1867,17 +1867,17 @@ Notes(JSContext *cx, unsigned argc, jsva JS_STATIC_ASSERT(JSTRY_CATCH == 0); JS_STATIC_ASSERT(JSTRY_FINALLY == 1); JS_STATIC_ASSERT(JSTRY_ITER == 2); static const char* const TryNoteNames[] = { "catch", "finally", "iter" }; static JSBool -TryNotes(JSContext *cx, JSScript *script, Sprinter *sp) +TryNotes(JSContext *cx, HandleScript script, Sprinter *sp) { JSTryNote *tn, *tnlimit; if (!script->hasTrynotes()) return true; tn = script->trynotes()->vector; tnlimit = tn + script->trynotes()->length; @@ -1887,21 +1887,19 @@ TryNotes(JSContext *cx, JSScript *script Sprint(sp, " %-7s %6u %8u %8u\n", TryNoteNames[tn->kind], tn->stackDepth, tn->start, tn->start + tn->length); } while (++tn != tnlimit); return true; } static bool -DisassembleScript(JSContext *cx, JSScript *script_, JSFunction *fun, bool lines, bool recursive, +DisassembleScript(JSContext *cx, HandleScript script, JSFunction *fun, bool lines, bool recursive, Sprinter *sp) { - Rooted<JSScript*> script(cx, script_); - if (fun) { Sprint(sp, "flags:"); if (fun->isLambda()) Sprint(sp, " LAMBDA"); if (fun->isHeavyweight()) Sprint(sp, " HEAVYWEIGHT"); if (fun->isExprClosure()) Sprint(sp, " EXPRESSION CLOSURE"); @@ -1923,17 +1921,17 @@ DisassembleScript(JSContext *cx, JSScrip ObjectArray *objects = script->objects(); for (unsigned i = 0; i != objects->length; ++i) { RawObject obj = objects->vector[i]; if (obj->isFunction()) { Sprint(sp, "\n"); RawFunction fun = obj->toFunction(); RootedScript script(cx); fun->maybeGetOrCreateScript(cx, &script); - if (!DisassembleScript(cx, script.get(), fun, lines, recursive, sp)) + if (!DisassembleScript(cx, script, fun, lines, recursive, sp)) return false; } } } return true; } namespace { @@ -1982,17 +1980,17 @@ DisassembleToSprinter(JSContext *cx, uns if (!js_Disassemble(cx, script, p.lines, sprinter)) return false; SrcNotes(cx, script, sprinter); TryNotes(cx, script, sprinter); } } else { for (unsigned i = 0; i < p.argc; i++) { JSFunction *fun; - JSScript *script = ValueToScript(cx, p.argv[i], &fun); + RootedScript script (cx, ValueToScript(cx, p.argv[i], &fun)); if (!script) return false; if (!DisassembleScript(cx, script, fun, p.lines, p.recursive, sprinter)) return false; } } return true; } @@ -2051,17 +2049,17 @@ DisassFile(JSContext *cx, unsigned argc, if (!filename) return false; uint32_t oldopts = JS_GetOptions(cx); JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL); CompileOptions options(cx); options.setUTF8(true) .setFileAndLine(filename.ptr(), 1); - JSScript *script = JS::Compile(cx, thisobj, options, filename.ptr()); + RootedScript script (cx, JS::Compile(cx, thisobj, options, filename.ptr())); JS_SetOptions(cx, oldopts); if (!script) return false; Sprinter sprinter(cx); if (!sprinter.init()) return false; bool ok = DisassembleScript(cx, script, NULL, p.lines, p.recursive, &sprinter); @@ -2424,17 +2422,17 @@ GetPDA(JSContext *cx, unsigned argc, jsv } JS_PutPropertyDescArray(cx, &pda); return ok; } static JSBool GetSLX(JSContext *cx, unsigned argc, jsval *vp) { - JSScript *script; + RootedScript script(cx); script = ValueToScript(cx, argc == 0 ? JSVAL_VOID : vp[2]); if (!script) return false; *vp = INT_TO_JSVAL(js_GetScriptLineExtent(script)); return true; } @@ -2603,20 +2601,20 @@ EvalInContext(JSContext *cx, unsigned ar return false; } if (srclen == 0) { JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(sobj)); return true; } - JSScript *script; + RootedScript script(cx); unsigned lineno; - JS_DescribeScriptedCaller(cx, &script, &lineno); + JS_DescribeScriptedCaller(cx, script.address(), &lineno); jsval rval; { Maybe<JSAutoCompartment> ac; unsigned flags; JSObject *unwrapped = UnwrapObject(sobj, true, &flags); if (flags & Wrapper::CROSS_COMPARTMENT) { sobj = unwrapped; ac.construct(cx, sobj); @@ -3309,17 +3307,17 @@ Snarf(JSContext *cx, unsigned argc, jsva str = JS_ValueToString(cx, JS_ARGV(cx, vp)[0]); if (!str) return false; JSAutoByteString filename(cx, str); if (!filename) return false; /* Get the currently executing script's name. */ - JSScript *script = GetTopScript(cx); + RootedScript script(cx, GetTopScript(cx)); JS_ASSERT(script->filename); const char *pathname = filename.ptr(); #ifdef XP_UNIX FreeOnReturn pnGuard(cx); if (pathname[0] != '/') { pathname = MakeAbsolutePathname(cx, script->filename, pathname); if (!pathname) return false; @@ -3376,34 +3374,34 @@ DecompileFunction(JSContext *cx, unsigne { return DecompileFunctionSomehow(cx, argc, vp, JS_DecompileFunction); } static JSBool DecompileThisScript(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); - JSScript *script = NULL; - if (!JS_DescribeScriptedCaller(cx, &script, NULL)) { + RootedScript script (cx); + if (!JS_DescribeScriptedCaller(cx, script.address(), NULL)) { args.rval().setString(cx->runtime->emptyString); return true; } JSString *result = JS_DecompileScript(cx, script, "test", 0); if (!result) return false; args.rval().setString(result); return true; } static JSBool ThisFilename(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); - JSScript *script = NULL; - if (!JS_DescribeScriptedCaller(cx, &script, NULL) || !script->filename) { + RootedScript script (cx); + if (!JS_DescribeScriptedCaller(cx, script.address(), NULL) || !script->filename) { args.rval().setString(cx->runtime->emptyString); return true; } JSString *filename = JS_NewStringCopyZ(cx, script->filename); if (!filename) return false; args.rval().setString(filename); return true;
--- a/js/src/vm/ForkJoin.h +++ b/js/src/vm/ForkJoin.h @@ -89,16 +89,17 @@ enum ParallelResult { TP_SUCCESS, TP_RET struct ForkJoinOp; // Executes the given |TaskSet| in parallel using the runtime's |ThreadPool|, // returning upon completion. In general, if there are |N| workers in the // threadpool, the problem will be divided into |N+1| slices, as the main // thread will also execute one slice. ParallelResult ExecuteForkJoinOp(JSContext *cx, ForkJoinOp &op); +class PerThreadData; class ForkJoinShared; class AutoRendezvous; class AutoSetForkJoinSlice; namespace gc { struct ArenaLists; } struct ForkJoinSlice { public:
--- a/js/src/vm/GlobalObject.cpp +++ b/js/src/vm/GlobalObject.cpp @@ -401,17 +401,17 @@ GlobalObject::initFunctionAndObjectClass if (self->shouldSplicePrototype(cx) && !self->splicePrototype(cx, tagged)) return NULL; /* * Notify any debuggers about the creation of the script for * |Function.prototype| -- after all initialization, for simplicity. */ RootedScript functionProtoScript(cx, functionProto->nonLazyScript()); - js_CallNewScriptHook(cx, functionProtoScript, functionProto); + CallNewScriptHook(cx, functionProtoScript, functionProto); return functionProto; } GlobalObject * GlobalObject::create(JSContext *cx, Class *clasp) { JS_ASSERT(clasp->flags & JSCLASS_IS_GLOBAL);
--- a/js/src/vm/ObjectImpl.cpp +++ b/js/src/vm/ObjectImpl.cpp @@ -255,16 +255,17 @@ js::ObjectImpl::slotInRange(uint32_t slo * causes stack pointer offsets to go awry and spp to refer to something higher * up the stack. */ MOZ_NEVER_INLINE #endif UnrootedShape js::ObjectImpl::nativeLookup(JSContext *cx, jsid idArg) { + AssertCanGC(); MOZ_ASSERT(isNative()); Shape **spp; RootedId id(cx, idArg); return Shape::search(cx, lastProperty(), id, &spp); } UnrootedShape js::ObjectImpl::nativeLookupNoAllocation(jsid id)
--- a/js/src/vm/SPSProfiler.cpp +++ b/js/src/vm/SPSProfiler.cpp @@ -366,17 +366,17 @@ SPSProfiler::discardMJITCode(mjit::JITSc return; unregisterScript(jscr->script, chunk); for (unsigned i = 0; i < chunk->nInlineFrames; i++) unregisterScript(chunk->inlineFrames()[i].fun->nonLazyScript(), chunk); } void -SPSProfiler::unregisterScript(JSScript *script, mjit::JITChunk *chunk) +SPSProfiler::unregisterScript(UnrootedScript script, mjit::JITChunk *chunk) { JITInfoMap::Ptr ptr = jminfo.lookup(script); if (!ptr) return; JMScriptInfo *info = ptr->value; for (unsigned i = 0; i < info->chunks.length(); i++) { if (info->chunks[i].chunk == chunk) { info->chunks.erase(&info->chunks[i]);
--- a/js/src/vm/SPSProfiler.h +++ b/js/src/vm/SPSProfiler.h @@ -233,17 +233,17 @@ class SPSProfiler bool registerICCode(mjit::JITChunk *chunk, JSScript *script, jsbytecode* pc, void *start, size_t size); jsbytecode *ipToPC(JSScript *script, size_t ip); private: JMChunkInfo *registerScript(mjit::JSActiveFrame *frame, mjit::PCLengthEntry *lenths, mjit::JITChunk *chunk); - void unregisterScript(JSScript *script, mjit::JITChunk *chunk); + void unregisterScript(UnrootedScript script, mjit::JITChunk *chunk); public: #else jsbytecode *ipToPC(JSScript *script, size_t ip) { return NULL; } #endif void setProfilingStack(ProfileEntry *stack, uint32_t *size, uint32_t max); const char *profileString(JSContext *cx, JSScript *script, JSFunction *maybeFun); void onScriptFinalized(JSScript *script);
--- a/js/src/vm/ScopeObject.cpp +++ b/js/src/vm/ScopeObject.cpp @@ -153,17 +153,17 @@ CallObject::create(JSContext *cx, Handle } /* * Create a CallObject for a JSScript that is not initialized to any particular * callsite. This object can either be initialized (with an enclosing scope and * callee) or used as a template for jit compilation. */ CallObject * -CallObject::createTemplateObject(JSContext *cx, JSScript *script) +CallObject::createTemplateObject(JSContext *cx, HandleScript script) { RootedShape shape(cx, script->bindings.callObjShape()); RootedTypeObject type(cx, cx->compartment->getNewType(cx, NULL)); if (!type) return NULL; HeapSlot *slots;
--- a/js/src/vm/ScopeObject.h +++ b/js/src/vm/ScopeObject.h @@ -184,17 +184,17 @@ class CallObject : public ScopeObject create(JSContext *cx, HandleScript script, HandleObject enclosing, HandleFunction callee); public: /* These functions are internal and are exposed only for JITs. */ static CallObject * create(JSContext *cx, HandleShape shape, HandleTypeObject type, HeapSlot *slots); static CallObject * - createTemplateObject(JSContext *cx, JSScript *script); + createTemplateObject(JSContext *cx, HandleScript script); static const uint32_t RESERVED_SLOTS = 2; static CallObject *createForFunction(JSContext *cx, HandleObject enclosing, HandleFunction callee); static CallObject *createForFunction(JSContext *cx, StackFrame *fp); static CallObject *createForStrictEval(JSContext *cx, StackFrame *fp);
--- a/js/src/vm/Stack-inl.h +++ b/js/src/vm/Stack-inl.h @@ -127,19 +127,18 @@ StackFrame::resetInlinePrev(StackFrame * flags_ |= StackFrame::HAS_PREVPC; prev_ = prevfp; prevpc_ = prevpc; prevInline_ = NULL; } inline void StackFrame::initCallFrame(JSContext *cx, JSFunction &callee, - JSScript *script, uint32_t nactual, StackFrame::Flags flagsArg) + UnrootedScript script, uint32_t nactual, StackFrame::Flags flagsArg) { - AutoAssertNoGC nogc; JS_ASSERT((flagsArg & ~(CONSTRUCTING | LOWERED_CALL_APPLY | OVERFLOW_ARGS | UNDERFLOW_ARGS)) == 0); JS_ASSERT(callee.nonLazyScript() == script); /* Initialize stack frame members. */ flags_ = FUNCTION | HAS_PREVPC | HAS_SCOPECHAIN | HAS_BLOCKCHAIN | flagsArg; @@ -410,17 +409,17 @@ StackSpace::getStackLimit(JSContext *cx, ? conservativeEnd_ : NULL; } /*****************************************************************************/ JS_ALWAYS_INLINE StackFrame * ContextStack::getCallFrame(JSContext *cx, MaybeReportError report, const CallArgs &args, - JSFunction *fun, JSScript *script, StackFrame::Flags *flags) const + JSFunction *fun, HandleScript script, StackFrame::Flags *flags) const { mozilla::Maybe<AutoAssertNoGC> maybeNoGC; if (report) AssertCanGC(); else maybeNoGC.construct(); JS_ASSERT(fun->nonLazyScript() == script); @@ -456,17 +455,17 @@ ContextStack::getCallFrame(JSContext *cx Value *dst = firstUnused; Value *src = args.base(); PodCopy(dst, src, ncopy); return reinterpret_cast<StackFrame *>(firstUnused + ncopy); } JS_ALWAYS_INLINE bool ContextStack::pushInlineFrame(JSContext *cx, FrameRegs ®s, const CallArgs &args, - JSFunction &callee, JSScript *script, + JSFunction &callee, HandleScript script, InitialFrameFlags initial, MaybeReportError report) { mozilla::Maybe<AutoAssertNoGC> maybeNoGC; if (report) AssertCanGC(); else maybeNoGC.construct(); @@ -488,29 +487,29 @@ ContextStack::pushInlineFrame(JSContext * to repoint the active registers to regs. See UncachedInlineCall. */ regs.prepareToRun(*fp, script); return true; } JS_ALWAYS_INLINE bool ContextStack::pushInlineFrame(JSContext *cx, FrameRegs ®s, const CallArgs &args, - JSFunction &callee, JSScript *script, + JSFunction &callee, HandleScript script, InitialFrameFlags initial, Value **stackLimit) { AssertCanGC(); if (!pushInlineFrame(cx, regs, args, callee, script, initial)) return false; *stackLimit = space().conservativeEnd_; return true; } JS_ALWAYS_INLINE StackFrame * ContextStack::getFixupFrame(JSContext *cx, MaybeReportError report, - const CallArgs &args, JSFunction *fun, JSScript *script, + const CallArgs &args, JSFunction *fun, HandleScript script, void *ncode, InitialFrameFlags initial, Value **stackLimit) { AssertCanGC(); JS_ASSERT(onTop()); JS_ASSERT(fun->nonLazyScript() == args.callee().toFunction()->nonLazyScript()); JS_ASSERT(fun->nonLazyScript() == script); StackFrame::Flags flags = ToFrameFlags(initial); @@ -543,17 +542,17 @@ inline void ContextStack::popFrameAfterOverflow() { /* Restore the regs to what they were on entry to JSOP_CALL. */ FrameRegs ®s = seg_->regs(); StackFrame *fp = regs.fp(); regs.popFrame(fp->actuals() + fp->numActualArgs()); } -inline JSScript * +inline UnrootedScript ContextStack::currentScript(jsbytecode **ppc, MaybeAllowCrossCompartment allowCrossCompartment) const { AutoAssertNoGC nogc; if (ppc) *ppc = NULL; @@ -563,39 +562,39 @@ ContextStack::currentScript(jsbytecode * FrameRegs ®s = this->regs(); StackFrame *fp = regs.fp(); #ifdef JS_ION if (fp->beginsIonActivation()) { RootedScript script(cx_); ion::GetPcScript(cx_, &script, ppc); if (!allowCrossCompartment && script->compartment() != cx_->compartment) - return NULL; + return UnrootedScript(NULL); return script; } #endif #ifdef JS_METHODJIT mjit::CallSite *inlined = regs.inlined(); if (inlined) { mjit::JITChunk *chunk = fp->jit()->chunk(regs.pc); JS_ASSERT(inlined->inlineIndex < chunk->nInlineFrames); mjit::InlineFrame *frame = &chunk->inlineFrames()[inlined->inlineIndex]; UnrootedScript script = frame->fun->nonLazyScript(); if (!allowCrossCompartment && script->compartment() != cx_->compartment) - return NULL; + return UnrootedScript(NULL); if (ppc) *ppc = script->code + inlined->pcOffset; return script; } #endif UnrootedScript script = fp->script(); if (!allowCrossCompartment && script->compartment() != cx_->compartment) - return NULL; + return UnrootedScript(NULL); if (ppc) *ppc = fp->pcQuadratic(*this); return script; } inline HandleObject ContextStack::currentScriptedScopeChain() const
--- a/js/src/vm/Stack.cpp +++ b/js/src/vm/Stack.cpp @@ -43,17 +43,17 @@ using namespace js; using mozilla::DebugOnly; /*****************************************************************************/ void -StackFrame::initExecuteFrame(JSScript *script, StackFrame *prev, FrameRegs *regs, +StackFrame::initExecuteFrame(UnrootedScript script, StackFrame *prev, FrameRegs *regs, const Value &thisv, JSObject &scopeChain, ExecuteType type) { /* * See encoding of ExecuteType. When GLOBAL isn't set, we are executing a * script in the context of another frame and the frame type is determined * by the context. */ flags_ = type | HAS_SCOPECHAIN | HAS_BLOCKCHAIN | HAS_PREVPC; @@ -67,17 +67,17 @@ StackFrame::initExecuteFrame(JSScript *s dstvp[0] = prev->calleev(); exec = prev->exec; u.evalScript = script; } else { JS_ASSERT(isGlobalFrame()); dstvp[0] = NullValue(); exec.script = script; #ifdef DEBUG - u.evalScript = (JSScript *)0xbad; + u.evalScript = (RawScript)0xbad; #endif } scopeChain_ = &scopeChain; prev_ = prev; prevpc_ = regs ? regs->pc : (jsbytecode *)0xbad; prevInline_ = regs ? regs->inlined() : NULL; blockChain_ = NULL; @@ -1239,17 +1239,17 @@ ContextStack::restoreFrameChain() } /*****************************************************************************/ void StackIter::poisonRegs() { pc_ = (jsbytecode *)0xbad; - script_ = (JSScript *)0xbad; + script_ = (RawScript)0xbad; } void StackIter::popFrame() { AutoAssertNoGC nogc; StackFrame *oldfp = fp_; JS_ASSERT(seg_->contains(oldfp));
--- a/js/src/vm/Stack.h +++ b/js/src/vm/Stack.h @@ -277,22 +277,22 @@ class StackFrame /* Ion frame state */ RUNNING_IN_ION = 0x400000, /* frame is running in Ion */ CALLING_INTO_ION = 0x800000 /* frame is calling into Ion */ }; private: mutable uint32_t flags_; /* bits described by Flags */ union { /* describes what code is executing in a */ - JSScript *script; /* global frame */ + RawScript script; /* global frame */ JSFunction *fun; /* function frame, pre GetScopeChain */ } exec; union { /* describes the arguments of a function */ unsigned nactual; /* for non-eval frames */ - JSScript *evalScript; /* the script of an eval-in-function */ + RawScript evalScript; /* the script of an eval-in-function */ } u; mutable JSObject *scopeChain_; /* if HAS_SCOPECHAIN, current scope chain */ StackFrame *prev_; /* if HAS_PREVPC, previous cx->regs->fp */ void *ncode_; /* for a jit frame, return address for method JIT */ Value rval_; /* if HAS_RVAL, return value of the frame */ StaticBlockObject *blockChain_; /* if HAS_BLOCKCHAIN, innermost let block */ ArgumentsObject *argsObj_; /* if HAS_ARGS_OBJ, the call's arguments object */ jsbytecode *prevpc_; /* if HAS_PREVPC, pc of previous frame*/ @@ -340,23 +340,23 @@ class StackFrame /* * Frame initialization, called by ContextStack operations after acquiring * the raw memory for the frame: */ /* Used for Invoke, Interpret, trace-jit LeaveTree, and method-jit stubs. */ void initCallFrame(JSContext *cx, JSFunction &callee, - JSScript *script, uint32_t nactual, StackFrame::Flags flags); + UnrootedScript script, uint32_t nactual, StackFrame::Flags flags); /* Used for getFixupFrame (for FixupArity). */ void initFixupFrame(StackFrame *prev, StackFrame::Flags flags, void *ncode, unsigned nactual); /* Used for eval. */ - void initExecuteFrame(JSScript *script, StackFrame *prev, FrameRegs *regs, + void initExecuteFrame(UnrootedScript script, StackFrame *prev, FrameRegs *regs, const Value &thisv, JSObject &scopeChain, ExecuteType type); public: /* * Frame prologue/epilogue * * Every stack frame must have 'prologue' called before executing the * first op and 'epilogue' called after executing the last op and before @@ -1187,17 +1187,17 @@ class FrameRegs } /* For EnterMethodJIT: */ void refreshFramePointer(StackFrame *fp) { fp_ = fp; } /* For stubs::CompileFunction, ContextStack: */ - void prepareToRun(StackFrame &fp, JSScript *script) { + void prepareToRun(StackFrame &fp, UnrootedScript script) { pc = script->code; sp = fp.slots() + script->nfixed; fp_ = &fp; inlined_ = NULL; } void setToEndOfScript() { UnrootedScript script = fp()->script(); @@ -1484,17 +1484,17 @@ class ContextStack /* Implementation details of push* public interface. */ StackSegment *pushSegment(JSContext *cx); enum MaybeExtend { CAN_EXTEND = true, CANT_EXTEND = false }; Value *ensureOnTop(JSContext *cx, MaybeReportError report, unsigned nvars, MaybeExtend extend, bool *pushedSeg); inline StackFrame * getCallFrame(JSContext *cx, MaybeReportError report, const CallArgs &args, - JSFunction *fun, JSScript *script, StackFrame::Flags *pflags) const; + JSFunction *fun, HandleScript script, StackFrame::Flags *pflags) const; /* Make pop* functions private since only called by guard classes. */ void popSegment(); friend class InvokeArgsGuard; void popInvokeArgs(const InvokeArgsGuard &iag); friend class FrameGuard; void popFrame(const FrameGuard &fg); friend class GeneratorFrameGuard; @@ -1585,50 +1585,50 @@ class ContextStack bool pushGeneratorFrame(JSContext *cx, JSGenerator *gen, GeneratorFrameGuard *gfg); /* * An "inline frame" may only be pushed from within the top, active * segment. This is the case for calls made inside mjit code and Interpret. * The 'stackLimit' overload updates 'stackLimit' if it changes. */ bool pushInlineFrame(JSContext *cx, FrameRegs ®s, const CallArgs &args, - JSFunction &callee, JSScript *script, + JSFunction &callee, HandleScript script, InitialFrameFlags initial, MaybeReportError report = REPORT_ERROR); bool pushInlineFrame(JSContext *cx, FrameRegs ®s, const CallArgs &args, - JSFunction &callee, JSScript *script, + JSFunction &callee, HandleScript script, InitialFrameFlags initial, Value **stackLimit); void popInlineFrame(FrameRegs ®s); /* Pop a partially-pushed frame after hitting the limit before throwing. */ void popFrameAfterOverflow(); /* * Get the topmost script and optional pc on the stack. By default, this * function only returns a JSScript in the current compartment, returning * NULL if the current script is in a different compartment. This behavior * can be overridden by passing ALLOW_CROSS_COMPARTMENT. */ enum MaybeAllowCrossCompartment { DONT_ALLOW_CROSS_COMPARTMENT = false, ALLOW_CROSS_COMPARTMENT = true }; - inline JSScript *currentScript(jsbytecode **pc = NULL, - MaybeAllowCrossCompartment = DONT_ALLOW_CROSS_COMPARTMENT) const; + inline UnrootedScript currentScript(jsbytecode **pc = NULL, + MaybeAllowCrossCompartment = DONT_ALLOW_CROSS_COMPARTMENT) const; /* Get the scope chain for the topmost scripted call on the stack. */ inline HandleObject currentScriptedScopeChain() const; /* * Called by the methodjit for an arity mismatch. Arity mismatch can be * hot, so getFixupFrame avoids doing call setup performed by jit code when * FixupArity returns. */ StackFrame *getFixupFrame(JSContext *cx, MaybeReportError report, - const CallArgs &args, JSFunction *fun, JSScript *script, + const CallArgs &args, JSFunction *fun, HandleScript script, void *ncode, InitialFrameFlags initial, Value **stackLimit); bool saveFrameChain(); void restoreFrameChain(); /* * As an optimization, the interpreter/mjit can operate on a local * FrameRegs instance repoint the ContextStack to this local instance.
--- a/js/src/vm/Xdr.cpp +++ b/js/src/vm/Xdr.cpp @@ -143,17 +143,17 @@ XDRState<mode>::codeScript(MutableHandle if (!VersionCheck(this)) return false; if (!XDRScript(this, NullPtr(), NullPtr(), NullPtr(), &script)) return false; if (mode == XDR_DECODE) { JS_ASSERT(!script->compileAndGo); - js_CallNewScriptHook(cx(), script, NULL); + CallNewScriptHook(cx(), script, NullPtr()); Debugger::onNewScript(cx(), script, NULL); scriptp.set(script); } return true; } XDRDecoder::XDRDecoder(JSContext *cx, const void *data, uint32_t length,