diff --git a/js/src/Makefile.in b/js/src/Makefile.in index 757d2cbf743c..fa42a4888689 100644 --- a/js/src/Makefile.in +++ b/js/src/Makefile.in @@ -677,6 +677,8 @@ ifeq ($(CPU_ARCH),x86) # Workaround compiler bug on PGO (Bug 721284) MonoIC.$(OBJ_SUFFIX): CXXFLAGS += -GL- Compiler.$(OBJ_SUFFIX): CXXFLAGS += -GL- +# Ditto (Bug 772303) +RegExp.$(OBJ_SUFFIX): CXXFLAGS += -GL- endif endif # _MSC_VER diff --git a/js/src/builtin/RegExp.cpp b/js/src/builtin/RegExp.cpp index 5fdae37bd9d3..7245078eb867 100644 --- a/js/src/builtin/RegExp.cpp +++ b/js/src/builtin/RegExp.cpp @@ -576,7 +576,7 @@ ExecuteRegExp(JSContext *cx, Native native, unsigned argc, Value *vp) return false; /* Step 4. */ - const Value &lastIndex = reobj->getLastIndex(); + Value lastIndex = reobj->getLastIndex(); /* Step 5. */ double i; @@ -588,7 +588,7 @@ ExecuteRegExp(JSContext *cx, Native native, unsigned argc, Value *vp) i = 0; const jschar *chars = linearInput->chars(); - size_t length = input->length(); + size_t length = linearInput->length(); /* Step 9a. */ if (i < 0 || i > length) { diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index b587f6f58a5b..6814e2b446ba 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -516,7 +516,10 @@ CheckStrictParameters(JSContext *cx, Parser *parser) return false; // Start with lastVariable(), not the last argument, for destructuring. - for (Shape::Range r = sc->bindings.lastVariable(); !r.empty(); r.popFront()) { + Shape::Range r = sc->bindings.lastVariable(); + Shape::Range::AutoRooter root(cx, &r); + + for (; !r.empty(); r.popFront()) { jsid id = r.front().propid(); if (!JSID_IS_ATOM(id)) continue; diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 56973ea026b9..838cd19d1260 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -4327,6 +4327,18 @@ JS::CheckStackRoots(JSContext *cx) // could happen.) JS_ASSERT(!cx->rootingUnnecessary); + // GCs can't happen when analysis/inference/compilation are active. + if (cx->compartment->activeAnalysis) + return; + + // Can switch to the atoms compartment during analysis. + if (IsAtomsCompartment(cx->compartment)) { + for (CompartmentsIter c(rt); !c.done(); c.next()) { + if (c.get()->activeAnalysis) + return; + } + } + AutoCopyFreeListToArenas copy(rt); JSTracer checker; diff --git a/js/src/jsinfer.cpp b/js/src/jsinfer.cpp index 5da3c2d5fecc..36bfd635874d 100644 --- a/js/src/jsinfer.cpp +++ b/js/src/jsinfer.cpp @@ -4452,8 +4452,8 @@ CheckNewScriptProperties(JSContext *cx, HandleTypeObject type, JSFunction *fun) * than we will use for subsequent new objects. Generate an object with the * appropriate final shape. */ - baseobj = NewReshapedObject(cx, type, baseobj->getParent(), kind, - baseobj->lastProperty()); + RootedShape shape(cx, baseobj->lastProperty()); + baseobj = NewReshapedObject(cx, type, baseobj->getParent(), kind, shape); if (!baseobj || !type->addDefiniteProperties(cx, baseobj) || !initializerList.append(done)) { @@ -5023,13 +5023,15 @@ JSFunction::setTypeForScriptedFunction(JSContext *cx, bool singleton) if (!setSingletonType(cx)) return false; } else { + RootedFunction self(cx, this); + TypeObject *type = cx->compartment->types.newTypeObject(cx, script(), JSProto_Function, getProto()); if (!type) return false; - setType(type); - type->interpretedFunction = this; + self->setType(type); + type->interpretedFunction = self; } return true; @@ -5203,10 +5205,10 @@ JSObject::makeLazyType(JSContext *cx) * looking at the class prototype key. */ - if (isSlowArray()) + if (self->isSlowArray()) type->flags |= OBJECT_FLAG_NON_DENSE_ARRAY | OBJECT_FLAG_NON_PACKED_ARRAY; - if (IsTypedArrayProto(this)) + if (IsTypedArrayProto(self)) type->flags |= OBJECT_FLAG_NON_TYPED_ARRAY; self->type_ = type; @@ -5259,7 +5261,7 @@ JSObject::setNewTypeUnknown(JSContext *cx) } TypeObject * -JSObject::getNewType(JSContext *cx, JSFunction *fun) +JSObject::getNewType(JSContext *cx, JSFunction *fun_) { TypeObjectSet &table = cx->compartment->newTypeObjects; @@ -5281,13 +5283,14 @@ JSObject::getNewType(JSContext *cx, JSFunction *fun) * Object.create is called with a prototype object that is also the * 'prototype' property of some scripted function. */ - if (type->newScript && type->newScript->fun != fun) + if (type->newScript && type->newScript->fun != fun_) type->clearNewScript(cx); return type; } RootedObject self(cx, this); + RootedFunction fun(cx, fun_); if (!setDelegate(cx)) return NULL; diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 195c21bb5ca9..3352cca4d83a 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -839,7 +839,7 @@ TryNoteIter::settle() * in *expr. */ static bool -DoIncDec(JSContext *cx, JSScript *script, jsbytecode *pc, const Value &v, Value *slot, Value *expr) +DoIncDec(JSContext *cx, HandleScript script, jsbytecode *pc, const Value &v, Value *slot, Value *expr) { const JSCodeSpec &cs = js_CodeSpec[*pc]; diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 869fee89142d..ebbc5541fa9d 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -2183,16 +2183,16 @@ JSObject::sealOrFreeze(JSContext *cx, ImmutabilityType it) return true; } -bool -JSObject::isSealedOrFrozen(JSContext *cx, ImmutabilityType it, bool *resultp) +/* static */ bool +JSObject::isSealedOrFrozen(JSContext *cx, HandleObject obj, ImmutabilityType it, bool *resultp) { - if (isExtensible()) { + if (obj->isExtensible()) { *resultp = false; return true; } AutoIdVector props(cx); - if (!GetPropertyNames(cx, this, JSITER_HIDDEN | JSITER_OWNONLY, &props)) + if (!GetPropertyNames(cx, obj, JSITER_HIDDEN | JSITER_OWNONLY, &props)) return false; RootedId id(cx); @@ -2200,7 +2200,7 @@ JSObject::isSealedOrFrozen(JSContext *cx, ImmutabilityType it, bool *resultp) id = props[i]; unsigned attrs; - if (!getGenericAttributes(cx, id, &attrs)) + if (!obj->getGenericAttributes(cx, id, &attrs)) return false; /* @@ -2241,7 +2241,7 @@ obj_isFrozen(JSContext *cx, unsigned argc, Value *vp) return false; bool frozen; - if (!obj->isFrozen(cx, &frozen)) + if (!JSObject::isFrozen(cx, obj, &frozen)) return false; vp->setBoolean(frozen); return true; @@ -2267,7 +2267,7 @@ obj_isSealed(JSContext *cx, unsigned argc, Value *vp) return false; bool sealed; - if (!obj->isSealed(cx, &sealed)) + if (!JSObject::isSealed(cx, obj, &sealed)) return false; vp->setBoolean(sealed); return true; @@ -2509,7 +2509,7 @@ js::NewObjectWithType(JSContext *cx, HandleTypeObject type, JSObject *parent, gc JSObject * js::NewReshapedObject(JSContext *cx, HandleTypeObject type, JSObject *parent, - gc::AllocKind kind, Shape *shape) + gc::AllocKind kind, HandleShape shape) { RootedObject res(cx, NewObjectWithType(cx, type, parent, kind)); if (!res) @@ -2612,16 +2612,20 @@ js_CreateThisForFunction(JSContext *cx, HandleObject callee, bool newType) JSObject *obj = js_CreateThisForFunctionWithProto(cx, callee, proto); if (obj && newType) { + RootedObject nobj(cx, obj); + /* * Reshape the object and give it a (lazily instantiated) singleton * type before passing it as the 'this' value for the call. */ - obj->clear(cx); - if (!obj->setSingletonType(cx)) + nobj->clear(cx); + if (!nobj->setSingletonType(cx)) return NULL; JSScript *calleeScript = callee->toFunction()->script(); - TypeScript::SetThis(cx, calleeScript, types::Type::ObjectType(obj)); + TypeScript::SetThis(cx, calleeScript, types::Type::ObjectType(nobj)); + + return nobj; } return obj; @@ -3527,10 +3531,12 @@ JSObject::growSlots(JSContext *cx, uint32_t oldCount, uint32_t newCount) gc::AllocKind kind = type()->newScript->allocKind; unsigned newScriptSlots = gc::GetGCKindSlots(kind); if (newScriptSlots == numFixedSlots() && gc::TryIncrementAllocKind(&kind)) { + AutoEnterTypeInference enter(cx); + Rooted typeObj(cx, type()); + RootedShape shape(cx, typeObj->newScript->shape); JSObject *obj = NewReshapedObject(cx, typeObj, - getParent(), kind, - typeObj->newScript->shape); + getParent(), kind, shape); if (!obj) return false; diff --git a/js/src/jsobj.h b/js/src/jsobj.h index be5c2cbcef07..1211fab7c0df 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -531,7 +531,7 @@ struct JSObject : public js::ObjectImpl */ bool sealOrFreeze(JSContext *cx, ImmutabilityType it); - bool isSealedOrFrozen(JSContext *cx, ImmutabilityType it, bool *resultp); + static bool isSealedOrFrozen(JSContext *cx, js::HandleObject obj, ImmutabilityType it, bool *resultp); static inline unsigned getSealedOrFrozenAttributes(unsigned attrs, ImmutabilityType it); @@ -543,8 +543,12 @@ struct JSObject : public js::ObjectImpl /* ES5 15.2.3.9: non-extensible, all properties non-configurable, all data props read-only */ bool freeze(JSContext *cx) { return sealOrFreeze(cx, FREEZE); } - bool isSealed(JSContext *cx, bool *resultp) { return isSealedOrFrozen(cx, SEAL, resultp); } - bool isFrozen(JSContext *cx, bool *resultp) { return isSealedOrFrozen(cx, FREEZE, resultp); } + static inline bool isSealed(JSContext *cx, js::HandleObject obj, bool *resultp) { + return isSealedOrFrozen(cx, obj, SEAL, resultp); + } + static inline bool isFrozen(JSContext *cx, js::HandleObject obj, bool *resultp) { + return isSealedOrFrozen(cx, obj, FREEZE, resultp); + } /* Accessors for elements. */ diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index b1f43c99c585..afe87487f8d0 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -1552,7 +1552,7 @@ CopyInitializerObject(JSContext *cx, HandleObject baseobj) JSObject * NewReshapedObject(JSContext *cx, HandleTypeObject type, JSObject *parent, - gc::AllocKind kind, Shape *shape); + gc::AllocKind kind, HandleShape shape); /* * As for gc::GetGCObjectKind, where numSlots is a guess at the final size of diff --git a/js/src/jsproxy.cpp b/js/src/jsproxy.cpp index a4a2f649fb2c..04efd4c915b8 100644 --- a/js/src/jsproxy.cpp +++ b/js/src/jsproxy.cpp @@ -367,7 +367,7 @@ IndirectProxyHandler::getPropertyDescriptor(JSContext *cx, JSObject *proxy, } static bool -GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, unsigned flags, +GetOwnPropertyDescriptor(JSContext *cx, HandleObject obj, jsid id, unsigned flags, JSPropertyDescriptor *desc) { // If obj is a proxy, we can do better than just guessing. This is @@ -389,7 +389,8 @@ IndirectProxyHandler::getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, bool set, PropertyDescriptor *desc) { - return GetOwnPropertyDescriptor(cx, GetProxyTargetObject(proxy), id, + RootedObject target(cx, GetProxyTargetObject(proxy)); + return GetOwnPropertyDescriptor(cx, target, id, JSRESOLVE_QUALIFIED, desc); } diff --git a/js/src/jsxml.cpp b/js/src/jsxml.cpp index ff49d45ac3a8..abf0cac53629 100644 --- a/js/src/jsxml.cpp +++ b/js/src/jsxml.cpp @@ -1717,7 +1717,7 @@ GetCurrentScopeChain(JSContext *cx) } static JSXML * -ParseXMLSource(JSContext *cx, JSString *src) +ParseXMLSource(JSContext *cx, HandleString src) { jsval nsval; JSLinearString *uri; @@ -1856,7 +1856,7 @@ ToXML(JSContext *cx, jsval v) JSObject *obj; JSXML *xml; Class *clasp; - JSString *str; + RootedString str(cx); uint32_t length; if (JSVAL_IS_PRIMITIVE(v)) { @@ -1937,7 +1937,7 @@ ToXMLList(JSContext *cx, jsval v) JSObject *obj, *listobj; JSXML *xml, *list, *kid; Class *clasp; - JSString *str; + RootedString str(cx); uint32_t i, length; if (JSVAL_IS_PRIMITIVE(v)) { diff --git a/js/src/methodjit/BaseAssembler.h b/js/src/methodjit/BaseAssembler.h index e6b736f167f7..f1f0ff441713 100644 --- a/js/src/methodjit/BaseAssembler.h +++ b/js/src/methodjit/BaseAssembler.h @@ -1375,7 +1375,7 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::MIPSRegiste }; /* Return f if the script is strict mode code, f otherwise. */ -#define STRICT_VARIANT(f) \ +#define STRICT_VARIANT(script, f) \ (FunctionTemplateConditional(script->strictModeCode, \ f, f)) diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index f5a269000ac4..f383a9663774 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -2523,7 +2523,7 @@ mjit::Compiler::generateMethod() prepareStubCall(Uses(1)); masm.move(ImmPtr(name), Registers::ArgReg1); - INLINE_STUBCALL(STRICT_VARIANT(stubs::DelProp), REJOIN_FALLTHROUGH); + INLINE_STUBCALL(STRICT_VARIANT(script, stubs::DelProp), REJOIN_FALLTHROUGH); frame.pop(); pushSyncedEntry(0); } @@ -2532,7 +2532,7 @@ mjit::Compiler::generateMethod() BEGIN_CASE(JSOP_DELELEM) { prepareStubCall(Uses(2)); - INLINE_STUBCALL(STRICT_VARIANT(stubs::DelElem), REJOIN_FALLTHROUGH); + INLINE_STUBCALL(STRICT_VARIANT(script, stubs::DelElem), REJOIN_FALLTHROUGH); frame.popn(2); pushSyncedEntry(0); } @@ -3032,7 +3032,7 @@ mjit::Compiler::generateMethod() prepareStubCall(Uses(0)); masm.move(ImmPtr(innerFun), Registers::ArgReg1); - INLINE_STUBCALL(STRICT_VARIANT(stubs::DefFun), REJOIN_FALLTHROUGH); + INLINE_STUBCALL(STRICT_VARIANT(script, stubs::DefFun), REJOIN_FALLTHROUGH); } END_CASE(JSOP_DEFFUN) @@ -4200,18 +4200,8 @@ mjit::Compiler::inlineCallHelper(uint32_t argc, bool callingNew, FrameSize &call if (icCalleeType.isSet()) notObjectJump = masm.testObject(Assembler::NotEqual, icCalleeType.reg()); - /* - * For an optimized apply, keep icCalleeData in a callee-saved register for - * the subsequent ic::SplatApplyArgs call. - */ Registers tempRegs(Registers::AvailRegs); - if (callIC.frameSize.isDynamic() && !Registers::isSaved(icCalleeData)) { - RegisterID x = tempRegs.takeAnyReg(Registers::SavedRegs).reg(); - masm.move(icCalleeData, x); - icCalleeData = x; - } else { - tempRegs.takeReg(icCalleeData); - } + tempRegs.takeReg(icCalleeData); /* Reserve space just before initialization of funGuard. */ RESERVE_IC_SPACE(masm); @@ -4252,9 +4242,16 @@ mjit::Compiler::inlineCallHelper(uint32_t argc, bool callingNew, FrameSize &call * Check after the function is known not to be a native so that the * catch-all/native path has a static depth. */ - if (callIC.frameSize.isDynamic()) + if (callIC.frameSize.isDynamic()) { OOL_STUBCALL(ic::SplatApplyArgs, REJOIN_CALL_SPLAT); + /* + * Restore identity of callee after SplatApplyArgs, which may + * have been clobbered (not callee save reg or changed by moving GC). + */ + stubcc.masm.loadPayload(frame.addressOf(origThis), icCalleeData); + } + /* * No-op jump that gets patched by ic::New/Call to the stub generated * by generateFullCallStub. @@ -4697,7 +4694,7 @@ mjit::Compiler::jsop_setprop_slow(PropertyName *name) { prepareStubCall(Uses(2)); masm.move(ImmPtr(name), Registers::ArgReg1); - INLINE_STUBCALL(STRICT_VARIANT(stubs::SetName), REJOIN_FALLTHROUGH); + INLINE_STUBCALL(STRICT_VARIANT(script, stubs::SetName), REJOIN_FALLTHROUGH); JS_STATIC_ASSERT(JSOP_SETNAME_LENGTH == JSOP_SETPROP_LENGTH); frame.shimmy(1); if (script->hasScriptCounts) @@ -5399,7 +5396,7 @@ mjit::Compiler::jsop_setprop(PropertyName *name, bool popGuaranteed) stubcc.linkExit(notObject.get(), Uses(2)); stubcc.leave(); stubcc.masm.move(ImmPtr(name), Registers::ArgReg1); - OOL_STUBCALL(STRICT_VARIANT(stubs::SetName), REJOIN_FALLTHROUGH); + OOL_STUBCALL(STRICT_VARIANT(script, stubs::SetName), REJOIN_FALLTHROUGH); } frame.storeTo(rhs, Address(reg, JSObject::getFixedSlotOffset(slot)), popGuaranteed); frame.unpinReg(reg); @@ -5463,7 +5460,7 @@ mjit::Compiler::jsop_setprop(PropertyName *name, bool popGuaranteed) stubcc.leave(); stubcc.masm.move(ImmPtr(name), Registers::ArgReg1); - OOL_STUBCALL(STRICT_VARIANT(stubs::SetName), REJOIN_FALLTHROUGH); + OOL_STUBCALL(STRICT_VARIANT(script, stubs::SetName), REJOIN_FALLTHROUGH); typeCheck = stubcc.masm.jump(); pic.hasTypeCheck = true; @@ -6316,7 +6313,7 @@ mjit::Compiler::jsop_setgname_slow(PropertyName *name) { prepareStubCall(Uses(2)); masm.move(ImmPtr(name), Registers::ArgReg1); - INLINE_STUBCALL(STRICT_VARIANT(stubs::SetGlobalName), REJOIN_FALLTHROUGH); + INLINE_STUBCALL(STRICT_VARIANT(script, stubs::SetGlobalName), REJOIN_FALLTHROUGH); frame.popn(2); pushSyncedEntry(0); } @@ -6453,7 +6450,7 @@ void mjit::Compiler::jsop_setelem_slow() { prepareStubCall(Uses(3)); - INLINE_STUBCALL(STRICT_VARIANT(stubs::SetElem), REJOIN_FALLTHROUGH); + INLINE_STUBCALL(STRICT_VARIANT(script, stubs::SetElem), REJOIN_FALLTHROUGH); frame.popn(3); frame.pushSynced(JSVAL_TYPE_UNKNOWN); } diff --git a/js/src/methodjit/FastOps.cpp b/js/src/methodjit/FastOps.cpp index 8b4d943873f0..4aae65cc46f6 100644 --- a/js/src/methodjit/FastOps.cpp +++ b/js/src/methodjit/FastOps.cpp @@ -1212,7 +1212,7 @@ mjit::Compiler::jsop_setelem_dense() masm.storeValue(vr, BaseIndex(slotsReg, key.reg(), masm.JSVAL_SCALE)); stubcc.leave(); - OOL_STUBCALL(STRICT_VARIANT(stubs::SetElem), REJOIN_FALLTHROUGH); + OOL_STUBCALL(STRICT_VARIANT(script, stubs::SetElem), REJOIN_FALLTHROUGH); if (!hoisted) frame.freeReg(slotsReg); @@ -1486,7 +1486,7 @@ mjit::Compiler::jsop_setelem_typed(int atype) frame.freeReg(objReg); stubcc.leave(); - OOL_STUBCALL(STRICT_VARIANT(stubs::SetElem), REJOIN_FALLTHROUGH); + OOL_STUBCALL(STRICT_VARIANT(script, stubs::SetElem), REJOIN_FALLTHROUGH); frame.shimmy(2); stubcc.rejoin(Changes(2)); @@ -1687,9 +1687,9 @@ mjit::Compiler::jsop_setelem(bool popGuaranteed) stubcc.leave(); #if defined JS_POLYIC passICAddress(&ic); - ic.slowPathCall = OOL_STUBCALL(STRICT_VARIANT(ic::SetElement), REJOIN_FALLTHROUGH); + ic.slowPathCall = OOL_STUBCALL(STRICT_VARIANT(script, ic::SetElement), REJOIN_FALLTHROUGH); #else - OOL_STUBCALL(STRICT_VARIANT(stubs::SetElem), REJOIN_FALLTHROUGH); + OOL_STUBCALL(STRICT_VARIANT(script, stubs::SetElem), REJOIN_FALLTHROUGH); #endif ic.fastPathRejoin = masm.label(); diff --git a/js/src/methodjit/MonoIC.cpp b/js/src/methodjit/MonoIC.cpp index acf0efcb4190..d90a33f080cd 100644 --- a/js/src/methodjit/MonoIC.cpp +++ b/js/src/methodjit/MonoIC.cpp @@ -58,12 +58,12 @@ PatchGetFallback(VMFrame &f, ic::GetGlobalNameIC *ic) void JS_FASTCALL ic::GetGlobalName(VMFrame &f, ic::GetGlobalNameIC *ic) { - JSObject &obj = f.fp()->global(); + RootedObject obj(f.cx, &f.fp()->global()); PropertyName *name = f.script()->getName(GET_UINT32_INDEX(f.pc())); RecompilationMonitor monitor(f.cx); - Shape *shape = obj.nativeLookup(f.cx, NameToId(name)); + Shape *shape = obj->nativeLookup(f.cx, NameToId(name)); if (monitor.recompiled()) { stubs::Name(f); @@ -83,10 +83,10 @@ ic::GetGlobalName(VMFrame &f, ic::GetGlobalNameIC *ic) /* Patch shape guard. */ Repatcher repatcher(f.chunk()); - repatcher.repatch(ic->fastPathStart.dataLabelPtrAtOffset(ic->shapeOffset), obj.lastProperty()); + repatcher.repatch(ic->fastPathStart.dataLabelPtrAtOffset(ic->shapeOffset), obj->lastProperty()); /* Patch loads. */ - uint32_t index = obj.dynamicSlotIndex(slot); + uint32_t index = obj->dynamicSlotIndex(slot); JSC::CodeLocationLabel label = ic->fastPathStart.labelAtOffset(ic->loadStoreOffset); repatcher.patchAddressOffsetForValueLoad(label, index * sizeof(Value)); @@ -107,9 +107,8 @@ template void JS_FASTCALL DisabledSetGlobal(VMFrame &f, ic::SetGlobalName static void PatchSetFallback(VMFrame &f, ic::SetGlobalNameIC *ic) { - JSScript *script = f.script(); Repatcher repatch(f.chunk()); - VoidStubSetGlobal stub = STRICT_VARIANT(DisabledSetGlobal); + VoidStubSetGlobal stub = STRICT_VARIANT(f.script(), DisabledSetGlobal); JSC::FunctionPtr fptr(JS_FUNC_TO_DATA_PTR(void *, stub)); repatch.relink(ic->slowPathCall, fptr); } @@ -153,21 +152,20 @@ UpdateSetGlobalName(VMFrame &f, ic::SetGlobalNameIC *ic, JSObject *obj, Shape *s void JS_FASTCALL ic::SetGlobalName(VMFrame &f, ic::SetGlobalNameIC *ic) { - JSObject &obj = f.fp()->global(); - JSScript *script = f.script(); - PropertyName *name = script->getName(GET_UINT32_INDEX(f.pc())); + RootedObject obj(f.cx, &f.fp()->global()); + RootedPropertyName name(f.cx, f.script()->getName(GET_UINT32_INDEX(f.pc()))); RecompilationMonitor monitor(f.cx); - Shape *shape = obj.nativeLookup(f.cx, NameToId(name)); + Shape *shape = obj->nativeLookup(f.cx, NameToId(name)); if (!monitor.recompiled()) { - LookupStatus status = UpdateSetGlobalName(f, ic, &obj, shape); + LookupStatus status = UpdateSetGlobalName(f, ic, obj, shape); if (status == Lookup_Error) THROW(); } - STRICT_VARIANT(stubs::SetGlobalName)(f, name); + STRICT_VARIANT(f.script(), stubs::SetGlobalName)(f, name); } class EqualityICLinker : public LinkerHelper @@ -764,8 +762,8 @@ class CallCompiler : public BaseCompiler args = CallArgsFromSp(f.u.call.dynamicArgc, f.regs.sp); } - JSFunction *fun; - if (!IsFunctionObject(args.calleev(), &fun)) + RootedFunction fun(cx); + if (!IsFunctionObject(args.calleev(), fun.address())) return false; if ((!callingNew && !fun->isNative()) || (callingNew && !fun->isNativeConstructor())) diff --git a/js/src/methodjit/PolyIC.cpp b/js/src/methodjit/PolyIC.cpp index 2f63806ec094..ac9da4a8ec45 100644 --- a/js/src/methodjit/PolyIC.cpp +++ b/js/src/methodjit/PolyIC.cpp @@ -68,7 +68,6 @@ class PICStubCompiler : public BaseCompiler protected: const char *type; VMFrame &f; - JSScript *script; ic::PICInfo &pic; void *stub; uint64_t gcNumber; @@ -76,8 +75,8 @@ class PICStubCompiler : public BaseCompiler public: bool canCallHook; - PICStubCompiler(const char *type, VMFrame &f, JSScript *script, ic::PICInfo &pic, void *stub) - : BaseCompiler(f.cx), type(type), f(f), script(script), pic(pic), stub(stub), + PICStubCompiler(const char *type, VMFrame &f, ic::PICInfo &pic, void *stub) + : BaseCompiler(f.cx), type(type), f(f), pic(pic), stub(stub), gcNumber(f.cx->runtime->gcNumber), canCallHook(pic.canCallHook) { } @@ -113,7 +112,7 @@ class PICStubCompiler : public BaseCompiler void spew(const char *event, const char *op) { #ifdef JS_METHODJIT_SPEW JaegerSpew(JSpew_PICs, "%s %s: %s (%s: %d)\n", - type, event, op, script->filename, CurrentLine(cx)); + type, event, op, f.script()->filename, CurrentLine(cx)); #endif } }; @@ -165,15 +164,15 @@ GeneratePrototypeGuards(JSContext *cx, Vector &mism class SetPropCompiler : public PICStubCompiler { - JSObject *obj; - PropertyName *name; + RootedObject obj; + RootedPropertyName name; int lastStubSecondShapeGuard; public: - SetPropCompiler(VMFrame &f, JSScript *script, JSObject *obj, ic::PICInfo &pic, PropertyName *name, + SetPropCompiler(VMFrame &f, JSObject *obj, ic::PICInfo &pic, PropertyName *name, VoidStubPIC stub) - : PICStubCompiler("setprop", f, script, pic, JS_FUNC_TO_DATA_PTR(void *, stub)), - obj(obj), name(name), lastStubSecondShapeGuard(pic.secondShapeGuard) + : PICStubCompiler("setprop", f, pic, JS_FUNC_TO_DATA_PTR(void *, stub)), + obj(f.cx, obj), name(f.cx, name), lastStubSecondShapeGuard(pic.secondShapeGuard) { } static void reset(Repatcher &repatcher, ic::PICInfo &pic) @@ -751,17 +750,17 @@ namespace mjit { class GetPropCompiler : public PICStubCompiler { - JSObject *obj; - PropertyName *name; - int lastStubSecondShapeGuard; + RootedObject obj; + RootedPropertyName name; + int lastStubSecondShapeGuard; public: - GetPropCompiler(VMFrame &f, JSScript *script, JSObject *obj, ic::PICInfo &pic, PropertyName *name, + GetPropCompiler(VMFrame &f, JSObject *obj, ic::PICInfo &pic, PropertyName *name, VoidStubPIC stub) - : PICStubCompiler("getprop", f, script, pic, + : PICStubCompiler("getprop", f, pic, JS_FUNC_TO_DATA_PTR(void *, stub)), - obj(obj), - name(name), + obj(f.cx, obj), + name(f.cx, name), lastStubSecondShapeGuard(pic.secondShapeGuard) { } @@ -872,7 +871,7 @@ class GetPropCompiler : public PICStubCompiler RecompilationMonitor monitor(f.cx); - JSObject *obj = f.fp()->global().getOrCreateStringPrototype(f.cx); + RootedObject obj(f.cx, f.fp()->global().getOrCreateStringPrototype(f.cx)); if (!obj) return error(); @@ -1217,12 +1216,15 @@ class GetPropCompiler : public PICStubCompiler linkerEpilogue(linker, start, shapeMismatches); } - LookupStatus generateStub(JSObject *holder, Shape *shape) + LookupStatus generateStub(JSObject *holder, HandleShape shape) { Vector shapeMismatches(cx); Assembler masm; + // Ignore GC pointers baked into assembly visible on the stack. + SkipRoot skip(cx, &masm); + Label start; Jump shapeGuardJump; Jump argsLenGuard; @@ -1445,9 +1447,9 @@ class ScopeNameCompiler : public PICStubCompiler } public: - ScopeNameCompiler(VMFrame &f, JSScript *script, JSObject *scopeChain, ic::PICInfo &pic, + ScopeNameCompiler(VMFrame &f, JSObject *scopeChain, ic::PICInfo &pic, PropertyName *name, VoidStubPIC stub) - : PICStubCompiler("name", f, script, pic, JS_FUNC_TO_DATA_PTR(void *, stub)), + : PICStubCompiler("name", f, pic, JS_FUNC_TO_DATA_PTR(void *, stub)), scopeChain(f.cx, scopeChain), name(f.cx, name), getprop(f.cx, NULL, name, *thisFromCtor(), f) { } @@ -1713,9 +1715,9 @@ class BindNameCompiler : public PICStubCompiler RootedPropertyName name; public: - BindNameCompiler(VMFrame &f, JSScript *script, JSObject *scopeChain, ic::PICInfo &pic, + BindNameCompiler(VMFrame &f, JSObject *scopeChain, ic::PICInfo &pic, PropertyName *name, VoidStubPIC stub) - : PICStubCompiler("bind", f, script, pic, JS_FUNC_TO_DATA_PTR(void *, stub)), + : PICStubCompiler("bind", f, pic, JS_FUNC_TO_DATA_PTR(void *, stub)), scopeChain(f.cx, scopeChain), name(f.cx, name) { } @@ -1860,9 +1862,7 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic) bool cached = pic->cached; VoidStubPIC stub = cached ? DisabledGetPropIC : DisabledGetPropNoCacheIC; - JSScript *script = f.fp()->script(); - - PropertyName *name = pic->name; + RootedPropertyName name(f.cx, pic->name); if (name == f.cx->runtime->atomState.lengthAtom) { if (IsOptimizedArguments(f.fp(), &f.regs.sp[-1])) { f.regs.sp[-1].setInt32(f.regs.fp()->numActualArgs()); @@ -1871,7 +1871,7 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic) if (!f.regs.sp[-1].isPrimitive()) { JSObject *obj = &f.regs.sp[-1].toObject(); if (obj->isArray() || obj->isString()) { - GetPropCompiler cc(f, script, obj, *pic, NULL, stub); + GetPropCompiler cc(f, obj, *pic, NULL, stub); if (obj->isArray()) { LookupStatus status = cc.generateArrayLengthStub(); if (status == Lookup_Error) @@ -1890,7 +1890,7 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic) } if (f.regs.sp[-1].isString()) { - GetPropCompiler cc(f, script, NULL, *pic, name, stub); + GetPropCompiler cc(f, NULL, *pic, name, stub); if (name == f.cx->runtime->atomState.lengthAtom) { LookupStatus status = cc.generateStringLengthStub(); if (status == Lookup_Error) @@ -1912,22 +1912,22 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic) RecompilationMonitor monitor(f.cx); - JSObject *obj = ValueToObject(f.cx, f.regs.sp[-1]); + RootedObject obj(f.cx, ValueToObject(f.cx, f.regs.sp[-1])); if (!obj) THROW(); if (!monitor.recompiled() && pic->shouldUpdate(f.cx)) { - GetPropCompiler cc(f, script, obj, *pic, name, stub); + GetPropCompiler cc(f, obj, *pic, name, stub); if (!cc.update()) THROW(); } - Value v; + RootedValue v(f.cx); if (cached) { - if (!GetPropertyOperation(f.cx, f.script(), f.pc(), f.regs.sp[-1], &v)) + if (!GetPropertyOperation(f.cx, f.script(), f.pc(), f.regs.sp[-1], v.address())) THROW(); } else { - if (!obj->getProperty(f.cx, name, &v)) + if (!obj->getProperty(f.cx, name, v.address())) THROW(); } @@ -1944,14 +1944,13 @@ DisabledSetPropIC(VMFrame &f, ic::PICInfo *pic) void JS_FASTCALL ic::SetProp(VMFrame &f, ic::PICInfo *pic) { - JSScript *script = f.fp()->script(); JS_ASSERT(pic->isSet()); - VoidStubPIC stub = STRICT_VARIANT(DisabledSetPropIC); + VoidStubPIC stub = STRICT_VARIANT(f.script(), DisabledSetPropIC); // Save this in case the compiler triggers a recompilation of this script. - PropertyName *name = pic->name; - VoidStubName nstub = STRICT_VARIANT(stubs::SetName); + RootedPropertyName name(f.cx, pic->name); + VoidStubName nstub = STRICT_VARIANT(f.script(), stubs::SetName); RecompilationMonitor monitor(f.cx); @@ -1962,7 +1961,7 @@ ic::SetProp(VMFrame &f, ic::PICInfo *pic) // Note, we can't use SetName for PROPINC PICs because the property // cache can't handle a GET and SET from the same scripted PC. if (!monitor.recompiled() && pic->shouldUpdate(f.cx)) { - SetPropCompiler cc(f, script, obj, *pic, name, stub); + SetPropCompiler cc(f, obj, *pic, name, stub); LookupStatus status = cc.update(); if (status == Lookup_Error) THROW(); @@ -1986,12 +1985,10 @@ DisabledXNameIC(VMFrame &f, ic::PICInfo *pic) void JS_FASTCALL ic::XName(VMFrame &f, ic::PICInfo *pic) { - JSScript *script = f.fp()->script(); - /* GETXPROP is guaranteed to have an object. */ JSObject *obj = &f.regs.sp[-1].toObject(); - ScopeNameCompiler cc(f, script, obj, *pic, pic->name, DisabledXNameIC); + ScopeNameCompiler cc(f, obj, *pic, pic->name, DisabledXNameIC); LookupStatus status = cc.updateForXName(); if (status == Lookup_Error) @@ -2006,16 +2003,14 @@ ic::XName(VMFrame &f, ic::PICInfo *pic) void JS_FASTCALL ic::Name(VMFrame &f, ic::PICInfo *pic) { - JSScript *script = f.fp()->script(); - - ScopeNameCompiler cc(f, script, f.fp()->scopeChain(), *pic, pic->name, DisabledNameIC); + ScopeNameCompiler cc(f, f.fp()->scopeChain(), *pic, pic->name, DisabledNameIC); LookupStatus status = cc.updateForName(); if (status == Lookup_Error) THROW(); - Value rval; - if (!cc.retrieve(&rval, PICInfo::NAME)) + RootedValue rval(f.cx); + if (!cc.retrieve(rval.address(), PICInfo::NAME)) THROW(); f.regs.sp[0] = rval; } @@ -2029,10 +2024,8 @@ DisabledBindNameIC(VMFrame &f, ic::PICInfo *pic) void JS_FASTCALL ic::BindName(VMFrame &f, ic::PICInfo *pic) { - JSScript *script = f.fp()->script(); - VoidStubPIC stub = DisabledBindNameIC; - BindNameCompiler cc(f, script, f.fp()->scopeChain(), *pic, pic->name, stub); + BindNameCompiler cc(f, f.fp()->scopeChain(), *pic, pic->name, stub); JSObject *obj = cc.update(); if (!obj) @@ -2181,7 +2174,7 @@ GetElementIC::purge(Repatcher &repatcher) } LookupStatus -GetElementIC::attachGetProp(VMFrame &f, JSObject *obj, const Value &v, PropertyName *name, +GetElementIC::attachGetProp(VMFrame &f, HandleObject obj, HandleValue v, HandlePropertyName name, Value *vp) { JS_ASSERT(v.isString()); @@ -2362,7 +2355,7 @@ GetElementIC::attachGetProp(VMFrame &f, JSObject *obj, const Value &v, PropertyN #if defined JS_METHODJIT_TYPED_ARRAY LookupStatus -GetElementIC::attachTypedArray(VMFrame &f, JSObject *obj, const Value &v, jsid id, Value *vp) +GetElementIC::attachTypedArray(VMFrame &f, HandleObject obj, HandleValue v, HandleId id, Value *vp) { JSContext *cx = f.cx; @@ -2455,16 +2448,18 @@ GetElementIC::attachTypedArray(VMFrame &f, JSObject *obj, const Value &v, jsid i #endif /* JS_METHODJIT_TYPED_ARRAY */ LookupStatus -GetElementIC::update(VMFrame &f, JSObject *obj, const Value &v, jsid id, Value *vp) +GetElementIC::update(VMFrame &f, HandleObject obj, HandleValue v, HandleId id, Value *vp) { - /* + /*JSObject *obj, const Value &v, jsid id, Value *vp) * Only treat this as a GETPROP for non-numeric string identifiers. The * GETPROP IC assumes the id has already gone through filtering for string * indexes in the emitter. */ uint32_t dummy; - if (v.isString() && JSID_IS_ATOM(id) && !JSID_TO_ATOM(id)->isIndex(&dummy)) - return attachGetProp(f, obj, v, JSID_TO_ATOM(id)->asPropertyName(), vp); + if (v.isString() && JSID_IS_ATOM(id) && !JSID_TO_ATOM(id)->isIndex(&dummy)) { + RootedPropertyName name(f.cx, JSID_TO_ATOM(id)->asPropertyName()); + return attachGetProp(f, obj, v, name, vp); + } #if defined JS_METHODJIT_TYPED_ARRAY /* @@ -2496,7 +2491,8 @@ ic::GetElement(VMFrame &f, ic::GetElementIC *ic) return; } - Value idval = f.regs.sp[-1]; + RootedValue idval_(cx, f.regs.sp[-1]); + Value &idval = idval_.get(); RecompilationMonitor monitor(cx); @@ -2526,7 +2522,7 @@ ic::GetElement(VMFrame &f, ic::GetElementIC *ic) #ifdef DEBUG f.regs.sp[-2] = MagicValue(JS_GENERIC_MAGIC); #endif - LookupStatus status = ic->update(f, obj, idval, id, &f.regs.sp[-2]); + LookupStatus status = ic->update(f, obj, idval_, id, &f.regs.sp[-2]); if (status != Lookup_Uncacheable) { if (status == Lookup_Error) THROW(); diff --git a/js/src/methodjit/PolyIC.h b/js/src/methodjit/PolyIC.h index 1908d493f105..a1d2aa95232f 100644 --- a/js/src/methodjit/PolyIC.h +++ b/js/src/methodjit/PolyIC.h @@ -243,10 +243,10 @@ struct GetElementIC : public BasePolyIC { } void purge(Repatcher &repatcher); - LookupStatus update(VMFrame &f, JSObject *obj, const Value &v, jsid id, Value *vp); - LookupStatus attachGetProp(VMFrame &f, JSObject *obj, const Value &v, PropertyName *name, + LookupStatus update(VMFrame &f, HandleObject obj, HandleValue v, HandleId id, Value *vp); + LookupStatus attachGetProp(VMFrame &f, HandleObject obj, HandleValue v, HandlePropertyName name, Value *vp); - LookupStatus attachTypedArray(VMFrame &f, JSObject *obj, const Value &v, jsid id, Value *vp); + LookupStatus attachTypedArray(VMFrame &f, HandleObject obj, HandleValue v, HandleId id, Value *vp); LookupStatus disable(VMFrame &f, const char *reason); LookupStatus error(JSContext *cx); bool shouldUpdate(JSContext *cx); diff --git a/js/src/methodjit/StubCalls.cpp b/js/src/methodjit/StubCalls.cpp index e7b128cbc49b..713852e0b63b 100644 --- a/js/src/methodjit/StubCalls.cpp +++ b/js/src/methodjit/StubCalls.cpp @@ -123,7 +123,7 @@ stubs::SetElem(VMFrame &f) Value &objval = regs.sp[-3]; Value &idval = regs.sp[-2]; - Value rval = regs.sp[-1]; + RootedValue rval(cx, regs.sp[-1]); RootedId id(cx); @@ -155,7 +155,7 @@ stubs::SetElem(VMFrame &f) } } } while (0); - if (!obj->setGeneric(cx, obj, id, &rval, strict)) + if (!obj->setGeneric(cx, obj, id, rval.address(), strict)) THROW(); end_setelem: /* :FIXME: Moving the assigned object into the lowest stack slot @@ -337,13 +337,13 @@ stubs::DefFun(VMFrame &f, JSFunction *fun_) Rooted parent(cx, &fp->varObj()); /* ES5 10.5 (NB: with subsequent errata). */ - PropertyName *name = fun->atom->asPropertyName(); + RootedPropertyName name(cx, fun->atom->asPropertyName()); RootedShape shape(cx); RootedObject pobj(cx); if (!parent->lookupProperty(cx, name, &pobj, &shape)) THROW(); - Value rval = ObjectValue(*fun); + RootedValue rval(cx, ObjectValue(*fun)); do { /* Steps 5d, 5f. */ @@ -386,7 +386,7 @@ stubs::DefFun(VMFrame &f, JSFunction *fun_) */ /* Step 5f. */ - if (!parent->setProperty(cx, parent, name, &rval, strict)) + if (!parent->setProperty(cx, parent, name, rval.address(), strict)) THROW(); } while (false); } @@ -465,8 +465,9 @@ StubEqualityOp(VMFrame &f) JSContext *cx = f.cx; FrameRegs ®s = f.regs; - Value rval = regs.sp[-1]; - Value lval = regs.sp[-2]; + RootedValue rval_(cx, regs.sp[-1]); + RootedValue lval_(cx, regs.sp[-2]); + Value &rval = rval_.get(), &lval = lval_.get(); bool cond; @@ -575,8 +576,9 @@ stubs::Add(VMFrame &f) { JSContext *cx = f.cx; FrameRegs ®s = f.regs; - Value rval = regs.sp[-1]; - Value lval = regs.sp[-2]; + RootedValue rval_(cx, regs.sp[-1]); + RootedValue lval_(cx, regs.sp[-2]); + Value &rval = rval_.get(), &lval = lval_.get(); /* The string + string case is easily the hottest; try it first. */ bool lIsString = lval.isString(); @@ -861,11 +863,11 @@ stubs::Neg(VMFrame &f) void JS_FASTCALL stubs::NewInitArray(VMFrame &f, uint32_t count) { + Rooted type(f.cx, (TypeObject *) f.scratch); RootedObject obj(f.cx, NewDenseAllocatedArray(f.cx, count)); if (!obj) THROW(); - TypeObject *type = (TypeObject *) f.scratch; if (type) { obj->setType(type); } else { @@ -881,7 +883,7 @@ void JS_FASTCALL stubs::NewInitObject(VMFrame &f, JSObject *baseobj) { JSContext *cx = f.cx; - TypeObject *type = (TypeObject *) f.scratch; + Rooted type(f.cx, (TypeObject *) f.scratch); RootedObject obj(cx); if (baseobj) { @@ -919,7 +921,7 @@ stubs::InitElem(VMFrame &f, uint32_t last) /* Find the object being initialized at top of stack. */ const Value &lref = regs.sp[-3]; JS_ASSERT(lref.isObject()); - JSObject *obj = &lref.toObject(); + RootedObject obj(cx, &lref.toObject()); /* Fetch id now that we have obj. */ RootedId id(cx); @@ -978,8 +980,8 @@ stubs::GetProp(VMFrame &f, PropertyName *name) JSContext *cx = f.cx; FrameRegs ®s = f.regs; - Value rval; - if (!GetPropertyOperation(cx, f.script(), f.pc(), f.regs.sp[-1], &rval)) + RootedValue rval(cx); + if (!GetPropertyOperation(cx, f.script(), f.pc(), f.regs.sp[-1], rval.address())) THROW(); regs.sp[-1] = rval; @@ -1022,8 +1024,7 @@ InitPropOrMethod(VMFrame &f, PropertyName *name, JSOp op) /* Load the property's initial value into rval. */ JS_ASSERT(regs.stackDepth() >= 2); - Value rval; - rval = regs.sp[-1]; + RootedValue rval(f.cx, regs.sp[-1]); /* Load the object being initialized into lval/obj. */ RootedObject obj(cx, ®s.sp[-2].toObject()); @@ -1033,7 +1034,7 @@ InitPropOrMethod(VMFrame &f, PropertyName *name, JSOp op) RootedId id(cx, NameToId(name)); if (JS_UNLIKELY(name == cx->runtime->atomState.protoAtom) - ? !baseops::SetPropertyHelper(cx, obj, obj, id, 0, &rval, false) + ? !baseops::SetPropertyHelper(cx, obj, obj, id, 0, rval.address(), false) : !DefineNativeProperty(cx, obj, id, rval, NULL, NULL, JSPROP_ENUMERATE, 0, 0, 0)) { THROW(); @@ -1434,7 +1435,7 @@ stubs::In(VMFrame &f) THROWV(JS_FALSE); } - JSObject *obj = &rref.toObject(); + RootedObject obj(cx, &rref.toObject()); RootedId id(cx); if (!FetchElementId(f.cx, obj, f.regs.sp[-2], id.address(), &f.regs.sp[-2])) THROWV(JS_FALSE); diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index ff5570c204c0..fbf56f039b73 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -1472,7 +1472,7 @@ SetThrowHook(JSContext *cx, unsigned argc, jsval *vp) static JSBool LineToPC(JSContext *cx, unsigned argc, jsval *vp) { - JSScript *script; + RootedScript script(cx); int32_t lineArg = 0; uint32_t lineno; jsbytecode *pc; diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index f5807f13b50f..86a3749fd4e6 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -4026,10 +4026,10 @@ DebuggerObject_isSealedHelper(JSContext *cx, unsigned argc, Value *vp, SealHelpe ErrorCopier ec(ac, dbg->toJSObject()); bool r; if (op == Seal) { - if (!obj->isSealed(cx, &r)) + if (!JSObject::isSealed(cx, obj, &r)) return false; } else if (op == Freeze) { - if (!obj->isFrozen(cx, &r)) + if (!JSObject::isFrozen(cx, obj, &r)) return false; } else { r = obj->isExtensible();