author | Shu-yu Guo <shu@rfrn.org> |
Wed, 29 Oct 2014 19:41:42 -0700 | |
changeset 213056 | 0fd81599968665168cf6cfaa000300ed39097b4d |
parent 213055 | e72c87749c0f0bf5b005844e0bc23641d02c9e1b |
child 213057 | de7878c31f764b45d6525283a7069ce2083a97c7 |
push id | 27738 |
push user | cbook@mozilla.com |
push date | Thu, 30 Oct 2014 13:46:07 +0000 |
treeherder | mozilla-central@1aa1b23d799e [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jandem, Waldo |
bugs | 1089761 |
milestone | 36.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
new file mode 100644 --- /dev/null +++ b/js/src/jit-test/tests/ion/bug1089761.js @@ -0,0 +1,14 @@ +var hits = 0; +for (var j = 0; j < 9; ++j) { + try { + (function() { + (function() { + eval("x") + let x + })() + })() + } catch (e) { + hits++; + } +} +assertEq(hits, 9);
--- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -4475,58 +4475,64 @@ CodeGenerator::visitNewDeclEnvObject(LNe bool initFixedSlots = ShouldInitFixedSlots(lir, templateObj); masm.createGCObject(objReg, tempReg, templateObj, gc::DefaultHeap, ool->entry(), initFixedSlots); masm.bind(ool->rejoin()); return true; } -typedef JSObject *(*NewCallObjectFn)(JSContext *, HandleShape, HandleTypeObject); +typedef JSObject *(*NewCallObjectFn)(JSContext *, HandleShape, HandleTypeObject, uint32_t); static const VMFunction NewCallObjectInfo = FunctionInfo<NewCallObjectFn>(NewCallObject); bool CodeGenerator::visitNewCallObject(LNewCallObject *lir) { Register objReg = ToRegister(lir->output()); Register tempReg = ToRegister(lir->temp()); NativeObject *templateObj = lir->mir()->templateObject(); + JSScript *script = lir->mir()->block()->info().script(); + uint32_t lexicalBegin = script->bindings.aliasedBodyLevelLexicalBegin(); OutOfLineCode *ool = oolCallVM(NewCallObjectInfo, lir, (ArgList(), ImmGCPtr(templateObj->lastProperty()), - ImmGCPtr(templateObj->type())), + ImmGCPtr(templateObj->type()), + Imm32(lexicalBegin)), StoreRegisterTo(objReg)); if (!ool) return false; // Inline call object creation, using the OOL path only for tricky cases. bool initFixedSlots = ShouldInitFixedSlots(lir, templateObj); masm.createGCObject(objReg, tempReg, templateObj, gc::DefaultHeap, ool->entry(), initFixedSlots); masm.bind(ool->rejoin()); return true; } -typedef JSObject *(*NewSingletonCallObjectFn)(JSContext *, HandleShape); +typedef JSObject *(*NewSingletonCallObjectFn)(JSContext *, HandleShape, uint32_t); static const VMFunction NewSingletonCallObjectInfo = FunctionInfo<NewSingletonCallObjectFn>(NewSingletonCallObject); bool CodeGenerator::visitNewSingletonCallObject(LNewSingletonCallObject *lir) { Register objReg = ToRegister(lir->output()); JSObject *templateObj = lir->mir()->templateObject(); + JSScript *script = lir->mir()->block()->info().script(); + uint32_t lexicalBegin = script->bindings.aliasedBodyLevelLexicalBegin(); OutOfLineCode *ool; ool = oolCallVM(NewSingletonCallObjectInfo, lir, - (ArgList(), ImmGCPtr(templateObj->lastProperty())), + (ArgList(), ImmGCPtr(templateObj->lastProperty()), + Imm32(lexicalBegin)), StoreRegisterTo(objReg)); if (!ool) return false; // Objects can only be given singleton types in VM calls. We make the call // out of line to not bloat inline code, even if (naively) this seems like // extra work. masm.jump(ool->entry());
--- a/js/src/jit/VMFunctions.cpp +++ b/js/src/jit/VMFunctions.cpp @@ -550,37 +550,37 @@ InterruptCheck(JSContext *cx) void * MallocWrapper(JSRuntime *rt, size_t nbytes) { return rt->pod_malloc<uint8_t>(nbytes); } JSObject * -NewCallObject(JSContext *cx, HandleShape shape, HandleTypeObject type) +NewCallObject(JSContext *cx, HandleShape shape, HandleTypeObject type, uint32_t lexicalBegin) { - JSObject *obj = CallObject::create(cx, shape, type); + JSObject *obj = CallObject::create(cx, shape, type, lexicalBegin); if (!obj) return nullptr; #ifdef JSGC_GENERATIONAL // The JIT creates call objects in the nursery, so elides barriers for // the initializing writes. The interpreter, however, may have allocated // the call object tenured, so barrier as needed before re-entering. if (!IsInsideNursery(obj)) cx->runtime()->gc.storeBuffer.putWholeCellFromMainThread(obj); #endif return obj; } JSObject * -NewSingletonCallObject(JSContext *cx, HandleShape shape) +NewSingletonCallObject(JSContext *cx, HandleShape shape, uint32_t lexicalBegin) { - JSObject *obj = CallObject::createSingleton(cx, shape); + JSObject *obj = CallObject::createSingleton(cx, shape, lexicalBegin); if (!obj) return nullptr; #ifdef JSGC_GENERATIONAL // The JIT creates call objects in the nursery, so elides barriers for // the initializing writes. The interpreter, however, may have allocated // the call object tenured, so barrier as needed before re-entering. MOZ_ASSERT(!IsInsideNursery(obj),
--- a/js/src/jit/VMFunctions.h +++ b/js/src/jit/VMFunctions.h @@ -662,18 +662,19 @@ bool CharCodeAt(JSContext *cx, HandleStr JSFlatString *StringFromCharCode(JSContext *cx, int32_t code); bool SetProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue value, bool strict, jsbytecode *pc); bool InterruptCheck(JSContext *cx); void *MallocWrapper(JSRuntime *rt, size_t nbytes); -JSObject *NewCallObject(JSContext *cx, HandleShape shape, HandleTypeObject type); -JSObject *NewSingletonCallObject(JSContext *cx, HandleShape shape); +JSObject *NewCallObject(JSContext *cx, HandleShape shape, HandleTypeObject type, + uint32_t lexicalBegin); +JSObject *NewSingletonCallObject(JSContext *cx, HandleShape shape, uint32_t lexicalBegin); JSObject *NewStringObject(JSContext *cx, HandleString str); bool SPSEnter(JSContext *cx, HandleScript script); bool SPSExit(JSContext *cx, HandleScript script); bool OperatorIn(JSContext *cx, HandleValue key, HandleObject obj, bool *out); bool OperatorInI(JSContext *cx, uint32_t index, HandleObject obj, bool *out);
--- a/js/src/vm/ScopeObject-inl.h +++ b/js/src/vm/ScopeObject-inl.h @@ -49,22 +49,27 @@ inline void CallObject::setAliasedVarFromArguments(JSContext *cx, const Value &argsValue, jsid id, const Value &v) { setSlot(argsValue.magicUint32(), v); if (hasSingletonType()) types::AddTypePropertyId(cx, this, id, v); } inline void -CallObject::setAliasedLexicalsToThrowOnTouch(JSScript *script) +CallObject::initRemainingSlotsToUninitializedLexicals(uint32_t begin) { - uint32_t aliasedLexicalBegin = script->bindings.aliasedBodyLevelLexicalBegin(); - uint32_t aliasedLexicalEnd = numFixedSlots(); - for (uint32_t slot = aliasedLexicalBegin; slot < aliasedLexicalEnd; slot++) - initFixedSlot(slot, MagicValue(JS_UNINITIALIZED_LEXICAL)); + uint32_t end = slotSpan(); + for (uint32_t slot = begin; slot < end; slot++) + initSlot(slot, MagicValue(JS_UNINITIALIZED_LEXICAL)); +} + +inline void +CallObject::initAliasedLexicalsToThrowOnTouch(JSScript *script) +{ + initRemainingSlotsToUninitializedLexicals(script->bindings.aliasedBodyLevelLexicalBegin()); } template <AllowGC allowGC> inline bool StaticScopeIter<allowGC>::done() const { return !obj; }
--- a/js/src/vm/ScopeObject.cpp +++ b/js/src/vm/ScopeObject.cpp @@ -134,49 +134,51 @@ void ScopeObject::setEnclosingScope(HandleObject obj) { MOZ_ASSERT_IF(obj->is<CallObject>() || obj->is<DeclEnvObject>() || obj->is<BlockObject>(), obj->isDelegate()); setFixedSlot(SCOPE_CHAIN_SLOT, ObjectValue(*obj)); } CallObject * -CallObject::create(JSContext *cx, HandleShape shape, HandleTypeObject type) +CallObject::create(JSContext *cx, HandleShape shape, HandleTypeObject type, uint32_t lexicalBegin) { MOZ_ASSERT(!type->singleton(), "passed a singleton type to create() (use createSingleton() " "instead)"); gc::AllocKind kind = gc::GetGCObjectKind(shape->numFixedSlots()); MOZ_ASSERT(CanBeFinalizedInBackground(kind, &CallObject::class_)); kind = gc::GetBackgroundAllocKind(kind); JSObject *obj = JSObject::create(cx, kind, gc::DefaultHeap, shape, type); if (!obj) return nullptr; + obj->as<CallObject>().initRemainingSlotsToUninitializedLexicals(lexicalBegin); return &obj->as<CallObject>(); } CallObject * -CallObject::createSingleton(JSContext *cx, HandleShape shape) +CallObject::createSingleton(JSContext *cx, HandleShape shape, uint32_t lexicalBegin) { gc::AllocKind kind = gc::GetGCObjectKind(shape->numFixedSlots()); MOZ_ASSERT(CanBeFinalizedInBackground(kind, &CallObject::class_)); kind = gc::GetBackgroundAllocKind(kind); RootedTypeObject type(cx, cx->getSingletonType(&class_, TaggedProto(nullptr))); if (!type) return nullptr; RootedObject obj(cx, JSObject::create(cx, kind, gc::TenuredHeap, shape, type)); if (!obj) return nullptr; MOZ_ASSERT(obj->hasSingletonType(), "type created inline above must be a singleton"); + obj->as<CallObject>().initRemainingSlotsToUninitializedLexicals(lexicalBegin); return &obj->as<CallObject>(); } /* * Create a CallObject for a JSScript that is not initialized to any particular * callsite. This object can either be initialized (with an enclosing scope and * callee) or used as a template for jit compilation. */ @@ -193,16 +195,20 @@ CallObject::createTemplateObject(JSConte gc::AllocKind kind = gc::GetGCObjectKind(shape->numFixedSlots()); MOZ_ASSERT(CanBeFinalizedInBackground(kind, &class_)); kind = gc::GetBackgroundAllocKind(kind); JSObject *obj = JSObject::create(cx, kind, heap, shape, type); if (!obj) return nullptr; + // Set uninitialized lexicals even on template objects, as Ion will use + // copy over the template object's slot values in the fast path. + obj->as<CallObject>().initAliasedLexicalsToThrowOnTouch(script); + return &obj->as<CallObject>(); } /* * Construct a call object for the given bindings. If this is a call object * for a function invocation, callee should be the function being called. * Otherwise it must be a call object for eval of strict mode code, and callee * must be null. @@ -212,17 +218,16 @@ CallObject::create(JSContext *cx, Handle { gc::InitialHeap heap = script->treatAsRunOnce() ? gc::TenuredHeap : gc::DefaultHeap; CallObject *callobj = CallObject::createTemplateObject(cx, script, heap); if (!callobj) return nullptr; callobj->as<ScopeObject>().setEnclosingScope(enclosing); callobj->initFixedSlot(CALLEE_SLOT, ObjectOrNullValue(callee)); - callobj->setAliasedLexicalsToThrowOnTouch(script); if (script->treatAsRunOnce()) { Rooted<CallObject*> ncallobj(cx, callobj); if (!JSObject::setSingletonType(cx, ncallobj)) return nullptr; return ncallobj; }
--- a/js/src/vm/ScopeObject.h +++ b/js/src/vm/ScopeObject.h @@ -232,36 +232,37 @@ class ScopeObject : public NativeObject class CallObject : public ScopeObject { static const uint32_t CALLEE_SLOT = 1; static CallObject * create(JSContext *cx, HandleScript script, HandleObject enclosing, HandleFunction callee); - inline void setAliasedLexicalsToThrowOnTouch(JSScript *script); + inline void initRemainingSlotsToUninitializedLexicals(uint32_t begin); + inline void initAliasedLexicalsToThrowOnTouch(JSScript *script); public: static const Class class_; /* These functions are internal and are exposed only for JITs. */ /* * Construct a bare-bones call object given a shape and a non-singleton * type. The call object must be further initialized to be usable. */ static CallObject * - create(JSContext *cx, HandleShape shape, HandleTypeObject type); + create(JSContext *cx, HandleShape shape, HandleTypeObject type, uint32_t lexicalBegin); /* * Construct a bare-bones call object given a shape and make it have * singleton type. The call object must be initialized to be usable. */ static CallObject * - createSingleton(JSContext *cx, HandleShape shape); + createSingleton(JSContext *cx, HandleShape shape, uint32_t lexicalBegin); static CallObject * createTemplateObject(JSContext *cx, HandleScript script, gc::InitialHeap heap); static const uint32_t RESERVED_SLOTS = 2; static CallObject *createForFunction(JSContext *cx, HandleObject enclosing, HandleFunction callee);