Bug 1135547 - Fix checks for cases where type sets might be incomplete, r=jandem.
authorBrian Hackett <bhackett1024@gmail.com>
Thu, 26 Feb 2015 15:14:59 -0600
changeset 231088 360e8f0d68d7fa3ee360dbee674a174eda1d285c
parent 231087 a250f116b5633014a6fdf2b555eced5822f3cbeb
child 231089 d7d9bbfa72c5b58e01aff2ba7fc524e6203889e5
push id28344
push userryanvm@gmail.com
push dateFri, 27 Feb 2015 18:20:08 +0000
treeherdermozilla-central@9dd9d1e5b43c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1135547
milestone39.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
Bug 1135547 - Fix checks for cases where type sets might be incomplete, r=jandem.
js/src/jit/CodeGenerator.cpp
js/src/jit/MacroAssembler.cpp
js/src/jit/MacroAssembler.h
js/src/vm/ObjectGroup.h
js/src/vm/TypeInference.cpp
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -3756,23 +3756,17 @@ CodeGenerator::emitObjectOrStringResultC
             masm.branchPtr(Assembler::Equal, output, ImmWord(0), &ok);
         if (mir->resultTypeSet()->getObjectCount() > 0)
             masm.guardObjectType(output, mir->resultTypeSet(), temp, &miss);
         else
             masm.jump(&miss);
         masm.jump(&ok);
 
         masm.bind(&miss);
-
-        // Type set guards might miss when an object's group changes and its
-        // properties become unknown, so check for this case.
-        masm.loadPtr(Address(output, JSObject::offsetOfGroup()), temp);
-        masm.branchTestPtr(Assembler::NonZero,
-                           Address(temp, ObjectGroup::offsetOfFlags()),
-                           Imm32(OBJECT_FLAG_UNKNOWN_PROPERTIES), &ok);
+        masm.guardTypeSetMightBeIncomplete(output, temp, &ok);
 
         masm.assumeUnreachable("MIR instruction returned object with unexpected type");
 
         masm.bind(&ok);
     }
 
     // Check that we have a valid GC pointer.
     saveVolatile();
@@ -3834,25 +3828,22 @@ CodeGenerator::emitValueResultChecks(LIn
     if (mir->resultTypeSet() && !mir->resultTypeSet()->unknown()) {
         // We have a result TypeSet, assert this value is in it.
         Label miss, ok;
         masm.guardTypeSet(output, mir->resultTypeSet(), BarrierKind::TypeSet, temp1, &miss);
         masm.jump(&ok);
 
         masm.bind(&miss);
 
-        // Type set guards might miss when an object's group changes and its
-        // properties become unknown, so check for this case.
+        // Check for cases where the type set guard might have missed due to
+        // changing object groups.
         Label realMiss;
         masm.branchTestObject(Assembler::NotEqual, output, &realMiss);
         Register payload = masm.extractObject(output, temp1);
-        masm.loadPtr(Address(payload, JSObject::offsetOfGroup()), temp1);
-        masm.branchTestPtr(Assembler::NonZero,
-                           Address(temp1, ObjectGroup::offsetOfFlags()),
-                           Imm32(OBJECT_FLAG_UNKNOWN_PROPERTIES), &ok);
+        masm.guardTypeSetMightBeIncomplete(payload, temp1, &ok);
         masm.bind(&realMiss);
 
         masm.assumeUnreachable("MIR instruction returned value with unexpected type");
 
         masm.bind(&ok);
     }
 
     // Check that we have a valid GC pointer.
--- a/js/src/jit/MacroAssembler.cpp
+++ b/js/src/jit/MacroAssembler.cpp
@@ -133,32 +133,43 @@ MacroAssembler::guardTypeSet(const Sourc
     } else {
 #ifdef DEBUG
         Label fail;
         Register obj = extractObject(address, scratch);
         guardObjectType(obj, types, scratch, &fail);
         jump(&matched);
         bind(&fail);
 
-        // Type set guards might miss when an object's type changes and its
-        // properties become unknown, so check for this case.
         if (obj == scratch)
             extractObject(address, scratch);
-        loadPtr(Address(obj, JSObject::offsetOfGroup()), scratch);
-        branchTestPtr(Assembler::NonZero,
-                      Address(scratch, ObjectGroup::offsetOfFlags()),
-                      Imm32(OBJECT_FLAG_UNKNOWN_PROPERTIES), &matched);
+        guardTypeSetMightBeIncomplete(obj, scratch, &matched);
 
         assumeUnreachable("Unexpected object type");
 #endif
     }
 
     bind(&matched);
 }
 
+void
+MacroAssembler::guardTypeSetMightBeIncomplete(Register obj, Register scratch, Label *label)
+{
+    // Type set guards might miss when an object's group changes. In this case
+    // either its properties will become unknown, or it will change to a native
+    // object with an original unboxed group. Jump to label if this might have
+    // happened for the input object.
+
+    loadPtr(Address(obj, JSObject::offsetOfGroup()), scratch);
+    load32(Address(scratch, ObjectGroup::offsetOfFlags()), scratch);
+    branchTest32(Assembler::NonZero, scratch, Imm32(OBJECT_FLAG_UNKNOWN_PROPERTIES), label);
+    and32(Imm32(OBJECT_FLAG_ADDENDUM_MASK), scratch);
+    branch32(Assembler::Equal,
+             scratch, Imm32(ObjectGroup::addendumOriginalUnboxedGroupValue()), label);
+}
+
 template <typename Set> void
 MacroAssembler::guardObjectType(Register obj, const Set *types,
                                 Register scratch, Label *miss)
 {
     MOZ_ASSERT(!types->unknown());
     MOZ_ASSERT(!types->hasType(TypeSet::AnyObjectType()));
     MOZ_ASSERT(types->getObjectCount());
     MOZ_ASSERT(scratch != InvalidReg);
--- a/js/src/jit/MacroAssembler.h
+++ b/js/src/jit/MacroAssembler.h
@@ -275,16 +275,18 @@ class MacroAssembler : public MacroAssem
     // register is required.
     template <typename Source, typename TypeSet>
     void guardTypeSet(const Source &address, const TypeSet *types, BarrierKind kind, Register scratch, Label *miss);
     template <typename TypeSet>
     void guardObjectType(Register obj, const TypeSet *types, Register scratch, Label *miss);
     template <typename Source>
     void guardType(const Source &address, TypeSet::Type type, Register scratch, Label *miss);
 
+    void guardTypeSetMightBeIncomplete(Register obj, Register scratch, Label *label);
+
     void loadObjShape(Register objReg, Register dest) {
         loadPtr(Address(objReg, JSObject::offsetOfShape()), dest);
     }
     void loadBaseShape(Register objReg, Register dest) {
         loadPtr(Address(objReg, JSObject::offsetOfShape()), dest);
 
         loadPtr(Address(dest, Shape::offsetOfBase()), dest);
     }
--- a/js/src/vm/ObjectGroup.h
+++ b/js/src/vm/ObjectGroup.h
@@ -523,16 +523,22 @@ class ObjectGroup : public gc::TenuredCe
     static inline uint32_t offsetOfAddendum() {
         return offsetof(ObjectGroup, addendum_);
     }
 
     static inline uint32_t offsetOfFlags() {
         return offsetof(ObjectGroup, flags_);
     }
 
+    // Get the bit pattern stored in an object's addendum when it has an
+    // original unboxed group.
+    static inline int32_t addendumOriginalUnboxedGroupValue() {
+        return Addendum_OriginalUnboxedGroup << OBJECT_FLAG_ADDENDUM_SHIFT;
+    }
+
   private:
     inline uint32_t basePropertyCount();
     inline void setBasePropertyCount(uint32_t count);
 
     static void staticAsserts() {
         JS_STATIC_ASSERT(offsetof(ObjectGroup, proto_) == offsetof(js::shadow::ObjectGroup, proto));
     }
 
--- a/js/src/vm/TypeInference.cpp
+++ b/js/src/vm/TypeInference.cpp
@@ -252,17 +252,18 @@ js::ObjectGroupHasProperty(JSContext *cx
             return true;
 
         TypeSet::Type type = TypeSet::GetValueType(value);
 
         // Type set guards might miss when an object's group changes and its
         // properties become unknown.
         if (value.isObject() &&
             !value.toObject().hasLazyGroup() &&
-            value.toObject().group()->flags() & OBJECT_FLAG_UNKNOWN_PROPERTIES)
+            ((value.toObject().group()->flags() & OBJECT_FLAG_UNKNOWN_PROPERTIES) ||
+             value.toObject().group()->maybeOriginalUnboxedGroup()))
         {
             return true;
         }
 
         AutoEnterAnalysis enter(cx);
 
         /*
          * We don't track types for properties inherited from prototypes which