author | Terrence Cole <terrence@mozilla.com> |
Mon, 05 Nov 2012 10:53:04 -0800 | |
changeset 112357 | 4cee05d5b1ce84770ad35222f7962289c323304f |
parent 112356 | ed1c5d55d104a435e241fa825930ed4697073874 |
child 112358 | 613bfe02f0c1096027e73238a9fcc27ee480531e |
push id | 23812 |
push user | emorley@mozilla.com |
push date | Tue, 06 Nov 2012 14:01:34 +0000 |
treeherder | mozilla-central@f4aeed115e54 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jorendorff |
bugs | 808181 |
milestone | 19.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/gc/Root.h +++ b/js/src/gc/Root.h @@ -72,16 +72,18 @@ class HandleBase {}; template <typename T> class MutableHandleBase {}; } /* namespace js */ namespace JS { +class AutoAssertNoGC; + template <typename T> class MutableHandle; JS_FRIEND_API(void) EnterAssertNoGCScope(); JS_FRIEND_API(void) LeaveAssertNoGCScope(); JS_FRIEND_API(bool) InNoGCScope(); /* * Handle provides an implicit constructor for NullPtr so that, given: @@ -400,26 +402,26 @@ class Return Return(const S &ptr, typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0) : ptr_(ptr) {} Return(NullPtr) : ptr_(NULL) {} /* - * |operator const T &| is the safest way to access a Return<T> without - * rooting it first: it will assert when used outside of an AutoAssertNoGC - * guard scope. + * |get(AutoAssertNoGC &)| is the safest way to access a Return<T> without + * rooting it first: it is impossible to call this method without an + * AutoAssertNoGC in scope, so the compiler will automatically catch any + * incorrect usage. * * Example: * AutoAssertNoGC nogc; - * RawScript script = fun->script(); + * RawScript script = fun->script().get(nogc); */ - operator const T &() const { - JS_ASSERT(InNoGCScope()); + const T &get(AutoAssertNoGC &) const { return ptr_; } /* * |operator->|'s result cannot be stored in a local variable, so it is safe * to use in a CanGC context iff no GC can occur anywhere within the same * expression (generally from one |;| to the next). |operator->| uses a * temporary object as a guard and will assert if a CanGC context is @@ -472,16 +474,17 @@ class Return * * To be rewritten as: * JS_ASSERT(fun->script() == myScript); * * Note: the new order tells C++ to use |Return<JSScript*>::operator=| * instead of direct pointer comparison. */ bool operator==(const T &other) { return ptr_ == other; } + bool operator!=(const T &other) { return ptr_ != other; } bool operator==(const Return<T> &other) { return ptr_ == other.ptr_; } bool operator==(const JS::Handle<T> &other) { return ptr_ == other.get(); } inline bool operator==(const Rooted<T> &other); }; /* * By default, pointers should use the inheritance hierarchy to find their * ThingRootKind. Some pointer types are explicitly set in jspubtd.h so that
--- a/js/src/ion/Bailouts.cpp +++ b/js/src/ion/Bailouts.cpp @@ -80,17 +80,17 @@ GetBailedJSScript(JSContext *cx) AutoAssertNoGC nogc; // Just after the frame conversion, we can safely interpret the ionTop as JS // frame because it targets the bailed JS frame converted to an exit frame. IonJSFrameLayout *frame = reinterpret_cast<IonJSFrameLayout*>(cx->runtime->ionTop); switch (GetCalleeTokenTag(frame->calleeToken())) { case CalleeToken_Function: { JSFunction *fun = CalleeTokenToFunction(frame->calleeToken()); - return fun->script(); + return fun->script().get(nogc); } case CalleeToken_Script: return CalleeTokenToScript(frame->calleeToken()); default: JS_NOT_REACHED("unexpected callee token kind"); return NULL; } } @@ -173,18 +173,18 @@ StackFrame::initFromBailout(JSContext *c } unsigned pcOff = iter.pcOffset(); regs.pc = script()->code + pcOff; if (iter.resumeAfter()) regs.pc = GetNextPc(regs.pc); IonSpew(IonSpew_Bailouts, " new PC is offset %u within script %p (line %d)", - pcOff, (void *)script(), PCToLineNumber(script(), regs.pc)); - JS_ASSERT(exprStackSlots == js_ReconstructStackDepth(cx, script(), regs.pc)); + pcOff, (void *)script().get(nogc), PCToLineNumber(script().get(nogc), regs.pc)); + JS_ASSERT(exprStackSlots == js_ReconstructStackDepth(cx, script().get(nogc), regs.pc)); } static StackFrame * PushInlinedFrame(JSContext *cx, StackFrame *callerFrame) { AssertCanGC(); // Grab the callee object out of the caller's frame, which has already been restored. @@ -658,17 +658,17 @@ ion::ThunkToInterpreter(Value *vp) if (status == Interpret_OSR) { // The interpreter currently does not ask to perform inline OSR, so // this path is unreachable. JS_NOT_REACHED("invalid"); IonSpew(IonSpew_Bailouts, "Performing inline OSR %s:%d", cx->fp()->script()->filename, - PCToLineNumber(cx->fp()->script(), cx->regs().pc)); + PCToLineNumber(cx->fp()->script().unsafeGet(), cx->regs().pc)); // We want to OSR again. We need to avoid the problem where frequent // bailouts cause recursive nestings of Interpret and EnterIon. The // interpreter therefore shortcuts out, and now we're responsible for // completing the OSR inline. // // Note that we set runningInIon so that if we re-enter C++ from within // the inlined OSR, StackIter will know to traverse these frames.
--- a/js/src/ion/IonBuilder.cpp +++ b/js/src/ion/IonBuilder.cpp @@ -144,17 +144,17 @@ IonBuilder::CFGState::LookupSwitch(jsbyt return state; } JSFunction * IonBuilder::getSingleCallTarget(uint32 argc, jsbytecode *pc) { AutoAssertNoGC nogc; - types::StackTypeSet *calleeTypes = oracle->getCallTarget(script(), argc, pc); + types::StackTypeSet *calleeTypes = oracle->getCallTarget(script().get(nogc), argc, pc); if (!calleeTypes) return NULL; RawObject obj = calleeTypes->getSingleton(); if (!obj || !obj->isFunction()) return NULL; return obj->toFunction();
--- a/js/src/ion/IonCaches.cpp +++ b/js/src/ion/IonCaches.cpp @@ -1624,17 +1624,17 @@ GenerateScopeChainGuard(MacroAssembler & AutoAssertNoGC nogc; if (scopeObj->isCall()) { // We can skip a guard on the call object if the script's bindings are // guaranteed to be immutable (and thus cannot introduce shadowing // variables). CallObject *callObj = &scopeObj->asCall(); if (!callObj->isForEval()) { RawFunction fun = &callObj->callee(); - RawScript script = fun->script(); + RawScript script = fun->script().get(nogc); if (!script->funHasExtensibleScope) return; } } else if (scopeObj->isGlobal()) { // If this is the last object on the scope walk, and the property we've // found is not configurable, then we don't need a shape guard because // the shape cannot be removed. if (shape && !shape->configurable())
--- a/js/src/ion/IonFrames.cpp +++ b/js/src/ion/IonFrames.cpp @@ -924,17 +924,17 @@ InlineFrameIterator::findNextFrame() // Skip extra slots. while (si_.moreSlots()) si_.skip(); si_.nextFrame(); callee_ = funval.toObject().toFunction(); - script_ = callee_->script(); + script_ = callee_->script().get(nogc); pc_ = script_->code + si_.pcOffset(); } framesRead_++; } InlineFrameIterator InlineFrameIterator::operator++()
--- a/js/src/ion/IonFrames.h +++ b/js/src/ion/IonFrames.h @@ -67,17 +67,17 @@ CalleeTokenToScript(CalleeToken token) static inline JSScript * ScriptFromCalleeToken(CalleeToken token) { AutoAssertNoGC nogc; switch (GetCalleeTokenTag(token)) { case CalleeToken_Script: return CalleeTokenToScript(token); case CalleeToken_Function: - return CalleeTokenToFunction(token)->script(); + return CalleeTokenToFunction(token)->script().get(nogc); } JS_NOT_REACHED("invalid callee token tag"); return NULL; } // In between every two frames lies a small header describing both frames. This // header, minimally, contains a returnAddress word and a descriptor word. The // descriptor describes the size and type of the previous frame, whereas the
--- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -7074,19 +7074,19 @@ JS_DescribeScriptedCaller(JSContext *cx, if (lineno) *lineno = 0; ScriptFrameIter i(cx); if (i.done()) return JS_FALSE; if (script) - *script = i.script(); + *script = i.script().get(nogc); if (lineno) - *lineno = js::PCToLineNumber(i.script(), i.pc()); + *lineno = js::PCToLineNumber(i.script().get(nogc), i.pc()); return JS_TRUE; } #ifdef JS_THREADSAFE static PRStatus CallOnce(void *func) { JSInitCallback init = JS_DATA_TO_FUNC_PTR(JSInitCallback, func);
--- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -613,17 +613,17 @@ PopulateReportBlame(JSContext *cx, JSErr * Walk stack until we find a frame that is associated with a non-builtin * rather than a builtin frame. */ NonBuiltinScriptFrameIter iter(cx); if (iter.done()) return; report->filename = iter.script()->filename; - report->lineno = PCToLineNumber(iter.script(), iter.pc(), &report->column); + report->lineno = PCToLineNumber(iter.script().get(nogc), iter.pc(), &report->column); report->originPrincipals = iter.script()->originPrincipals; } /* * We don't post an exception in this case, since doing so runs into * complications of pre-allocating an exception object which required * running the Exception class initializer early etc. * Instead we just invoke the errorReporter with an "Out Of Memory"
--- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -447,17 +447,17 @@ JS_ReleaseFunctionLocalNameArray(JSConte { cx->tempLifoAlloc().release(mark); } JS_PUBLIC_API(JSScript *) JS_GetFunctionScript(JSContext *cx, JSFunction *fun) { AutoAssertNoGC nogc; - return fun->maybeScript(); + return fun->maybeScript().get(nogc); } JS_PUBLIC_API(JSNative) JS_GetFunctionNative(JSContext *cx, JSFunction *fun) { return fun->maybeNative(); } @@ -496,17 +496,17 @@ JS_BrokenFrameIterator(JSContext *cx, JS *iteratorp = Jsvalify(fp); return *iteratorp; } JS_PUBLIC_API(JSScript *) JS_GetFrameScript(JSContext *cx, JSStackFrame *fpArg) { AutoAssertNoGC nogc; - return Valueify(fpArg)->script(); + return Valueify(fpArg)->script().get(nogc); } JS_PUBLIC_API(jsbytecode *) JS_GetFramePC(JSContext *cx, JSStackFrame *fpArg) { /* * This API is used to compute the line number for jsd and XPConnect * exception handling backtraces. Once the stack gets really deep, the @@ -541,17 +541,17 @@ JS_SetTopFrameAnnotation(JSContext *cx, // Note that if this frame is running in Ion, the actual calling frame // could be inlined or a callee and thus we won't have a correct |fp|. // To account for this, ion::InvalidationBailout will transfer an // annotation from the old cx->fp() to the new top frame. This works // because we will never EnterIon on a frame with an annotation. fp->setAnnotation(annotation); - RawScript script = fp->script(); + RawScript script = fp->script().get(nogc); ReleaseAllJITCode(cx->runtime->defaultFreeOp()); // Ensure that we'll never try to compile this again. JS_ASSERT(!script->hasIonScript()); script->ion = ION_DISABLED_SCRIPT; } @@ -1010,17 +1010,17 @@ GetAtomTotalSize(JSContext *cx, JSAtom * JS_PUBLIC_API(size_t) JS_GetFunctionTotalSize(JSContext *cx, JSFunction *fun) { AutoAssertNoGC nogc; size_t nbytes = sizeof *fun; nbytes += JS_GetObjectTotalSize(cx, fun); if (fun->isInterpreted()) - nbytes += JS_GetScriptTotalSize(cx, fun->script()); + nbytes += JS_GetScriptTotalSize(cx, fun->script().get(nogc)); if (fun->displayAtom()) nbytes += GetAtomTotalSize(cx, fun->displayAtom()); return nbytes; } JS_PUBLIC_API(size_t) JS_GetScriptTotalSize(JSContext *cx, JSScript *script) { @@ -1202,18 +1202,18 @@ js_CallContextDebugHandler(JSContext *cx JS_PUBLIC_API(StackDescription *) JS::DescribeStack(JSContext *cx, unsigned maxFrames) { AutoAssertNoGC nogc; Vector<FrameDescription> frames(cx); for (ScriptFrameIter i(cx); !i.done(); ++i) { FrameDescription desc; - desc.script = i.script(); - desc.lineno = PCToLineNumber(i.script(), i.pc()); + desc.script = i.script().get(nogc); + desc.lineno = PCToLineNumber(i.script().get(nogc), i.pc()); desc.fun = i.maybeCallee(); if (!frames.append(desc)) return NULL; if (frames.length() == maxFrames) break; } StackDescription *desc = js_new<StackDescription>();
--- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -125,17 +125,17 @@ fun_getProperty(JSContext *cx, HandleObj #ifdef JS_ION AutoAssertNoGC nogc; // If this script hasn't been compiled yet, make sure it will never // be compiled. IonMonkey does not guarantee |f.arguments| can be // fully recovered, so we try to mitigate observing this behavior by // detecting its use early. - RawScript script = iter.script(); + RawScript script = iter.script().get(nogc); if (!script->hasIonScript()) ion::ForbidCompilation(cx, script); #endif vp.setObject(*argsobj); return true; } @@ -1118,17 +1118,17 @@ fun_isGenerator(JSContext *cx, unsigned RawFunction fun; if (!IsFunctionObject(vp[1], &fun)) { JS_SET_RVAL(cx, vp, BooleanValue(false)); return true; } bool result = false; if (fun->isInterpreted()) { - RawScript script = fun->script(); + RawScript script = fun->script().get(nogc); JS_ASSERT(script->length != 0); result = script->isGenerator; } JS_SET_RVAL(cx, vp, BooleanValue(result)); return true; } #endif
--- a/js/src/jsinferinlines.h +++ b/js/src/jsinferinlines.h @@ -679,17 +679,17 @@ UseNewTypeForClone(JSFunction *fun) * * Each instance of the innermost function will have a different wrapped * initialize method. We capture this, along with similar cases, by looking * for short scripts which use both .apply and arguments. For such scripts, * whenever creating a new instance of the function we both give that * instance a singleton type and clone the underlying script. */ - RawScript script = fun->script(); + RawScript script = fun->script().get(nogc); if (script->length >= 50) return false; if (script->hasConsts() || script->hasObjects() || script->hasRegexps() || fun->isHeavyweight()) return false; bool hasArguments = false; @@ -881,17 +881,17 @@ TypeScript::GetPcScript(JSContext *cx, M { AutoAssertNoGC nogc; #ifdef JS_ION if (cx->fp()->beginsIonActivation()) { ion::GetPcScript(cx, script, pc); return; } #endif - script.set(cx->fp()->script()); + script.set(cx->fp()->script().get(nogc)); *pc = cx->regs().pc; } /* static */ inline void TypeScript::MonitorOverflow(JSContext *cx) { RootedScript script(cx); jsbytecode *pc;
--- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -5255,16 +5255,17 @@ js_GetterOnlyPropertyStub(JSContext *cx, * Routines to print out values during debugging. These are FRIEND_API to help * the debugger find them and to support temporarily hacking js_Dump* calls * into other code. */ void dumpValue(const Value &v) { + AutoAssertNoGC nogc; if (v.isNull()) fprintf(stderr, "null"); else if (v.isUndefined()) fprintf(stderr, "undefined"); else if (v.isInt32()) fprintf(stderr, "%d", v.toInt32()); else if (v.isDouble()) fprintf(stderr, "%g", v.toDouble()); @@ -5274,17 +5275,17 @@ dumpValue(const Value &v) JSFunction *fun = v.toObject().toFunction(); if (fun->displayAtom()) { fputs("<function ", stderr); FileEscapedString(stderr, fun->displayAtom(), 0); } else { fputs("<unnamed function", stderr); } if (fun->isInterpreted()) { - JSScript *script = fun->script(); + JSScript *script = fun->script().get(nogc); fprintf(stderr, " (%s:%u)", script->filename ? script->filename : "", script->lineno); } fprintf(stderr, " at %p>", (void *) fun); } else if (v.isObject()) { JSObject *obj = &v.toObject(); Class *clasp = obj->getClass(); fprintf(stderr, "<%s%s at %p>", @@ -5540,19 +5541,19 @@ JS_FRIEND_API(void) js_DumpBacktrace(JSContext *cx) { AutoAssertNoGC nogc; Sprinter sprinter(cx); sprinter.init(); size_t depth = 0; for (StackIter i(cx); !i.done(); ++i, ++depth) { if (i.isScript()) { - const char *filename = JS_GetScriptFilename(cx, i.script()); - unsigned line = JS_PCToLineNumber(cx, i.script(), i.pc()); - RawScript script = i.script(); + const char *filename = JS_GetScriptFilename(cx, i.script().get(nogc)); + unsigned line = JS_PCToLineNumber(cx, i.script().get(nogc), i.pc()); + RawScript script = i.script().get(nogc); sprinter.printf("#%d %14p %s:%d (%p @ %d)\n", depth, (i.isIon() ? 0 : i.interpFrame()), filename, line, script, i.pc() - script->code); } else { sprinter.printf("#%d ???\n", depth); } } fprintf(stdout, "%s", sprinter.string());
--- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -1841,17 +1841,17 @@ JSScript::enclosingScriptsCompiledSucces * 'script' field will be NULL until the enclosing script successfully * compiles. Thus, we can detect failed compilation by looking for * JSFunctions in the enclosingScope chain without scripts. */ RawObject enclosing = enclosingScope_; while (enclosing) { if (enclosing->isFunction()) { RawFunction fun = enclosing->toFunction(); - if (!fun->script()) + if (!fun->script().get(nogc)) return false; enclosing = fun->script()->enclosingScope_; } else { enclosing = enclosing->asStaticBlock().enclosingStaticScope(); } } return true; } @@ -2109,36 +2109,36 @@ js_GetScriptLineExtent(RawScript script) } namespace js { unsigned CurrentLine(JSContext *cx) { AutoAssertNoGC nogc; - return PCToLineNumber(cx->fp()->script(), cx->regs().pc); + return PCToLineNumber(cx->fp()->script().get(nogc), cx->regs().pc); } void CurrentScriptFileLineOriginSlow(JSContext *cx, const char **file, unsigned *linenop, JSPrincipals **origin) { AutoAssertNoGC nogc; NonBuiltinScriptFrameIter iter(cx); if (iter.done()) { *file = NULL; *linenop = 0; *origin = NULL; return; } - RawScript script = iter.script(); + RawScript script = iter.script().get(nogc); *file = script->filename; - *linenop = PCToLineNumber(iter.script(), iter.pc()); + *linenop = PCToLineNumber(iter.script().get(nogc), iter.pc()); *origin = script->originPrincipals; } } /* namespace js */ template <class T> static inline T * Rebase(RawScript dst, RawScript src, T *srcp)
--- a/js/src/jsscriptinlines.h +++ b/js/src/jsscriptinlines.h @@ -43,17 +43,17 @@ CurrentScriptFileLineOriginSlow(JSContex inline void CurrentScriptFileLineOrigin(JSContext *cx, const char **file, unsigned *linenop, JSPrincipals **origin, LineOption opt = NOT_CALLED_FROM_JSOP_EVAL) { if (opt == CALLED_FROM_JSOP_EVAL) { AutoAssertNoGC nogc; JS_ASSERT(JSOp(*cx->regs().pc) == JSOP_EVAL); JS_ASSERT(*(cx->regs().pc + JSOP_EVAL_LENGTH) == JSOP_LINENO); - RawScript script = cx->fp()->script(); + RawScript script = cx->fp()->script().get(nogc); *file = script->filename; *linenop = GET_UINT16(cx->regs().pc + JSOP_EVAL_LENGTH); *origin = script->originPrincipals; return; } CurrentScriptFileLineOriginSlow(cx, file, linenop, origin); }
--- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -2364,17 +2364,17 @@ LambdaIsGetElem(JSObject &lambda) if (!lambda.isFunction()) return NULL; JSFunction *fun = lambda.toFunction(); if (!fun->isInterpreted()) return NULL; - RawScript script = fun->script(); + RawScript script = fun->script().get(nogc); jsbytecode *pc = script->code; /* * JSOP_GETALIASEDVAR tells us exactly where to find the base object 'b'. * Rule out the (unlikely) possibility of a heavyweight function since it * would make our scope walk off by 1. */ if (JSOp(*pc) != JSOP_GETALIASEDVAR || fun->isHeavyweight())
--- a/js/src/jsworkers.cpp +++ b/js/src/jsworkers.cpp @@ -83,40 +83,40 @@ js::CancelOffThreadIonCompile(JSCompartm if (!ion) return; AutoLockWorkerThreadState lock(compartment->rt); /* Cancel any pending entries for which processing hasn't started. */ for (size_t i = 0; i < state.ionWorklist.length(); i++) { ion::IonBuilder *builder = state.ionWorklist[i]; - if (CompiledScriptMatches(compartment, script, builder->script())) { + if (CompiledScriptMatches(compartment, script, builder->script().unsafeGet())) { FinishOffThreadIonCompile(builder); state.ionWorklist[i--] = state.ionWorklist.back(); state.ionWorklist.popBack(); } } /* Wait for in progress entries to finish up. */ for (size_t i = 0; i < state.numThreads; i++) { const WorkerThread &helper = state.threads[i]; while (helper.ionBuilder && - CompiledScriptMatches(compartment, script, helper.ionBuilder->script())) + CompiledScriptMatches(compartment, script, helper.ionBuilder->script().unsafeGet())) { helper.ionBuilder->cancel(); state.wait(WorkerThreadState::MAIN); } } ion::OffThreadCompilationVector &compilations = ion->finishedOffThreadCompilations(); /* Cancel code generation for any completed entries. */ for (size_t i = 0; i < compilations.length(); i++) { ion::IonBuilder *builder = compilations[i]; - if (CompiledScriptMatches(compartment, script, builder->script())) { + if (CompiledScriptMatches(compartment, script, builder->script().unsafeGet())) { ion::FinishOffThreadBuilder(builder); compilations[i--] = compilations.back(); compilations.popBack(); } } } bool
--- a/js/src/methodjit/BaseAssembler.h +++ b/js/src/methodjit/BaseAssembler.h @@ -141,17 +141,17 @@ class Assembler : public ValueAssembler #endif sps(sps), vmframe(vmframe), pc(NULL) { AutoAssertNoGC nogc; startLabel = label(); if (vmframe) - sps->setPushed(vmframe->script()); + sps->setPushed(vmframe->script().get(nogc)); } Assembler(MJITInstrumentation *sps, jsbytecode **pc) : callPatches(SystemAllocPolicy()), availInCall(0), extraStackSpace(0), stackAdjust(0), #ifdef DEBUG
--- a/js/src/methodjit/BaseCompiler.h +++ b/js/src/methodjit/BaseCompiler.h @@ -133,17 +133,17 @@ class LinkerHelper : public JSC::LinkBuf m_size = masm.size(); // must come after call to executableAllocAndCopy()! return pool; } JSC::CodeLocationLabel finalize(VMFrame &f) { AutoAssertNoGC nogc; masm.finalize(*this); JSC::CodeLocationLabel label = finalizeCodeAddendum(); - Probes::registerICCode(f.cx, f.chunk(), f.script(), f.pc(), + Probes::registerICCode(f.cx, f.chunk(), f.script().get(nogc), f.pc(), label.executableAddress(), masm.size()); return label; } void maybeLink(MaybeJump jump, JSC::CodeLocationLabel label) { if (!jump.isSet()) return; link(jump.get(), label);
--- a/js/src/methodjit/InvokeHelpers.cpp +++ b/js/src/methodjit/InvokeHelpers.cpp @@ -680,24 +680,24 @@ stubs::ScriptDebugEpilogue(VMFrame &f) if (!js::ScriptDebugEpilogue(f.cx, f.fp(), JS_TRUE)) THROW(); } void JS_FASTCALL stubs::ScriptProbeOnlyPrologue(VMFrame &f) { AutoAssertNoGC nogc; - Probes::enterScript(f.cx, f.script(), f.script()->function(), f.fp()); + Probes::enterScript(f.cx, f.script().get(nogc), f.script()->function(), f.fp()); } void JS_FASTCALL stubs::ScriptProbeOnlyEpilogue(VMFrame &f) { AutoAssertNoGC nogc; - Probes::exitScript(f.cx, f.script(), f.script()->function(), f.fp()); + Probes::exitScript(f.cx, f.script().get(nogc), f.script()->function(), f.fp()); } void JS_FASTCALL stubs::CrossChunkShim(VMFrame &f, void *edge_) { AssertCanGC(); DebugOnly<CrossChunkEdge*> edge = (CrossChunkEdge *) edge_;
--- a/js/src/methodjit/MonoIC.cpp +++ b/js/src/methodjit/MonoIC.cpp @@ -879,17 +879,17 @@ class CallCompiler : public BaseCompiler /* * Write the rejoin state to indicate this is a compilation call made * from an IC (the recompiler cannot detect calls made from ICs * automatically). */ masm.storePtr(ImmPtr((void *) ic.frameSize.rejoinState(f.pc(), false)), FrameAddress(offsetof(VMFrame, stubRejoin))); - masm.bumpStubCount(f.script(), f.pc(), Registers::tempCallReg()); + masm.bumpStubCount(f.script().get(nogc), f.pc(), Registers::tempCallReg()); /* Try and compile. On success we get back the nmap pointer. */ void *compilePtr = JS_FUNC_TO_DATA_PTR(void *, stubs::CompileFunction); DataLabelPtr inlined; if (ic.frameSize.isStatic()) { masm.move(Imm32(ic.frameSize.staticArgc()), Registers::ArgReg1); masm.fallibleVMCall(cx->typeInferenceEnabled(), compilePtr, f.regs.pc, &inlined, ic.frameSize.staticLocalSlots()); @@ -996,17 +996,17 @@ class CallCompiler : public BaseCompiler RegisterID t0 = tempRegs.takeAnyReg().reg(); /* Guard that it's actually a function object. */ Jump claspGuard = masm.testObjClass(Assembler::NotEqual, ic.funObjReg, t0, &FunctionClass); /* Guard that it's the same script. */ Address scriptAddr(ic.funObjReg, JSFunction::offsetOfNativeOrScript()); Jump funGuard = masm.branchPtr(Assembler::NotEqual, scriptAddr, - ImmPtr(obj->toFunction()->script())); + ImmPtr(obj->toFunction()->script().get(nogc))); Jump done = masm.jump(); LinkerHelper linker(masm, JSC::JAEGER_CODE); JSC::ExecutablePool *ep = poolForSize(linker, CallICInfo::Pool_ClosureStub); if (!ep) return false; ic.hasJsFunCheck = true; @@ -1256,17 +1256,17 @@ class CallCompiler : public BaseCompiler THROWV(NULL); } #endif return NULL; } AutoAssertNoGC nogc; JS_ASSERT(fun); - JSScript *script = fun->script(); + JSScript *script = fun->script().get(nogc); JS_ASSERT(script); uint32_t flags = callingNew ? StackFrame::CONSTRUCTING : 0; if (!ic.hit) { ic.hit = true; return ucr.codeAddr; } @@ -1427,17 +1427,17 @@ void ic::GenerateArgumentCheckStub(VMFrame &f) { AutoAssertNoGC nogc; JS_ASSERT(f.cx->typeInferenceEnabled()); JITScript *jit = f.jit(); StackFrame *fp = f.fp(); JSFunction *fun = fp->fun(); - JSScript *script = fun->script(); + JSScript *script = fun->script().get(nogc); if (jit->argsCheckPool) jit->resetArgsCheck(); Assembler masm; Vector<Jump> mismatches(f.cx); if (!f.fp()->isConstructing()) {
--- a/js/src/methodjit/PolyIC.cpp +++ b/js/src/methodjit/PolyIC.cpp @@ -1075,17 +1075,17 @@ class GetPropCompiler : public PICStubCo if (tempRegs.hasReg(pic.objReg)) { tempRegs.takeReg(pic.objReg); } else { holdObjReg = tempRegs.takeAnyReg().reg(); masm.move(pic.objReg, holdObjReg); } RegisterID t0 = tempRegs.takeAnyReg().reg(); - masm.bumpStubCount(f.script(), f.pc(), t0); + masm.bumpStubCount(f.script().get(nogc), f.pc(), t0); /* * Use three values above sp on the stack for use by the call to store * the object and id being passed into the call as handles and to store * the resulting value. Temporary slots are used by GETPROP for this, * plus there is extra room on the stack reserved for a callee frame. */ int32_t initialFrameDepth = f.regs.sp - f.fp()->slots() + 3; @@ -1189,17 +1189,17 @@ class GetPropCompiler : public PICStubCo if (tempRegs.hasReg(pic.objReg)) { tempRegs.takeReg(pic.objReg); } else { holdObjReg = tempRegs.takeAnyReg().reg(); masm.move(pic.objReg, holdObjReg); } RegisterID t0 = tempRegs.takeAnyReg().reg(); - masm.bumpStubCount(f.script(), f.pc(), t0); + masm.bumpStubCount(f.script().get(nogc), f.pc(), t0); /* * A JSNative has the following signature: * * JSBool native(JSContext *cx, unsigned argc, Value *vp); * * Since we are calling a getter, argc is always 0. vp must point to two * values, the callee and the holder. We use vp == sp to avoid clobbering
--- a/js/src/methodjit/Retcon.cpp +++ b/js/src/methodjit/Retcon.cpp @@ -343,17 +343,17 @@ ClearAllFrames(JSCompartment *compartmen for (VMFrame *f = compartment->rt->jaegerRuntime().activeFrame(); f != NULL; f = f->previous) { if (f->entryfp->compartment() != compartment) continue; - Recompiler::patchFrame(compartment, f, f->fp()->script()); + Recompiler::patchFrame(compartment, f, f->fp()->script().get(nogc)); // Clear ncode values from all frames associated with the VMFrame. // Patching the VMFrame's return address will cause all its frames to // finish in the interpreter, unless the interpreter enters one of the // intermediate frames at a loop boundary (where EnterMethodJIT will // overwrite ncode). However, leaving stale values for ncode in stack // frames can confuse the recompiler, which may see the VMFrame before // it has resumed execution.
--- a/js/src/methodjit/StubCalls.cpp +++ b/js/src/methodjit/StubCalls.cpp @@ -832,17 +832,17 @@ stubs::TriggerIonCompile(VMFrame &f) } #endif void JS_FASTCALL stubs::RecompileForInline(VMFrame &f) { AutoAssertNoGC nogc; ExpandInlineFrames(f.cx->compartment); - Recompiler::clearStackReferences(f.cx->runtime->defaultFreeOp(), f.script()); + Recompiler::clearStackReferences(f.cx->runtime->defaultFreeOp(), f.script().get(nogc)); f.jit()->destroyChunk(f.cx->runtime->defaultFreeOp(), f.chunkIndex(), /* resetUses = */ false); } void JS_FASTCALL stubs::Trap(VMFrame &f, uint32_t trapTypes) { Value rval; @@ -1300,17 +1300,17 @@ FindNativeCode(VMFrame &f, jsbytecode *t return NULL; } void * JS_FASTCALL stubs::LookupSwitch(VMFrame &f, jsbytecode *pc) { AutoAssertNoGC nogc; jsbytecode *jpc = pc; - JSScript *script = f.fp()->script(); + JSScript *script = f.fp()->script().get(nogc); /* This is correct because the compiler adjusts the stack beforehand. */ Value lval = f.regs.sp[-1]; if (!lval.isPrimitive()) return FindNativeCode(f, pc + GET_JUMP_OFFSET(pc)); JS_ASSERT(pc[0] == JSOP_LOOKUPSWITCH); @@ -1626,17 +1626,17 @@ stubs::CheckArgumentTypes(VMFrame &f) #ifdef DEBUG void JS_FASTCALL stubs::AssertArgumentTypes(VMFrame &f) { AutoAssertNoGC nogc; StackFrame *fp = f.fp(); JSFunction *fun = fp->fun(); - RawScript script = fun->script(); + RawScript script = fun->script().get(nogc); /* * Don't check the type of 'this' for constructor frames, the 'this' value * has not been constructed yet. */ if (!fp->isConstructing()) { Type type = GetValueType(f.cx, fp->thisValue()); if (!TypeScript::ThisTypes(script)->hasType(type)) @@ -1671,17 +1671,17 @@ stubs::InvariantFailure(VMFrame &f, void * recompilation we will return to the call's rejoin point. */ void *repatchCode = f.scratch; JS_ASSERT(repatchCode); void **frameAddr = f.returnAddressLocation(); *frameAddr = repatchCode; /* Recompile the outermost script, and don't hoist any bounds checks. */ - RawScript script = f.fp()->script(); + RawScript script = f.fp()->script().get(nogc); JS_ASSERT(!script->failedBoundsCheck); script->failedBoundsCheck = true; ExpandInlineFrames(f.cx->compartment); mjit::Recompiler::clearStackReferences(f.cx->runtime->defaultFreeOp(), script); mjit::ReleaseScriptCode(f.cx->runtime->defaultFreeOp(), script);
--- a/js/src/vm/ArgumentsObject-inl.h +++ b/js/src/vm/ArgumentsObject-inl.h @@ -69,33 +69,33 @@ ArgumentsObject::setArg(unsigned i, cons inline const Value & ArgumentsObject::element(uint32_t i) const { AutoAssertNoGC nogc; JS_ASSERT(!isElementDeleted(i)); const Value &v = data()->args[i]; if (v.isMagic(JS_FORWARD_TO_CALL_OBJECT)) { CallObject &callobj = getFixedSlot(MAYBE_CALL_SLOT).toObject().asCall(); - for (AliasedFormalIter fi(callobj.callee().script()); ; fi++) { + for (AliasedFormalIter fi(callobj.callee().script().get(nogc)); ; fi++) { if (fi.frameIndex() == i) return callobj.aliasedVar(fi); } } return v; } inline void ArgumentsObject::setElement(uint32_t i, const Value &v) { AutoAssertNoGC nogc; JS_ASSERT(!isElementDeleted(i)); HeapValue &lhs = data()->args[i]; if (lhs.isMagic(JS_FORWARD_TO_CALL_OBJECT)) { CallObject &callobj = getFixedSlot(MAYBE_CALL_SLOT).toObject().asCall(); - for (AliasedFormalIter fi(callobj.callee().script()); ; fi++) { + for (AliasedFormalIter fi(callobj.callee().script().get(nogc)); ; fi++) { if (fi.frameIndex() == i) { callobj.setAliasedVar(fi, v); return; } } } lhs = v; }
--- a/js/src/vm/ArgumentsObject.cpp +++ b/js/src/vm/ArgumentsObject.cpp @@ -44,17 +44,17 @@ CopyStackFrameArguments(const StackFrame (dst++)->init(*src++); } } /* static */ void ArgumentsObject::MaybeForwardToCallObject(StackFrame *fp, JSObject *obj, ArgumentsData *data) { AutoAssertNoGC nogc; - RawScript script = fp->script(); + RawScript script = fp->script().get(nogc); if (fp->fun()->isHeavyweight() && script->argsObjAliasesFormals()) { obj->initFixedSlot(MAYBE_CALL_SLOT, ObjectValue(fp->callObj())); for (AliasedFormalIter fi(script); fi; fi++) data->args[fi.frameIndex()] = MagicValue(JS_FORWARD_TO_CALL_OBJECT); } } struct CopyStackFrameArgs
--- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -1190,17 +1190,17 @@ Debugger::onSingleStep(JSContext *cx, Va * anyway, to make sure the count has the correct non-zero value. * * The converse --- ensuring that we do receive traps when we should --- can * be done with unit tests. */ { AutoAssertNoGC nogc; uint32_t stepperCount = 0; - JSScript *trappingScript = fp->script(); + JSScript *trappingScript = fp->script().get(nogc); GlobalObject *global = &fp->global(); if (GlobalObject::DebuggerVector *debuggers = global->getDebuggers()) { for (Debugger **p = debuggers->begin(); p != debuggers->end(); p++) { Debugger *dbg = *p; for (FrameMap::Range r = dbg->frames.all(); !r.empty(); r.popFront()) { StackFrame *frame = r.front().key; JSObject *frameobj = r.front().value; if (frame->script() == trappingScript && @@ -3457,17 +3457,17 @@ DebuggerFrame_getScript(JSContext *cx, u return true; } static JSBool DebuggerFrame_getOffset(JSContext *cx, unsigned argc, Value *vp) { THIS_FRAME(cx, argc, vp, "get offset", args, thisobj, fp); AutoAssertNoGC nogc; - RawScript script = fp->script(); + RawScript script = fp->script().get(nogc); jsbytecode *pc = fp->pcQuadratic(cx); JS_ASSERT(script->code <= pc); JS_ASSERT(pc < script->code + script->length); size_t offset = pc - script->code; args.rval().setNumber(double(offset)); return true; }
--- a/js/src/vm/SPSProfiler.cpp +++ b/js/src/vm/SPSProfiler.cpp @@ -354,22 +354,23 @@ SPSProfiler::registerICCode(mjit::JITChu JS_ASSERT(ptr); return ptr->value->ics.append(ICInfo(base, size, pc)); } void SPSProfiler::discardMJITCode(mjit::JITScript *jscr, mjit::JITChunk *chunk, void* address) { + AutoAssertNoGC nogc; if (!jminfo.initialized()) return; unregisterScript(jscr->script, chunk); for (unsigned i = 0; i < chunk->nInlineFrames; i++) - unregisterScript(chunk->inlineFrames()[i].fun->script(), chunk); + unregisterScript(chunk->inlineFrames()[i].fun->script().get(nogc), chunk); } void SPSProfiler::unregisterScript(JSScript *script, mjit::JITChunk *chunk) { JITInfoMap::Ptr ptr = jminfo.lookup(script); if (!ptr) return;
--- a/js/src/vm/ScopeObject.cpp +++ b/js/src/vm/ScopeObject.cpp @@ -81,17 +81,17 @@ StaticScopeIter::block() const return obj->asStaticBlock(); } JSScript * StaticScopeIter::funScript() const { AutoAssertNoGC nogc; JS_ASSERT(type() == FUNCTION); - return obj->toFunction()->script(); + return obj->toFunction()->script().get(nogc); } /*****************************************************************************/ StaticScopeIter js::ScopeCoordinateToStaticScope(JSScript *script, jsbytecode *pc) { JS_ASSERT(pc >= script->code && pc < script->code + script->length); @@ -1203,17 +1203,17 @@ class DebugScopeProxy : public BaseProxy return false; AutoAssertNoGC nogc; unsigned i = shape->shortid(); if (block.staticBlock().isAliased(i)) return false; if (maybefp) { - RawScript script = maybefp->script(); + RawScript script = maybefp->script().get(nogc); unsigned local = block.slotToLocalIndex(script->bindings, shape->slot()); if (action == GET) *vp = maybefp->unaliasedLocal(local); else maybefp->unaliasedLocal(local) = *vp; JS_ASSERT(analyze::LocalSlot(script, local) >= analyze::TotalSlots(script)); } else { if (action == GET)
--- a/js/src/vm/Stack-inl.h +++ b/js/src/vm/Stack-inl.h @@ -133,17 +133,17 @@ inline void StackFrame::initCallFrame(JSContext *cx, JSFunction &callee, JSScript *script, uint32_t nactual, StackFrame::Flags flagsArg) { AutoAssertNoGC nogc; JS_ASSERT((flagsArg & ~(CONSTRUCTING | LOWERED_CALL_APPLY | OVERFLOW_ARGS | UNDERFLOW_ARGS)) == 0); - JS_ASSERT(script == callee.script()); + JS_ASSERT(callee.script() == script); /* Initialize stack frame members. */ flags_ = FUNCTION | HAS_PREVPC | HAS_SCOPECHAIN | HAS_BLOCKCHAIN | flagsArg; exec.fun = &callee; u.nactual = nactual; scopeChain_ = callee.environment(); ncode_ = NULL; initPrev(cx); @@ -558,26 +558,26 @@ ContextStack::currentScript(jsbytecode * #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]; - RawScript script = frame->fun->script(); + RawScript script = frame->fun->script().get(nogc); if (!allowCrossCompartment && script->compartment() != cx_->compartment) return NULL; if (ppc) *ppc = script->code + inlined->pcOffset; return script; } #endif - RawScript script = fp->script(); + RawScript script = fp->script().get(nogc); if (!allowCrossCompartment && script->compartment() != cx_->compartment) return NULL; if (ppc) *ppc = fp->pcQuadratic(*this); return script; }
--- a/js/src/vm/Stack.h +++ b/js/src/vm/Stack.h @@ -1192,17 +1192,17 @@ class FrameRegs pc = script->code; sp = fp.slots() + script->nfixed; fp_ = &fp; inlined_ = NULL; } void setToEndOfScript() { AutoAssertNoGC nogc; - RawScript script = fp()->script(); + RawScript script = fp()->script().get(nogc); sp = fp()->base(); pc = script->code + script->length - JSOP_STOP_LENGTH; JS_ASSERT(*pc == JSOP_STOP); } /* For expandInlineFrames: */ void expandInline(StackFrame *innerfp, jsbytecode *innerpc) { pc = innerpc;