Bug 1398768 part 9 - Clean up and rename SetOrExtendBoxedOrUnboxedDenseElements. r=evilpie
authorJan de Mooij <jdemooij@mozilla.com>
Fri, 29 Sep 2017 12:05:39 +0200
changeset 426334 a02ebffc8cce8d0e99c4704adf047242271ebf1b
parent 426333 4403e849f86015a40d9c0e97852ee7a910a8c4ad
child 426335 e56861273c64b1de61f237e0c3183f76c8be69fe
push id97
push userfmarier@mozilla.com
push dateSat, 14 Oct 2017 01:12:59 +0000
reviewersevilpie
bugs1398768
milestone58.0a1
Bug 1398768 part 9 - Clean up and rename SetOrExtendBoxedOrUnboxedDenseElements. r=evilpie
js/src/jit/CodeGenerator.cpp
js/src/jit/VMFunctions.cpp
js/src/jit/VMFunctions.h
js/src/jsarray.cpp
js/src/jsarray.h
js/src/vm/NativeObject-inl.h
js/src/vm/NativeObject.h
js/src/vm/UnboxedObject-inl.h
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -8708,21 +8708,20 @@ CodeGenerator::visitFallibleStoreElement
         // of a jump) does a masm.assumeUnreachable().
     }
 
     emitStoreElementHoleV(lir);
 
     masm.bind(&isFrozen);
 }
 
-typedef bool (*SetDenseOrUnboxedArrayElementFn)(JSContext*, HandleObject, int32_t,
-                                                HandleValue, bool strict);
-static const VMFunction SetDenseOrUnboxedArrayElementInfo =
-    FunctionInfo<SetDenseOrUnboxedArrayElementFn>(SetDenseOrUnboxedArrayElement,
-                                                  "SetDenseOrUnboxedArrayElement");
+typedef bool (*SetDenseElementFn)(JSContext*, HandleNativeObject, int32_t, HandleValue,
+                                  bool strict);
+static const VMFunction SetDenseElementInfo =
+    FunctionInfo<SetDenseElementFn>(jit::SetDenseElement, "SetDenseElement");
 
 void
 CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
 {
     Register object, elements;
     LInstruction* ins = ool->ins();
     const LAllocation* index;
     MIRType valueType;
@@ -8821,17 +8820,17 @@ CodeGenerator::visitOutOfLineStoreElemen
 
     pushArg(Imm32(ool->strict()));
     pushArg(value);
     if (index->isConstant())
         pushArg(Imm32(ToInt32(index)));
     else
         pushArg(ToRegister(index));
     pushArg(object);
-    callVM(SetDenseOrUnboxedArrayElementInfo, ins);
+    callVM(SetDenseElementInfo, ins);
 
     restoreLive(ins);
     masm.jump(ool->rejoin());
 }
 
 template <typename T>
 static void
 StoreUnboxedPointer(MacroAssembler& masm, T address, MIRType type, const LAllocation* value,
@@ -9010,17 +9009,17 @@ CodeGenerator::visitArrayPopShiftT(LArra
 {
     Register obj = ToRegister(lir->object());
     Register elements = ToRegister(lir->temp0());
     Register length = ToRegister(lir->temp1());
     TypedOrValueRegister out(lir->mir()->type(), ToAnyRegister(lir->output()));
     emitArrayPopShift(lir, lir->mir(), obj, elements, length, out);
 }
 
-typedef bool (*ArrayPushDenseFn)(JSContext*, HandleObject, HandleValue, uint32_t*);
+typedef bool (*ArrayPushDenseFn)(JSContext*, HandleArrayObject, HandleValue, uint32_t*);
 static const VMFunction ArrayPushDenseInfo =
     FunctionInfo<ArrayPushDenseFn>(jit::ArrayPushDense, "ArrayPushDense");
 
 void
 CodeGenerator::emitArrayPush(LInstruction* lir, const MArrayPush* mir, Register obj,
                              const ConstantOrRegister& value, Register elementsTemp, Register length)
 {
     OutOfLineCode* ool = oolCallVM(ArrayPushDenseInfo, lir, ArgList(obj, value), StoreRegisterTo(length));
--- a/js/src/jit/VMFunctions.cpp
+++ b/js/src/jit/VMFunctions.cpp
@@ -345,40 +345,39 @@ ArrayPopDense(JSContext* cx, HandleObjec
     // have to monitor the return value.
     rval.set(argv[0]);
     if (rval.isUndefined())
         TypeScript::Monitor(cx, rval);
     return true;
 }
 
 bool
-ArrayPushDense(JSContext* cx, HandleObject obj, HandleValue v, uint32_t* length)
+ArrayPushDense(JSContext* cx, HandleArrayObject arr, HandleValue v, uint32_t* length)
 {
-    *length = obj->as<ArrayObject>().length();
-    DenseElementResult result =
-        SetOrExtendBoxedOrUnboxedDenseElements(cx, obj, *length, v.address(), 1,
-                                               ShouldUpdateTypes::DontUpdate);
+    *length = arr->length();
+    DenseElementResult result = arr->setOrExtendDenseElements(cx, *length, v.address(), 1,
+                                                              ShouldUpdateTypes::DontUpdate);
     if (result != DenseElementResult::Incomplete) {
         (*length)++;
         return result == DenseElementResult::Success;
     }
 
     // AutoDetectInvalidation uses GetTopJitJSScript(cx)->ionScript(), but it's
-    // possible the SetOrExtendAnyBoxedOrUnboxedDenseElements call already
-    // invalidated the IonScript. JSJitFrameIter::ionScript works when the
-    // script is invalidated so we use that instead.
+    // possible the setOrExtendDenseElements call already invalidated the
+    // IonScript. JSJitFrameIter::ionScript works when the script is invalidated
+    // so we use that instead.
     JSJitFrameIter frame(cx);
     MOZ_ASSERT(frame.type() == JitFrame_Exit);
     ++frame;
     IonScript* ionScript = frame.ionScript();
 
     JS::AutoValueArray<3> argv(cx);
     AutoDetectInvalidation adi(cx, argv[0], ionScript);
     argv[0].setUndefined();
-    argv[1].setObject(*obj);
+    argv[1].setObject(*arr);
     argv[2].set(v);
     if (!js::array_push(cx, 1, argv.begin()))
         return false;
 
     if (argv[0].isInt32()) {
         *length = argv[0].toInt32();
         return true;
     }
@@ -1291,26 +1290,25 @@ ForcedRecompile(JSContext* cx)
 
 bool
 Recompile(JSContext* cx)
 {
     return RecompileImpl(cx, /* force = */ false);
 }
 
 bool
-SetDenseOrUnboxedArrayElement(JSContext* cx, HandleObject obj, int32_t index,
-                              HandleValue value, bool strict)
+SetDenseElement(JSContext* cx, HandleNativeObject obj, int32_t index, HandleValue value,
+                bool strict)
 {
     // This function is called from Ion code for StoreElementHole's OOL path.
-    // In this case we know the object is native or an unboxed array and that
-    // no type changes are needed.
+    // In this case we know the object is native and that no type changes are
+    // needed.
 
-    DenseElementResult result =
-        SetOrExtendBoxedOrUnboxedDenseElements(cx, obj, index, value.address(), 1,
-                                               ShouldUpdateTypes::DontUpdate);
+    DenseElementResult result = obj->setOrExtendDenseElements(cx, index, value.address(), 1,
+                                                              ShouldUpdateTypes::DontUpdate);
     if (result != DenseElementResult::Incomplete)
         return result == DenseElementResult::Success;
 
     RootedValue indexVal(cx, Int32Value(index));
     return SetObjectElement(cx, obj, indexVal, value, strict);
 }
 
 void
--- a/js/src/jit/VMFunctions.h
+++ b/js/src/jit/VMFunctions.h
@@ -657,17 +657,18 @@ bool GreaterThanOrEqual(JSContext* cx, M
 template<bool Equal>
 bool StringsEqual(JSContext* cx, HandleString left, HandleString right, bool* res);
 
 MOZ_MUST_USE bool StringSplitHelper(JSContext* cx, HandleString str, HandleString sep,
                                     HandleObjectGroup group, uint32_t limit,
                                     MutableHandleValue result);
 
 MOZ_MUST_USE bool ArrayPopDense(JSContext* cx, HandleObject obj, MutableHandleValue rval);
-MOZ_MUST_USE bool ArrayPushDense(JSContext* cx, HandleObject obj, HandleValue v, uint32_t* length);
+MOZ_MUST_USE bool ArrayPushDense(JSContext* cx, HandleArrayObject arr, HandleValue v,
+                                 uint32_t* length);
 MOZ_MUST_USE bool ArrayShiftDense(JSContext* cx, HandleObject obj, MutableHandleValue rval);
 JSString* ArrayJoin(JSContext* cx, HandleObject array, HandleString sep);
 MOZ_MUST_USE bool SetArrayLength(JSContext* cx, HandleObject obj, HandleValue value, bool strict);
 
 MOZ_MUST_USE bool
 CharCodeAt(JSContext* cx, HandleString str, int32_t index, uint32_t* code);
 JSFlatString* StringFromCharCode(JSContext* cx, int32_t code);
 JSString* StringFromCodePoint(JSContext* cx, int32_t codePoint);
@@ -791,18 +792,18 @@ JSObject* CreateDerivedTypedObj(JSContex
 
 MOZ_MUST_USE bool
 Recompile(JSContext* cx);
 MOZ_MUST_USE bool
 ForcedRecompile(JSContext* cx);
 JSString* StringReplace(JSContext* cx, HandleString string, HandleString pattern,
                         HandleString repl);
 
-MOZ_MUST_USE bool SetDenseOrUnboxedArrayElement(JSContext* cx, HandleObject obj, int32_t index,
-                                                HandleValue value, bool strict);
+MOZ_MUST_USE bool SetDenseElement(JSContext* cx, HandleNativeObject obj, int32_t index,
+                                  HandleValue value, bool strict);
 
 void AssertValidObjectPtr(JSContext* cx, JSObject* obj);
 void AssertValidObjectOrNullPtr(JSContext* cx, JSObject* obj);
 void AssertValidStringPtr(JSContext* cx, JSString* str);
 void AssertValidSymbolPtr(JSContext* cx, JS::Symbol* sym);
 void AssertValidValue(JSContext* cx, Value* v);
 
 void MarkValueFromIon(JSRuntime* rt, Value* vp);
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -333,18 +333,18 @@ HasAndGetElement(JSContext* cx, HandleOb
     return HasAndGetElement(cx, obj, obj, index, hole, vp);
 }
 
 bool
 ElementAdder::append(JSContext* cx, HandleValue v)
 {
     MOZ_ASSERT(index_ < length_);
     if (resObj_) {
-        DenseElementResult result =
-            SetOrExtendBoxedOrUnboxedDenseElements(cx, resObj_, index_, v.address(), 1);
+        NativeObject* resObj = &resObj_->as<NativeObject>();
+        DenseElementResult result = resObj->setOrExtendDenseElements(cx, index_, v.address(), 1);
         if (result == DenseElementResult::Failure)
             return false;
         if (result == DenseElementResult::Incomplete) {
             if (!DefineDataElement(cx, resObj_, index_, v))
                 return false;
         }
     } else {
         vp_[index_] = v;
@@ -1486,19 +1486,19 @@ SetArrayElements(JSContext* cx, HandleOb
 {
     MOZ_ASSERT(count <= MAX_ARRAY_INDEX);
     MOZ_ASSERT(start + count < uint64_t(DOUBLE_INTEGRAL_PRECISION_LIMIT));
 
     if (count == 0)
         return true;
 
     if (!ObjectMayHaveExtraIndexedProperties(obj) && start <= UINT32_MAX) {
-        DenseElementResult result =
-            SetOrExtendBoxedOrUnboxedDenseElements(cx, obj, uint32_t(start), vector, count,
-                                                   updateTypes);
+        NativeObject* nobj = &obj->as<NativeObject>();
+        DenseElementResult result = nobj->setOrExtendDenseElements(cx, uint32_t(start), vector,
+                                                                   count, updateTypes);
         if (result != DenseElementResult::Incomplete)
             return result == DenseElementResult::Success;
     }
 
     RootedId id(cx);
     const Value* end = vector + count;
     while (vector < end) {
         if (!CheckForInterrupt(cx))
@@ -2278,28 +2278,27 @@ js::array_push(JSContext* cx, unsigned a
 
     // Step 2.
     uint64_t length;
     if (!GetLengthProperty(cx, obj, &length))
         return false;
 
     if (!ObjectMayHaveExtraIndexedProperties(obj) && length <= UINT32_MAX) {
         DenseElementResult result =
-            SetOrExtendBoxedOrUnboxedDenseElements(cx, obj, uint32_t(length),
-                                                   args.array(), args.length());
+            obj->as<NativeObject>().setOrExtendDenseElements(cx, uint32_t(length),
+                                                             args.array(), args.length());
         if (result != DenseElementResult::Incomplete) {
             if (result == DenseElementResult::Failure)
                 return false;
 
             uint32_t newlength = uint32_t(length) + args.length();
             args.rval().setNumber(newlength);
 
-            // SetOrExtendAnyBoxedOrUnboxedDenseElements takes care of updating the
-            // length for boxed and unboxed arrays. Handle updates to the length of
-            // non-arrays here.
+            // setOrExtendDenseElements takes care of updating the length for
+            // arrays. Handle updates to the length of non-arrays here.
             if (!obj->is<ArrayObject>()) {
                 MOZ_ASSERT(obj->is<NativeObject>());
                 return SetLengthProperty(cx, obj, newlength);
             }
 
             return true;
         }
     }
@@ -4011,18 +4010,17 @@ ArrayObject*
 js::NewCopiedArrayTryUseGroup(JSContext* cx, HandleObjectGroup group,
                               const Value* vp, size_t length, NewObjectKind newKind,
                               ShouldUpdateTypes updateTypes)
 {
     ArrayObject* obj = NewFullyAllocatedArrayTryUseGroup(cx, group, length, newKind);
     if (!obj)
         return nullptr;
 
-    DenseElementResult result =
-        SetOrExtendBoxedOrUnboxedDenseElements(cx, obj, 0, vp, length, updateTypes);
+    DenseElementResult result = obj->setOrExtendDenseElements(cx, 0, vp, length, updateTypes);
     if (result == DenseElementResult::Failure)
         return nullptr;
 
     MOZ_ASSERT(result == DenseElementResult::Success);
     return obj;
 }
 
 ArrayObject*
--- a/js/src/jsarray.h
+++ b/js/src/jsarray.h
@@ -97,22 +97,16 @@ NewPartlyAllocatedArrayTryReuseGroup(JSC
 
 extern ArrayObject*
 NewFullyAllocatedArrayForCallingAllocationSite(JSContext* cx, size_t length,
                                                NewObjectKind newKind = GenericObject);
 
 extern ArrayObject*
 NewPartlyAllocatedArrayForCallingAllocationSite(JSContext* cx, size_t length, HandleObject proto);
 
-enum class ShouldUpdateTypes
-{
-    Update,
-    DontUpdate
-};
-
 extern ArrayObject*
 NewCopiedArrayTryUseGroup(JSContext* cx, HandleObjectGroup group,
                           const Value* vp, size_t length,
                           NewObjectKind newKind = GenericObject,
                           ShouldUpdateTypes updateTypes = ShouldUpdateTypes::Update);
 
 extern ArrayObject*
 NewCopiedArrayForCallingAllocationSite(JSContext* cx, const Value* vp, size_t length,
--- a/js/src/vm/NativeObject-inl.h
+++ b/js/src/vm/NativeObject-inl.h
@@ -391,16 +391,48 @@ NativeObject::ensureDenseElements(JSCont
     DenseElementResult result = extendDenseElements(cx, requiredCapacity, extra);
     if (result != DenseElementResult::Success)
         return result;
 
     ensureDenseInitializedLengthNoPackedCheck(cx, index, extra);
     return DenseElementResult::Success;
 }
 
+inline DenseElementResult
+NativeObject::setOrExtendDenseElements(JSContext* cx, uint32_t start, const Value* vp,
+                                       uint32_t count,
+                                       ShouldUpdateTypes updateTypes)
+{
+    if (denseElementsAreFrozen())
+        return DenseElementResult::Incomplete;
+
+    if (is<ArrayObject>() &&
+        !as<ArrayObject>().lengthIsWritable() &&
+        start + count >= as<ArrayObject>().length())
+    {
+        return DenseElementResult::Incomplete;
+    }
+
+    DenseElementResult result = ensureDenseElements(cx, start, count);
+    if (result != DenseElementResult::Success)
+        return result;
+
+    if (is<ArrayObject>() && start + count >= as<ArrayObject>().length())
+        as<ArrayObject>().setLengthInt32(start + count);
+
+    if (updateTypes == ShouldUpdateTypes::DontUpdate && !shouldConvertDoubleElements()) {
+        copyDenseElements(start, vp, count);
+    } else {
+        for (size_t i = 0; i < count; i++)
+            setDenseElementWithType(cx, start + i, vp[i]);
+    }
+
+    return DenseElementResult::Success;
+}
+
 inline Value
 NativeObject::getDenseOrTypedArrayElement(uint32_t idx)
 {
     if (is<TypedArrayObject>())
         return as<TypedArrayObject>().getElement(idx);
     return getDenseElement(idx);
 }
 
--- a/js/src/vm/NativeObject.h
+++ b/js/src/vm/NativeObject.h
@@ -401,16 +401,21 @@ class NewObjectCache;
 // such operations, and for similar operations on unboxed arrays and methods
 // that work on both kinds of objects.
 enum class DenseElementResult {
     Failure,
     Success,
     Incomplete
 };
 
+enum class ShouldUpdateTypes {
+    Update,
+    DontUpdate
+};
+
 /*
  * NativeObject specifies the internal implementation of a native object.
  *
  * Native objects use ShapedObject::shape_ to record property information.  Two
  * native objects with the same shape are guaranteed to have the same number of
  * fixed slots.
  *
  * Native objects extend the base implementation of an object with storage for
@@ -1224,16 +1229,20 @@ class NativeObject : public ShapedObject
     inline Value getDenseOrTypedArrayElement(uint32_t idx);
 
     inline void copyDenseElements(uint32_t dstStart, const Value* src, uint32_t count);
     inline void initDenseElements(const Value* src, uint32_t count);
     inline void initDenseElements(NativeObject* src, uint32_t srcStart, uint32_t count);
     inline void moveDenseElements(uint32_t dstStart, uint32_t srcStart, uint32_t count);
     inline void moveDenseElementsNoPreBarrier(uint32_t dstStart, uint32_t srcStart, uint32_t count);
 
+    inline DenseElementResult
+    setOrExtendDenseElements(JSContext* cx, uint32_t start, const Value* vp, uint32_t count,
+                             ShouldUpdateTypes updateTypes = ShouldUpdateTypes::Update);
+
     bool shouldConvertDoubleElements() {
         return getElementsHeader()->shouldConvertDoubleElements();
     }
 
     inline void setShouldConvertDoubleElements();
     inline void clearShouldConvertDoubleElements();
 
     bool denseElementsAreCopyOnWrite() {
--- a/js/src/vm/UnboxedObject-inl.h
+++ b/js/src/vm/UnboxedObject-inl.h
@@ -163,49 +163,11 @@ SetUnboxedValue(JSContext* cx, JSObject*
 /////////////////////////////////////////////////////////////////////
 
 inline const UnboxedLayout&
 UnboxedPlainObject::layout() const
 {
     return group()->unboxedLayout();
 }
 
-/////////////////////////////////////////////////////////////////////
-// Template methods for NativeObject and UnboxedArrayObject accesses.
-/////////////////////////////////////////////////////////////////////
-
-static inline DenseElementResult
-SetOrExtendBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* obj,
-                                       uint32_t start, const Value* vp, uint32_t count,
-                                       ShouldUpdateTypes updateTypes = ShouldUpdateTypes::Update)
-{
-    NativeObject* nobj = &obj->as<NativeObject>();
-
-    if (nobj->denseElementsAreFrozen())
-        return DenseElementResult::Incomplete;
-
-    if (obj->is<ArrayObject>() &&
-        !obj->as<ArrayObject>().lengthIsWritable() &&
-        start + count >= obj->as<ArrayObject>().length())
-    {
-        return DenseElementResult::Incomplete;
-    }
-
-    DenseElementResult result = nobj->ensureDenseElements(cx, start, count);
-    if (result != DenseElementResult::Success)
-        return result;
-
-    if (obj->is<ArrayObject>() && start + count >= obj->as<ArrayObject>().length())
-        obj->as<ArrayObject>().setLengthInt32(start + count);
-
-    if (updateTypes == ShouldUpdateTypes::DontUpdate && !nobj->shouldConvertDoubleElements()) {
-        nobj->copyDenseElements(start, vp, count);
-    } else {
-        for (size_t i = 0; i < count; i++)
-            nobj->setDenseElementWithType(cx, start + i, vp[i]);
-    }
-
-    return DenseElementResult::Success;
-}
-
 } // namespace js
 
 #endif // vm_UnboxedObject_inl_h