diff --git a/js/src/gc/Barrier.h b/js/src/gc/Barrier.h index d23c91d4afdc..be1f98b75ff4 100644 --- a/js/src/gc/Barrier.h +++ b/js/src/gc/Barrier.h @@ -104,7 +104,7 @@ * reference them. The solution is to maintain information about these pointers, * and mark their targets when we start a minor collection. * - * The pointers can be thoughs of as edges in object graph, and the set of edges + * The pointers can be thought of as edges in object graph, and the set of edges * from the tenured generation into the nursery is know as the remembered set. * Post barriers are used to track this remembered set. * diff --git a/js/src/jit/JitOptions.cpp b/js/src/jit/JitOptions.cpp index aa937a56c807..30272863ba2b 100644 --- a/js/src/jit/JitOptions.cpp +++ b/js/src/jit/JitOptions.cpp @@ -161,6 +161,9 @@ JitOptions::JitOptions() // The bytecode length limit for small function. SET_DEFAULT(smallFunctionMaxBytecodeLength_, 100); + + // Toggles whether unboxed plain objects can be created by the VM. + SET_DEFAULT(disableUnboxedObjects, false); } bool diff --git a/js/src/jit/JitOptions.h b/js/src/jit/JitOptions.h index c2caf9b976ca..2e562a2929f7 100644 --- a/js/src/jit/JitOptions.h +++ b/js/src/jit/JitOptions.h @@ -67,6 +67,9 @@ struct JitOptions uint32_t osrPcMismatchesBeforeRecompile; uint32_t smallFunctionMaxBytecodeLength_; + // The options below affect the rest of the VM, and not just the JIT. + bool disableUnboxedObjects; + JitOptions(); bool isSmallFunction(JSScript* script) const; void setEagerCompilation(); diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 9a3bc4793747..058b6fdc23de 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -1137,8 +1137,7 @@ class JS_PUBLIC_API(RuntimeOptions) { ion_(true), asmJS_(true), nativeRegExp_(true), - unboxedObjects_(false), // Not enabled by default yet - unboxedArrays_(false), // Ditto + unboxedArrays_(false), werror_(false), strictMode_(false), extraWarnings_(false), @@ -1182,12 +1181,6 @@ class JS_PUBLIC_API(RuntimeOptions) { return *this; } - bool unboxedObjects() const { return unboxedObjects_; } - RuntimeOptions& setUnboxedObjects(bool flag) { - unboxedObjects_ = flag; - return *this; - } - bool unboxedArrays() const { return unboxedArrays_; } RuntimeOptions& setUnboxedArrays(bool flag) { unboxedArrays_ = flag; @@ -1239,7 +1232,6 @@ class JS_PUBLIC_API(RuntimeOptions) { bool ion_ : 1; bool asmJS_ : 1; bool nativeRegExp_ : 1; - bool unboxedObjects_ : 1; bool unboxedArrays_ : 1; bool werror_ : 1; bool strictMode_ : 1; diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index f930a13a3289..4948e9963a79 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -132,7 +132,6 @@ static bool enableBaseline = false; static bool enableIon = false; static bool enableAsmJS = false; static bool enableNativeRegExp = false; -static bool enableUnboxedObjects = false; static bool enableUnboxedArrays = false; #ifdef JS_GC_ZEAL static char gZealStr[128]; @@ -5778,16 +5777,17 @@ SetRuntimeOptions(JSRuntime* rt, const OptionParser& op) enableIon = !op.getBoolOption("no-ion"); enableAsmJS = !op.getBoolOption("no-asmjs"); enableNativeRegExp = !op.getBoolOption("no-native-regexp"); - enableUnboxedObjects = op.getBoolOption("unboxed-objects"); enableUnboxedArrays = op.getBoolOption("unboxed-arrays"); JS::RuntimeOptionsRef(rt).setBaseline(enableBaseline) .setIon(enableIon) .setAsmJS(enableAsmJS) .setNativeRegExp(enableNativeRegExp) - .setUnboxedObjects(enableUnboxedObjects) .setUnboxedArrays(enableUnboxedArrays); + if (op.getBoolOption("no-unboxed-objects")) + jit::js_JitOptions.disableUnboxedObjects = true; + if (const char* str = op.getStringOption("ion-scalar-replacement")) { if (strcmp(str, "on") == 0) jit::js_JitOptions.disableScalarReplacement = false; @@ -5991,7 +5991,6 @@ SetWorkerRuntimeOptions(JSRuntime* rt) .setIon(enableIon) .setAsmJS(enableAsmJS) .setNativeRegExp(enableNativeRegExp) - .setUnboxedObjects(enableUnboxedObjects) .setUnboxedArrays(enableUnboxedArrays); rt->setOffthreadIonCompilationEnabled(offthreadCompilation); rt->profilingScripts = enableDisassemblyDumps; @@ -6134,7 +6133,7 @@ main(int argc, char** argv, char** envp) || !op.addBoolOption('\0', "no-ion", "Disable IonMonkey") || !op.addBoolOption('\0', "no-asmjs", "Disable asm.js compilation") || !op.addBoolOption('\0', "no-native-regexp", "Disable native regexp compilation") - || !op.addBoolOption('\0', "unboxed-objects", "Allow creating unboxed plain objects") + || !op.addBoolOption('\0', "no-unboxed-objects", "Disable creating unboxed plain objects") || !op.addBoolOption('\0', "unboxed-arrays", "Allow creating unboxed arrays") || !op.addStringOption('\0', "ion-scalar-replacement", "on/off", "Scalar Replacement (default: on, off to disable)") diff --git a/js/src/vm/NativeObject.cpp b/js/src/vm/NativeObject.cpp index 0eaaa2cf6912..874aa8ba8189 100644 --- a/js/src/vm/NativeObject.cpp +++ b/js/src/vm/NativeObject.cpp @@ -357,6 +357,8 @@ NativeObject::setLastPropertyMakeNative(ExclusiveContext* cx, Shape* shape) size_t oldSpan = shape->numFixedSlots(); size_t newSpan = shape->slotSpan(); + initializeSlotRange(0, oldSpan); + // A failure at this point will leave the object as a mutant, and we // can't recover. if (oldSpan != newSpan && !updateSlotsForSpan(cx, oldSpan, newSpan)) diff --git a/js/src/vm/ObjectGroup.cpp b/js/src/vm/ObjectGroup.cpp index 5f5c61cd3681..b5cdcddf9972 100644 --- a/js/src/vm/ObjectGroup.cpp +++ b/js/src/vm/ObjectGroup.cpp @@ -43,8 +43,12 @@ ObjectGroup::ObjectGroup(const Class* clasp, TaggedProto proto, JSCompartment* c void ObjectGroup::finalize(FreeOp* fop) { + if (newScriptDontCheckGeneration()) + newScriptDontCheckGeneration()->clear(); fop->delete_(newScriptDontCheckGeneration()); fop->delete_(maybeUnboxedLayoutDontCheckGeneration()); + if (maybePreliminaryObjectsDontCheckGeneration()) + maybePreliminaryObjectsDontCheckGeneration()->clear(); fop->delete_(maybePreliminaryObjectsDontCheckGeneration()); } diff --git a/js/src/vm/ReceiverGuard.cpp b/js/src/vm/ReceiverGuard.cpp index 5b64176dfead..80e4208991bb 100644 --- a/js/src/vm/ReceiverGuard.cpp +++ b/js/src/vm/ReceiverGuard.cpp @@ -59,6 +59,6 @@ HeapReceiverGuard::trace(JSTracer* trc) { if (shape_) TraceEdge(trc, &shape_, "receiver_guard_shape"); - else + if (group_) TraceEdge(trc, &group_, "receiver_guard_group"); } diff --git a/js/src/vm/TypeInference-inl.h b/js/src/vm/TypeInference-inl.h index a0e31ea0ec01..1a41c5932dbc 100644 --- a/js/src/vm/TypeInference-inl.h +++ b/js/src/vm/TypeInference-inl.h @@ -445,7 +445,7 @@ MarkObjectGroupFlags(ExclusiveContext* cx, JSObject* obj, ObjectGroupFlags flags } inline void -MarkObjectGroupUnknownProperties(JSContext* cx, ObjectGroup* obj) +MarkObjectGroupUnknownProperties(ExclusiveContext* cx, ObjectGroup* obj) { if (!obj->unknownProperties()) obj->markUnknown(cx); diff --git a/js/src/vm/TypeInference.cpp b/js/src/vm/TypeInference.cpp index c36ba05b587b..e95922b2e3df 100644 --- a/js/src/vm/TypeInference.cpp +++ b/js/src/vm/TypeInference.cpp @@ -2864,6 +2864,11 @@ ObjectGroup::markUnknown(ExclusiveContext* cx) prop->types.setNonDataProperty(cx); } } + + if (maybeUnboxedLayout() && maybeUnboxedLayout()->nativeGroup()) + MarkObjectGroupUnknownProperties(cx, maybeUnboxedLayout()->nativeGroup()); + if (ObjectGroup* unboxedGroup = maybeOriginalUnboxedGroup()) + MarkObjectGroupUnknownProperties(cx, unboxedGroup); } TypeNewScript* diff --git a/js/src/vm/TypeInference.h b/js/src/vm/TypeInference.h index d935c62ea1f2..4402e3b5c74b 100644 --- a/js/src/vm/TypeInference.h +++ b/js/src/vm/TypeInference.h @@ -806,6 +806,10 @@ class PreliminaryObjectArrayWithTemplate : public PreliminaryObjectArray : shape_(shape) {} + void clear() { + shape_.init(nullptr); + } + Shape* shape() { return shape_; } @@ -914,6 +918,13 @@ class TypeNewScript js_free(initializerList); } + void clear() { + function_.init(nullptr); + templateObject_.init(nullptr); + initializedShape_.init(nullptr); + initializedGroup_.init(nullptr); + } + static void writeBarrierPre(TypeNewScript* newScript); bool analyzed() const { diff --git a/js/src/vm/UnboxedObject.cpp b/js/src/vm/UnboxedObject.cpp index 5c1b704d82cc..5b56d63050b0 100644 --- a/js/src/vm/UnboxedObject.cpp +++ b/js/src/vm/UnboxedObject.cpp @@ -1885,26 +1885,26 @@ bool js::TryConvertToUnboxedLayout(ExclusiveContext* cx, Shape* templateShape, ObjectGroup* group, PreliminaryObjectArray* objects) { - // Unboxed objects are nightly only for now. The getenv() call will be + bool isArray = !templateShape; + + // Unboxed arrays are nightly only for now. The getenv() call will be // removed when they are on by default. See bug 1153266. + if (isArray) { #ifdef NIGHTLY_BUILD - if (templateShape) { - if (!getenv("JS_OPTION_USE_UNBOXED_OBJECTS")) { - if (!group->runtimeFromAnyThread()->options().unboxedObjects()) + if (!getenv("JS_OPTION_USE_UNBOXED_ARRAYS")) { + if (!group->runtimeFromAnyThread()->options().unboxedArrays()) return true; } +#else + return true; +#endif } else { - if (!group->runtimeFromAnyThread()->options().unboxedArrays()) + if (jit::js_JitOptions.disableUnboxedObjects) return true; } -#else - return true; -#endif MOZ_ASSERT_IF(templateShape, !templateShape->getObjectFlags()); - bool isArray = !templateShape; - if (group->runtimeFromAnyThread()->isSelfHostingGlobal(cx->global())) return true; diff --git a/js/src/vm/UnboxedObject.h b/js/src/vm/UnboxedObject.h index b6e6e0d07c07..154c4b5994a7 100644 --- a/js/src/vm/UnboxedObject.h +++ b/js/src/vm/UnboxedObject.h @@ -108,8 +108,15 @@ class UnboxedLayout : public mozilla::LinkedListElement } ~UnboxedLayout() { + if (newScript_) + newScript_->clear(); js_delete(newScript_); js_free(traceList_); + + nativeGroup_.init(nullptr); + nativeShape_.init(nullptr); + replacementNewGroup_.init(nullptr); + constructorCode_.init(nullptr); } bool isArray() {