From 4caa9c00f11b398d08b2527de1e8ea7ff5020868 Mon Sep 17 00:00:00 2001 From: Jan de Mooij Date: Sun, 22 Jan 2017 12:55:33 +0100 Subject: [PATCH] Bug 1326067 part 7 - Fix type update code to use the unboxed object instead of the UnboxedExpandoObject. r=bhackett --- js/src/jit/BaselineCacheIRCompiler.cpp | 4 ++++ js/src/jit/BaselineIC.cpp | 18 ++++++++++++++++-- js/src/jit/CacheIR.cpp | 11 +++++++---- js/src/jit/CacheIR.h | 8 +++++++- js/src/jit/SharedIC.cpp | 3 ++- js/src/jit/SharedIC.h | 5 +++++ 6 files changed, 41 insertions(+), 8 deletions(-) diff --git a/js/src/jit/BaselineCacheIRCompiler.cpp b/js/src/jit/BaselineCacheIRCompiler.cpp index 4df93e3c390ee..1da584a062bd4 100644 --- a/js/src/jit/BaselineCacheIRCompiler.cpp +++ b/js/src/jit/BaselineCacheIRCompiler.cpp @@ -103,6 +103,7 @@ class MOZ_RAII AutoStubFrame } void enter(MacroAssembler& masm, Register scratch, CallCanGC canGC = CallCanGC::CanGC) { + MOZ_ASSERT(compiler.allocator.stackPushed() == 0); if (compiler.engine_ == ICStubEngine::Baseline) { EmitBaselineEnterStubFrame(masm, scratch); #ifdef DEBUG @@ -663,6 +664,9 @@ bool BaselineCacheIRCompiler::callTypeUpdateIC(AutoStubFrame& stubFrame, Register obj, ValueOperand val, Register scratch, LiveGeneralRegisterSet saveRegs) { + // Ensure the stack is empty for the VM call below. + allocator.discardStack(masm); + // R0 contains the value that needs to be typechecked. MOZ_ASSERT(val == R0); MOZ_ASSERT(scratch == R1.scratchReg()); diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp index 0b2d01708d318..073051297e1c7 100644 --- a/js/src/jit/BaselineIC.cpp +++ b/js/src/jit/BaselineIC.cpp @@ -281,10 +281,21 @@ DoTypeUpdateFallback(JSContext* cx, BaselineFrame* frame, ICUpdatedStub* stub, H RootedId id(cx); switch (stub->kind()) { - case ICStub::CacheIR_Updated: + case ICStub::CacheIR_Updated: { id = stub->toCacheIR_Updated()->updateStubId(); MOZ_ASSERT(id != JSID_EMPTY); + // The group should match the object's group, except when the object is + // an unboxed expando object: in that case, the group is the group of + // the unboxed object. + RootedObjectGroup group(cx, stub->toCacheIR_Updated()->updateStubGroup()); +#ifdef DEBUG + if (obj->is()) + MOZ_ASSERT(group->clasp() == &UnboxedPlainObject::class_); + else + MOZ_ASSERT(obj->group() == group); +#endif + // If we're storing null/undefined to a typed object property, check if // we want to include it in this property's type information. if (MOZ_UNLIKELY(obj->is()) && value.isNullOrUndefined()) { @@ -311,8 +322,10 @@ DoTypeUpdateFallback(JSContext* cx, BaselineFrame* frame, ICUpdatedStub* stub, H } } - AddTypePropertyId(cx, obj, id, value); + JSObject* maybeSingleton = obj->isSingleton() ? obj.get() : nullptr; + AddTypePropertyId(cx, group, maybeSingleton, id, value); break; + } case ICStub::SetElem_DenseOrUnboxedArray: case ICStub::SetElem_DenseOrUnboxedArrayAdd: { id = JSID_VOID; @@ -2854,6 +2867,7 @@ DoSetPropFallback(JSContext* cx, BaselineFrame* frame, ICSetProp_Fallback* stub_ JitSpew(JitSpew_BaselineIC, " Attached CacheIR stub"); attached = true; + newStub->toCacheIR_Updated()->updateStubGroup() = gen.updateStubGroup(); newStub->toCacheIR_Updated()->updateStubId() = gen.updateStubId(); if (gen.shouldNotePreliminaryObjectStub()) diff --git a/js/src/jit/CacheIR.cpp b/js/src/jit/CacheIR.cpp index 1bab2893c7b9f..dab92876866db 100644 --- a/js/src/jit/CacheIR.cpp +++ b/js/src/jit/CacheIR.cpp @@ -1553,6 +1553,7 @@ SetPropIRGenerator::SetPropIRGenerator(JSContext* cx, jsbytecode* pc, CacheKind rhsVal_(rhsVal), isTemporarilyUnoptimizable_(isTemporarilyUnoptimizable), preliminaryObjectAction_(PreliminaryObjectAction::None), + updateStubGroup_(cx), updateStubId_(cx, JSID_EMPTY), needUpdateStub_(false) {} @@ -1657,7 +1658,7 @@ SetPropIRGenerator::tryAttachNativeSetSlot(HandleObject obj, ObjOperandId objId, else preliminaryObjectAction_ = PreliminaryObjectAction::Unlink; - setUpdateStubInfo(id); + setUpdateStubInfo(nobj->group(), id); EmitStoreSlotAndReturn(writer, objId, nobj, propShape, rhsId); return true; } @@ -1681,7 +1682,9 @@ SetPropIRGenerator::tryAttachUnboxedExpandoSetSlot(HandleObject obj, ObjOperandI ObjOperandId expandoId = writer.guardAndLoadUnboxedExpando(objId); writer.guardShape(expandoId, expando->lastProperty()); - setUpdateStubInfo(id); + // Property types must be added to the unboxed object's group, not the + // expando's group (it has unknown properties). + setUpdateStubInfo(obj->group(), id); EmitStoreSlotAndReturn(writer, expandoId, expando, propShape, rhsId); return true; } @@ -1715,7 +1718,7 @@ SetPropIRGenerator::tryAttachUnboxedProperty(HandleObject obj, ObjOperandId objI rhsId); writer.returnFromIC(); - setUpdateStubInfo(id); + setUpdateStubInfo(obj->group(), id); preliminaryObjectAction_ = PreliminaryObjectAction::Unlink; return true; } @@ -1749,7 +1752,7 @@ SetPropIRGenerator::tryAttachTypedObjectProperty(HandleObject obj, ObjOperandId writer.guardShape(objId, obj->as().shape()); writer.guardGroup(objId, obj->group()); - setUpdateStubInfo(id); + setUpdateStubInfo(obj->group(), id); // Scalar types can always be stored without a type update stub. if (fieldDescr->is()) { diff --git a/js/src/jit/CacheIR.h b/js/src/jit/CacheIR.h index c5b81b05f0237..70ca137646f64 100644 --- a/js/src/jit/CacheIR.h +++ b/js/src/jit/CacheIR.h @@ -890,12 +890,14 @@ class MOZ_RAII SetPropIRGenerator : public IRGenerator PreliminaryObjectAction preliminaryObjectAction_; // If Baseline needs an update stub, this contains information to create it. + RootedObjectGroup updateStubGroup_; RootedId updateStubId_; bool needUpdateStub_; - void setUpdateStubInfo(jsid id) { + void setUpdateStubInfo(ObjectGroup* group, jsid id) { MOZ_ASSERT(!needUpdateStub_); needUpdateStub_ = true; + updateStubGroup_ = group; updateStubId_ = id; } @@ -921,6 +923,10 @@ class MOZ_RAII SetPropIRGenerator : public IRGenerator bool shouldNotePreliminaryObjectStub() const { return preliminaryObjectAction_ == PreliminaryObjectAction::NotePreliminary; } + ObjectGroup* updateStubGroup() const { + MOZ_ASSERT(updateStubGroup_); + return updateStubGroup_; + } jsid updateStubId() const { MOZ_ASSERT(needUpdateStub_); return updateStubId_; diff --git a/js/src/jit/SharedIC.cpp b/js/src/jit/SharedIC.cpp index 29e524b75daec..f7025bc0c4ef5 100644 --- a/js/src/jit/SharedIC.cpp +++ b/js/src/jit/SharedIC.cpp @@ -415,7 +415,8 @@ ICStub::trace(JSTracer* trc) break; case ICStub::CacheIR_Updated: { ICCacheIR_Updated* stub = toCacheIR_Updated(); - TraceEdge(trc, &stub->updateStubId(), "baseline-updated-id"); + TraceEdge(trc, &stub->updateStubGroup(), "baseline-update-stub-group"); + TraceEdge(trc, &stub->updateStubId(), "baseline-update-stub-id"); TraceCacheIRStub(trc, this, stub->stubInfo()); break; } diff --git a/js/src/jit/SharedIC.h b/js/src/jit/SharedIC.h index d81eb42aecd07..7e736331c5757 100644 --- a/js/src/jit/SharedIC.h +++ b/js/src/jit/SharedIC.h @@ -959,15 +959,20 @@ class ICUpdatedStub : public ICStub class ICCacheIR_Updated : public ICUpdatedStub { const CacheIRStubInfo* stubInfo_; + GCPtrObjectGroup updateStubGroup_; GCPtrId updateStubId_; public: ICCacheIR_Updated(JitCode* stubCode, const CacheIRStubInfo* stubInfo) : ICUpdatedStub(ICStub::CacheIR_Updated, stubCode), stubInfo_(stubInfo), + updateStubGroup_(nullptr), updateStubId_(JSID_EMPTY) {} + GCPtrObjectGroup& updateStubGroup() { + return updateStubGroup_; + } GCPtrId& updateStubId() { return updateStubId_; }