summaryrefslogtreecommitdiffstats
path: root/js/src/vm/ObjectGroup.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/vm/ObjectGroup.cpp')
-rw-r--r--js/src/vm/ObjectGroup.cpp158
1 files changed, 149 insertions, 9 deletions
diff --git a/js/src/vm/ObjectGroup.cpp b/js/src/vm/ObjectGroup.cpp
index 91070b3f6..d05a48646 100644
--- a/js/src/vm/ObjectGroup.cpp
+++ b/js/src/vm/ObjectGroup.cpp
@@ -18,10 +18,11 @@
#include "vm/ArrayObject.h"
#include "vm/Shape.h"
#include "vm/TaggedProto.h"
+#include "vm/UnboxedObject.h"
#include "jsobjinlines.h"
-#include "vm/NativeObject-inl.h"
+#include "vm/UnboxedObject-inl.h"
using namespace js;
@@ -55,6 +56,7 @@ ObjectGroup::finalize(FreeOp* fop)
if (newScriptDontCheckGeneration())
newScriptDontCheckGeneration()->clear();
fop->delete_(newScriptDontCheckGeneration());
+ fop->delete_(maybeUnboxedLayoutDontCheckGeneration());
if (maybePreliminaryObjectsDontCheckGeneration())
maybePreliminaryObjectsDontCheckGeneration()->clear();
fop->delete_(maybePreliminaryObjectsDontCheckGeneration());
@@ -81,6 +83,8 @@ ObjectGroup::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const
size_t n = 0;
if (TypeNewScript* newScript = newScriptDontCheckGeneration())
n += newScript->sizeOfIncludingThis(mallocSizeOf);
+ if (UnboxedLayout* layout = maybeUnboxedLayoutDontCheckGeneration())
+ n += layout->sizeOfIncludingThis(mallocSizeOf);
return n;
}
@@ -529,7 +533,8 @@ ObjectGroup::defaultNewGroup(ExclusiveContext* cx, const Class* clasp,
if (p) {
ObjectGroup* group = p->group;
MOZ_ASSERT_IF(clasp, group->clasp() == clasp);
- MOZ_ASSERT_IF(!clasp, group->clasp() == &PlainObject::class_);
+ MOZ_ASSERT_IF(!clasp, group->clasp() == &PlainObject::class_ ||
+ group->clasp() == &UnboxedPlainObject::class_);
MOZ_ASSERT(group->proto() == proto);
return group;
}
@@ -772,7 +777,7 @@ GetValueTypeForTable(const Value& v)
return type;
}
-/* static */ ArrayObject*
+/* static */ JSObject*
ObjectGroup::newArrayObject(ExclusiveContext* cx,
const Value* vp, size_t length,
NewObjectKind newKind, NewArrayKind arrayKind)
@@ -836,13 +841,56 @@ ObjectGroup::newArrayObject(ExclusiveContext* cx,
AddTypePropertyId(cx, group, nullptr, JSID_VOID, elementType);
+ if (elementType != TypeSet::UnknownType()) {
+ // Keep track of the initial objects we create with this type.
+ // If the initial ones have a consistent shape and property types, we
+ // will try to use an unboxed layout for the group.
+ PreliminaryObjectArrayWithTemplate* preliminaryObjects =
+ cx->new_<PreliminaryObjectArrayWithTemplate>(nullptr);
+ if (!preliminaryObjects)
+ return nullptr;
+ group->setPreliminaryObjects(preliminaryObjects);
+ }
+
if (!p.add(cx, *table, ObjectGroupCompartment::ArrayObjectKey(elementType), group))
return nullptr;
}
// The type of the elements being added will already be reflected in type
- // information.
+ // information, but make sure when creating an unboxed array that the
+ // common element type is suitable for the unboxed representation.
ShouldUpdateTypes updateTypes = ShouldUpdateTypes::DontUpdate;
+ if (!MaybeAnalyzeBeforeCreatingLargeArray(cx, group, vp, length))
+ return nullptr;
+ if (group->maybePreliminaryObjects())
+ group->maybePreliminaryObjects()->maybeAnalyze(cx, group);
+ if (group->maybeUnboxedLayout()) {
+ switch (group->unboxedLayout().elementType()) {
+ case JSVAL_TYPE_BOOLEAN:
+ if (elementType != TypeSet::BooleanType())
+ updateTypes = ShouldUpdateTypes::Update;
+ break;
+ case JSVAL_TYPE_INT32:
+ if (elementType != TypeSet::Int32Type())
+ updateTypes = ShouldUpdateTypes::Update;
+ break;
+ case JSVAL_TYPE_DOUBLE:
+ if (elementType != TypeSet::Int32Type() && elementType != TypeSet::DoubleType())
+ updateTypes = ShouldUpdateTypes::Update;
+ break;
+ case JSVAL_TYPE_STRING:
+ if (elementType != TypeSet::StringType())
+ updateTypes = ShouldUpdateTypes::Update;
+ break;
+ case JSVAL_TYPE_OBJECT:
+ if (elementType != TypeSet::NullType() && !elementType.get().isObjectUnchecked())
+ updateTypes = ShouldUpdateTypes::Update;
+ break;
+ default:
+ MOZ_CRASH();
+ }
+ }
+
return NewCopiedArrayTryUseGroup(cx, group, vp, length, newKind, updateTypes);
}
@@ -852,15 +900,49 @@ GiveObjectGroup(ExclusiveContext* cx, JSObject* source, JSObject* target)
{
MOZ_ASSERT(source->group() != target->group());
- if (!target->is<ArrayObject>() || !source->is<ArrayObject>()) {
+ if (!target->is<ArrayObject>() && !target->is<UnboxedArrayObject>())
+ return true;
+
+ if (target->group()->maybePreliminaryObjects()) {
+ bool force = IsInsideNursery(source);
+ target->group()->maybePreliminaryObjects()->maybeAnalyze(cx, target->group(), force);
+ }
+
+ if (target->is<ArrayObject>()) {
+ ObjectGroup* sourceGroup = source->group();
+
+ if (source->is<UnboxedArrayObject>()) {
+ Shape* shape = target->as<ArrayObject>().lastProperty();
+ if (!UnboxedArrayObject::convertToNativeWithGroup(cx, source, target->group(), shape))
+ return false;
+ } else if (source->is<ArrayObject>()) {
+ source->setGroup(target->group());
+ } else {
+ return true;
+ }
+
+ if (sourceGroup->maybePreliminaryObjects())
+ sourceGroup->maybePreliminaryObjects()->unregisterObject(source);
+ if (target->group()->maybePreliminaryObjects())
+ target->group()->maybePreliminaryObjects()->registerNewObject(source);
+
+ for (size_t i = 0; i < source->as<ArrayObject>().getDenseInitializedLength(); i++) {
+ Value v = source->as<ArrayObject>().getDenseElement(i);
+ AddTypePropertyId(cx, source->group(), source, JSID_VOID, v);
+ }
+
return true;
}
- source->setGroup(target->group());
+ if (target->is<UnboxedArrayObject>()) {
+ if (!source->is<UnboxedArrayObject>())
+ return true;
+ if (source->as<UnboxedArrayObject>().elementType() != JSVAL_TYPE_INT32)
+ return true;
+ if (target->as<UnboxedArrayObject>().elementType() != JSVAL_TYPE_DOUBLE)
+ return true;
- for (size_t i = 0; i < source->as<ArrayObject>().getDenseInitializedLength(); i++) {
- Value v = source->as<ArrayObject>().getDenseElement(i);
- AddTypePropertyId(cx, source->group(), source, JSID_VOID, v);
+ return source->as<UnboxedArrayObject>().convertInt32ToDouble(cx, target->group());
}
return true;
@@ -969,6 +1051,46 @@ js::CombinePlainObjectPropertyTypes(ExclusiveContext* cx, JSObject* newObj,
}
}
}
+ } else if (newObj->is<UnboxedPlainObject>()) {
+ const UnboxedLayout& layout = newObj->as<UnboxedPlainObject>().layout();
+ const int32_t* traceList = layout.traceList();
+ if (!traceList)
+ return true;
+
+ uint8_t* newData = newObj->as<UnboxedPlainObject>().data();
+ uint8_t* oldData = oldObj->as<UnboxedPlainObject>().data();
+
+ for (; *traceList != -1; traceList++) {}
+ traceList++;
+ for (; *traceList != -1; traceList++) {
+ JSObject* newInnerObj = *reinterpret_cast<JSObject**>(newData + *traceList);
+ JSObject* oldInnerObj = *reinterpret_cast<JSObject**>(oldData + *traceList);
+
+ if (!newInnerObj || !oldInnerObj || SameGroup(oldInnerObj, newInnerObj))
+ continue;
+
+ if (!GiveObjectGroup(cx, newInnerObj, oldInnerObj))
+ return false;
+
+ if (SameGroup(oldInnerObj, newInnerObj))
+ continue;
+
+ if (!GiveObjectGroup(cx, oldInnerObj, newInnerObj))
+ return false;
+
+ if (SameGroup(oldInnerObj, newInnerObj)) {
+ for (size_t i = 1; i < ncompare; i++) {
+ if (compare[i].isObject() && SameGroup(&compare[i].toObject(), newObj)) {
+ uint8_t* otherData = compare[i].toObject().as<UnboxedPlainObject>().data();
+ JSObject* otherInnerObj = *reinterpret_cast<JSObject**>(otherData + *traceList);
+ if (otherInnerObj && !SameGroup(otherInnerObj, newInnerObj)) {
+ if (!GiveObjectGroup(cx, otherInnerObj, newInnerObj))
+ return false;
+ }
+ }
+ }
+ }
+ }
}
return true;
@@ -1192,6 +1314,12 @@ ObjectGroup::newPlainObject(ExclusiveContext* cx, IdValuePair* properties, size_
RootedObjectGroup group(cx, p->value().group);
+ // Watch for existing groups which now use an unboxed layout.
+ if (group->maybeUnboxedLayout()) {
+ MOZ_ASSERT(group->unboxedLayout().properties().length() == nproperties);
+ return UnboxedPlainObject::createWithProperties(cx, group, newKind, properties);
+ }
+
// Update property types according to the properties we are about to add.
// Do this before we do anything which can GC, which might move or remove
// this table entry.
@@ -1378,6 +1506,18 @@ ObjectGroup::allocationSiteGroup(JSContext* cx, JSScript* scriptArg, jsbytecode*
}
}
+ if (kind == JSProto_Array &&
+ (JSOp(*pc) == JSOP_NEWARRAY || IsCallPC(pc)) &&
+ cx->options().unboxedArrays())
+ {
+ PreliminaryObjectArrayWithTemplate* preliminaryObjects =
+ cx->new_<PreliminaryObjectArrayWithTemplate>(nullptr);
+ if (preliminaryObjects)
+ res->setPreliminaryObjects(preliminaryObjects);
+ else
+ cx->recoverFromOutOfMemory();
+ }
+
if (!table->add(p, key, res)) {
ReportOutOfMemory(cx);
return nullptr;