Bug 819118 - Use accessor rather than direct script access; r=billm
authorTerrence Cole <terrence@mozilla.com>
Wed, 05 Dec 2012 14:21:44 -0800
changeset 121282 9602f98a6a7035f6681cf10e03ab443e06606709
parent 121281 513ec84b5c883c206ad4ebbbfa30d7c134d5065b
child 121283 a41a29550c44067a34093483a8e0b36cfb227d3d
push idunknown
push userunknown
push dateunknown
reviewersbillm
bugs819118
milestone20.0a1
Bug 819118 - Use accessor rather than direct script access; r=billm This abstracts the requirement to manually cast from HeapPtr to Unrooted.
js/src/ion/IonBuilder.cpp
js/src/ion/MCallOptimize.cpp
js/src/ion/TypeOracle.cpp
js/src/ion/TypeOracle.h
js/src/jsgcinlines.h
js/src/jsscript.h
--- a/js/src/ion/IonBuilder.cpp
+++ b/js/src/ion/IonBuilder.cpp
@@ -57,27 +57,27 @@ bool
 IonBuilder::abort(const char *message, ...)
 {
     // Don't call PCToLineNumber in release builds.
 #ifdef DEBUG
     va_list ap;
     va_start(ap, message);
     abortFmt(message, ap);
     va_end(ap);
-    IonSpew(IonSpew_Abort, "aborted @ %s:%d", script_->filename, PCToLineNumber(script_, pc));
+    IonSpew(IonSpew_Abort, "aborted @ %s:%d", script()->filename, PCToLineNumber(script(), pc));
 #endif
     return false;
 }
 
 void
 IonBuilder::spew(const char *message)
 {
     // Don't call PCToLineNumber in release builds.
 #ifdef DEBUG
-    IonSpew(IonSpew_MIR, "%s @ %s:%d", message, script_->filename, PCToLineNumber(script_, pc));
+    IonSpew(IonSpew_MIR, "%s @ %s:%d", message, script()->filename, PCToLineNumber(script(), pc));
 #endif
 }
 
 static inline int32_t
 GetJumpOffset(jsbytecode *pc)
 {
     JS_ASSERT(js_CodeSpec[JSOp(*pc)].type() == JOF_JUMP);
     return GET_JUMP_OFFSET(pc);
@@ -163,17 +163,17 @@ IonBuilder::getSingleCallTarget(uint32_t
 
     return obj->toFunction();
 }
 
 uint32_t
 IonBuilder::getPolyCallTargets(uint32_t argc, jsbytecode *pc,
                                AutoObjectVector &targets, uint32_t maxTargets)
 {
-    types::TypeSet *calleeTypes = oracle->getCallTarget(script_, argc, pc);
+    types::TypeSet *calleeTypes = oracle->getCallTarget(script(), argc, pc);
     if (!calleeTypes)
         return 0;
 
     if (calleeTypes->baseFlags() != 0)
         return 0;
 
     unsigned objCount = calleeTypes->getObjectCount();
 
@@ -195,17 +195,17 @@ IonBuilder::canInlineTarget(JSFunction *
 {
     AssertCanGC();
 
     if (!target->isInterpreted()) {
         IonSpew(IonSpew_Inlining, "Cannot inline due to non-interpreted");
         return false;
     }
 
-    if (target->getParent() != &script_->global()) {
+    if (target->getParent() != &script()->global()) {
         IonSpew(IonSpew_Inlining, "Cannot inline due to scope mismatch");
         return false;
     }
 
     RootedScript inlineScript(cx, target->nonLazyScript());
     ExecutionMode executionMode = info().executionMode();
     if (!CanIonCompile(inlineScript, executionMode)) {
         IonSpew(IonSpew_Inlining, "Cannot inline due to disable Ion compilation");
@@ -220,17 +220,17 @@ IonBuilder::canInlineTarget(JSFunction *
             return false;
         }
         builder = builder->callerBuilder_;
     }
 
     bool canInline = oracle->canEnterInlinedFunction(target);
 
     if (!canInline) {
-        IonSpew(IonSpew_Inlining, "Cannot inline due to oracle veto %d", script_->lineno);
+        IonSpew(IonSpew_Inlining, "Cannot inline due to oracle veto %d", script()->lineno);
         return false;
     }
 
     IonSpew(IonSpew_Inlining, "Inlining good to go!");
     return true;
 }
 
 void
@@ -269,20 +269,20 @@ IonBuilder::pushLoop(CFGState::State ini
 bool
 IonBuilder::build()
 {
     current = newBlock(pc);
     if (!current)
         return false;
 
     IonSpew(IonSpew_Scripts, "Analyzing script %s:%d (%p) (usecount=%d) (maxloopcount=%d)",
-            script_->filename, script_->lineno, (void *)script_, (int)script_->getUseCount(),
-            (int)script_->getMaxLoopCount());
-
-    if (!graph().addScript(script_))
+            script()->filename, script()->lineno, (void *)script(), (int)script()->getUseCount(),
+            (int)script()->getMaxLoopCount());
+
+    if (!graph().addScript(script()))
         return false;
 
     if (!initParameters())
         return false;
 
     // Initialize local variables.
     for (uint32_t i = 0; i < info().nlocals(); i++) {
         MConstant *undef = MConstant::New(UndefinedValue());
@@ -298,17 +298,17 @@ IonBuilder::build()
         MInstruction *scope = MConstant::New(UndefinedValue());
         current->add(scope);
         current->initSlot(info().scopeChainSlot(), scope);
     }
 
     // Emit the start instruction, so we can begin real instructions.
     current->makeStart(MStart::New(MStart::StartType_Default));
     if (instrumentedProfiling())
-        current->add(MFunctionBoundary::New(script_, MFunctionBoundary::Enter));
+        current->add(MFunctionBoundary::New(script(), MFunctionBoundary::Enter));
 
     // Parameters have been checked to correspond to the typeset, now we unbox
     // what we can in an infallible manner.
     rewriteParameters();
 
     // It's safe to start emitting actual IR, so now build the scope chain.
     if (!initScopeChain())
         return false;
@@ -341,17 +341,17 @@ IonBuilder::build()
         MInstruction *ins = current->getEntrySlot(i)->toInstruction();
         if (ins->type() == MIRType_Value)
             ins->setResumePoint(current->entryResumePoint());
     }
 
     // Recompile to inline calls if this function is hot.
     insertRecompileCheck();
 
-    if (script_->argumentsHasVarBinding()) {
+    if (script()->argumentsHasVarBinding()) {
         lazyArguments_ = MConstant::New(MagicValue(JS_OPTIMIZED_ARGUMENTS));
         current->add(lazyArguments_);
     }
 
     if (!traverseBytecode())
         return false;
 
     if (!processIterators())
@@ -395,19 +395,19 @@ IonBuilder::processIterators()
     return true;
 }
 
 bool
 IonBuilder::buildInline(IonBuilder *callerBuilder, MResumePoint *callerResumePoint,
                         MDefinition *thisDefn, MDefinitionVector &argv)
 {
     IonSpew(IonSpew_Scripts, "Inlining script %s:%d (%p)",
-            script_->filename, script_->lineno, (void *)script_);
-
-    if (!graph().addScript(script_))
+            script()->filename, script()->lineno, (void *)script());
+
+    if (!graph().addScript(script()))
         return false;
 
     callerBuilder_ = callerBuilder;
     callerResumePoint_ = callerResumePoint;
 
     if (callerBuilder->failedBoundsCheck_)
         failedBoundsCheck_ = true;
 
@@ -425,17 +425,17 @@ IonBuilder::buildInline(IonBuilder *call
     MBasicBlock *predecessor = callerBuilder->current;
     JS_ASSERT(predecessor == callerResumePoint->block());
 
     // All further instructions generated in from this scope should be
     // considered as part of the function that we're inlining. We also need to
     // keep track of the inlining depth because all scripts inlined on the same
     // level contiguously have only one Inline_Exit node.
     if (instrumentedProfiling())
-        predecessor->add(MFunctionBoundary::New(script_,
+        predecessor->add(MFunctionBoundary::New(script(),
                                                 MFunctionBoundary::Inline_Enter,
                                                 inliningDepth));
 
     predecessor->end(MGoto::New(current));
     if (!current->addPredecessorWithoutPhis(predecessor))
         return false;
 
     // Explicitly pass Undefined for missing arguments.
@@ -449,17 +449,17 @@ IonBuilder::buildInline(IonBuilder *call
             MConstant *undef = MConstant::New(UndefinedValue());
             current->add(undef);
             if (!argv.append(undef))
                 return false;
         }
     }
 
     // The Oracle ensures that the inlined script does not use the scope chain.
-    JS_ASSERT(!script_->analysis()->usesScopeChain());
+    JS_ASSERT(!script()->analysis()->usesScopeChain());
     MInstruction *scope = MConstant::New(UndefinedValue());
     current->add(scope);
     current->initSlot(info().scopeChainSlot(), scope);
 
     current->initSlot(info().thisSlot(), thisDefn);
 
     IonSpew(IonSpew_Inlining, "Initializing %u arg slots", nargs);
 
@@ -501,19 +501,19 @@ IonBuilder::rewriteParameters()
 
     for (uint32_t i = START_SLOT; i < CountArgSlots(info().fun()); i++) {
         MParameter *param = current->getSlot(i)->toParameter();
 
         // Find the original (not cloned) type set for the MParameter, as we
         // will be adding constraints to it.
         types::StackTypeSet *types;
         if (param->index() == MParameter::THIS_SLOT)
-            types = oracle->thisTypeSet(script_);
+            types = oracle->thisTypeSet(script());
         else
-            types = oracle->parameterTypeSet(script_, param->index());
+            types = oracle->parameterTypeSet(script(), param->index());
         if (!types)
             continue;
 
         JSValueType definiteType = types->getKnownTypeTag();
         if (definiteType == JSVAL_TYPE_UNKNOWN)
             continue;
 
         MInstruction *actual = NULL;
@@ -549,44 +549,44 @@ IonBuilder::rewriteParameters()
 
 bool
 IonBuilder::initParameters()
 {
     if (!info().fun())
         return true;
 
     MParameter *param = MParameter::New(MParameter::THIS_SLOT,
-                                        cloneTypeSet(oracle->thisTypeSet(script_)));
+                                        cloneTypeSet(oracle->thisTypeSet(script())));
     current->add(param);
     current->initSlot(info().thisSlot(), param);
 
     for (uint32_t i = 0; i < info().nargs(); i++) {
-        param = MParameter::New(i, cloneTypeSet(oracle->parameterTypeSet(script_, i)));
+        param = MParameter::New(i, cloneTypeSet(oracle->parameterTypeSet(script(), i)));
         current->add(param);
         current->initSlot(info().argSlot(i), param);
     }
 
     return true;
 }
 
 bool
 IonBuilder::initScopeChain()
 {
     MInstruction *scope = NULL;
 
     // If the script doesn't use the scopechain, then it's already initialized
     // from earlier.
-    if (!script_->analysis()->usesScopeChain())
+    if (!script()->analysis()->usesScopeChain())
         return true;
 
     // The scope chain is only tracked in scripts that have NAME opcodes which
     // will try to access the scope. For other scripts, the scope instructions
     // will be held live by resume points and code will still be generated for
     // them, so just use a constant undefined value.
-    if (!script_->compileAndGo)
+    if (!script()->compileAndGo)
         return abort("non-CNG global scripts are not supported");
 
     if (JSFunction *fun = info().fun()) {
         MCallee *callee = MCallee::New();
         current->add(callee);
 
         scope = MFunctionEnvironment::New(callee);
         current->add(scope);
@@ -599,17 +599,17 @@ IonBuilder::initScopeChain()
                     return false;
             }
 
             scope = createCallObject(callee, scope);
             if (!scope)
                 return false;
         }
     } else {
-        scope = MConstant::New(ObjectValue(script_->global()));
+        scope = MConstant::New(ObjectValue(script()->global()));
         current->add(scope);
     }
 
     current->setScopeChain(scope);
     return true;
 }
 
 // We try to build a control-flow graph in the order that it would be built as
@@ -952,17 +952,17 @@ IonBuilder::inspectOpcode(JSOp op)
       case JSOP_GETGNAME:
       case JSOP_CALLGNAME:
       {
         RootedPropertyName name(cx, info().getAtom(pc)->asPropertyName());
         return jsop_getgname(name);
       }
 
       case JSOP_BINDGNAME:
-        return pushConstant(ObjectValue(script_->global()));
+        return pushConstant(ObjectValue(script()->global()));
 
       case JSOP_SETGNAME:
       {
         RootedPropertyName name(cx, info().getAtom(pc)->asPropertyName());
         return jsop_setgname(name);
       }
 
       case JSOP_NAME:
@@ -2296,17 +2296,17 @@ IonBuilder::lookupSwitch(JSOp op, jssrcn
     bool defaultShared = false;
 
     MBasicBlock *prevCond = NULL;
     MCompare *prevCmpIns = NULL;
     MBasicBlock *prevBody = NULL;
     bool prevShared = false;
     jsbytecode *prevpc = NULL;
     for (unsigned int i = 0; i < ncases; i++) {
-        Value rval = script_->getConst(GET_UINT32_INDEX(pc2));
+        Value rval = script()->getConst(GET_UINT32_INDEX(pc2));
         pc2 += UINT32_INDEX_LEN;
         jsbytecode *casepc = pc + GET_JUMP_OFFSET(pc2);
         pc2 += JUMP_OFFSET_LEN;
         JS_ASSERT(casepc > pc && casepc <= exitpc);
         JS_ASSERT_IF(i > 0, prevpc <= casepc);
 
         // Create case block
         MBasicBlock *cond = newBlock(((i == 0) ? current : prevCond), casepc);
@@ -2862,17 +2862,17 @@ IonBuilder::processReturn(JSOp op)
 
       default:
         def = NULL;
         JS_NOT_REACHED("unknown return op");
         break;
     }
 
     if (instrumentedProfiling())
-        current->add(MFunctionBoundary::New(script_, MFunctionBoundary::Exit));
+        current->add(MFunctionBoundary::New(script(), MFunctionBoundary::Exit));
     MReturn *ret = MReturn::New(def);
     current->end(ret);
 
     if (!graph().addExit(current))
         return ControlStatus_Error;
 
     // Make sure no one tries to use this block now.
     current = NULL;
@@ -2906,17 +2906,17 @@ IonBuilder::pushConstant(const Value &v)
 
 bool
 IonBuilder::jsop_bitnot()
 {
     MDefinition *input = current->pop();
     MBitNot *ins = MBitNot::New(input);
 
     current->add(ins);
-    ins->infer(oracle->unaryTypes(script_, pc));
+    ins->infer(oracle->unaryTypes(script(), pc));
 
     current->push(ins);
     if (ins->isEffectful() && !resumeAfter(ins))
         return false;
     return true;
 }
 bool
 IonBuilder::jsop_bitop(JSOp op)
@@ -2952,29 +2952,29 @@ IonBuilder::jsop_bitop(JSOp op)
         break;
 
       default:
         JS_NOT_REACHED("unexpected bitop");
         return false;
     }
 
     current->add(ins);
-    ins->infer(oracle->binaryTypes(script_, pc));
+    ins->infer(oracle->binaryTypes(script(), pc));
 
     current->push(ins);
     if (ins->isEffectful() && !resumeAfter(ins))
         return false;
 
     return true;
 }
 
 bool
 IonBuilder::jsop_binary(JSOp op, MDefinition *left, MDefinition *right)
 {
-    TypeOracle::Binary b = oracle->binaryOp(script_, pc);
+    TypeOracle::Binary b = oracle->binaryOp(script(), pc);
 
     if (op == JSOP_ADD && b.rval == MIRType_String &&
         (b.lhs == MIRType_String || b.lhs == MIRType_Int32) &&
         (b.rhs == MIRType_String || b.rhs == MIRType_Int32))
     {
         MConcat *ins = MConcat::New(left, right);
         current->add(ins);
         current->push(ins);
@@ -3003,17 +3003,17 @@ IonBuilder::jsop_binary(JSOp op, MDefini
         ins = MMod::New(left, right);
         break;
 
       default:
         JS_NOT_REACHED("unexpected binary opcode");
         return false;
     }
 
-    TypeOracle::BinaryTypes types = oracle->binaryTypes(script_, pc);
+    TypeOracle::BinaryTypes types = oracle->binaryTypes(script(), pc);
     current->add(ins);
     ins->infer(cx, types);
     current->push(ins);
 
     if (ins->isEffectful())
         return resumeAfter(ins);
     return maybeInsertResume();
 }
@@ -3025,17 +3025,17 @@ IonBuilder::jsop_binary(JSOp op)
     MDefinition *left = current->pop();
 
     return jsop_binary(op, left, right);
 }
 
 bool
 IonBuilder::jsop_pos()
 {
-    TypeOracle::Unary types = oracle->unaryOp(script_, pc);
+    TypeOracle::Unary types = oracle->unaryOp(script(), pc);
     if (IsNumberType(types.ival)) {
         // Already int32 or double.
         JS_ASSERT(IsNumberType(types.rval));
         return true;
     }
 
     // Compile +x as x * 1.
     MDefinition *value = current->pop();
@@ -3199,57 +3199,58 @@ IonBuilder::makeInliningDecision(AutoObj
     //     higher proportion of the runtime of the function than for larger
     //     functions.
     //  2. The cost of inlining (in terms of size expansion of the SSA graph),
     //     and size expansion of the ultimately generated code, will be
     //     less significant.
     //  3. Do not inline functions which are not called as frequently as their
     //     callers.
 
-    uint32_t callerUses = script_->getUseCount();
+    uint32_t callerUses = script()->getUseCount();
 
     uint32_t totalSize = 0;
     uint32_t checkUses = js_IonOptions.usesBeforeInlining;
     bool allFunctionsAreSmall = true;
     RootedFunction target(cx);
-    RootedScript script(cx);
+    RootedScript targetScript(cx);
     for (size_t i = 0; i < targets.length(); i++) {
         target = targets[i]->toFunction();
         if (!target->isInterpreted())
             return false;
 
-        script = target->nonLazyScript();
-        uint32_t calleeUses = script->getUseCount();
+        targetScript = target->nonLazyScript();
+        uint32_t calleeUses = targetScript->getUseCount();
 
         if (target->nargs < argc) {
             IonSpew(IonSpew_Inlining, "Not inlining, overflow of arguments.");
             return false;
         }
 
-        totalSize += script->length;
+        totalSize += targetScript->length;
         if (totalSize > js_IonOptions.inlineMaxTotalBytecodeLength)
             return false;
 
-        if (script->length > js_IonOptions.smallFunctionMaxBytecodeLength)
+        if (targetScript->length > js_IonOptions.smallFunctionMaxBytecodeLength)
             allFunctionsAreSmall = false;
 
         if (calleeUses * js_IonOptions.inlineUseCountRatio < callerUses) {
             IonSpew(IonSpew_Inlining, "Not inlining, callee is not hot");
             return false;
         }
     }
     if (allFunctionsAreSmall)
         checkUses = js_IonOptions.smallFunctionUsesBeforeInlining;
 
-    if (script_->getUseCount() < checkUses) {
+    if (script()->getUseCount() < checkUses) {
         IonSpew(IonSpew_Inlining, "Not inlining, caller is not hot");
         return false;
     }
 
-    if (!oracle->canInlineCall(script_, pc)) {
+    RootedScript scriptRoot(cx, script());
+    if (!oracle->canInlineCall(scriptRoot, pc)) {
         IonSpew(IonSpew_Inlining, "Cannot inline due to uninlineable call site");
         return false;
     }
 
     for (size_t i = 0; i < targets.length(); i++) {
         if (!canInlineTarget(targets[i]->toFunction())) {
             IonSpew(IonSpew_Inlining, "Decided not to inline");
             return false;
@@ -3773,17 +3774,18 @@ IonBuilder::createDeclEnvObject(MDefinit
 }
 
 MInstruction *
 IonBuilder::createCallObject(MDefinition *callee, MDefinition *scope)
 {
     // Create a template CallObject that we'll use to generate inline object
     // creation.
 
-    RootedObject templateObj(cx, CallObject::createTemplateObject(cx, script_));
+    RootedScript scriptRoot(cx, script());
+    RootedObject templateObj(cx, CallObject::createTemplateObject(cx, scriptRoot));
     if (!templateObj)
         return NULL;
 
     // If the CallObject needs dynamic slots, allocate those now.
     MInstruction *slots;
     if (templateObj->hasDynamicSlots()) {
         size_t nslots = JSObject::dynamicSlotsCount(templateObj->numFixedSlots(),
                                                     templateObj->slotSpan());
@@ -3799,17 +3801,17 @@ IonBuilder::createCallObject(MDefinition
     MInstruction *callObj = MNewCallObject::New(templateObj, slots);
     current->add(callObj);
 
     // Initialize the object's reserved slots.
     current->add(MStoreFixedSlot::New(callObj, CallObject::enclosingScopeSlot(), scope));
     current->add(MStoreFixedSlot::New(callObj, CallObject::calleeSlot(), callee));
 
     // Initialize argument slots.
-    for (AliasedFormalIter i(script_); i; i++) {
+    for (AliasedFormalIter i(script()); i; i++) {
         unsigned slot = i.scopeSlot();
         unsigned formal = i.frameIndex();
         MDefinition *param = current->getSlot(info().argSlot(formal));
         if (slot >= templateObj->numFixedSlots())
             current->add(MStoreSlot::New(slots, slot - templateObj->numFixedSlots(), param));
         else
             current->add(MStoreFixedSlot::New(callObj, slot, param));
     }
@@ -3947,17 +3949,17 @@ IonBuilder::jsop_funcall(uint32_t argc)
     // argc+2: The native 'call' function.
 
     // If |Function.prototype.call| may be overridden, don't optimize callsite.
     RootedFunction native(cx, getSingleCallTarget(argc, pc));
     if (!native || !native->isNative() || native->native() != &js_fun_call)
         return makeCall(native, argc, false);
 
     // Extract call target.
-    types::StackTypeSet *funTypes = oracle->getCallArg(script_, argc, 0, pc);
+    types::StackTypeSet *funTypes = oracle->getCallArg(script(), argc, 0, pc);
     RootedObject funobj(cx, (funTypes) ? funTypes->getSingleton() : NULL);
     RootedFunction target(cx, (funobj && funobj->isFunction()) ? funobj->toFunction() : NULL);
 
     // Unwrap the (JSFunction *) parameter.
     int funcDepth = -((int)argc + 1);
     MPassArg *passFunc = current->peek(funcDepth)->toPassArg();
     current->rewriteAtDepth(funcDepth, passFunc->getArgument());
 
@@ -3989,17 +3991,17 @@ bool
 IonBuilder::jsop_funapply(uint32_t argc)
 {
     RootedFunction native(cx, getSingleCallTarget(argc, pc));
     if (argc != 2)
         return makeCall(native, argc, false);
 
     // Disable compilation if the second argument to |apply| cannot be guaranteed
     // to be either definitely |arguments| or definitely not |arguments|.
-    types::StackTypeSet *argObjTypes = oracle->getCallArg(script_, argc, 2, pc);
+    types::StackTypeSet *argObjTypes = oracle->getCallArg(script(), argc, 2, pc);
     LazyArgumentsType isArgObj = oracle->isArgumentObject(argObjTypes);
     if (isArgObj == MaybeArguments)
         return abort("fun.apply with MaybeArguments");
 
     // Fallback to regular call if arg 2 is not definitely |arguments|.
     if (isArgObj != DefinitelyArguments)
         return makeCall(native, argc, false);
 
@@ -4012,17 +4014,17 @@ IonBuilder::jsop_funapply(uint32_t argc)
 
     // Stack for JSOP_FUNAPPLY:
     // 1:      MPassArg(Vp)
     // 2:      MPassArg(This)
     // argc+1: MPassArg(JSFunction *), the 'f' in |f.call()|, in |this| position.
     // argc+2: The native 'apply' function.
 
     // Extract call target.
-    types::StackTypeSet *funTypes = oracle->getCallArg(script_, argc, 0, pc);
+    types::StackTypeSet *funTypes = oracle->getCallArg(script(), argc, 0, pc);
     RootedObject funobj(cx, (funTypes) ? funTypes->getSingleton() : NULL);
     RootedFunction target(cx, (funobj && funobj->isFunction()) ? funobj->toFunction() : NULL);
 
     // Vp
     MPassArg *passVp = current->pop()->toPassArg();
     passVp->replaceAllUsesWith(passVp->getArgument());
     passVp->block()->discard(passVp);
 
@@ -4046,30 +4048,30 @@ IonBuilder::jsop_funapply(uint32_t argc)
 
     MApplyArgs *apply = MApplyArgs::New(target, argFunc, numArgs, argThis);
     current->add(apply);
     current->push(apply);
     if (!resumeAfter(apply))
         return false;
 
     types::StackTypeSet *barrier;
-    types::StackTypeSet *types = oracle->returnTypeSet(script_, pc, &barrier);
+    types::StackTypeSet *types = oracle->returnTypeSet(script(), pc, &barrier);
     return pushTypeBarrier(apply, types, barrier);
 }
 
 bool
 IonBuilder::jsop_call(uint32_t argc, bool constructing)
 {
     AssertCanGC();
 
     // Acquire known call target if existent.
     AutoObjectVector targets(cx);
     uint32_t numTargets = getPolyCallTargets(argc, pc, targets, 4);
     types::StackTypeSet *barrier;
-    types::StackTypeSet *types = oracle->returnTypeSet(script_, pc, &barrier);
+    types::StackTypeSet *types = oracle->returnTypeSet(script(), pc, &barrier);
 
     // Attempt to inline native and scripted functions.
     if (inliningEnabled()) {
         // Inline a single native call if possible.
         if (numTargets == 1 && targets[0]->toFunction()->isNative()) {
             RootedFunction target(cx, targets[0]->toFunction());
             switch (inlineNativeCall(target->native(), argc, constructing)) {
               case InliningStatus_Inlined:
@@ -4178,62 +4180,63 @@ IonBuilder::makeCallBarrier(HandleFuncti
 
     return pushTypeBarrier(call, types, barrier);
 }
 
 bool
 IonBuilder::makeCall(HandleFunction target, uint32_t argc, bool constructing)
 {
     types::StackTypeSet *barrier;
-    types::StackTypeSet *types = oracle->returnTypeSet(script_, pc, &barrier);
+    types::StackTypeSet *types = oracle->returnTypeSet(script(), pc, &barrier);
     return makeCallBarrier(target, argc, constructing, types, barrier);
 }
 
 bool
 IonBuilder::jsop_compare(JSOp op)
 {
     MDefinition *right = current->pop();
     MDefinition *left = current->pop();
 
     MCompare *ins = MCompare::New(left, right, op);
     current->add(ins);
     current->push(ins);
 
-    ins->infer(cx, oracle->binaryTypes(script_, pc));
+    TypeOracle::BinaryTypes b = oracle->binaryTypes(script(), pc);
+    ins->infer(cx, b);
 
     if (ins->isEffectful() && !resumeAfter(ins))
         return false;
     return true;
 }
 
 JSObject *
 IonBuilder::getNewArrayTemplateObject(uint32_t count)
 {
     RootedObject templateObject(cx, NewDenseUnallocatedArray(cx, count));
     if (!templateObject)
         return NULL;
 
-    RootedScript script(cx, script_);
-    if (types::UseNewTypeForInitializer(cx, script, pc, JSProto_Array)) {
+    RootedScript scriptRoot(cx, script());
+    if (types::UseNewTypeForInitializer(cx, scriptRoot, pc, JSProto_Array)) {
         if (!JSObject::setSingletonType(cx, templateObject))
             return NULL;
     } else {
-        types::TypeObject *type = types::TypeScript::InitObject(cx, script, pc, JSProto_Array);
+        types::TypeObject *type = types::TypeScript::InitObject(cx, scriptRoot, pc, JSProto_Array);
         if (!type)
             return NULL;
         templateObject->setType(type);
     }
 
     return templateObject;
 }
 
 bool
 IonBuilder::jsop_newarray(uint32_t count)
 {
-    JS_ASSERT(script_->compileAndGo);
+    JS_ASSERT(script()->compileAndGo);
 
     JSObject *templateObject = getNewArrayTemplateObject(count);
     if (!templateObject)
         return false;
 
     MNewArray *ins = new MNewArray(count, templateObject, MNewArray::NewArray_Allocating);
 
     current->add(ins);
@@ -4241,54 +4244,54 @@ IonBuilder::jsop_newarray(uint32_t count
 
     return true;
 }
 
 bool
 IonBuilder::jsop_newobject(HandleObject baseObj)
 {
     // Don't bake in the TypeObject for non-CNG scripts.
-    JS_ASSERT(script_->compileAndGo);
+    JS_ASSERT(script()->compileAndGo);
 
     RootedObject templateObject(cx);
 
     if (baseObj) {
         templateObject = CopyInitializerObject(cx, baseObj);
     } else {
         gc::AllocKind kind = GuessObjectGCKind(0);
         templateObject = NewBuiltinClassInstance(cx, &ObjectClass, kind);
     }
 
     if (!templateObject)
         return false;
 
-    RootedScript script(cx, script_);
-    if (types::UseNewTypeForInitializer(cx, script, pc, JSProto_Object)) {
+    RootedScript scriptRoot(cx, script());
+    if (types::UseNewTypeForInitializer(cx, scriptRoot, pc, JSProto_Object)) {
         if (!JSObject::setSingletonType(cx, templateObject))
             return false;
     } else {
-        types::TypeObject *type = types::TypeScript::InitObject(cx, script, pc, JSProto_Object);
+        types::TypeObject *type = types::TypeScript::InitObject(cx, scriptRoot, pc, JSProto_Object);
         if (!type)
             return false;
         templateObject->setType(type);
     }
 
     MNewObject *ins = MNewObject::New(templateObject);
 
     current->add(ins);
     current->push(ins);
 
     return resumeAfter(ins);
 }
 
 bool
 IonBuilder::jsop_initelem()
 {
-    if (oracle->propertyWriteCanSpecialize(script_, pc)) {
-        if (oracle->elementWriteIsDenseArray(script_, pc))
+    if (oracle->propertyWriteCanSpecialize(script(), pc)) {
+        if (oracle->elementWriteIsDenseArray(script(), pc))
             return jsop_initelem_dense();
     }
 
     return abort("NYI: JSOP_INITELEM supports for non dense objects/arrays.");
 }
 
 bool
 IonBuilder::jsop_initelem_dense()
@@ -4331,17 +4334,17 @@ CanEffectlesslyCallLookupGenericOnObject
 bool
 IonBuilder::jsop_initprop(HandlePropertyName name)
 {
     MDefinition *value = current->pop();
     MDefinition *obj = current->peek(-1);
 
     RootedObject templateObject(cx, obj->toNewObject()->templateObject());
 
-    if (!oracle->propertyWriteCanSpecialize(script_, pc)) {
+    if (!oracle->propertyWriteCanSpecialize(script(), pc)) {
         // This should only happen for a few names like __proto__.
         return abort("INITPROP Monitored initprop");
     }
 
     if (!CanEffectlesslyCallLookupGenericOnObject(templateObject))
         return abort("INITPROP template object is special");
 
     RootedObject holder(cx);
@@ -4355,17 +4358,17 @@ IonBuilder::jsop_initprop(HandleProperty
     if (!shape || holder != templateObject) {
         // JSOP_NEWINIT becomes an MNewObject without preconfigured properties.
         MInitProp *init = MInitProp::New(obj, name, value);
         current->add(init);
         return resumeAfter(init);
     }
 
     bool needsBarrier = true;
-    TypeOracle::BinaryTypes b = oracle->binaryTypes(script_, pc);
+    TypeOracle::BinaryTypes b = oracle->binaryTypes(script(), pc);
     if (b.lhsTypes &&
         ((jsid)id == types::MakeTypeId(cx, id)) &&
         !b.lhsTypes->propertyNeedsBarrier(cx, id))
     {
         needsBarrier = false;
     }
 
     if (templateObject->isFixedSlot(shape->slot())) {
@@ -4679,25 +4682,25 @@ IonBuilder::insertRecompileCheck()
 {
     if (!inliningEnabled())
         return;
 
     if (inliningDepth > 0)
         return;
 
     // Don't recompile if we are already inlining.
-    if (script_->getUseCount() >= js_IonOptions.usesBeforeInlining)
+    if (script()->getUseCount() >= js_IonOptions.usesBeforeInlining)
         return;
 
     // Don't recompile if the oracle cannot provide inlining information
     // or if the script has no calls.
     if (!oracle->canInlineCalls())
         return;
 
-    uint32_t minUses = UsesBeforeIonRecompile(script_, pc);
+    uint32_t minUses = UsesBeforeIonRecompile(script(), pc);
     MRecompileCheck *check = MRecompileCheck::New(minUses);
     current->add(check);
 }
 
 static inline bool
 TestSingletonProperty(JSContext *cx, HandleObject obj, HandleId id, bool *isKnownConstant)
 {
     // We would like to completely no-op property/global accesses which can
@@ -4955,39 +4958,40 @@ IonBuilder::jsop_getgname(HandleProperty
     // Optimize undefined, NaN, and Infinity.
     if (name == cx->names().undefined)
         return pushConstant(UndefinedValue());
     if (name == cx->names().NaN)
         return pushConstant(cx->runtime->NaNValue);
     if (name == cx->names().Infinity)
         return pushConstant(cx->runtime->positiveInfinityValue);
 
-    RootedObject globalObj(cx, &script_->global());
+    RootedObject globalObj(cx, &script()->global());
     JS_ASSERT(globalObj->isNative());
 
     RootedId id(cx, NameToId(name));
 
     // For the fastest path, the property must be found, and it must be found
     // as a normal data property on exactly the global object.
     const js::Shape *shape = globalObj->nativeLookup(cx, id);
     if (!shape || !shape->hasDefaultGetter() || !shape->hasSlot())
         return jsop_getname(name);
 
-    types::HeapTypeSet *propertyTypes = oracle->globalPropertyTypeSet(script_, pc, id);
+    types::HeapTypeSet *propertyTypes = oracle->globalPropertyTypeSet(script(), pc, id);
     if (propertyTypes && propertyTypes->isOwnProperty(cx, globalObj->getType(cx), true)) {
         // The property has been reconfigured as non-configurable, non-enumerable
         // or non-writable.
         return jsop_getname(name);
     }
 
     // If the property is permanent, a shape guard isn't necessary.
     JSValueType knownType = JSVAL_TYPE_UNKNOWN;
 
-    types::StackTypeSet *barrier = oracle->propertyReadBarrier(script_, pc);
-    types::StackTypeSet *types = oracle->propertyRead(script_, pc);
+    RootedScript scriptRoot(cx, script());
+    types::StackTypeSet *barrier = oracle->propertyReadBarrier(scriptRoot, pc);
+    types::StackTypeSet *types = oracle->propertyRead(script(), pc);
     if (types) {
         JSObject *singleton = types->getSingleton();
 
         knownType = types->getKnownTypeTag();
         if (!barrier) {
             if (singleton) {
                 // Try to inline a known constant value.
                 bool isKnownConstant;
@@ -5024,23 +5028,23 @@ IonBuilder::jsop_getgname(HandleProperty
 
     current->push(load);
     return pushTypeBarrier(load, types, barrier);
 }
 
 bool
 IonBuilder::jsop_setgname(HandlePropertyName name)
 {
-    RootedObject globalObj(cx, &script_->global());
+    RootedObject globalObj(cx, &script()->global());
     RootedId id(cx, NameToId(name));
 
     JS_ASSERT(globalObj->isNative());
 
     bool canSpecialize;
-    types::HeapTypeSet *propertyTypes = oracle->globalPropertyWrite(script_, pc, id, &canSpecialize);
+    types::HeapTypeSet *propertyTypes = oracle->globalPropertyWrite(script(), pc, id, &canSpecialize);
 
     // This should only happen for a few names like __proto__.
     if (!canSpecialize || globalObj->watched())
         return jsop_setprop(name);
 
     // For the fastest path, the property must be found, and it must be found
     // as a normal data property on exactly the global object.
     const js::Shape *shape = globalObj->nativeLookup(cx, id);
@@ -5095,17 +5099,17 @@ IonBuilder::jsop_setgname(HandleProperty
     return resumeAfter(store);
 }
 
 bool
 IonBuilder::jsop_getname(HandlePropertyName name)
 {
     MDefinition *object;
     if (js_CodeSpec[*pc].format & JOF_GNAME) {
-        MInstruction *global = MConstant::New(ObjectValue(script_->global()));
+        MInstruction *global = MConstant::New(ObjectValue(script()->global()));
         current->add(global);
         object = global;
     } else {
         current->push(current->scopeChain());
         object = current->pop();
     }
 
     MGetNameCache *ins;
@@ -5115,41 +5119,43 @@ IonBuilder::jsop_getname(HandlePropertyN
         ins = MGetNameCache::New(object, name, MGetNameCache::NAME);
 
     current->add(ins);
     current->push(ins);
 
     if (!resumeAfter(ins))
         return false;
 
-    types::StackTypeSet *barrier = oracle->propertyReadBarrier(script_, pc);
-    types::StackTypeSet *types = oracle->propertyRead(script_, pc);
+    RootedScript scriptRoot(cx, script());
+    types::StackTypeSet *barrier = oracle->propertyReadBarrier(scriptRoot, pc);
+    types::StackTypeSet *types = oracle->propertyRead(script(), pc);
 
     monitorResult(ins, barrier, types);
     return pushTypeBarrier(ins, types, barrier);
 }
 
 bool
 IonBuilder::jsop_intrinsicname(HandlePropertyName name)
 {
-    types::StackTypeSet *types = oracle->propertyRead(script_, pc);
+    types::StackTypeSet *types = oracle->propertyRead(script(), pc);
     JSValueType type = types->getKnownTypeTag();
 
     // If we haven't executed this opcode yet, we need to get the intrinsic
     // value and monitor the result.
     if (type == JSVAL_TYPE_UNKNOWN) {
         MCallGetIntrinsicValue *ins = MCallGetIntrinsicValue::New(name);
 
         current->add(ins);
         current->push(ins);
 
         if (!resumeAfter(ins))
             return false;
 
-        types::StackTypeSet *barrier = oracle->propertyReadBarrier(script_, pc);
+        RootedScript scriptRoot(cx, script());
+        types::StackTypeSet *barrier = oracle->propertyReadBarrier(scriptRoot, pc);
         monitorResult(ins, barrier, types);
         return pushTypeBarrier(ins, types, barrier);
     }
 
     // Bake in the intrinsic. Make sure that TI agrees with us on the type.
     RootedValue vp(cx, UndefinedValue());
     if (!cx->global()->getIntrinsicValue(cx, name, &vp))
         return false;
@@ -5161,41 +5167,41 @@ IonBuilder::jsop_intrinsicname(HandlePro
     current->push(ins);
 
     return true;
 }
 
 bool
 IonBuilder::jsop_bindname(PropertyName *name)
 {
-    JS_ASSERT(script_->analysis()->usesScopeChain());
+    JS_ASSERT(script()->analysis()->usesScopeChain());
 
     MDefinition *scopeChain = current->scopeChain();
-    MBindNameCache *ins = MBindNameCache::New(scopeChain, name, script_, pc);
+    MBindNameCache *ins = MBindNameCache::New(scopeChain, name, script(), pc);
 
     current->add(ins);
     current->push(ins);
 
     return resumeAfter(ins);
 }
 
 bool
 IonBuilder::jsop_getelem()
 {
-    if (oracle->elementReadIsDenseArray(script_, pc))
+    if (oracle->elementReadIsDenseArray(script(), pc))
         return jsop_getelem_dense();
 
     int arrayType = TypedArray::TYPE_MAX;
-    if (oracle->elementReadIsTypedArray(script_, pc, &arrayType))
+    if (oracle->elementReadIsTypedArray(script(), pc, &arrayType))
         return jsop_getelem_typed(arrayType);
 
-    if (oracle->elementReadIsString(script_, pc))
+    if (oracle->elementReadIsString(script(), pc))
         return jsop_getelem_string();
 
-    LazyArgumentsType isArguments = oracle->elementReadMagicArguments(script_, pc);
+    LazyArgumentsType isArguments = oracle->elementReadMagicArguments(script(), pc);
     if (isArguments == MaybeArguments)
         return abort("Type is not definitely lazy arguments.");
     if (isArguments == DefinitelyArguments)
         return jsop_arguments_getelem();
 
     MDefinition *rhs = current->pop();
     MDefinition *lhs = current->pop();
 
@@ -5203,46 +5209,48 @@ IonBuilder::jsop_getelem()
 
     // TI does not account for GETELEM with string indexes, so we have to monitor
     // the result of MGetElementCache if it's expected to access string properties.
     // If the result of MGetElementCache is not monitored, we won't generate any
     // getprop stubs.
     bool mustMonitorResult = false;
     bool cacheable = false;
 
-    oracle->elementReadGeneric(script_, pc, &cacheable, &mustMonitorResult);
+    oracle->elementReadGeneric(script(), pc, &cacheable, &mustMonitorResult);
 
     if (cacheable)
         ins = MGetElementCache::New(lhs, rhs, mustMonitorResult);
     else
         ins = MCallGetElement::New(lhs, rhs);
 
     current->add(ins);
     current->push(ins);
 
     if (!resumeAfter(ins))
         return false;
 
-    types::StackTypeSet *barrier = oracle->propertyReadBarrier(script_, pc);
-    types::StackTypeSet *types = oracle->propertyRead(script_, pc);
+    RootedScript scriptRoot(cx, script());
+    types::StackTypeSet *barrier = oracle->propertyReadBarrier(scriptRoot, pc);
+    types::StackTypeSet *types = oracle->propertyRead(script(), pc);
 
     if (mustMonitorResult)
         monitorResult(ins, barrier, types);
     return pushTypeBarrier(ins, types, barrier);
 }
 
 bool
 IonBuilder::jsop_getelem_dense()
 {
     if (oracle->arrayPrototypeHasIndexedProperty())
         return abort("GETELEM Array proto has indexed properties");
 
-    types::StackTypeSet *barrier = oracle->propertyReadBarrier(script_, pc);
-    types::StackTypeSet *types = oracle->propertyRead(script_, pc);
-    bool needsHoleCheck = !oracle->elementReadIsPacked(script_, pc);
+    RootedScript scriptRoot(cx, script());
+    types::StackTypeSet *barrier = oracle->propertyReadBarrier(scriptRoot, pc);
+    types::StackTypeSet *types = oracle->propertyRead(script(), pc);
+    bool needsHoleCheck = !oracle->elementReadIsPacked(script(), pc);
     bool maybeUndefined = types->hasType(types::Type::UndefinedType());
 
     MDefinition *id = current->pop();
     MDefinition *obj = current->pop();
 
     JSValueType knownType = JSVAL_TYPE_UNKNOWN;
     if (!barrier) {
         knownType = types->getKnownTypeTag();
@@ -5326,18 +5334,19 @@ GetTypedArrayElements(MDefinition *obj)
         return MConstantElements::New(data);
     }
     return MTypedArrayElements::New(obj);
 }
 
 bool
 IonBuilder::jsop_getelem_typed(int arrayType)
 {
-    types::StackTypeSet *barrier = oracle->propertyReadBarrier(script_, pc);
-    types::StackTypeSet *types = oracle->propertyRead(script_, pc);
+    RootedScript scriptRoot(cx, script());
+    types::StackTypeSet *barrier = oracle->propertyReadBarrier(scriptRoot, pc);
+    types::StackTypeSet *types = oracle->propertyRead(script(), pc);
 
     MDefinition *id = current->pop();
     MDefinition *obj = current->pop();
 
     bool maybeUndefined = types->hasType(types::Type::UndefinedType());
 
     // Reading from an Uint32Array will result in a double for values
     // that don't fit in an int32. We have to bailout if this happens
@@ -5424,41 +5433,41 @@ IonBuilder::jsop_getelem_string()
     current->add(idInt32);
     id = idInt32;
 
     MStringLength *length = MStringLength::New(str);
     current->add(length);
 
     // This will cause an invalidation of this script once the 'undefined' type
     // is monitored by the interpreter.
-    JS_ASSERT(oracle->propertyRead(script_, pc)->getKnownTypeTag() == JSVAL_TYPE_STRING);
+    JS_ASSERT(oracle->propertyRead(script(), pc)->getKnownTypeTag() == JSVAL_TYPE_STRING);
     id = addBoundsCheck(id, length);
 
     MCharCodeAt *charCode = MCharCodeAt::New(str, id);
     current->add(charCode);
 
     MFromCharCode *result = MFromCharCode::New(charCode);
     current->add(result);
     current->push(result);
     return true;
 }
 
 bool
 IonBuilder::jsop_setelem()
 {
-    if (oracle->propertyWriteCanSpecialize(script_, pc)) {
-        if (oracle->elementWriteIsDenseArray(script_, pc))
+    if (oracle->propertyWriteCanSpecialize(script(), pc)) {
+        if (oracle->elementWriteIsDenseArray(script(), pc))
             return jsop_setelem_dense();
 
         int arrayType = TypedArray::TYPE_MAX;
-        if (oracle->elementWriteIsTypedArray(script_, pc, &arrayType))
+        if (oracle->elementWriteIsTypedArray(script(), pc, &arrayType))
             return jsop_setelem_typed(arrayType);
     }
 
-    LazyArgumentsType isArguments = oracle->elementWriteMagicArguments(script_, pc);
+    LazyArgumentsType isArguments = oracle->elementWriteMagicArguments(script(), pc);
     if (isArguments == MaybeArguments)
         return abort("Type is not definitely lazy arguments.");
     if (isArguments == DefinitelyArguments)
         return jsop_arguments_setelem();
 
     MDefinition *value = current->pop();
     MDefinition *index = current->pop();
     MDefinition *object = current->pop();
@@ -5471,18 +5480,18 @@ IonBuilder::jsop_setelem()
 }
 
 bool
 IonBuilder::jsop_setelem_dense()
 {
     if (oracle->arrayPrototypeHasIndexedProperty())
         return abort("SETELEM Array proto has indexed properties");
 
-    MIRType elementType = oracle->elementWrite(script_, pc);
-    bool packed = oracle->elementWriteIsPacked(script_, pc);
+    MIRType elementType = oracle->elementWrite(script(), pc);
+    bool packed = oracle->elementWriteIsPacked(script(), pc);
 
     MDefinition *value = current->pop();
     MDefinition *id = current->pop();
     MDefinition *obj = current->pop();
 
     // Ensure id is an integer.
     MInstruction *idInt32 = MToInt32::New(id);
     current->add(idInt32);
@@ -5491,17 +5500,17 @@ IonBuilder::jsop_setelem_dense()
     // Get the elements vector.
     MElements *elements = MElements::New(obj);
     current->add(elements);
 
     // Use MStoreElementHole if this SETELEM has written to out-of-bounds
     // indexes in the past. Otherwise, use MStoreElement so that we can hoist
     // the initialized length and bounds check.
     MStoreElementCommon *store;
-    if (oracle->setElementHasWrittenHoles(script_, pc)) {
+    if (oracle->setElementHasWrittenHoles(script(), pc)) {
         MStoreElementHole *ins = MStoreElementHole::New(obj, elements, id, value);
         store = ins;
 
         current->add(ins);
         current->push(value);
 
         if (!resumeAfter(ins))
             return false;
@@ -5517,17 +5526,17 @@ IonBuilder::jsop_setelem_dense()
         current->add(ins);
         current->push(value);
 
         if (!resumeAfter(ins))
             return false;
     }
 
     // Determine whether a write barrier is required.
-    if (oracle->elementWriteNeedsBarrier(script_, pc))
+    if (oracle->elementWriteNeedsBarrier(script(), pc))
         store->setNeedsBarrier();
 
     if (elementType != MIRType_None && packed)
         store->setElementType(elementType);
 
     return true;
 }
 
@@ -5577,17 +5586,17 @@ IonBuilder::jsop_length()
 
     RootedPropertyName name(cx, info().getAtom(pc)->asPropertyName());
     return jsop_getprop(name);
 }
 
 bool
 IonBuilder::jsop_length_fastPath()
 {
-    TypeOracle::UnaryTypes sig = oracle->unaryTypes(script_, pc);
+    TypeOracle::UnaryTypes sig = oracle->unaryTypes(script(), pc);
     if (!sig.inTypes || !sig.outTypes)
         return false;
 
     if (sig.outTypes->getKnownTypeTag() != JSVAL_TYPE_INT32)
         return false;
 
     switch (sig.inTypes->getKnownTypeTag()) {
       case JSVAL_TYPE_STRING: {
@@ -5648,18 +5657,19 @@ IonBuilder::jsop_arguments_length()
     current->add(ins);
     current->push(ins);
     return true;
 }
 
 bool
 IonBuilder::jsop_arguments_getelem()
 {
-    types::StackTypeSet *barrier = oracle->propertyReadBarrier(script_, pc);
-    types::StackTypeSet *types = oracle->propertyRead(script_, pc);
+    RootedScript scriptRoot(cx, script());
+    types::StackTypeSet *barrier = oracle->propertyReadBarrier(scriptRoot, pc);
+    types::StackTypeSet *types = oracle->propertyRead(script(), pc);
 
     MDefinition *idx = current->pop();
 
     // Type Inference has guaranteed this is an optimized arguments object.
     MDefinition *args = current->pop();
     args->setFoldedUnchecked();
 
     // To ensure that we are not looking above the number of actual arguments.
@@ -6134,18 +6144,19 @@ IonBuilder::invalidatedIdempotentCache()
 }
 
 bool
 IonBuilder::loadSlot(MDefinition *obj, Shape *shape, MIRType rvalType)
 {
     JS_ASSERT(shape->hasDefaultGetter());
     JS_ASSERT(shape->hasSlot());
 
-    types::StackTypeSet *barrier = oracle->propertyReadBarrier(script_, pc);
-    types::StackTypeSet *types = oracle->propertyRead(script_, pc);
+    RootedScript scriptRoot(cx, script());
+    types::StackTypeSet *barrier = oracle->propertyReadBarrier(scriptRoot, pc);
+    types::StackTypeSet *types = oracle->propertyRead(script(), pc);
 
     if (shape->slot() < shape->numFixedSlots()) {
         MLoadFixedSlot *load = MLoadFixedSlot::New(obj, shape->slot());
         current->add(load);
         current->push(load);
 
         load->setResultType(rvalType);
         return pushTypeBarrier(load, types, barrier);
@@ -6189,20 +6200,21 @@ IonBuilder::storeSlot(MDefinition *obj, 
     return resumeAfter(store);
 }
 
 bool
 IonBuilder::jsop_getprop(HandlePropertyName name)
 {
     RootedId id(cx, NameToId(name));
 
-    types::StackTypeSet *barrier = oracle->propertyReadBarrier(script_, pc);
-    types::StackTypeSet *types = oracle->propertyRead(script_, pc);
-    TypeOracle::Unary unary = oracle->unaryOp(script_, pc);
-    TypeOracle::UnaryTypes uTypes = oracle->unaryTypes(script_, pc);
+    RootedScript scriptRoot(cx, script());
+    types::StackTypeSet *barrier = oracle->propertyReadBarrier(scriptRoot, pc);
+    types::StackTypeSet *types = oracle->propertyRead(script(), pc);
+    TypeOracle::Unary unary = oracle->unaryOp(script(), pc);
+    TypeOracle::UnaryTypes uTypes = oracle->unaryTypes(script(), pc);
 
     bool emitted = false;
 
     // Try to optimize arguments.length.
     if (!getPropTryArgumentsLength(&emitted) || emitted)
         return emitted;
 
     // Try to hardcode known constants.
@@ -6236,17 +6248,17 @@ IonBuilder::jsop_getprop(HandlePropertyN
     monitorResult(call, barrier, types);
     return pushTypeBarrier(call, types, barrier);
 }
 
 bool
 IonBuilder::getPropTryArgumentsLength(bool *emitted)
 {
     JS_ASSERT(*emitted == false);
-    LazyArgumentsType isArguments = oracle->propertyReadMagicArguments(script_, pc);
+    LazyArgumentsType isArguments = oracle->propertyReadMagicArguments(script(), pc);
 
     if (isArguments == MaybeArguments)
         return abort("Type is not definitely lazy arguments.");
     if (isArguments != DefinitelyArguments)
         return true;
     if (JSOp(*pc) != JSOP_LENGTH)
         return true;
 
@@ -6258,17 +6270,17 @@ bool
 IonBuilder::getPropTryConstant(bool *emitted, HandleId id, types::StackTypeSet *barrier,
                                types::StackTypeSet *types, TypeOracle::UnaryTypes unaryTypes)
 {
     JS_ASSERT(*emitted == false);
     JSObject *singleton = types ? types->getSingleton() : NULL;
     if (!singleton || barrier)
         return true;
 
-    RootedObject global(cx, &script_->global());
+    RootedObject global(cx, &script()->global());
 
     bool isConstant, testObject, testString;
     if (!TestSingletonPropertyTypes(cx, unaryTypes.inTypes, global, id,
                                     &isConstant, &testObject, &testString))
         return false;
 
     if (!isConstant)
         return true;
@@ -6383,22 +6395,22 @@ IonBuilder::getPropTryCommonGetter(bool 
     return true;
 }
 
 bool
 IonBuilder::getPropTryMonomorphic(bool *emitted, HandleId id, types::StackTypeSet *barrier,
                                   TypeOracle::Unary unary, TypeOracle::UnaryTypes unaryTypes)
 {
     JS_ASSERT(*emitted == false);
-    bool accessGetter = oracle->propertyReadAccessGetter(script_, pc);
+    bool accessGetter = oracle->propertyReadAccessGetter(script(), pc);
 
     if (unary.ival != MIRType_Object)
         return true;
 
-    Shape *objShape = mjit::GetPICSingleShape(cx, script_, pc, info().constructing());
+    Shape *objShape = mjit::GetPICSingleShape(cx, script(), pc, info().constructing());
     if (!objShape || objShape->inDictionary()) {
         spew("GETPROP not monomorphic");
         return true;
     }
 
     MDefinition *obj = current->pop();
 
     // The JM IC was monomorphic, so we inline the property access as long as
@@ -6423,17 +6435,17 @@ IonBuilder::getPropTryMonomorphic(bool *
 }
 
 bool
 IonBuilder::getPropTryPolymorphic(bool *emitted, HandlePropertyName name, HandleId id,
                                   types::StackTypeSet *barrier, types::StackTypeSet *types,
                                   TypeOracle::Unary unary, TypeOracle::UnaryTypes unaryTypes)
 {
     JS_ASSERT(*emitted == false);
-    bool accessGetter = oracle->propertyReadAccessGetter(script_, pc);
+    bool accessGetter = oracle->propertyReadAccessGetter(script(), pc);
 
     // The input value must either be an object, or we should have strong suspicions
     // that it can be safely unboxed to an object.
     if (unary.ival != MIRType_Object && !unaryTypes.inTypes->objectOrSentinel())
         return true;
 
     MIRType rvalType = unary.rval;
     if (barrier || IsNullOrUndefined(unary.rval) || accessGetter)
@@ -6445,17 +6457,18 @@ IonBuilder::getPropTryPolymorphic(bool *
 
     // Try to mark the cache as idempotent. We only do this if JM is enabled
     // (its ICs are used to mark property reads as likely non-idempotent) or
     // if we are compiling eagerly (to improve test coverage).
     if (unary.ival == MIRType_Object &&
         (cx->methodJitEnabled || js_IonOptions.eagerCompilation) &&
         !invalidatedIdempotentCache())
     {
-        if (oracle->propertyReadIdempotent(script_, pc, id))
+        RootedScript scriptRoot(cx, script());
+        if (oracle->propertyReadIdempotent(scriptRoot, pc, id))
             load->setIdempotent();
     }
 
     if (JSOp(*pc) == JSOP_CALLPROP) {
         if (!annotateGetPropertyCache(cx, obj, load, unaryTypes.inTypes, types))
             return false;
     }
 
@@ -6480,19 +6493,19 @@ IonBuilder::getPropTryPolymorphic(bool *
 }
 
 bool
 IonBuilder::jsop_setprop(HandlePropertyName name)
 {
     MDefinition *value = current->pop();
     MDefinition *obj = current->pop();
 
-    bool monitored = !oracle->propertyWriteCanSpecialize(script_, pc);
-
-    TypeOracle::BinaryTypes binaryTypes = oracle->binaryTypes(script_, pc);
+    bool monitored = !oracle->propertyWriteCanSpecialize(script(), pc);
+
+    TypeOracle::BinaryTypes binaryTypes = oracle->binaryTypes(script(), pc);
 
     if (!monitored) {
         if (types::HeapTypeSet *propTypes = GetDefiniteSlot(cx, binaryTypes.lhsTypes, name)) {
             MStoreFixedSlot *fixed = MStoreFixedSlot::New(obj, propTypes->definiteSlot(), value);
             current->add(fixed);
             current->push(value);
             if (propTypes->needsBarrier(cx))
                 fixed->setNeedsBarrier();
@@ -6536,46 +6549,46 @@ IonBuilder::jsop_setprop(HandlePropertyN
         MCall *call = makeCallHelper(setter, 1, false);
         if (!call)
             return false;
 
         current->push(value);
         return resumeAfter(call);
     }
 
-    oracle->binaryOp(script_, pc);
+    oracle->binaryOp(script(), pc);
 
     MSetPropertyInstruction *ins;
     if (monitored) {
-        ins = MCallSetProperty::New(obj, value, name, script_->strictModeCode);
+        ins = MCallSetProperty::New(obj, value, name, script()->strictModeCode);
     } else {
         Shape *objShape;
-        if ((objShape = mjit::GetPICSingleShape(cx, script_, pc, info().constructing())) &&
+        if ((objShape = mjit::GetPICSingleShape(cx, script(), pc, info().constructing())) &&
             !objShape->inDictionary())
         {
             // The JM IC was monomorphic, so we inline the property access as
             // long as the shape is not in dictionary mode. We cannot be sure
             // that the shape is still a lastProperty, and calling Shape::search
             // on dictionary mode shapes that aren't lastProperty is invalid.
             obj = addShapeGuard(obj, objShape, Bailout_CachedShapeGuard);
 
             Shape *shape = objShape->search(cx, NameToId(name));
             JS_ASSERT(shape);
 
             spew("Inlining monomorphic SETPROP");
 
             jsid typeId = types::MakeTypeId(cx, id);
-            bool needsBarrier = oracle->propertyWriteNeedsBarrier(script_, pc, typeId);
+            bool needsBarrier = oracle->propertyWriteNeedsBarrier(script(), pc, typeId);
 
             return storeSlot(obj, shape, value, needsBarrier);
         }
 
         spew("SETPROP not monomorphic");
 
-        ins = MSetPropertyCache::New(obj, value, name, script_->strictModeCode);
+        ins = MSetPropertyCache::New(obj, value, name, script()->strictModeCode);
 
         if (!binaryTypes.lhsTypes || binaryTypes.lhsTypes->propertyNeedsBarrier(cx, id))
             ins->setNeedsBarrier();
     }
 
     current->add(ins);
     current->push(value);
 
@@ -6593,17 +6606,17 @@ IonBuilder::jsop_delprop(HandlePropertyN
     current->push(ins);
 
     return resumeAfter(ins);
 }
 
 bool
 IonBuilder::jsop_regexp(RegExpObject *reobj)
 {
-    JSObject *prototype = script_->global().getOrCreateRegExpPrototype(cx);
+    JSObject *prototype = script()->global().getOrCreateRegExpPrototype(cx);
     if (!prototype)
         return false;
 
     MRegExp *ins = MRegExp::New(reobj, prototype, MRegExp::MustClone);
     current->add(ins);
     current->push(ins);
 
     return true;
@@ -6617,105 +6630,105 @@ IonBuilder::jsop_object(JSObject *obj)
     current->push(ins);
 
     return true;
 }
 
 bool
 IonBuilder::jsop_lambda(JSFunction *fun)
 {
-    JS_ASSERT(script_->analysis()->usesScopeChain());
+    JS_ASSERT(script()->analysis()->usesScopeChain());
     MLambda *ins = MLambda::New(current->scopeChain(), fun);
     current->add(ins);
     current->push(ins);
 
     return resumeAfter(ins);
 }
 
 bool
 IonBuilder::jsop_deflocalfun(uint32_t local, JSFunction *fun)
 {
-    JS_ASSERT(script_->analysis()->usesScopeChain());
+    JS_ASSERT(script()->analysis()->usesScopeChain());
 
     MLambda *ins = MLambda::New(current->scopeChain(), fun);
     current->add(ins);
     current->push(ins);
 
     current->setLocal(local);
     current->pop();
 
     return resumeAfter(ins);
 }
 
 bool
 IonBuilder::jsop_defvar(uint32_t index)
 {
     JS_ASSERT(JSOp(*pc) == JSOP_DEFVAR || JSOp(*pc) == JSOP_DEFCONST);
 
-    PropertyName *name = script_->getName(index);
+    PropertyName *name = script()->getName(index);
 
     // Bake in attrs.
     unsigned attrs = JSPROP_ENUMERATE | JSPROP_PERMANENT;
     if (JSOp(*pc) == JSOP_DEFCONST)
         attrs |= JSPROP_READONLY;
 
     // Pass the ScopeChain.
-    JS_ASSERT(script_->analysis()->usesScopeChain());
+    JS_ASSERT(script()->analysis()->usesScopeChain());
 
     // Bake the name pointer into the MDefVar.
     MDefVar *defvar = MDefVar::New(name, attrs, current->scopeChain());
     current->add(defvar);
 
     return resumeAfter(defvar);
 }
 
 bool
 IonBuilder::jsop_this()
 {
     if (!info().fun())
         return abort("JSOP_THIS outside of a JSFunction.");
 
-    if (script_->strictModeCode) {
+    if (script()->strictModeCode) {
         current->pushSlot(info().thisSlot());
         return true;
     }
 
-    types::StackTypeSet *types = oracle->thisTypeSet(script_);
+    types::StackTypeSet *types = oracle->thisTypeSet(script());
     if (types && types->getKnownTypeTag() == JSVAL_TYPE_OBJECT) {
         // This is safe, because if the entry type of |this| is an object, it
         // will necessarily be an object throughout the entire function. OSR
         // can introduce a phi, but this phi will be specialized.
         current->pushSlot(info().thisSlot());
         return true;
     }
 
     return abort("JSOP_THIS hard case not yet handled");
 }
 
 bool
 IonBuilder::jsop_typeof()
 {
-    TypeOracle::Unary unary = oracle->unaryOp(script_, pc);
+    TypeOracle::Unary unary = oracle->unaryOp(script(), pc);
 
     MDefinition *input = current->pop();
     MTypeOf *ins = MTypeOf::New(input, unary.ival);
 
     current->add(ins);
     current->push(ins);
 
     if (ins->isEffectful() && !resumeAfter(ins))
         return false;
     return true;
 }
 
 bool
 IonBuilder::jsop_toid()
 {
     // No-op if the index is an integer.
-    TypeOracle::Unary unary = oracle->unaryOp(script_, pc);
+    TypeOracle::Unary unary = oracle->unaryOp(script(), pc);
     if (unary.ival == MIRType_Int32)
         return true;
 
     MDefinition *index = current->pop();
     MToId *ins = MToId::New(current->peek(-1), index);
 
     current->add(ins);
     current->push(ins);
@@ -6786,21 +6799,21 @@ IonBuilder::walkScopeChain(unsigned hops
 
     return scope;
 }
 
 bool
 IonBuilder::jsop_getaliasedvar(ScopeCoordinate sc)
 {
     types::StackTypeSet *barrier;
-    types::StackTypeSet *actual = oracle->aliasedVarBarrier(script_, pc, &barrier);
+    types::StackTypeSet *actual = oracle->aliasedVarBarrier(script(), pc, &barrier);
 
     MDefinition *obj = walkScopeChain(sc.hops);
 
-    RootedShape shape(cx, ScopeCoordinateToStaticScope(script_, pc).scopeShape());
+    RootedShape shape(cx, ScopeCoordinateToStaticScope(script(), pc).scopeShape());
 
     MInstruction *load;
     if (shape->numFixedSlots() <= sc.slot) {
         MInstruction *slots = MSlots::New(obj);
         current->add(slots);
 
         load = MLoadSlot::New(slots, sc.slot - shape->numFixedSlots());
     } else {
@@ -6824,17 +6837,17 @@ IonBuilder::jsop_getaliasedvar(ScopeCoor
 }
 
 bool
 IonBuilder::jsop_setaliasedvar(ScopeCoordinate sc)
 {
     MDefinition *rval = current->peek(-1);
     MDefinition *obj = walkScopeChain(sc.hops);
 
-    RootedShape shape(cx, ScopeCoordinateToStaticScope(script_, pc).scopeShape());
+    RootedShape shape(cx, ScopeCoordinateToStaticScope(script(), pc).scopeShape());
 
     MInstruction *store;
     if (shape->numFixedSlots() <= sc.slot) {
         MInstruction *slots = MSlots::New(obj);
         current->add(slots);
 
         store = MStoreSlot::NewBarriered(slots, sc.slot - shape->numFixedSlots(), rval);
     } else {
@@ -6843,17 +6856,17 @@ IonBuilder::jsop_setaliasedvar(ScopeCoor
 
     current->add(store);
     return resumeAfter(store);
 }
 
 bool
 IonBuilder::jsop_in()
 {
-    if (oracle->inObjectIsDenseArray(script_, pc))
+    if (oracle->inObjectIsDenseArray(script(), pc))
         return jsop_in_dense();
 
     MDefinition *obj = current->pop();
     MDefinition *id = current->pop();
     MIn *ins = new MIn(id, obj);
 
     current->add(ins);
     current->push(ins);
@@ -6862,17 +6875,17 @@ IonBuilder::jsop_in()
 }
 
 bool
 IonBuilder::jsop_in_dense()
 {
     if (oracle->arrayPrototypeHasIndexedProperty())
         return abort("JSOP_IN Array proto has indexed properties");
 
-    bool needsHoleCheck = !oracle->inArrayIsPacked(script_, pc);
+    bool needsHoleCheck = !oracle->inArrayIsPacked(script(), pc);
 
     MDefinition *obj = current->pop();
     MDefinition *id = current->pop();
 
     // Ensure id is an integer.
     MInstruction *idInt32 = MToInt32::New(id);
     current->add(idInt32);
     id = idInt32;
@@ -6894,17 +6907,17 @@ IonBuilder::jsop_in_dense()
 }
 
 bool
 IonBuilder::jsop_instanceof()
 {
     MDefinition *rhs = current->pop();
     MDefinition *obj = current->pop();
 
-    TypeOracle::BinaryTypes types = oracle->binaryTypes(script_, pc);
+    TypeOracle::BinaryTypes types = oracle->binaryTypes(script(), pc);
 
     // If this is an 'x instanceof function' operation and we can determine the
     // exact function and prototype object being tested for, use a typed path.
     do {
         RawObject rhsObject = types.rhsTypes ? types.rhsTypes->getSingleton() : NULL;
         if (!rhsObject || !rhsObject->isFunction() || rhsObject->isBoundFunction())
             break;
 
--- a/js/src/ion/MCallOptimize.cpp
+++ b/js/src/ion/MCallOptimize.cpp
@@ -108,33 +108,33 @@ IonBuilder::discardCall(uint32_t argc, M
     bb->pop();
     return true;
 }
 
 types::StackTypeSet *
 IonBuilder::getInlineReturnTypeSet()
 {
     types::StackTypeSet *barrier;
-    types::StackTypeSet *returnTypes = oracle->returnTypeSet(script_, pc, &barrier);
+    types::StackTypeSet *returnTypes = oracle->returnTypeSet(script(), pc, &barrier);
 
     JS_ASSERT(returnTypes);
     return returnTypes;
 }
 
 MIRType
 IonBuilder::getInlineReturnType()
 {
     types::StackTypeSet *returnTypes = getInlineReturnTypeSet();
     return MIRTypeFromValueType(returnTypes->getKnownTypeTag());
 }
 
 types::StackTypeSet *
 IonBuilder::getInlineArgTypeSet(uint32_t argc, uint32_t arg)
 {
-    types::StackTypeSet *argTypes = oracle->getCallArg(script_, argc, arg, pc);
+    types::StackTypeSet *argTypes = oracle->getCallArg(script(), argc, arg, pc);
     JS_ASSERT(argTypes);
     return argTypes;
 }
 
 MIRType
 IonBuilder::getInlineArgType(uint32_t argc, uint32_t arg)
 {
     types::StackTypeSet *argTypes = getInlineArgTypeSet(argc, arg);
--- a/js/src/ion/TypeOracle.cpp
+++ b/js/src/ion/TypeOracle.cpp
@@ -61,28 +61,28 @@ MIRType
 TypeInferenceOracle::getMIRType(HeapTypeSet *types)
 {
     return GetMIRType(types->getKnownTypeTag(cx));
 }
 
 TypeOracle::UnaryTypes
 TypeInferenceOracle::unaryTypes(JSScript *script, jsbytecode *pc)
 {
-    JS_ASSERT(script == this->script_);
+    JS_ASSERT(script == this->script());
 
     UnaryTypes res;
     res.inTypes = script->analysis()->poppedTypes(pc, 0);
     res.outTypes = script->analysis()->pushedTypes(pc, 0);
     return res;
 }
 
 TypeOracle::BinaryTypes
 TypeInferenceOracle::binaryTypes(JSScript *script, jsbytecode *pc)
 {
-    JS_ASSERT(script == this->script_);
+    JS_ASSERT(script == this->script());
 
     JSOp op = (JSOp)*pc;
 
     BinaryTypes res;
     if (op == JSOP_NEG || op == JSOP_POS) {
         res.lhsTypes = script->analysis()->poppedTypes(pc, 0);
         res.rhsTypes = NULL;
         res.outTypes = script->analysis()->pushedTypes(pc, 0);
@@ -92,28 +92,28 @@ TypeInferenceOracle::binaryTypes(JSScrip
         res.outTypes = script->analysis()->pushedTypes(pc, 0);
     }
     return res;
 }
 
 TypeOracle::Unary
 TypeInferenceOracle::unaryOp(JSScript *script, jsbytecode *pc)
 {
-    JS_ASSERT(script == this->script_);
+    JS_ASSERT(script == this->script());
 
     Unary res;
     res.ival = getMIRType(script->analysis()->poppedTypes(pc, 0));
     res.rval = getMIRType(script->analysis()->pushedTypes(pc, 0));
     return res;
 }
 
 TypeOracle::Binary
 TypeInferenceOracle::binaryOp(JSScript *script, jsbytecode *pc)
 {
-    JS_ASSERT(script == this->script_);
+    JS_ASSERT(script == this->script());
 
     JSOp op = (JSOp)*pc;
 
     Binary res;
     if (op == JSOP_NEG || op == JSOP_POS) {
         res.lhs = getMIRType(script->analysis()->poppedTypes(pc, 0));
         res.rhs = MIRType_Int32;
         res.rval = getMIRType(script->analysis()->pushedTypes(pc, 0));
@@ -123,55 +123,55 @@ TypeInferenceOracle::binaryOp(JSScript *
         res.rval = getMIRType(script->analysis()->pushedTypes(pc, 0));
     }
     return res;
 }
 
 StackTypeSet *
 TypeInferenceOracle::thisTypeSet(JSScript *script)
 {
-    JS_ASSERT(script == this->script_);
+    JS_ASSERT(script == this->script());
     return TypeScript::ThisTypes(script);
 }
 
 bool
 TypeInferenceOracle::getOsrTypes(jsbytecode *osrPc, Vector<MIRType> &slotTypes)
 {
     JS_ASSERT(JSOp(*osrPc) == JSOP_LOOPENTRY);
-    JS_ASSERT(script_->code < osrPc);
-    JS_ASSERT(osrPc < script_->code + script_->length);
+    JS_ASSERT(script()->code < osrPc);
+    JS_ASSERT(osrPc < script()->code + script()->length);
 
     Vector<types::StackTypeSet *> slotTypeSets(cx);
-    if (!slotTypeSets.resize(TotalSlots(script_)))
+    if (!slotTypeSets.resize(TotalSlots(script())))
         return false;
 
-    for (uint32_t slot = ThisSlot(); slot < TotalSlots(script_); slot++)
-        slotTypeSets[slot] = TypeScript::SlotTypes(script_, slot);
+    for (uint32_t slot = ThisSlot(); slot < TotalSlots(script()); slot++)
+        slotTypeSets[slot] = TypeScript::SlotTypes(script(), slot);
 
-    jsbytecode *pc = script_->code;
-    ScriptAnalysis *analysis = script_->analysis();
+    jsbytecode *pc = script()->code;
+    ScriptAnalysis *analysis = script()->analysis();
 
     // To determine the slot types at the OSR pc, we have to do a forward walk
     // over the bytecode to reconstruct the types.
     for (;;) {
         Bytecode *opinfo = analysis->maybeCode(pc);
         if (opinfo) {
             if (opinfo->jumpTarget) {
                 // Update variable types for all new values at this bytecode.
                 if (const SlotValue *newv = analysis->newValues(pc)) {
                     while (newv->slot) {
-                        if (newv->slot < TotalSlots(script_))
+                        if (newv->slot < TotalSlots(script()))
                             slotTypeSets[newv->slot] = analysis->getValueTypes(newv->value);
                         newv++;
                     }
                 }
             }
 
             if (BytecodeUpdatesSlot(JSOp(*pc))) {
-                uint32_t slot = GetBytecodeSlot(script_, pc);
+                uint32_t slot = GetBytecodeSlot(script(), pc);
                 if (analysis->trackSlot(slot))
                     slotTypeSets[slot] = analysis->pushedTypes(pc, 0);
             }
         }
 
         if (pc == osrPc)
             break;
 
@@ -184,35 +184,35 @@ TypeInferenceOracle::getOsrTypes(jsbytec
     // scripts. This means we have to subtract 1 for global/eval scripts.
     JS_ASSERT(ThisSlot() == 1);
     JS_ASSERT(ArgSlot(0) == 2);
 
 #ifdef DEBUG
     uint32_t stackDepth = analysis->getCode(osrPc).stackDepth;
 #endif
 
-    if (script_->function()) {
-        JS_ASSERT(slotTypes.length() == TotalSlots(script_) + stackDepth);
+    if (script()->function()) {
+        JS_ASSERT(slotTypes.length() == TotalSlots(script()) + stackDepth);
 
-        for (size_t i = ThisSlot(); i < TotalSlots(script_); i++)
+        for (size_t i = ThisSlot(); i < TotalSlots(script()); i++)
             slotTypes[i] = getMIRType(slotTypeSets[i]);
     } else {
-        JS_ASSERT(slotTypes.length() == TotalSlots(script_) + stackDepth - 1);
+        JS_ASSERT(slotTypes.length() == TotalSlots(script()) + stackDepth - 1);
 
-        for (size_t i = ArgSlot(0); i < TotalSlots(script_); i++)
+        for (size_t i = ArgSlot(0); i < TotalSlots(script()); i++)
             slotTypes[i - 1] = getMIRType(slotTypeSets[i]);
     }
 
     return true;
 }
 
 StackTypeSet *
 TypeInferenceOracle::parameterTypeSet(JSScript *script, size_t index)
 {
-    JS_ASSERT(script == this->script_);
+    JS_ASSERT(script == this->script());
     return TypeScript::ArgTypes(script, index);
 }
 
 StackTypeSet *
 TypeInferenceOracle::propertyRead(JSScript *script, jsbytecode *pc)
 {
     return script->analysis()->pushedTypes(pc, 0);
 }
@@ -479,24 +479,24 @@ TypeInferenceOracle::elementWrite(JSScri
     }
 
     return elementType;
 }
 
 bool
 TypeInferenceOracle::arrayPrototypeHasIndexedProperty()
 {
-    RootedScript script(cx, script_);
-    return ArrayPrototypeHasIndexedProperty(cx, script);
+    RootedScript scriptRoot(cx, script());
+    return ArrayPrototypeHasIndexedProperty(cx, scriptRoot);
 }
 
 bool
 TypeInferenceOracle::canInlineCalls()
 {
-    return script_->analysis()->hasFunctionCalls();
+    return script()->analysis()->hasFunctionCalls();
 }
 
 bool
 TypeInferenceOracle::propertyWriteCanSpecialize(JSScript *script, jsbytecode *pc)
 {
     return !script->analysis()->getCode(pc).monitoredTypes;
 }
 
@@ -514,20 +514,20 @@ TypeInferenceOracle::elementWriteNeedsBa
     // a property. The object is the third value popped by SETELEM.
     StackTypeSet *types = script->analysis()->poppedTypes(pc, 2);
     return types->propertyNeedsBarrier(cx, JSID_VOID);
 }
 
 StackTypeSet *
 TypeInferenceOracle::getCallTarget(JSScript *caller, uint32_t argc, jsbytecode *pc)
 {
-    JS_ASSERT(caller == this->script_);
+    JS_ASSERT(caller == this->script());
     JS_ASSERT(js_CodeSpec[*pc].format & JOF_INVOKE && JSOp(*pc) != JSOP_EVAL);
 
-    ScriptAnalysis *analysis = script_->analysis();
+    ScriptAnalysis *analysis = script()->analysis();
     return analysis->poppedTypes(pc, argc + 1);
 }
 
 StackTypeSet *
 TypeInferenceOracle::getCallArg(JSScript *script, uint32_t argc, uint32_t arg, jsbytecode *pc)
 {
     JS_ASSERT(argc >= arg);
     // Bytecode order: Function, This, Arg0, Arg1, ..., ArgN, Call.
--- a/js/src/ion/TypeOracle.h
+++ b/js/src/ion/TypeOracle.h
@@ -203,16 +203,18 @@ class TypeInferenceOracle : public TypeO
     MIRType getMIRType(types::StackTypeSet *types);
     MIRType getMIRType(types::HeapTypeSet *types);
 
   public:
     TypeInferenceOracle() : cx(NULL), script_(NULL) {}
 
     bool init(JSContext *cx, JSScript *script);
 
+    UnrootedScript script() { return script_.get(); }
+
     UnaryTypes unaryTypes(JSScript *script, jsbytecode *pc);
     BinaryTypes binaryTypes(JSScript *script, jsbytecode *pc);
     Unary unaryOp(JSScript *script, jsbytecode *pc);
     Binary binaryOp(JSScript *script, jsbytecode *pc);
     types::StackTypeSet *thisTypeSet(JSScript *script);
     bool getOsrTypes(jsbytecode *osrPc, Vector<MIRType> &slotTypes);
     types::StackTypeSet *parameterTypeSet(JSScript *script, size_t index);
     types::HeapTypeSet *globalPropertyTypeSet(JSScript *script, jsbytecode *pc, jsid id);
--- a/js/src/jsgcinlines.h
+++ b/js/src/jsgcinlines.h
@@ -523,17 +523,17 @@ NewGCThing(JSContext *cx, js::gc::AllocK
     return static_cast<T *>(t);
 }
 
 /* Alternate form which allocates a GC thing if doing so cannot trigger a GC. */
 template <typename T>
 inline T *
 TryNewGCThing(JSContext *cx, js::gc::AllocKind kind, size_t thingSize)
 {
-    AssertCanGC();
+    AutoAssertNoGC nogc;
     JS_ASSERT(thingSize == js::gc::Arena::thingSize(kind));
     JS_ASSERT_IF(cx->compartment == cx->runtime->atomsCompartment,
                  kind == js::gc::FINALIZE_STRING || kind == js::gc::FINALIZE_SHORT_STRING);
     JS_ASSERT(!cx->runtime->isHeapBusy());
     JS_ASSERT(!cx->runtime->noGCOrAllocationCheck);
 
 #ifdef JS_GC_ZEAL
     if (cx->runtime->needZealousGC())
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -5,24 +5,25 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef jsscript_h___
 #define jsscript_h___
 /*
  * JS script descriptor.
  */
-#include "jsprvtd.h"
 #include "jsdbgapi.h"
-#include "jsclist.h"
 #include "jsinfer.h"
 #include "jsopcode.h"
 #include "jsscope.h"
 
 #include "gc/Barrier.h"
+#include "gc/Root.h"
+
+ForwardDeclareJS(Script);
 
 namespace js {
 
 namespace ion {
     struct IonScript;
     struct IonScriptCounts;
 }