author | Sean Stangl <sstangl@mozilla.com> |
Fri, 11 Dec 2015 11:27:55 -0500 | |
changeset 278069 | 989883d9a10ac4dfc5ab964e9b36417c1f99882e |
parent 278068 | e779e01003e891cbbd6919aae279359120374efd |
child 278070 | 8554cdd93607ca19ab378583a9b3c498562b4a59 |
push id | 29841 |
push user | ryanvm@gmail.com |
push date | Sat, 02 Jan 2016 00:29:52 +0000 |
treeherder | autoland@f7fbc524f9f3 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jandem |
bugs | 470143 |
milestone | 46.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/bug470143.js @@ -0,0 +1,6 @@ +// Test that getname caches correctly handle typeof for missing names. +function f() { for (i = 0; i < 2000; ++i) { var k = typeof nosuchvar; } return k; } + +assertEq(f(), "undefined"); +this.nosuchvar = 5; +assertEq(f(), "number");
--- a/js/src/jit/IonCaches.cpp +++ b/js/src/jit/IonCaches.cpp @@ -4916,16 +4916,73 @@ IsCacheableNameCallGetter(HandleObject s return false; return IsCacheableGetPropCallNative(obj, holder, shape) || IsCacheableGetPropCallPropertyOp(obj, holder, shape) || IsCacheableGetPropCallScripted(obj, holder, shape); } bool +NameIC::attachTypeOfNoProperty(JSContext* cx, HandleScript outerScript, IonScript* ion, + HandleObject scopeChain) +{ + MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_); + Label failures; + StubAttacher attacher(*this); + + Register scratchReg = outputReg().valueReg().scratchReg(); + + masm.movePtr(scopeChainReg(), scratchReg); + + // Generate scope chain guards. + // Since the property was not defined on any object, iterate until reaching the global. + JSObject* tobj = scopeChain; + while (true) { + GenerateScopeChainGuard(masm, tobj, scratchReg, nullptr, &failures); + + if (tobj->is<GlobalObject>()) + break; + + // Load the next link. + tobj = &tobj->as<ScopeObject>().enclosingScope(); + masm.extractObject(Address(scratchReg, ScopeObject::offsetOfEnclosingScope()), scratchReg); + } + + masm.moveValue(UndefinedValue(), outputReg().valueReg()); + attacher.jumpRejoin(masm); + + masm.bind(&failures); + attacher.jumpNextStub(masm); + + // TODO: ICNameStub_TypeOfNoProperty + return linkAndAttachStub(cx, masm, attacher, ion, "generic", + JS::TrackedOutcome::ICNameStub_ReadSlot); +} + +static bool +IsCacheableNameNoProperty(HandleObject scopeChain, HandleObject obj, + HandleObject holder, HandleShape shape, jsbytecode* pc, + NameIC& cache) +{ + if (cache.isTypeOf() && !shape) { + MOZ_ASSERT(!obj); + MOZ_ASSERT(!holder); + MOZ_ASSERT(scopeChain); + + // Assert those extra things checked by IsCacheableNoProperty(). + MOZ_ASSERT(cache.outputReg().hasValue()); + MOZ_ASSERT(pc != nullptr); + + return true; + } + + return false; +} + +bool NameIC::update(JSContext* cx, HandleScript outerScript, size_t cacheIndex, HandleObject scopeChain, MutableHandleValue vp) { IonScript* ion = outerScript->ionScript(); NameIC& cache = ion->getCache(cacheIndex).toName(); RootedPropertyName name(cx, cache.name()); @@ -4957,16 +5014,19 @@ NameIC::update(JSContext* cx, HandleScri } } else if (IsCacheableNameCallGetter(scopeChain, obj, holder, shape)) { void* returnAddr = GetReturnAddressToIonCode(cx); if (!cache.attachCallGetter(cx, outerScript, ion, scopeChain, obj, holder, shape, returnAddr)) { return false; } + } else if (IsCacheableNameNoProperty(scopeChain, obj, holder, shape, pc, cache)) { + if (!cache.attachTypeOfNoProperty(cx, outerScript, ion, scopeChain)) + return false; } } // Monitor changes to cache entry. TypeScript::Monitor(cx, script, pc, vp); return true; }
--- a/js/src/jit/IonCaches.h +++ b/js/src/jit/IonCaches.h @@ -789,16 +789,19 @@ class NameIC : public IonCache bool attachReadSlot(JSContext* cx, HandleScript outerScript, IonScript* ion, HandleObject scopeChain, HandleObject holderBase, HandleNativeObject holder, HandleShape shape); bool attachCallGetter(JSContext* cx, HandleScript outerScript, IonScript* ion, HandleObject scopeChain, HandleObject obj, HandleObject holder, HandleShape shape, void* returnAddr); + bool attachTypeOfNoProperty(JSContext* cx, HandleScript outerScript, IonScript* ion, + HandleObject scopeChain); + static bool update(JSContext* cx, HandleScript outerScript, size_t cacheIndex, HandleObject scopeChain, MutableHandleValue vp); }; #undef CACHE_HEADER // Implement cache casts now that the compiler can see the inheritance.