From c22a493144e39d76bfa42c46f9d6d17a5143ac35 Mon Sep 17 00:00:00 2001
From: wolfbeast <mcwerewolf@wolfbeast.com>
Date: Sat, 22 Feb 2020 21:09:32 +0100
Subject: Revert #1142 - Remove unboxed objects

- accounting for removal of watch()/unwatch()
---
 js/src/jsobj.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'js/src/jsobj.cpp')

diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp
index ef1291079..3d7f294fe 100644
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -42,7 +42,6 @@
 #include "frontend/BytecodeCompiler.h"
 #include "gc/Marking.h"
 #include "gc/Policy.h"
-#include "gc/StoreBuffer-inl.h"
 #include "jit/BaselineJIT.h"
 #include "js/MemoryMetrics.h"
 #include "js/Proxy.h"
@@ -54,6 +53,7 @@
 #include "vm/RegExpStaticsObject.h"
 #include "vm/Shape.h"
 #include "vm/TypedArrayCommon.h"
+#include "vm/UnboxedObject-inl.h"
 
 #include "jsatominlines.h"
 #include "jsboolinlines.h"
-- 
cgit v1.2.3


From af69cb07db0d810a1a1a507b890e6beb23dc421c Mon Sep 17 00:00:00 2001
From: wolfbeast <mcwerewolf@wolfbeast.com>
Date: Sun, 23 Feb 2020 14:41:40 +0100
Subject: Revert #1137 - Remove unboxed arrays

- accounting for removal of watch()/unwatch()
- updated for intermediate code changes.
---
 js/src/jsobj.cpp | 47 +++++++++++++++++++++++++++++++----------------
 1 file changed, 31 insertions(+), 16 deletions(-)

(limited to 'js/src/jsobj.cpp')

diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp
index 3d7f294fe..901a9f505 100644
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -1136,18 +1136,19 @@ js::CloneObject(JSContext* cx, HandleObject obj, Handle<js::TaggedProto> proto)
 }
 
 static bool
-GetScriptArrayObjectElements(JSContext* cx, HandleArrayObject arr, MutableHandle<GCVector<Value>> values)
+GetScriptArrayObjectElements(JSContext* cx, HandleObject obj, MutableHandle<GCVector<Value>> values)
 {
-    MOZ_ASSERT(!arr->isSingleton());
-    MOZ_ASSERT(!arr->isIndexed());
+    MOZ_ASSERT(!obj->isSingleton());
+    MOZ_ASSERT(obj->is<ArrayObject>() || obj->is<UnboxedArrayObject>());
+    MOZ_ASSERT(!obj->isIndexed());
 
-    size_t length = arr->length();
+    size_t length = GetAnyBoxedOrUnboxedArrayLength(obj);
     if (!values.appendN(MagicValue(JS_ELEMENTS_HOLE), length))
         return false;
 
-    size_t initlen = arr->getDenseInitializedLength();
+    size_t initlen = GetAnyBoxedOrUnboxedInitializedLength(obj);
     for (size_t i = 0; i < initlen; i++)
-        values[i].set(arr->getDenseElement(i));
+        values[i].set(GetAnyBoxedOrUnboxedDenseElement(obj, i));
 
     return true;
 }
@@ -1199,12 +1200,13 @@ js::DeepCloneObjectLiteral(JSContext* cx, HandleObject obj, NewObjectKind newKin
     MOZ_ASSERT_IF(obj->isSingleton(),
                   cx->compartment()->behaviors().getSingletonsAsTemplates());
     MOZ_ASSERT(obj->is<PlainObject>() ||
-               obj->is<ArrayObject>());
+               obj->is<ArrayObject>() ||
+			   obj->is<UnboxedArrayObject>());
     MOZ_ASSERT(newKind != SingletonObject);
 
-    if (obj->is<ArrayObject>()) {
+    if (obj->is<ArrayObject>() || obj->is<UnboxedArrayObject>()) {
         Rooted<GCVector<Value>> values(cx, GCVector<Value>(cx));
-        if (!GetScriptArrayObjectElements(cx, obj.as<ArrayObject>(), &values))
+        if (!GetScriptArrayObjectElements(cx, obj, &values))
             return nullptr;
 
         // Deep clone any elements.
@@ -1318,8 +1320,9 @@ js::XDRObjectLiteral(XDRState<mode>* xdr, MutableHandleObject obj)
     {
         if (mode == XDR_ENCODE) {
             MOZ_ASSERT(obj->is<PlainObject>() ||
-                       obj->is<ArrayObject>());
-            isArray = obj->is<ArrayObject>() ? 1 : 0;
+                       obj->is<ArrayObject>() ||
+                       obj->is<UnboxedArrayObject>());
+            isArray = (obj->is<ArrayObject>() || obj->is<UnboxedArrayObject>()) ? 1 : 0;
         }
 
         if (!xdr->codeUint32(&isArray))
@@ -1331,11 +1334,8 @@ js::XDRObjectLiteral(XDRState<mode>* xdr, MutableHandleObject obj)
 
     if (isArray) {
         Rooted<GCVector<Value>> values(cx, GCVector<Value>(cx));
-        if (mode == XDR_ENCODE) {
-            RootedArrayObject arr(cx, &obj->as<ArrayObject>());
-            if (!GetScriptArrayObjectElements(cx, arr, &values))
-                return false;
-        }
+        if (mode == XDR_ENCODE && !GetScriptArrayObjectElements(cx, obj, &values))
+            return false;
 
         uint32_t initialized;
         if (mode == XDR_ENCODE)
@@ -2315,6 +2315,11 @@ js::LookupOwnPropertyPure(ExclusiveContext* cx, JSObject* obj, jsid id, Shape**
         // us the resolve hook won't define a property with this id.
         if (ClassMayResolveId(cx->names(), obj->getClass(), id, obj))
             return false;
+    } else if (obj->is<UnboxedArrayObject>()) {
+        if (obj->as<UnboxedArrayObject>().containsProperty(cx, id)) {
+            MarkNonNativePropertyFound<NoGC>(propp);
+            return true;
+        }
     } else if (obj->is<TypedObject>()) {
         if (obj->as<TypedObject>().typeDescr().hasProperty(cx->names(), id)) {
             MarkNonNativePropertyFound<NoGC>(propp);
@@ -3606,6 +3611,16 @@ JSObject::allocKindForTenure(const js::Nursery& nursery) const
     if (IsProxy(this))
         return as<ProxyObject>().allocKindForTenure();
 
+    // Unboxed arrays use inline data if their size is small enough.
+    if (is<UnboxedArrayObject>()) {
+        const UnboxedArrayObject* nobj = &as<UnboxedArrayObject>();
+        size_t nbytes = UnboxedArrayObject::offsetOfInlineElements() +
+                        nobj->capacity() * nobj->elementSize();
+        if (nbytes <= JSObject::MAX_BYTE_SIZE)
+            return GetGCObjectKindForBytes(nbytes);
+        return AllocKind::OBJECT0;
+    }
+
     // Inlined typed objects are followed by their data, so make sure we copy
     // it all over to the new object.
     if (is<InlineTypedObject>()) {
-- 
cgit v1.2.3


From 0d1eea2ebfcf1a3746ff0125a6fa340e8b90d722 Mon Sep 17 00:00:00 2001
From: wolfbeast <mcwerewolf@wolfbeast.com>
Date: Sun, 23 Feb 2020 19:43:47 +0100
Subject: Revert #1091 Remove unboxed object code phase 1 + extras.

This should be the last code backout for this. merging this branch
should get us back to the way we were (+ additional code changes for
later changes) as fasr as the unused unboxed code is concerned.
---
 js/src/jsobj.cpp | 76 ++++++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 58 insertions(+), 18 deletions(-)

(limited to 'js/src/jsobj.cpp')

diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp
index 901a9f505..d4379bd7d 100644
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -53,7 +53,6 @@
 #include "vm/RegExpStaticsObject.h"
 #include "vm/Shape.h"
 #include "vm/TypedArrayCommon.h"
-#include "vm/UnboxedObject-inl.h"
 
 #include "jsatominlines.h"
 #include "jsboolinlines.h"
@@ -869,6 +868,9 @@ static inline JSObject*
 CreateThisForFunctionWithGroup(JSContext* cx, HandleObjectGroup group,
                                NewObjectKind newKind)
 {
+    if (group->maybeUnboxedLayout() && newKind != SingletonObject)
+        return UnboxedPlainObject::create(cx, group, newKind);
+
     if (TypeNewScript* newScript = group->newScript()) {
         if (newScript->analyzed()) {
             // The definite properties analysis has been performed for this
@@ -1157,27 +1159,46 @@ static bool
 GetScriptPlainObjectProperties(JSContext* cx, HandleObject obj,
                                MutableHandle<IdValueVector> properties)
 {
-    MOZ_ASSERT(obj->is<PlainObject>());
-    PlainObject* nobj = &obj->as<PlainObject>();
+    if (obj->is<PlainObject>()) {
+        PlainObject* nobj = &obj->as<PlainObject>();
 
-    if (!properties.appendN(IdValuePair(), nobj->slotSpan()))
-        return false;
+        if (!properties.appendN(IdValuePair(), nobj->slotSpan()))
+            return false;
 
-    for (Shape::Range<NoGC> r(nobj->lastProperty()); !r.empty(); r.popFront()) {
-        Shape& shape = r.front();
-        MOZ_ASSERT(shape.isDataDescriptor());
-        uint32_t slot = shape.slot();
-        properties[slot].get().id = shape.propid();
-        properties[slot].get().value = nobj->getSlot(slot);
+        for (Shape::Range<NoGC> r(nobj->lastProperty()); !r.empty(); r.popFront()) {
+            Shape& shape = r.front();
+            MOZ_ASSERT(shape.isDataDescriptor());
+            uint32_t slot = shape.slot();
+            properties[slot].get().id = shape.propid();
+            properties[slot].get().value = nobj->getSlot(slot);
+        }
+
+        for (size_t i = 0; i < nobj->getDenseInitializedLength(); i++) {
+            Value v = nobj->getDenseElement(i);
+            if (!v.isMagic(JS_ELEMENTS_HOLE) && !properties.append(IdValuePair(INT_TO_JSID(i), v)))
+                return false;
+        }
+
+        return true;
     }
 
-    for (size_t i = 0; i < nobj->getDenseInitializedLength(); i++) {
-        Value v = nobj->getDenseElement(i);
-        if (!v.isMagic(JS_ELEMENTS_HOLE) && !properties.append(IdValuePair(INT_TO_JSID(i), v)))
+    if (obj->is<UnboxedPlainObject>()) {
+        UnboxedPlainObject* nobj = &obj->as<UnboxedPlainObject>();
+
+        const UnboxedLayout& layout = nobj->layout();
+        if (!properties.appendN(IdValuePair(), layout.properties().length()))
             return false;
+
+        for (size_t i = 0; i < layout.properties().length(); i++) {
+            const UnboxedLayout::Property& property = layout.properties()[i];
+            properties[i].get().id = NameToId(property.name);
+            properties[i].get().value = nobj->getValue(property);
+        }
+
+        return true;
     }
 
-    return true;
+    MOZ_CRASH("Bad object kind");
 }
 
 static bool
@@ -1199,9 +1220,8 @@ js::DeepCloneObjectLiteral(JSContext* cx, HandleObject obj, NewObjectKind newKin
     /* NB: Keep this in sync with XDRObjectLiteral. */
     MOZ_ASSERT_IF(obj->isSingleton(),
                   cx->compartment()->behaviors().getSingletonsAsTemplates());
-    MOZ_ASSERT(obj->is<PlainObject>() ||
-               obj->is<ArrayObject>() ||
-			   obj->is<UnboxedArrayObject>());
+    MOZ_ASSERT(obj->is<PlainObject>() || obj->is<UnboxedPlainObject>() ||
+               obj->is<ArrayObject>() || obj->is<UnboxedArrayObject>());
     MOZ_ASSERT(newKind != SingletonObject);
 
     if (obj->is<ArrayObject>() || obj->is<UnboxedArrayObject>()) {
@@ -1320,6 +1340,7 @@ js::XDRObjectLiteral(XDRState<mode>* xdr, MutableHandleObject obj)
     {
         if (mode == XDR_ENCODE) {
             MOZ_ASSERT(obj->is<PlainObject>() ||
+                       obj->is<UnboxedPlainObject>() ||
                        obj->is<ArrayObject>() ||
                        obj->is<UnboxedArrayObject>());
             isArray = (obj->is<ArrayObject>() || obj->is<UnboxedArrayObject>()) ? 1 : 0;
@@ -2315,6 +2336,11 @@ js::LookupOwnPropertyPure(ExclusiveContext* cx, JSObject* obj, jsid id, Shape**
         // us the resolve hook won't define a property with this id.
         if (ClassMayResolveId(cx->names(), obj->getClass(), id, obj))
             return false;
+    } else if (obj->is<UnboxedPlainObject>()) {
+        if (obj->as<UnboxedPlainObject>().containsUnboxedOrExpandoProperty(cx, id)) {
+            MarkNonNativePropertyFound<NoGC>(propp);
+            return true;
+        }
     } else if (obj->is<UnboxedArrayObject>()) {
         if (obj->as<UnboxedArrayObject>().containsProperty(cx, id)) {
             MarkNonNativePropertyFound<NoGC>(propp);
@@ -2576,6 +2602,11 @@ js::SetPrototype(JSContext* cx, HandleObject obj, HandleObject proto, JS::Object
             break;
     }
 
+    // Convert unboxed objects to their native representations before changing
+    // their prototype/group, as they depend on the group for their layout.
+    if (!MaybeConvertUnboxedObjectToNative(cx, obj))
+        return false;
+
     Rooted<TaggedProto> taggedProto(cx, TaggedProto(proto));
     if (!SetClassAndProto(cx, obj, obj->getClass(), taggedProto))
         return false;
@@ -2599,6 +2630,9 @@ js::PreventExtensions(JSContext* cx, HandleObject obj, ObjectOpResult& result, I
     if (!obj->nonProxyIsExtensible())
         return result.succeed();
 
+    if (!MaybeConvertUnboxedObjectToNative(cx, obj))
+        return false;
+
     // Force lazy properties to be resolved.
     AutoIdVector props(cx);
     if (!js::GetPropertyKeys(cx, obj, JSITER_HIDDEN | JSITER_OWNONLY, &props))
@@ -3611,6 +3645,12 @@ JSObject::allocKindForTenure(const js::Nursery& nursery) const
     if (IsProxy(this))
         return as<ProxyObject>().allocKindForTenure();
 
+    // Unboxed plain objects are sized according to the data they store.
+    if (is<UnboxedPlainObject>()) {
+        size_t nbytes = as<UnboxedPlainObject>().layoutDontCheckGeneration().size();
+        return GetGCObjectKindForBytes(UnboxedPlainObject::offsetOfData() + nbytes);
+    }
+
     // Unboxed arrays use inline data if their size is small enough.
     if (is<UnboxedArrayObject>()) {
         const UnboxedArrayObject* nobj = &as<UnboxedArrayObject>();
-- 
cgit v1.2.3