diff --git a/js/src/gc/Barrier.h b/js/src/gc/Barrier.h index 564ddb2a7973..bd97c2ccdb06 100644 --- a/js/src/gc/Barrier.h +++ b/js/src/gc/Barrier.h @@ -612,7 +612,8 @@ class ReadBarriered public: ReadBarriered() : value(NULL) {} ReadBarriered(T *value) : value(value) {} - ReadBarriered(Unrooted unrooted) : value(unrooted) {} + ReadBarriered(const Unrooted &unrooted) : value(unrooted) {} + ReadBarriered(const Rooted &rooted) : value(rooted) {} T *get() const { if (!value) diff --git a/js/src/gc/Root.h b/js/src/gc/Root.h index daffa850796e..0f56988d44c1 100644 --- a/js/src/gc/Root.h +++ b/js/src/gc/Root.h @@ -76,11 +76,6 @@ * updating the value of the referenced Rooted. A MutableHandle can be * created from a Rooted by using |Rooted::operator&()|. * - * - Return is the type of a value returned from a function. Return is - * opaque and cannot be accessed unless correctly rooted. It is invalid to - * create a named Return, so the return value must be assigned to - * Rooted immediately, or discarded and not referenced again. - * * In some cases the small performance overhead of exact rooting is too much. * In these cases, try the following: * @@ -117,6 +112,24 @@ * There also exists a set of RawT typedefs for modules without rooting * concerns, such as the GC. Do not use these as they provide no rooting * protection whatsoever. + * + * The following diagram explains the list of supported, implicit type + * conversions between classes of this family: + * + * RawT ----> UnrootedT + * | ^ + * | | + * | v + * +--------> Rooted <---> Handle + * ^ ^ + * | | + * | | + * +---> MutableHandle + * (via &) + * + * Currently all of these types implicit conversion to RawT. These are present + * only for the purpose of bootstrapping exact rooting and will be removed in + * the future (Bug 817164). */ namespace js { @@ -310,6 +323,10 @@ typedef MutableHandle MutableHandleString; typedef MutableHandle MutableHandleId; typedef MutableHandle MutableHandleValue; +} /* namespace JS */ + +namespace js { + /* * Raw pointer used as documentation that a parameter does not need to be * rooted. @@ -321,10 +338,6 @@ typedef JSString * RawString; typedef jsid RawId; typedef Value RawValue; -} /* namespace JS */ - -namespace js { - /* * 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 @@ -383,172 +396,11 @@ class InternalHandle {} }; -/* - * Return wraps GC things that are returned from accessor methods. The - * wrapper helps to ensure correct rooting of the returned pointer and safe - * access while unrooted. - * - * Example usage in a method declaration: - * - * class Foo { - * HeapPtrScript script_; - * ... - * public: - * Return script() { return script_; } - * }; - * - * Example usage of method (1): - * - * Foo foo(...); - * RootedScript script(cx, foo->script()); - * - * Example usage of method (2): - * - * Foo foo(...); - * foo->script()->needsArgsObj(); - * - * The purpose of this class is to assert eagerly on incorrect use of GC thing - * pointers. For example: - * - * RootedShape shape(cx, ...); - * shape->parent.init(js_NewGCThing(cx, ...)); - * - * In this expression, C++ is allowed to order these calls as follows: - * - * Call Effect - * ---- ------ - * 1) RootedShape::operator-> Stores shape::ptr_ to stack. - * 2) js_NewGCThing Triggers GC and compaction of shapes. This - * moves shape::ptr_ to a new location. - * 3) HeapPtrObject::init This call takes the relocated shape::ptr_ - * as |this|, crashing or, worse, corrupting - * the program's state on the first access - * to a member variable. - * - * If Shape::parent were an accessor function returning a Return, this - * could not happen: Return ensures either immediate rooting or no GC within - * the same expression. - */ -template -class Return -{ - typedef void (Return::* ConvertibleToBool)(); - void nonNull() {} - - public: - template - inline Return(const Unrooted &unrooted, - typename mozilla::EnableIf::value, int>::Type dummy = 0); - - template - Return(const S &ptr, - typename mozilla::EnableIf::value, int>::Type dummy = 0) - : ptr_(ptr) - { - EnterAssertNoGCScope(); - } - - Return(NullPtr) : ptr_(NULL) { - EnterAssertNoGCScope(); - } - - Return(const Return &ret) : ptr_(ret.ptr_) { - EnterAssertNoGCScope(); - } - - ~Return() { - LeaveAssertNoGCScope(); - } - -#ifndef DEBUG - /* - * In DEBUG builds, |Unrooted| has a constructor that accepts - * |Return|, which allows direct assignment into a |Unrooted|. This - * is safe because |Unrooted| implies a NoGCScope. In optimized builds, - * however, |Unrooted| does not exist, only the UnrootedT typedef to a - * raw T. Thus, this unsafe unpack is protected by a different mechanism - * in debug builds. - */ - operator const T &() { return ptr_; } -#endif /* DEBUG */ - - /* - * |get(AutoAssertNoGC &)| is the safest way to access a Return 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; - * UnrootedScript script = fun->script().get(nogc); - */ - 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->| is - * protected at runtime by the fact that |Return| is an AutoAssertNoGC. - * Still, care must be taken to avoid having the |Return| on the stack - * during a GC, which would result in a runtime assertion. - * - * INCORRECT: - * fun->script()->bindings = myBindings->clone(cx, ...); - * - * The compiler is allowed to reorder |fun->script()::operator->()| above - * the call to |clone(cx, ...)|. In this case, the raw js::Script* C++ - * stores on the stack may be corrupted by a GC under |clone|. The - * subsequent dereference of this pointer to get |bindings| will result in - * an invalid access. |Return| ensures that such usage asserts in DEBUG - * builds when it encounters this situation. Without this assertion, it is - * possible for such access to corrupt program state instead of crashing - * immediately. - * - * CORRECT: - * RootedScript clone(cx, myBindings->clone(cx, ...)); - * fun->script()->bindings = clone; - */ - const T &operator->() const { - return ptr_; - } - - /* - * |unsafeGet()| is unsafe for most uses. Usage of this method should be - * restricted to GC internals, assertions, or include a comment explaining - * how its usage is protected. - */ - const T &unsafeGet() const { - return ptr_; - } - - /* - * |operator==| is safe to use in any context. It is present to allow: - * JS_ASSERT(myScript == fun->script().unsafeGet()); - * - * To be rewritten as: - * JS_ASSERT(fun->script() == myScript); - * - * Note: the new order tells C++ to use |Return::operator=| - * instead of direct pointer comparison. - */ - operator ConvertibleToBool() const { return ptr_ ? &Return::nonNull : 0; } - bool operator==(const T &other) { return ptr_ == other; } - bool operator!=(const T &other) { return ptr_ != other; } - bool operator==(const Return &other) { return ptr_ == other.ptr_; } - bool operator==(const JS::Handle &other) { return ptr_ == other.get(); } - inline bool operator==(const Rooted &other); - - private: - const T ptr_; -}; - +#ifdef DEBUG /* * |Unrooted| acts as an AutoAssertNoGC after it is initialized. It otherwise * acts like as a normal pointer of type T. */ -#ifdef DEBUG template class Unrooted { @@ -565,40 +417,18 @@ class Unrooted * type, this is safe because Unrooted acts as an AutoAssertNoGC scope. */ template - inline Unrooted(Rooted &root, - typename mozilla::EnableIf::value, int>::Type dummy = 0); + inline Unrooted(const Rooted &root, + typename mozilla::EnableIf::value, int>::Type dummy = 0); template - Unrooted(JS::Handle &root, - typename mozilla::EnableIf::value, int>::Type dummy = 0) + Unrooted(const JS::Handle &root, + typename mozilla::EnableIf::value, int>::Type dummy = 0) : ptr_(root.get()) { JS_ASSERT(ptr_ != UninitializedTag()); EnterAssertNoGCScope(); } - /* - * |Unrooted| can accept |Return| without any casts. This is safe - * because |Unrooted| acts as an |AutoAssertNoGC| scope. This is to - * enable usage such as: - * - * Return - * CreateFoo(JSContext *cx, ...) - * { - * Unrooted foo = js_NewFoo(cx); - * foo.initialize(...); - * return foo; - * } - */ - template - Unrooted(const Return &ret, - typename mozilla::EnableIf::value, int>::Type dummy = 0) - : ptr_(ret.unsafeGet()) - { - JS_ASSERT(ptr_ != UninitializedTag()); - EnterAssertNoGCScope(); - } - /* * |Unrooted| can initialize by copying from a convertible type * |Unrooted|. This enables usage such as: @@ -625,6 +455,10 @@ class Unrooted EnterAssertNoGCScope(); } + Unrooted(const JS::NullPtr &) : ptr_(NULL) { + EnterAssertNoGCScope(); + } + ~Unrooted() { if (ptr_ != UninitializedTag()) LeaveAssertNoGCScope(); @@ -636,16 +470,6 @@ class Unrooted ptr_ = UninitializedTag(); } - /* See notes for Unrooted::Unrooted(const Return &) */ - template - Unrooted &operator=(const Return &other) { - JS_ASSERT(other.unsafeGet() != UninitializedTag()); - if (ptr_ == UninitializedTag()) - EnterAssertNoGCScope(); - ptr_ = other.unsafeGet(); - return *this; - } - /* See notes for Unrooted::Unrooted(const T &) */ Unrooted &operator=(T other) { JS_ASSERT(other != UninitializedTag()); @@ -682,11 +506,19 @@ class Unrooted * This macro simplifies declaration of the required matching raw-pointer for * optimized builds and Unrooted template for debug builds. */ -# define ForwardDeclare(type) \ - class type; \ - typedef Unrooted Unrooted##type; \ +# define ForwardDeclare(type) \ + class type; \ + typedef Unrooted Unrooted##type; \ typedef type * Raw##type +# define ForwardDeclareJS(type) \ + struct JS##type; \ + namespace js { \ + typedef Unrooted Unrooted##type; \ + typedef JS##type * Raw##type; \ + } \ + struct JS##type + template T DropUnrooted(Unrooted &unrooted) { @@ -709,16 +541,19 @@ inline RawId DropUnrooted(RawId &id) { return id; } #else /* NDEBUG */ /* In opt builds |UnrootedFoo| is a real |Foo*|. */ -# define ForwardDeclare(type) \ - class type; \ - typedef type * Unrooted##type; \ +# define ForwardDeclare(type) \ + class type; \ + typedef type * Unrooted##type; \ typedef type * Raw##type -/* - * Note: we still define Unrooted in optimized builds so that we do not need - * #ifdef DEBUG around every debug specialization. We just ensure that the - * class is never initialized by deleting its constructors. - */ +# define ForwardDeclareJS(type) \ + struct JS##type; \ + namespace js { \ + typedef JS##type * Unrooted##type; \ + typedef JS##type * Raw##type; \ + } \ + struct JS##type + template class Unrooted { @@ -733,16 +568,6 @@ T DropUnrooted(T &unrooted) { return unrooted; } #endif /* DEBUG */ -template template -inline -Return::Return(const Unrooted &unrooted, - typename mozilla::EnableIf::value, int>::Type dummy) - /* Note: |static_cast| acquires raw.ptr_ in DEBUG builds. */ - : ptr_(static_cast(unrooted)) -{ - EnterAssertNoGCScope(); -} - /* * By default, pointers should use the inheritance hierarchy to find their * ThingRootKind. Some pointer types are explicitly set in jspubtd.h so that @@ -855,19 +680,10 @@ class Rooted : public RootedBase init(pt); } - template - Rooted(JSContext *cx, const Return &initial - MOZ_GUARD_OBJECT_NOTIFIER_PARAM) - : ptr(initial.unsafeGet()) - { - MOZ_GUARD_OBJECT_NOTIFIER_INIT; - init(cx); - } - template Rooted(JSContext *cx, const Unrooted &initial MOZ_GUARD_OBJECT_NOTIFIER_PARAM) - : ptr(initial.ptr_) + : ptr(static_cast(initial)) #if defined(JSGC_ROOT_ANALYSIS) , scanned(false) #endif @@ -876,15 +692,6 @@ class Rooted : public RootedBase init(cx); } - template - Rooted(js::PerThreadData *pt, const Return &initial - MOZ_GUARD_OBJECT_NOTIFIER_PARAM) - : ptr(initial.ptr_) - { - MOZ_GUARD_OBJECT_NOTIFIER_INIT; - init(pt); - } - ~Rooted() { #if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING) JS_ASSERT(*stack == this); @@ -914,12 +721,6 @@ class Rooted : public RootedBase return ptr; } - template - T &operator=(const Return &value) { - ptr = value.unsafeGet(); - return ptr; - } - private: void commonInit(Rooted **thingGCRooters) { #if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING) @@ -953,18 +754,11 @@ template <> class Rooted; #endif -template -bool -Return::operator==(const Rooted &other) -{ - return ptr_ == other.get(); -} - #ifdef DEBUG template template inline -Unrooted::Unrooted(Rooted &root, - typename mozilla::EnableIf::value, int>::Type dummy) +Unrooted::Unrooted(const Rooted &root, + typename mozilla::EnableIf::value, int>::Type dummy) : ptr_(root.get()) { JS_ASSERT(ptr_ != UninitializedTag()); diff --git a/js/src/ion/Bailouts.cpp b/js/src/ion/Bailouts.cpp index 5be009637ed7..a5f4bd9d2cca 100644 --- a/js/src/ion/Bailouts.cpp +++ b/js/src/ion/Bailouts.cpp @@ -74,7 +74,7 @@ IonBailoutIterator::dump() const } } -static JSScript* +static UnrootedScript GetBailedJSScript(JSContext *cx) { AutoAssertNoGC nogc; @@ -85,7 +85,7 @@ GetBailedJSScript(JSContext *cx) switch (GetCalleeTokenTag(frame->calleeToken())) { case CalleeToken_Function: { JSFunction *fun = CalleeTokenToFunction(frame->calleeToken()); - return fun->nonLazyScript().get(nogc); + return fun->nonLazyScript(); } case CalleeToken_Script: return CalleeTokenToScript(frame->calleeToken()); @@ -178,8 +178,8 @@ StackFrame::initFromBailout(JSContext *cx, SnapshotIterator &iter) regs.pc = GetNextPc(regs.pc); IonSpew(IonSpew_Bailouts, " new PC is offset %u within script %p (line %d)", - pcOff, (void *)script().get(nogc), PCToLineNumber(script().get(nogc), regs.pc)); - JS_ASSERT(exprStackSlots == js_ReconstructStackDepth(cx, script().get(nogc), regs.pc)); + pcOff, (void *)script(), PCToLineNumber(script(), regs.pc)); + JS_ASSERT(exprStackSlots == js_ReconstructStackDepth(cx, script(), regs.pc)); } static StackFrame * @@ -324,7 +324,7 @@ ConvertFrames(JSContext *cx, IonActivation *activation, IonBailoutIterator &it) // we flag it here manually that the entry has happened. case Bailout_ArgumentCheck: fp->unsetPushedSPSFrame(); - Probes::enterScript(cx, fp->script().unsafeGet(), fp->script()->function(), fp); + Probes::enterScript(cx, fp->script(), fp->script()->function(), fp); return BAILOUT_RETURN_ARGUMENT_CHECK; } @@ -502,8 +502,9 @@ ion::ReflowTypeInfo(uint32_t bailoutResult) uint32_t ion::RecompileForInlining() { + AutoAssertNoGC nogc; JSContext *cx = GetIonContext()->cx; - RawScript script = cx->fp()->script().unsafeGet(); + UnrootedScript script = cx->fp()->script(); IonSpew(IonSpew_Inlining, "Recompiling script to inline calls %s:%d", script->filename, script->lineno); @@ -663,7 +664,7 @@ ion::ThunkToInterpreter(Value *vp) IonSpew(IonSpew_Bailouts, "Performing inline OSR %s:%d", cx->fp()->script()->filename, - PCToLineNumber(cx->fp()->script().unsafeGet(), cx->regs().pc)); + PCToLineNumber(cx->fp()->script(), 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 diff --git a/js/src/ion/CodeGenerator.cpp b/js/src/ion/CodeGenerator.cpp index 69b606faaa3e..927533dc1706 100644 --- a/js/src/ion/CodeGenerator.cpp +++ b/js/src/ion/CodeGenerator.cpp @@ -311,7 +311,7 @@ CodeGenerator::visitLambda(LLambda *lir) JS_STATIC_ASSERT(offsetof(JSFunction, flags) == offsetof(JSFunction, nargs) + 2); masm.store32(Imm32(u.word), Address(output, offsetof(JSFunction, nargs))); - masm.storePtr(ImmGCPtr(fun->nonLazyScript().unsafeGet()), + masm.storePtr(ImmGCPtr(fun->nonLazyScript()), Address(output, JSFunction::offsetOfNativeOrScript())); masm.storePtr(scopeChain, Address(output, JSFunction::offsetOfEnvironment())); masm.storePtr(ImmGCPtr(fun->displayAtom()), Address(output, JSFunction::offsetOfAtom())); diff --git a/js/src/ion/Ion.cpp b/js/src/ion/Ion.cpp index ec82dbbafcf6..55e9a00843b2 100644 --- a/js/src/ion/Ion.cpp +++ b/js/src/ion/Ion.cpp @@ -1170,7 +1170,7 @@ SequentialCompileContext::compile(IonBuilder *builder, MIRGraph *graph, JS_ASSERT(!builder->script()->ion); JSContext *cx = GetIonContext()->cx; - IonSpewNewFunction(graph, builder->script().unsafeGet()); + IonSpewNewFunction(graph, builder->script()); if (!builder->build()) { IonSpew(IonSpew_Abort, "Builder failed to build."); @@ -1510,7 +1510,7 @@ EnterIon(JSContext *cx, StackFrame *fp, void *jitcode) } calleeToken = CalleeToToken(&fp->callee()); } else { - calleeToken = CalleeToToken(fp->script().unsafeGet()); + calleeToken = CalleeToToken(fp->script()); } // Caller must construct |this| before invoking the Ion function. @@ -1817,6 +1817,7 @@ void ion::Invalidate(types::TypeCompartment &types, FreeOp *fop, const Vector &invalid, bool resetUses) { + AutoAssertNoGC nogc; IonSpew(IonSpew_Invalidate, "Start invalidation."); AutoFlushCache afc ("Invalidate"); diff --git a/js/src/ion/IonBuilder.cpp b/js/src/ion/IonBuilder.cpp index 54c4e33c6fda..a4377b397923 100644 --- a/js/src/ion/IonBuilder.cpp +++ b/js/src/ion/IonBuilder.cpp @@ -152,7 +152,7 @@ IonBuilder::getSingleCallTarget(uint32_t argc, jsbytecode *pc) { AutoAssertNoGC nogc; - types::StackTypeSet *calleeTypes = oracle->getCallTarget(script().get(nogc), argc, pc); + types::StackTypeSet *calleeTypes = oracle->getCallTarget(script(), argc, pc); if (!calleeTypes) return NULL; @@ -3849,7 +3849,7 @@ IonBuilder::createThisScriptedSingleton(HandleFunction target, HandleObject prot types::TypeObject *type = proto->getNewType(cx, target); if (!type) return NULL; - if (!types::TypeScript::ThisTypes(target->nonLazyScript().unsafeGet())->hasType(types::Type::ObjectType(type))) + if (!types::TypeScript::ThisTypes(target->nonLazyScript())->hasType(types::Type::ObjectType(type))) return NULL; RootedObject templateObject(cx, js_CreateThisForFunctionWithProto(cx, target, proto)); diff --git a/js/src/ion/IonBuilder.h b/js/src/ion/IonBuilder.h index bcd327b2978f..5115b7106222 100644 --- a/js/src/ion/IonBuilder.h +++ b/js/src/ion/IonBuilder.h @@ -479,7 +479,7 @@ class IonBuilder : public MIRGenerator void clearForBackEnd(); - Return script() const { return script_; } + UnrootedScript script() const { return script_.get(); } CodeGenerator *backgroundCodegen() const { return backgroundCodegen_; } void setBackgroundCodegen(CodeGenerator *codegen) { backgroundCodegen_ = codegen; } diff --git a/js/src/ion/IonCaches.cpp b/js/src/ion/IonCaches.cpp index 4a1e02de2611..ecaadc0045b3 100644 --- a/js/src/ion/IonCaches.cpp +++ b/js/src/ion/IonCaches.cpp @@ -1626,7 +1626,7 @@ GenerateScopeChainGuard(MacroAssembler &masm, JSObject *scopeObj, CallObject *callObj = &scopeObj->asCall(); if (!callObj->isForEval()) { RawFunction fun = &callObj->callee(); - RawScript script = fun->nonLazyScript().get(nogc); + UnrootedScript script = fun->nonLazyScript(); if (!script->funHasExtensibleScope) return; } diff --git a/js/src/ion/IonFrames-inl.h b/js/src/ion/IonFrames-inl.h index a62345cc3f13..83071064e8c3 100644 --- a/js/src/ion/IonFrames-inl.h +++ b/js/src/ion/IonFrames-inl.h @@ -81,7 +81,7 @@ IonFrameIterator::frameSize() const } // Returns the JSScript associated with the topmost Ion frame. -inline JSScript * +inline UnrootedScript GetTopIonJSScript(JSContext *cx, const SafepointIndex **safepointIndexOut, void **returnAddrOut) { AutoAssertNoGC nogc; diff --git a/js/src/ion/IonFrames.cpp b/js/src/ion/IonFrames.cpp index 4c0ed14d4f46..c7307aa6cb2a 100644 --- a/js/src/ion/IonFrames.cpp +++ b/js/src/ion/IonFrames.cpp @@ -926,7 +926,7 @@ InlineFrameIterator::findNextFrame() si_.nextFrame(); callee_ = funval.toObject().toFunction(); - script_ = callee_->nonLazyScript().get(nogc); + script_ = callee_->nonLazyScript(); pc_ = script_->code + si_.pcOffset(); } diff --git a/js/src/ion/IonFrames.h b/js/src/ion/IonFrames.h index 147997c3bae1..9086cae83a43 100644 --- a/js/src/ion/IonFrames.h +++ b/js/src/ion/IonFrames.h @@ -42,7 +42,7 @@ CalleeToToken(JSFunction *fun) return CalleeToken(uintptr_t(fun) | uintptr_t(CalleeToken_Function)); } static inline CalleeToken -CalleeToToken(JSScript *script) +CalleeToToken(RawScript script) { return CalleeToken(uintptr_t(script) | uintptr_t(CalleeToken_Script)); } @@ -57,14 +57,14 @@ CalleeTokenToFunction(CalleeToken token) JS_ASSERT(CalleeTokenIsFunction(token)); return (JSFunction *)token; } -static inline JSScript * +static inline UnrootedScript CalleeTokenToScript(CalleeToken token) { JS_ASSERT(GetCalleeTokenTag(token) == CalleeToken_Script); - return (JSScript *)(uintptr_t(token) & ~uintptr_t(0x3)); + return (RawScript)(uintptr_t(token) & ~uintptr_t(0x3)); } -static inline JSScript * +static inline UnrootedScript ScriptFromCalleeToken(CalleeToken token) { AutoAssertNoGC nogc; @@ -72,10 +72,10 @@ ScriptFromCalleeToken(CalleeToken token) case CalleeToken_Script: return CalleeTokenToScript(token); case CalleeToken_Function: - return CalleeTokenToFunction(token)->nonLazyScript().get(nogc); + return CalleeTokenToFunction(token)->nonLazyScript(); } JS_NOT_REACHED("invalid callee token tag"); - return NULL; + return UnrootedScript(NULL); } // In between every two frames lies a small header describing both frames. This @@ -269,7 +269,7 @@ MakeFrameDescriptor(uint32_t frameSize, FrameType type) namespace js { namespace ion { -JSScript * +UnrootedScript GetTopIonJSScript(JSContext *cx, const SafepointIndex **safepointIndexOut = NULL, void **returnAddrOut = NULL); diff --git a/js/src/ion/VMFunctions.cpp b/js/src/ion/VMFunctions.cpp index fa2e71c23fb4..4651e3a9480e 100644 --- a/js/src/ion/VMFunctions.cpp +++ b/js/src/ion/VMFunctions.cpp @@ -53,7 +53,7 @@ InvokeFunction(JSContext *cx, JSFunction *fun, uint32_t argc, Value *argv, Value // 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).unsafeGet()) + if (fun->isInterpretedLazy() && !fun->getOrCreateScript(cx)) return false; if (!fun->nonLazyScript()->canIonCompile()) { JSScript *script = GetTopIonJSScript(cx); @@ -103,7 +103,7 @@ InvokeConstructor(JSContext *cx, JSObject *obj, uint32_t argc, Value *argv, Valu if (obj->isFunction()) { if (obj->toFunction()->isInterpretedLazy() && - !obj->toFunction()->getOrCreateScript(cx).unsafeGet()) + !obj->toFunction()->getOrCreateScript(cx)) { return false; } diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index e019463e28d6..444f7497da44 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -7096,9 +7096,9 @@ JS_DescribeScriptedCaller(JSContext *cx, JSScript **script, unsigned *lineno) return JS_FALSE; if (script) - *script = i.script().get(nogc); + *script = i.script(); if (lineno) - *lineno = js::PCToLineNumber(i.script().get(nogc), i.pc()); + *lineno = js::PCToLineNumber(i.script(), i.pc()); return JS_TRUE; } diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 520cb9e17a30..015ee8d96692 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -1621,12 +1621,12 @@ typedef JS::MutableHandle JSMutableHandleString; typedef JS::MutableHandle JSMutableHandleValue; typedef JS::MutableHandle JSMutableHandleId; -typedef JS::RawObject JSRawObject; -typedef JS::RawFunction JSRawFunction; -typedef JS::RawScript JSRawScript; -typedef JS::RawString JSRawString; -typedef JS::RawId JSRawId; -typedef JS::RawValue JSRawValue; +typedef js::RawObject JSRawObject; +typedef js::RawFunction JSRawFunction; +typedef js::RawScript JSRawScript; +typedef js::RawString JSRawString; +typedef js::RawId JSRawId; +typedef js::RawValue JSRawValue; /* JSClass operation signatures. */ diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index 53fd704c6e7b..fd59561b245d 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -663,7 +663,7 @@ PopulateReportBlame(JSContext *cx, JSErrorReport *report) return; report->filename = iter.script()->filename; - report->lineno = PCToLineNumber(iter.script().get(nogc), iter.pc(), &report->column); + report->lineno = PCToLineNumber(iter.script(), iter.pc(), &report->column); report->originPrincipals = iter.script()->originPrincipals; } diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index 57543b0bebeb..5889ae7c968e 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -448,8 +448,7 @@ JS_ReleaseFunctionLocalNameArray(JSContext *cx, void *mark) JS_PUBLIC_API(JSScript *) JS_GetFunctionScript(JSContext *cx, JSFunction *fun) { - AutoAssertNoGC nogc; - return fun->maybeNonLazyScript().get(nogc); + return fun->maybeNonLazyScript(); } JS_PUBLIC_API(JSNative) @@ -497,8 +496,7 @@ JS_BrokenFrameIterator(JSContext *cx, JSStackFrame **iteratorp) JS_PUBLIC_API(JSScript *) JS_GetFrameScript(JSContext *cx, JSStackFrame *fpArg) { - AutoAssertNoGC nogc; - return Valueify(fpArg)->script().get(nogc); + return Valueify(fpArg)->script(); } JS_PUBLIC_API(jsbytecode *) @@ -543,7 +541,7 @@ JS_SetTopFrameAnnotation(JSContext *cx, void *annotation) // because we will never EnterIon on a frame with an annotation. fp->setAnnotation(annotation); - RawScript script = fp->script().get(nogc); + UnrootedScript script = fp->script(); ReleaseAllJITCode(cx->runtime->defaultFreeOp()); @@ -1013,7 +1011,7 @@ JS_GetFunctionTotalSize(JSContext *cx, JSFunction *fun) size_t nbytes = sizeof *fun; nbytes += JS_GetObjectTotalSize(cx, fun); if (fun->isInterpreted()) - nbytes += JS_GetScriptTotalSize(cx, fun->nonLazyScript().get(nogc)); + nbytes += JS_GetScriptTotalSize(cx, fun->nonLazyScript()); if (fun->displayAtom()) nbytes += GetAtomTotalSize(cx, fun->displayAtom()); return nbytes; @@ -1205,8 +1203,8 @@ JS::DescribeStack(JSContext *cx, unsigned maxFrames) for (ScriptFrameIter i(cx); !i.done(); ++i) { FrameDescription desc; - desc.script = i.script().get(nogc); - desc.lineno = PCToLineNumber(i.script().get(nogc), i.pc()); + desc.script = i.script(); + desc.lineno = PCToLineNumber(i.script(), i.pc()); desc.fun = i.maybeCallee(); if (!frames.append(desc)) return NULL; diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index fa25e404acc7..cb3bd104313b 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -125,13 +125,11 @@ fun_getProperty(JSContext *cx, HandleObject obj_, HandleId id, MutableHandleValu return false; #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().get(nogc); + UnrootedScript script = iter.script(); if (!script->hasAnyIonScript()) ion::ForbidCompilation(cx, script); #endif @@ -344,7 +342,7 @@ fun_resolve(JSContext *cx, HandleObject obj, HandleId id, unsigned flags, PropertyOp getter; StrictPropertyOp setter; unsigned attrs = JSPROP_PERMANENT; - if (fun->isInterpretedLazy() && !fun->getOrCreateScript(cx).unsafeGet()) + if (fun->isInterpretedLazy() && !fun->getOrCreateScript(cx)) return false; if (fun->isInterpreted() ? fun->inStrictMode() : fun->isBoundFunction()) { JSObject *throwTypeError = fun->global().getThrowTypeError(); @@ -1112,7 +1110,7 @@ fun_isGenerator(JSContext *cx, unsigned argc, Value *vp) bool result = false; if (fun->hasScript()) { - RawScript script = fun->nonLazyScript().get(nogc); + UnrootedScript script = fun->nonLazyScript(); JS_ASSERT(script->length != 0); result = script->isGenerator; } @@ -1480,7 +1478,7 @@ js_CloneFunctionObject(JSContext *cx, HandleFunction fun, HandleObject parent, clone->nargs = fun->nargs; clone->flags = fun->flags & ~JSFunction::EXTENDED; if (fun->isInterpreted()) { - clone->initScript(fun->nonLazyScript().unsafeGet()); + clone->initScript(fun->nonLazyScript()); clone->initEnvironment(parent); } else { clone->initNative(fun->native(), fun->jitInfo()); diff --git a/js/src/jsfun.h b/js/src/jsfun.h index eb419773d812..96d65f2261cf 100644 --- a/js/src/jsfun.h +++ b/js/src/jsfun.h @@ -13,11 +13,12 @@ #include "jspubtd.h" #include "jsobj.h" #include "jsatom.h" -#include "jsscript.h" #include "jsstr.h" #include "gc/Barrier.h" +ForwardDeclareJS(Script); + namespace js { class FunctionExtended; } struct JSFunction : public JSObject @@ -178,13 +179,13 @@ struct JSFunction : public JSObject static inline size_t offsetOfEnvironment() { return offsetof(JSFunction, u.i.env_); } static inline size_t offsetOfAtom() { return offsetof(JSFunction, atom_); } - js::Return getOrCreateScript(JSContext *cx) { + js::UnrootedScript getOrCreateScript(JSContext *cx) { JS_ASSERT(isInterpreted()); if (isInterpretedLazy()) { js::RootedFunction self(cx, this); js::MaybeCheckStackRoots(cx); if (!initializeLazyScript(cx)) - return js::NullPtr(); + return js::UnrootedScript(NULL); } JS_ASSERT(hasScript()); return JS::HandleScript::fromMarkedLocation(&u.i.script_); @@ -195,17 +196,17 @@ struct JSFunction : public JSObject script.set(NULL); return true; } - script.set(getOrCreateScript(cx).unsafeGet()); + script.set(getOrCreateScript(cx)); return hasScript(); } - js::Return nonLazyScript() const { + js::UnrootedScript nonLazyScript() const { JS_ASSERT(hasScript()); return JS::HandleScript::fromMarkedLocation(&u.i.script_); } - js::Return maybeNonLazyScript() const { - return isInterpreted() ? nonLazyScript() : JS::NullPtr(); + js::UnrootedScript maybeNonLazyScript() const { + return isInterpreted() ? nonLazyScript() : js::UnrootedScript(NULL); } js::HeapPtrScript &mutableScript() { diff --git a/js/src/jsgcinlines.h b/js/src/jsgcinlines.h index 71303f28db60..2fe46445abaf 100644 --- a/js/src/jsgcinlines.h +++ b/js/src/jsgcinlines.h @@ -601,7 +601,7 @@ js_NewGCShape(JSContext *cx) return js::gc::NewGCThing(cx, js::gc::FINALIZE_SHAPE, sizeof(js::Shape)); } -inline js::Return +inline js::UnrootedBaseShape js_NewGCBaseShape(JSContext *cx) { return js::gc::NewGCThing(cx, js::gc::FINALIZE_BASE_SHAPE, sizeof(js::BaseShape)); diff --git a/js/src/jsinfer.cpp b/js/src/jsinfer.cpp index 118ff72a5a8b..9286625bfbcf 100644 --- a/js/src/jsinfer.cpp +++ b/js/src/jsinfer.cpp @@ -1423,10 +1423,10 @@ TypeConstraintPropagateThis::newType(JSContext *cx, TypeSet *source, Type type) return; } - if (!(callee->getOrCreateScript(cx).unsafeGet() && callee->nonLazyScript()->ensureHasTypes(cx))) + if (!(callee->getOrCreateScript(cx) && callee->nonLazyScript()->ensureHasTypes(cx))) return; - TypeSet *thisTypes = TypeScript::ThisTypes(callee->nonLazyScript().unsafeGet()); + TypeSet *thisTypes = TypeScript::ThisTypes(callee->nonLazyScript()); if (this->types) this->types->addSubset(cx, thisTypes); else @@ -5561,7 +5561,7 @@ JSScript::makeAnalysis(JSContext *cx) /* static */ bool JSFunction::setTypeForScriptedFunction(JSContext *cx, HandleFunction fun, bool singleton) { - JS_ASSERT(fun->nonLazyScript().unsafeGet()); + JS_ASSERT(fun->nonLazyScript()); JS_ASSERT(fun->nonLazyScript()->function() == fun); if (!cx->typeInferenceEnabled()) @@ -5717,7 +5717,7 @@ JSObject::makeLazyType(JSContext *cx) RootedObject self(cx, this); /* De-lazification of functions can GC, so we need to do it up here. */ if (self->isFunction() && self->toFunction()->isInterpretedLazy()) { - if (!self->toFunction()->getOrCreateScript(cx).unsafeGet()) + if (!self->toFunction()->getOrCreateScript(cx)) return NULL; } JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(getClass()); diff --git a/js/src/jsinferinlines.h b/js/src/jsinferinlines.h index 6365903ec913..da17b3e7c334 100644 --- a/js/src/jsinferinlines.h +++ b/js/src/jsinferinlines.h @@ -703,7 +703,7 @@ UseNewTypeForClone(JSFunction *fun) * instance a singleton type and clone the underlying script. */ - RawScript script = fun->nonLazyScript().get(nogc); + UnrootedScript script = fun->nonLazyScript(); if (script->length >= 50) return false; @@ -905,7 +905,7 @@ TypeScript::GetPcScript(JSContext *cx, MutableHandleScript script, jsbytecode ** return; } #endif - script.set(cx->fp()->script().get(nogc)); + script.set(cx->fp()->script()); *pc = cx->regs().pc; } diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index b7c3b310ee98..9ce1e36cb223 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -2333,7 +2333,7 @@ BEGIN_CASE(JSOP_FUNCALL) InitialFrameFlags initial = construct ? INITIAL_CONSTRUCT : INITIAL_NONE; bool newType = cx->typeInferenceEnabled() && UseNewType(cx, script, regs.pc); - RawScript funScript = fun->getOrCreateScript(cx).unsafeGet(); + RawScript funScript = fun->getOrCreateScript(cx); if (!funScript) goto error; if (!cx->stack.pushInlineFrame(cx, regs, args, *fun, funScript, initial)) diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 1a7fb6984272..96423b597af7 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -5240,7 +5240,7 @@ dumpValue(const Value &v) fputs("hasScript()) { - JSScript *script = fun->nonLazyScript().get(nogc); + UnrootedScript script = fun->nonLazyScript(); fprintf(stderr, " (%s:%u)", script->filename ? script->filename : "", script->lineno); } @@ -5506,9 +5506,9 @@ js_DumpBacktrace(JSContext *cx) size_t depth = 0; for (StackIter i(cx); !i.done(); ++i, ++depth) { if (i.isScript()) { - 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); + const char *filename = JS_GetScriptFilename(cx, i.script()); + unsigned line = JS_PCToLineNumber(cx, i.script(), i.pc()); + RawScript script = i.script(); sprinter.printf("#%d %14p %s:%d (%p @ %d)\n", depth, (i.isIon() ? 0 : i.interpFrame()), filename, line, script, i.pc() - script->code); diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index 39e7d7d85eb3..3b8f6c8782ad 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -815,7 +815,7 @@ inline bool JSObject::isWith() const { return hasClass(&js::WithClass); } inline bool JSObject::isDebugScope() const { - extern bool js_IsDebugScopeSlow(JS::RawObject obj); + extern bool js_IsDebugScopeSlow(js::RawObject obj); return getClass() == &js::ObjectProxyClass && js_IsDebugScopeSlow(const_cast(this)); } diff --git a/js/src/jsopcode.cpp b/js/src/jsopcode.cpp index 2ef8bd302dac..743699369e2d 100644 --- a/js/src/jsopcode.cpp +++ b/js/src/jsopcode.cpp @@ -1192,7 +1192,7 @@ js_NewPrinter(JSContext *cx, const char *name, JSFunction *fun, jp->localNames = NULL; jp->decompiledOpcodes = NULL; if (fun && fun->hasScript()) { - if (!SetPrinterLocalNames(cx, fun->nonLazyScript().unsafeGet(), jp)) { + if (!SetPrinterLocalNames(cx, fun->nonLazyScript(), jp)) { js_DestroyPrinter(jp); return NULL; } @@ -1853,7 +1853,7 @@ GetArgOrVarAtom(JSPrinter *jp, unsigned slot) { LOCAL_ASSERT_RV(jp->fun, NULL); LOCAL_ASSERT_RV(slot < jp->script->bindings.count(), NULL); - LOCAL_ASSERT_RV(jp->script == jp->fun->nonLazyScript().unsafeGet(), NULL); + LOCAL_ASSERT_RV(jp->script == jp->fun->nonLazyScript(), NULL); JSAtom *name = (*jp->localNames)[slot].name(); #if !JS_HAS_DESTRUCTURING LOCAL_ASSERT_RV(name, NULL); @@ -4812,10 +4812,10 @@ Decompile(SprintStack *ss, jsbytecode *pc, int nb) */ LifoAllocScope las(&cx->tempLifoAlloc()); outerLocalNames = jp->localNames; - if (!SetPrinterLocalNames(cx, fun->nonLazyScript().unsafeGet(), jp)) + if (!SetPrinterLocalNames(cx, fun->nonLazyScript(), jp)) return NULL; - inner = fun->nonLazyScript().unsafeGet(); + inner = fun->nonLazyScript(); if (!InitSprintStack(cx, &ss2, jp, StackDepth(inner))) { js_delete(jp->localNames); jp->localNames = outerLocalNames; @@ -6224,7 +6224,7 @@ FindStartPC(JSContext *cx, ScriptFrameIter &iter, int spindex, int skipStackHits *valuepc = NULL; PCStack pcstack; - if (!pcstack.init(cx, iter.script().unsafeGet(), current)) + if (!pcstack.init(cx, iter.script(), current)) return false; if (spindex == JSDVG_SEARCH_STACK) { diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index ea18657a3473..dff192736fb6 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -2133,7 +2133,7 @@ unsigned js::CurrentLine(JSContext *cx) { AutoAssertNoGC nogc; - return PCToLineNumber(cx->fp()->script().get(nogc), cx->regs().pc); + return PCToLineNumber(cx->fp()->script(), cx->regs().pc); } void @@ -2150,9 +2150,9 @@ js::CurrentScriptFileLineOriginSlow(JSContext *cx, const char **file, unsigned * return; } - RawScript script = iter.script().get(nogc); + UnrootedScript script = iter.script(); *file = script->filename; - *linenop = PCToLineNumber(iter.script().get(nogc), iter.pc()); + *linenop = PCToLineNumber(iter.script(), iter.pc()); *origin = script->originPrincipals; } diff --git a/js/src/jsscriptinlines.h b/js/src/jsscriptinlines.h index 97370d4c2768..5de333f29c96 100644 --- a/js/src/jsscriptinlines.h +++ b/js/src/jsscriptinlines.h @@ -48,7 +48,7 @@ CurrentScriptFileLineOrigin(JSContext *cx, const char **file, unsigned *linenop, 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().get(nogc); + UnrootedScript script = cx->fp()->script(); *file = script->filename; *linenop = GET_UINT16(cx->regs().pc + JSOP_EVAL_LENGTH); *origin = script->originPrincipals; diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index 83ddd2a87c82..6ef3a90427ab 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -2369,7 +2369,7 @@ LambdaIsGetElem(JSObject &lambda) if (!fun->hasScript()) return NULL; - RawScript script = fun->nonLazyScript().get(nogc); + UnrootedScript script = fun->nonLazyScript(); jsbytecode *pc = script->code; /* diff --git a/js/src/jsworkers.cpp b/js/src/jsworkers.cpp index 83659e558c90..59e70b27a051 100644 --- a/js/src/jsworkers.cpp +++ b/js/src/jsworkers.cpp @@ -92,7 +92,7 @@ js::CancelOffThreadIonCompile(JSCompartment *compartment, JSScript *script) /* 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().unsafeGet())) { + if (CompiledScriptMatches(compartment, script, builder->script())) { FinishOffThreadIonCompile(builder); state.ionWorklist[i--] = state.ionWorklist.back(); state.ionWorklist.popBack(); @@ -103,7 +103,7 @@ js::CancelOffThreadIonCompile(JSCompartment *compartment, JSScript *script) for (size_t i = 0; i < state.numThreads; i++) { const WorkerThread &helper = state.threads[i]; while (helper.ionBuilder && - CompiledScriptMatches(compartment, script, helper.ionBuilder->script().unsafeGet())) + CompiledScriptMatches(compartment, script, helper.ionBuilder->script())) { helper.ionBuilder->cancel(); state.wait(WorkerThreadState::MAIN); @@ -115,7 +115,7 @@ js::CancelOffThreadIonCompile(JSCompartment *compartment, JSScript *script) /* 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().unsafeGet())) { + if (CompiledScriptMatches(compartment, script, builder->script())) { ion::FinishOffThreadBuilder(builder); compilations[i--] = compilations.back(); compilations.popBack(); @@ -316,7 +316,7 @@ WorkerThread::threadLoop() ionBuilder = state.ionWorklist.popCopy(); DebugOnly executionMode = ionBuilder->info().executionMode(); - JS_ASSERT(GetIonScript(ionBuilder->script().unsafeGet(), executionMode) == ION_COMPILING_SCRIPT); + JS_ASSERT(GetIonScript(ionBuilder->script(), executionMode) == ION_COMPILING_SCRIPT); state.unlock(); diff --git a/js/src/methodjit/BaseAssembler.h b/js/src/methodjit/BaseAssembler.h index 1b86e613d5b4..c3fa0d197778 100644 --- a/js/src/methodjit/BaseAssembler.h +++ b/js/src/methodjit/BaseAssembler.h @@ -148,7 +148,7 @@ class Assembler : public ValueAssembler AutoAssertNoGC nogc; startLabel = label(); if (vmframe) - sps->setPushed(vmframe->script().get(nogc)); + sps->setPushed(vmframe->script()); } Assembler(MJITInstrumentation *sps, jsbytecode **pc) diff --git a/js/src/methodjit/BaseCompiler.h b/js/src/methodjit/BaseCompiler.h index 971f0e83860c..5a9010586e86 100644 --- a/js/src/methodjit/BaseCompiler.h +++ b/js/src/methodjit/BaseCompiler.h @@ -138,7 +138,7 @@ class LinkerHelper : public JSC::LinkBuffer AutoAssertNoGC nogc; masm.finalize(*this); JSC::CodeLocationLabel label = finalizeCodeAddendum(); - Probes::registerICCode(f.cx, f.chunk(), f.script().get(nogc), f.pc(), + Probes::registerICCode(f.cx, f.chunk(), f.script(), f.pc(), label.executableAddress(), masm.size()); return label; } diff --git a/js/src/methodjit/InvokeHelpers.cpp b/js/src/methodjit/InvokeHelpers.cpp index 6687d5cb7b17..946aab8653da 100644 --- a/js/src/methodjit/InvokeHelpers.cpp +++ b/js/src/methodjit/InvokeHelpers.cpp @@ -299,7 +299,7 @@ UncachedInlineCall(VMFrame &f, InitialFrameFlags initial, return false; /* Try to compile if not already compiled. */ - if (ShouldJaegerCompileCallee(cx, f.script().unsafeGet(), newscript, f.jit())) { + if (ShouldJaegerCompileCallee(cx, f.script(), newscript, f.jit())) { CompileStatus status = CanMethodJIT(cx, newscript, newscript->code, construct, CompileRequest_JIT, f.fp()); if (status == Compile_Error) { @@ -663,7 +663,7 @@ void JS_FASTCALL stubs::ScriptDebugPrologue(VMFrame &f) { AssertCanGC(); - Probes::enterScript(f.cx, f.script().unsafeGet(), f.script()->function(), f.fp()); + Probes::enterScript(f.cx, f.script(), f.script()->function(), f.fp()); JSTrapStatus status = js::ScriptDebugPrologue(f.cx, f.fp()); switch (status) { case JSTRAP_CONTINUE: @@ -690,14 +690,14 @@ void JS_FASTCALL stubs::ScriptProbeOnlyPrologue(VMFrame &f) { AutoAssertNoGC nogc; - Probes::enterScript(f.cx, f.script().get(nogc), f.script()->function(), f.fp()); + Probes::enterScript(f.cx, f.script(), f.script()->function(), f.fp()); } void JS_FASTCALL stubs::ScriptProbeOnlyEpilogue(VMFrame &f) { AutoAssertNoGC nogc; - Probes::exitScript(f.cx, f.script().get(nogc), f.script()->function(), f.fp()); + Probes::exitScript(f.cx, f.script(), f.script()->function(), f.fp()); } void JS_FASTCALL @@ -708,13 +708,13 @@ stubs::CrossChunkShim(VMFrame &f, void *edge_) mjit::ExpandInlineFrames(f.cx->compartment); - RawScript script = f.script().unsafeGet(); + UnrootedScript script = f.script(); JS_ASSERT(edge->target < script->length); JS_ASSERT(script->code + edge->target == f.pc()); - CompileStatus status = CanMethodJIT(f.cx, script, f.pc(), f.fp()->isConstructing(), + CompileStatus status = CanMethodJIT(f.cx, DropUnrooted(script), f.pc(), + f.fp()->isConstructing(), CompileRequest_Interpreter, f.fp()); - script = NULL; if (status == Compile_Error) THROW(); @@ -870,7 +870,7 @@ js_InternalInterpret(void *returnData, void *returnType, void *returnReg, js::VM } case REJOIN_THIS_CREATED: { - Probes::enterScript(f.cx, f.script().unsafeGet(), f.script()->function(), fp); + Probes::enterScript(f.cx, f.script(), f.script()->function(), fp); if (script->debugMode) { JSTrapStatus status = js::ScriptDebugPrologue(f.cx, f.fp()); @@ -930,7 +930,7 @@ js_InternalInterpret(void *returnData, void *returnType, void *returnReg, js::VM } /* FALLTHROUGH */ case REJOIN_EVAL_PROLOGUE: - Probes::enterScript(cx, f.script().unsafeGet(), f.script()->function(), fp); + Probes::enterScript(cx, f.script(), f.script()->function(), fp); if (cx->compartment->debugMode()) { JSTrapStatus status = ScriptDebugPrologue(cx, fp); switch (status) { diff --git a/js/src/methodjit/MethodJIT.h b/js/src/methodjit/MethodJIT.h index 6ef4b32d7ba7..98db4259e955 100644 --- a/js/src/methodjit/MethodJIT.h +++ b/js/src/methodjit/MethodJIT.h @@ -218,7 +218,7 @@ struct VMFrame inline unsigned chunkIndex(); /* Get the inner script/PC in case of inlining. */ - inline Return script(); + inline UnrootedScript script(); inline jsbytecode *pc(); #if defined(JS_CPU_SPARC) @@ -1064,7 +1064,7 @@ VMFrame::chunkIndex() return jit()->chunkIndex(regs.pc); } -inline Return +inline UnrootedScript VMFrame::script() { AutoAssertNoGC nogc; diff --git a/js/src/methodjit/MonoIC.cpp b/js/src/methodjit/MonoIC.cpp index 547be5516c2f..55bbe09f5ed2 100644 --- a/js/src/methodjit/MonoIC.cpp +++ b/js/src/methodjit/MonoIC.cpp @@ -884,7 +884,7 @@ class CallCompiler : public BaseCompiler masm.storePtr(ImmPtr((void *) ic.frameSize.rejoinState(f.pc(), false)), FrameAddress(offsetof(VMFrame, stubRejoin))); - masm.bumpStubCount(f.script().get(nogc), f.pc(), Registers::tempCallReg()); + masm.bumpStubCount(f.script(), 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); @@ -1001,7 +1001,7 @@ class CallCompiler : public BaseCompiler /* Guard that it's the same script. */ Address scriptAddr(ic.funObjReg, JSFunction::offsetOfNativeOrScript()); Jump funGuard = masm.branchPtr(Assembler::NotEqual, scriptAddr, - ImmPtr(obj->toFunction()->nonLazyScript().get(nogc))); + ImmPtr(obj->toFunction()->nonLazyScript())); Jump done = masm.jump(); LinkerHelper linker(masm, JSC::JAEGER_CODE); @@ -1259,9 +1259,8 @@ class CallCompiler : public BaseCompiler return NULL; } - AutoAssertNoGC nogc; JS_ASSERT(fun); - JSScript *script = fun->nonLazyScript().get(nogc); + UnrootedScript script = fun->nonLazyScript(); JS_ASSERT(script); uint32_t flags = callingNew ? StackFrame::CONSTRUCTING : 0; @@ -1433,7 +1432,7 @@ ic::GenerateArgumentCheckStub(VMFrame &f) JITScript *jit = f.jit(); StackFrame *fp = f.fp(); JSFunction *fun = fp->fun(); - JSScript *script = fun->nonLazyScript().get(nogc); + UnrootedScript script = fun->nonLazyScript(); if (jit->argsCheckPool) jit->resetArgsCheck(); diff --git a/js/src/methodjit/PolyIC.cpp b/js/src/methodjit/PolyIC.cpp index 12fc0928d02a..1f997ebd8530 100644 --- a/js/src/methodjit/PolyIC.cpp +++ b/js/src/methodjit/PolyIC.cpp @@ -770,7 +770,7 @@ namespace js { namespace mjit { inline void -MarkNotIdempotent(JSScript *script, jsbytecode *pc) +MarkNotIdempotent(UnrootedScript script, jsbytecode *pc) { if (!script->hasAnalysis()) return; @@ -1080,7 +1080,7 @@ class GetPropCompiler : public PICStubCompiler } RegisterID t0 = tempRegs.takeAnyReg().reg(); - masm.bumpStubCount(f.script().get(nogc), f.pc(), t0); + masm.bumpStubCount(f.script(), f.pc(), t0); /* * Use three values above sp on the stack for use by the call to store @@ -1194,7 +1194,7 @@ class GetPropCompiler : public PICStubCompiler } RegisterID t0 = tempRegs.takeAnyReg().reg(); - masm.bumpStubCount(f.script().get(nogc), f.pc(), t0); + masm.bumpStubCount(f.script(), f.pc(), t0); /* * A JSNative has the following signature: @@ -1273,10 +1273,7 @@ class GetPropCompiler : public PICStubCompiler bool setStubShapeOffset = true; if (obj->isDenseArray()) { - { - RawScript script = f.script().unsafeGet(); - MarkNotIdempotent(script, f.pc()); - } + MarkNotIdempotent(f.script(), f.pc()); start = masm.label(); shapeGuardJump = masm.branchPtr(Assembler::NotEqual, @@ -1392,10 +1389,7 @@ class GetPropCompiler : public PICStubCompiler } if (shape && !shape->hasDefaultGetter()) { - { - RawScript script = f.script().unsafeGet(); - MarkNotIdempotent(script, f.pc()); - } + MarkNotIdempotent(f.script(), f.pc()); if (shape->hasGetterValue()) { generateNativeGetterStub(masm, shape, start, shapeMismatches); @@ -1500,24 +1494,19 @@ class GetPropCompiler : public PICStubCompiler /* Don't touch the IC if it may have been destroyed. */ if (!monitor.recompiled()) pic.hadUncacheable = true; - RawScript script = f.script().unsafeGet(); - MarkNotIdempotent(script, f.pc()); + MarkNotIdempotent(f.script(), f.pc()); return status; } // Mark as not idempotent to avoid recompilation in Ion Monkey // GetPropertyCache. - if (!obj->hasIdempotentProtoChain()) { - RawScript script = f.script().unsafeGet(); - MarkNotIdempotent(script, f.pc()); - } + if (!obj->hasIdempotentProtoChain()) + MarkNotIdempotent(f.script(), f.pc()); // The property is missing, Mark as not idempotent to avoid // recompilation in Ion Monkey GetPropertyCache. - if (!getprop.holder) { - RawScript script = f.script().unsafeGet(); - MarkNotIdempotent(script, f.pc()); - } + if (!getprop.holder) + MarkNotIdempotent(f.script(), f.pc()); if (hadGC()) return Lookup_Uncacheable; diff --git a/js/src/methodjit/Retcon.cpp b/js/src/methodjit/Retcon.cpp index 5f3e67a52ffa..f186de15b0fd 100644 --- a/js/src/methodjit/Retcon.cpp +++ b/js/src/methodjit/Retcon.cpp @@ -350,7 +350,7 @@ ClearAllFrames(JSCompartment *compartment) if (f->entryfp->compartment() != compartment) continue; - Recompiler::patchFrame(compartment, f, f->fp()->script().get(nogc)); + Recompiler::patchFrame(compartment, f, f->fp()->script()); // Clear ncode values from all frames associated with the VMFrame. // Patching the VMFrame's return address will cause all its frames to diff --git a/js/src/methodjit/StubCalls.cpp b/js/src/methodjit/StubCalls.cpp index 05870499b8d0..c1df3f377329 100644 --- a/js/src/methodjit/StubCalls.cpp +++ b/js/src/methodjit/StubCalls.cpp @@ -866,7 +866,7 @@ stubs::RecompileForInline(VMFrame &f) { AutoAssertNoGC nogc; ExpandInlineFrames(f.cx->compartment); - Recompiler::clearStackReferences(f.cx->runtime->defaultFreeOp(), f.script().get(nogc)); + Recompiler::clearStackReferences(f.cx->runtime->defaultFreeOp(), f.script()); f.jit()->destroyChunk(f.cx->runtime->defaultFreeOp(), f.chunkIndex(), /* resetUses = */ false); } @@ -1334,7 +1334,7 @@ stubs::LookupSwitch(VMFrame &f, jsbytecode *pc) { AutoAssertNoGC nogc; jsbytecode *jpc = pc; - JSScript *script = f.fp()->script().get(nogc); + UnrootedScript script = f.fp()->script(); /* This is correct because the compiler adjusts the stack beforehand. */ Value lval = f.regs.sp[-1]; @@ -1660,7 +1660,7 @@ stubs::AssertArgumentTypes(VMFrame &f) AutoAssertNoGC nogc; StackFrame *fp = f.fp(); JSFunction *fun = fp->fun(); - RawScript script = fun->nonLazyScript().get(nogc); + UnrootedScript script = fun->nonLazyScript(); /* * Don't check the type of 'this' for constructor frames, the 'this' value @@ -1705,7 +1705,7 @@ stubs::InvariantFailure(VMFrame &f, void *rval) *frameAddr = repatchCode; /* Recompile the outermost script, and don't hoist any bounds checks. */ - RawScript script = f.fp()->script().get(nogc); + UnrootedScript script = f.fp()->script(); JS_ASSERT(!script->failedBoundsCheck); script->failedBoundsCheck = true; diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 82f8b4473682..0d5d3580345d 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -1541,7 +1541,7 @@ TrapHandler(JSContext *cx, JSScript *, jsbytecode *pc, jsval *rval, /* Debug-mode currently disables Ion compilation. */ JSStackFrame *caller = Jsvalify(iter.interpFrame()); - RawScript script = iter.script().unsafeGet(); + RootedScript script(cx, iter.script()); size_t length; const jschar *chars = JS_GetStringCharsAndLength(cx, str, &length); diff --git a/js/src/vm/ArgumentsObject-inl.h b/js/src/vm/ArgumentsObject-inl.h index 81010397b719..c3a6d55e39ec 100644 --- a/js/src/vm/ArgumentsObject-inl.h +++ b/js/src/vm/ArgumentsObject-inl.h @@ -74,7 +74,7 @@ ArgumentsObject::element(uint32_t i) const 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().nonLazyScript().get(nogc)); ; fi++) { + for (AliasedFormalIter fi(callobj.callee().nonLazyScript()); ; fi++) { if (fi.frameIndex() == i) return callobj.aliasedVar(fi); } @@ -90,7 +90,7 @@ ArgumentsObject::setElement(uint32_t i, const Value &v) 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().nonLazyScript().get(nogc)); ; fi++) { + for (AliasedFormalIter fi(callobj.callee().nonLazyScript()); ; fi++) { if (fi.frameIndex() == i) { callobj.setAliasedVar(fi, v); return; diff --git a/js/src/vm/ArgumentsObject.cpp b/js/src/vm/ArgumentsObject.cpp index 3326163cc3a5..bf5566ccc4be 100644 --- a/js/src/vm/ArgumentsObject.cpp +++ b/js/src/vm/ArgumentsObject.cpp @@ -48,8 +48,7 @@ CopyStackFrameArguments(const StackFrame *fp, HeapValue *dst) /* static */ void ArgumentsObject::MaybeForwardToCallObject(StackFrame *fp, JSObject *obj, ArgumentsData *data) { - AutoAssertNoGC nogc; - RawScript script = fp->script().get(nogc); + UnrootedScript script = fp->script(); if (fp->fun()->isHeavyweight() && script->argsObjAliasesFormals()) { obj->initFixedSlot(MAYBE_CALL_SLOT, ObjectValue(fp->callObj())); for (AliasedFormalIter fi(script); fi; fi++) diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index 363aca9af5c1..62bc35f1dcad 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -1198,7 +1198,7 @@ Debugger::onSingleStep(JSContext *cx, Value *vp) { AutoAssertNoGC nogc; uint32_t stepperCount = 0; - JSScript *trappingScript = fp->script().get(nogc); + UnrootedScript trappingScript = fp->script(); GlobalObject *global = &fp->global(); if (GlobalObject::DebuggerVector *debuggers = global->getDebuggers()) { for (Debugger **p = debuggers->begin(); p != debuggers->end(); p++) { @@ -3496,7 +3496,7 @@ DebuggerFrame_getOffset(JSContext *cx, unsigned argc, Value *vp) { THIS_FRAME(cx, argc, vp, "get offset", args, thisobj, fp); AutoAssertNoGC nogc; - RawScript script = fp->script().get(nogc); + UnrootedScript script = fp->script(); jsbytecode *pc = fp->pcQuadratic(cx); JS_ASSERT(script->code <= pc); JS_ASSERT(pc < script->code + script->length); diff --git a/js/src/vm/SPSProfiler.cpp b/js/src/vm/SPSProfiler.cpp index ccf7b18c8c80..6db2a8493b97 100644 --- a/js/src/vm/SPSProfiler.cpp +++ b/js/src/vm/SPSProfiler.cpp @@ -367,7 +367,7 @@ SPSProfiler::discardMJITCode(mjit::JITScript *jscr, unregisterScript(jscr->script, chunk); for (unsigned i = 0; i < chunk->nInlineFrames; i++) - unregisterScript(chunk->inlineFrames()[i].fun->nonLazyScript().get(nogc), chunk); + unregisterScript(chunk->inlineFrames()[i].fun->nonLazyScript(), chunk); } void diff --git a/js/src/vm/ScopeObject.cpp b/js/src/vm/ScopeObject.cpp index 357c70906284..a45fc9c48d0a 100644 --- a/js/src/vm/ScopeObject.cpp +++ b/js/src/vm/ScopeObject.cpp @@ -81,12 +81,11 @@ StaticScopeIter::block() const return obj->asStaticBlock(); } -JSScript * +UnrootedScript StaticScopeIter::funScript() const { - AutoAssertNoGC nogc; JS_ASSERT(type() == FUNCTION); - return obj->toFunction()->nonLazyScript().get(nogc); + return obj->toFunction()->nonLazyScript(); } /*****************************************************************************/ @@ -1206,7 +1205,7 @@ class DebugScopeProxy : public BaseProxyHandler return false; if (maybefp) { - RawScript script = maybefp->script().get(nogc); + UnrootedScript script = maybefp->script(); unsigned local = block.slotToLocalIndex(script->bindings, shape->slot()); if (action == GET) *vp = maybefp->unaliasedLocal(local); diff --git a/js/src/vm/ScopeObject.h b/js/src/vm/ScopeObject.h index 75bd5d0d7cec..0021a1931cf3 100644 --- a/js/src/vm/ScopeObject.h +++ b/js/src/vm/ScopeObject.h @@ -71,7 +71,7 @@ class StaticScopeIter Type type() const; StaticBlockObject &block() const; - JSScript *funScript() const; + UnrootedScript funScript() const; }; /*****************************************************************************/ diff --git a/js/src/vm/Stack-inl.h b/js/src/vm/Stack-inl.h index 5d56d48c2db3..992c569b5293 100644 --- a/js/src/vm/Stack-inl.h +++ b/js/src/vm/Stack-inl.h @@ -579,7 +579,7 @@ ContextStack::currentScript(jsbytecode **ppc, 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->nonLazyScript().get(nogc); + UnrootedScript script = frame->fun->nonLazyScript(); if (!allowCrossCompartment && script->compartment() != cx_->compartment) return NULL; if (ppc) @@ -588,7 +588,7 @@ ContextStack::currentScript(jsbytecode **ppc, } #endif - RawScript script = fp->script().get(nogc); + UnrootedScript script = fp->script(); if (!allowCrossCompartment && script->compartment() != cx_->compartment) return NULL; diff --git a/js/src/vm/Stack.h b/js/src/vm/Stack.h index 99c5eae6441d..5fca8590739c 100644 --- a/js/src/vm/Stack.h +++ b/js/src/vm/Stack.h @@ -9,6 +9,7 @@ #define Stack_h__ #include "jsfun.h" +#include "jsscript.h" #ifdef JS_ION #include "ion/IonFrameIterator.h" #endif @@ -609,11 +610,11 @@ class StackFrame * the same VMFrame. Other calls force expansion of the inlined frames. */ - js::Return script() const { + UnrootedScript script() const { return isFunctionFrame() ? isEvalFrame() ? u.evalScript - : (JSScript*)fun()->nonLazyScript().unsafeGet() + : (RawScript)fun()->nonLazyScript() : exec.script; } @@ -1199,8 +1200,7 @@ class FrameRegs } void setToEndOfScript() { - AutoAssertNoGC nogc; - RawScript script = fp()->script().get(nogc); + UnrootedScript script = fp()->script(); sp = fp()->base(); pc = script->code + script->length - JSOP_STOP_LENGTH; JS_ASSERT(*pc == JSOP_STOP); @@ -1800,7 +1800,7 @@ class StackIter StackFrame *interpFrame() const { JS_ASSERT(isScript() && !isIon()); return fp_; } jsbytecode *pc() const { JS_ASSERT(isScript()); return pc_; } - js::Return script() const { JS_ASSERT(isScript()); return script_; } + UnrootedScript script() const { JS_ASSERT(isScript()); return script_; } JSFunction *callee() const; Value calleev() const; unsigned numActualArgs() const;