From e95089d84ac71276bd059e52293ab42c2259d89e Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Wed, 12 Jun 2019 03:19:09 +0000 Subject: Make use of ArrayObjects in favor of generic JS objects. ArrayObjects has been a thing for years but been under-used. About time they are used where prudent. --- js/src/frontend/BytecodeEmitter.cpp | 4 +-- js/src/jit/BaselineCompiler.cpp | 6 ++-- js/src/jit/BaselineIC.cpp | 8 ++--- js/src/jit/CodeGenerator.cpp | 8 ++--- js/src/jit/Recover.cpp | 2 +- js/src/jsarray.cpp | 68 ++++++++++--------------------------- js/src/jsarray.h | 24 ++++++------- js/src/jsstr.cpp | 6 ++-- js/src/jsstr.h | 2 +- js/src/vm/JSONParser.cpp | 4 +-- js/src/vm/ObjectGroup.cpp | 7 ++-- js/src/vm/ObjectGroup.h | 10 +++--- js/src/vm/Stack.cpp | 2 +- js/src/vm/Stack.h | 2 +- 14 files changed, 57 insertions(+), 96 deletions(-) (limited to 'js') diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index c524184d6..ea6baeec7 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -6281,8 +6281,8 @@ ParseNode::getConstantValue(ExclusiveContext* cx, AllowConstantObjects allowObje } MOZ_ASSERT(idx == count); - JSObject* obj = ObjectGroup::newArrayObject(cx, values.begin(), values.length(), - newKind, arrayKind); + ArrayObject* obj = ObjectGroup::newArrayObject(cx, values.begin(), values.length(), + newKind, arrayKind); if (!obj) return false; diff --git a/js/src/jit/BaselineCompiler.cpp b/js/src/jit/BaselineCompiler.cpp index 3fa5a80ed..93e3759b9 100644 --- a/js/src/jit/BaselineCompiler.cpp +++ b/js/src/jit/BaselineCompiler.cpp @@ -2055,7 +2055,7 @@ BaselineCompiler::emit_JSOP_SPREADCALLARRAY() return emit_JSOP_NEWARRAY(); } -typedef JSObject* (*NewArrayCopyOnWriteFn)(JSContext*, HandleArrayObject, gc::InitialHeap); +typedef ArrayObject* (*NewArrayCopyOnWriteFn)(JSContext*, HandleArrayObject, gc::InitialHeap); const VMFunction jit::NewArrayCopyOnWriteInfo = FunctionInfo(js::NewDenseCopyOnWriteArray, "NewDenseCopyOnWriteArray"); @@ -4136,14 +4136,14 @@ BaselineCompiler::emit_JSOP_REST() { frame.syncStack(0); - JSObject* templateObject = + ArrayObject* templateObject = ObjectGroup::newArrayObject(cx, nullptr, 0, TenuredObject, ObjectGroup::NewArrayKind::UnknownIndex); if (!templateObject) return false; // Call IC. - ICRest_Fallback::Compiler compiler(cx, &templateObject->as()); + ICRest_Fallback::Compiler compiler(cx, templateObject); if (!emitOpIC(compiler.getStub(&stubSpace_))) return false; diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp index 28e263ac7..2b0822655 100644 --- a/js/src/jit/BaselineIC.cpp +++ b/js/src/jit/BaselineIC.cpp @@ -5765,10 +5765,10 @@ static bool CopyArray(JSContext* cx, HandleArrayObject arr, MutableHandleValue result) { uint32_t length = arr->length(); - JSObject* nobj = NewFullyAllocatedArrayTryReuseGroup(cx, arr, length, TenuredObject); + ArrayObject* nobj = NewFullyAllocatedArrayTryReuseGroup(cx, arr, length, TenuredObject); if (!nobj) return false; - EnsureArrayGroupAnalyzed(cx, nobj); + EnsureArrayGroupAnalyzed(cx, nobj); //XXX CopyBoxedOrUnboxedDenseElements(cx, nobj, arr, 0, 0, length); result.setObject(*nobj); @@ -8547,8 +8547,8 @@ static bool DoRestFallback(JSContext* cx, BaselineFrame* frame, ICRest_Fallback* unsigned numRest = numActuals > numFormals ? numActuals - numFormals : 0; Value* rest = frame->argv() + numFormals; - JSObject* obj = ObjectGroup::newArrayObject(cx, rest, numRest, GenericObject, - ObjectGroup::NewArrayKind::UnknownIndex); + ArrayObject* obj = ObjectGroup::newArrayObject(cx, rest, numRest, GenericObject, + ObjectGroup::NewArrayKind::UnknownIndex); if (!obj) return false; res.setObject(*obj); diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp index 485e881fe..ae9c61031 100644 --- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -5169,11 +5169,11 @@ static JSObject* NewArrayWithGroup(JSContext* cx, uint32_t length, HandleObjectGroup group, bool convertDoubleElements) { - JSObject* res = NewFullyAllocatedArrayTryUseGroup(cx, group, length); + ArrayObject* res = NewFullyAllocatedArrayTryUseGroup(cx, group, length); if (!res) return nullptr; if (convertDoubleElements) - res->as().setShouldConvertDoubleElements(); + res->setShouldConvertDoubleElements(); return res; } @@ -5319,7 +5319,7 @@ CodeGenerator::visitNewArrayCopyOnWrite(LNewArrayCopyOnWrite* lir) masm.bind(ool->rejoin()); } -typedef JSObject* (*ArrayConstructorOneArgFn)(JSContext*, HandleObjectGroup, int32_t length); +typedef ArrayObject* (*ArrayConstructorOneArgFn)(JSContext*, HandleObjectGroup, int32_t length); static const VMFunction ArrayConstructorOneArgInfo = FunctionInfo(ArrayConstructorOneArg, "ArrayConstructorOneArg"); @@ -7765,7 +7765,7 @@ CodeGenerator::visitSinCos(LSinCos *lir) masm.freeStack(sizeof(double) * 2); } -typedef JSObject* (*StringSplitFn)(JSContext*, HandleObjectGroup, HandleString, HandleString, uint32_t); +typedef ArrayObject* (*StringSplitFn)(JSContext*, HandleObjectGroup, HandleString, HandleString, uint32_t); static const VMFunction StringSplitInfo = FunctionInfo(js::str_split_string, "str_split_string"); diff --git a/js/src/jit/Recover.cpp b/js/src/jit/Recover.cpp index 6fd71f377..8fe6ee3fb 100644 --- a/js/src/jit/Recover.cpp +++ b/js/src/jit/Recover.cpp @@ -1355,7 +1355,7 @@ RNewArray::recover(JSContext* cx, SnapshotIterator& iter) const RootedValue result(cx); RootedObjectGroup group(cx, templateObject->group()); - JSObject* resultObject = NewFullyAllocatedArrayTryUseGroup(cx, group, count_); + ArrayObject* resultObject = NewFullyAllocatedArrayTryUseGroup(cx, group, count_); if (!resultObject) return false; diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index da692c1b5..0d6f78fcf 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -2811,7 +2811,7 @@ SliceSlowly(JSContext* cx, HandleObject obj, HandleObject receiver, } static bool -SliceSparse(JSContext* cx, HandleObject obj, uint32_t begin, uint32_t end, HandleObject result) +SliceSparse(JSContext* cx, HandleObject obj, uint32_t begin, uint32_t end, HandleArrayObject result) { MOZ_ASSERT(begin <= end); @@ -2866,7 +2866,7 @@ ArraySliceOrdinary(JSContext* cx, HandleObject obj, uint32_t length, uint32_t be if (initlen > begin) count = Min(initlen - begin, end - begin); - RootedObject narr(cx, NewFullyAllocatedArrayTryReuseGroup(cx, obj, count)); + RootedArrayObject narr(cx, NewFullyAllocatedArrayTryReuseGroup(cx, obj, count)); if (!narr) return false; @@ -2882,7 +2882,7 @@ ArraySliceOrdinary(JSContext* cx, HandleObject obj, uint32_t length, uint32_t be return true; } - RootedObject narr(cx, NewPartlyAllocatedArrayTryReuseGroup(cx, obj, end - begin)); + RootedArrayObject narr(cx, NewPartlyAllocatedArrayTryReuseGroup(cx, obj, end - begin)); if (!narr) return false; @@ -3069,7 +3069,7 @@ array_isArray(JSContext* cx, unsigned argc, Value* vp) static bool ArrayFromCallArgs(JSContext* cx, CallArgs& args, HandleObject proto = nullptr) { - JSObject* obj = NewCopiedArrayForCallingAllocationSite(cx, args.array(), args.length(), proto); + ArrayObject* obj = NewCopiedArrayForCallingAllocationSite(cx, args.array(), args.length(), proto); if (!obj) return false; @@ -3234,7 +3234,7 @@ ArrayConstructorImpl(JSContext* cx, CallArgs& args, bool isConstructor) } } - JSObject* obj = NewPartlyAllocatedArrayForCallingAllocationSite(cx, length, proto); + ArrayObject* obj = NewPartlyAllocatedArrayForCallingAllocationSite(cx, length, proto); if (!obj) return false; @@ -3260,7 +3260,7 @@ js::array_construct(JSContext* cx, unsigned argc, Value* vp) return ArrayConstructorImpl(cx, args, /* isConstructor = */ false); } -JSObject* +ArrayObject* js::ArrayConstructorOneArg(JSContext* cx, HandleObjectGroup group, int32_t lengthInt) { if (lengthInt < 0) { @@ -3555,7 +3555,7 @@ js::NewDenseFullyAllocatedArrayWithTemplate(JSContext* cx, uint32_t length, JSOb return arr; } -JSObject* +ArrayObject* js::NewDenseCopyOnWriteArray(JSContext* cx, HandleArrayObject templateObject, gc::InitialHeap heap) { MOZ_ASSERT(!gc::IsInsideNursery(templateObject)); @@ -3573,7 +3573,7 @@ js::NewDenseCopyOnWriteArray(JSContext* cx, HandleArrayObject templateObject, gc // specified group cannot be used, ensure that the created array at least has // the given [[Prototype]]. template -static inline JSObject* +static inline ArrayObject* NewArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length, NewObjectKind newKind = GenericObject) { @@ -3603,14 +3603,14 @@ NewArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length return res; } -JSObject* +ArrayObject* js::NewFullyAllocatedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length, NewObjectKind newKind) { return NewArrayTryUseGroup(cx, group, length, newKind); } -JSObject* +ArrayObject* js::NewPartlyAllocatedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length) { return NewArrayTryUseGroup(cx, group, length); @@ -3624,7 +3624,7 @@ js::NewPartlyAllocatedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup g // |length| is larger than the input object's initialized length (in which case // UnboxedArrayObject::MaximumCapacity might be exceeded). template -static inline JSObject* +static inline ArrayObject* NewArrayTryReuseGroup(JSContext* cx, JSObject* obj, size_t length, NewObjectKind newKind = GenericObject) { @@ -3641,20 +3641,20 @@ NewArrayTryReuseGroup(JSContext* cx, JSObject* obj, size_t length, return NewArrayTryUseGroup(cx, group, length, newKind); } -JSObject* +ArrayObject* js::NewFullyAllocatedArrayTryReuseGroup(JSContext* cx, JSObject* obj, size_t length, NewObjectKind newKind) { return NewArrayTryReuseGroup(cx, obj, length, newKind); } -JSObject* +ArrayObject* js::NewPartlyAllocatedArrayTryReuseGroup(JSContext* cx, JSObject* obj, size_t length) { return NewArrayTryReuseGroup(cx, obj, length); } -JSObject* +ArrayObject* js::NewFullyAllocatedArrayForCallingAllocationSite(JSContext* cx, size_t length, NewObjectKind newKind) { @@ -3664,7 +3664,7 @@ js::NewFullyAllocatedArrayForCallingAllocationSite(JSContext* cx, size_t length, return NewArrayTryUseGroup(cx, group, length, newKind); } -JSObject* +ArrayObject* js::NewPartlyAllocatedArrayForCallingAllocationSite(JSContext* cx, size_t length, HandleObject proto) { RootedObjectGroup group(cx, ObjectGroup::callingAllocationSiteGroup(cx, JSProto_Array, proto)); @@ -3673,44 +3673,12 @@ js::NewPartlyAllocatedArrayForCallingAllocationSite(JSContext* cx, size_t length return NewArrayTryUseGroup(cx, group, length); } -bool -js::MaybeAnalyzeBeforeCreatingLargeArray(ExclusiveContext* cx, HandleObjectGroup group, - const Value* vp, size_t length) -{ - static const size_t EagerPreliminaryObjectAnalysisThreshold = 800; - - // Force analysis to see if an unboxed array can be used when making a - // sufficiently large array, to avoid excessive analysis and copying later - // on. If this is the first array of its group that is being created, first - // make a dummy array with the initial elements of the array we are about - // to make, so there is some basis for the unboxed array analysis. - if (length > EagerPreliminaryObjectAnalysisThreshold) { - if (PreliminaryObjectArrayWithTemplate* objects = group->maybePreliminaryObjects()) { - if (objects->empty()) { - size_t nlength = Min(length, 100); - JSObject* obj = NewFullyAllocatedArrayTryUseGroup(cx, group, nlength); - if (!obj) - return false; - DebugOnly result = - SetOrExtendBoxedOrUnboxedDenseElements(cx, obj, 0, vp, nlength, - ShouldUpdateTypes::Update); - MOZ_ASSERT(result.value == DenseElementResult::Success); - } - objects->maybeAnalyze(cx, group, /* forceAnalyze = */ true); - } - } - return true; -} - -JSObject* +ArrayObject* js::NewCopiedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, const Value* vp, size_t length, NewObjectKind newKind, ShouldUpdateTypes updateTypes) { - if (!MaybeAnalyzeBeforeCreatingLargeArray(cx, group, vp, length)) - return nullptr; - - JSObject* obj = NewFullyAllocatedArrayTryUseGroup(cx, group, length, newKind); + ArrayObject* obj = NewFullyAllocatedArrayTryUseGroup(cx, group, length, newKind); if (!obj) return nullptr; @@ -3722,7 +3690,7 @@ js::NewCopiedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, return obj; } -JSObject* +ArrayObject* js::NewCopiedArrayForCallingAllocationSite(JSContext* cx, const Value* vp, size_t length, HandleObject proto /* = nullptr */) { diff --git a/js/src/jsarray.h b/js/src/jsarray.h index e22cde881..ecde87c3b 100644 --- a/js/src/jsarray.h +++ b/js/src/jsarray.h @@ -72,30 +72,30 @@ extern ArrayObject* NewDenseFullyAllocatedArrayWithTemplate(JSContext* cx, uint32_t length, JSObject* templateObject); /* Create a dense array with the same copy-on-write elements as another object. */ -extern JSObject* +extern ArrayObject* NewDenseCopyOnWriteArray(JSContext* cx, HandleArrayObject templateObject, gc::InitialHeap heap); // The methods below can create either boxed or unboxed arrays. -extern JSObject* +extern ArrayObject* NewFullyAllocatedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length, NewObjectKind newKind = GenericObject); -extern JSObject* +extern ArrayObject* NewPartlyAllocatedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length); -extern JSObject* +extern ArrayObject* NewFullyAllocatedArrayTryReuseGroup(JSContext* cx, JSObject* obj, size_t length, NewObjectKind newKind = GenericObject); -extern JSObject* +extern ArrayObject* NewPartlyAllocatedArrayTryReuseGroup(JSContext* cx, JSObject* obj, size_t length); -extern JSObject* +extern ArrayObject* NewFullyAllocatedArrayForCallingAllocationSite(JSContext* cx, size_t length, NewObjectKind newKind = GenericObject); -extern JSObject* +extern ArrayObject* NewPartlyAllocatedArrayForCallingAllocationSite(JSContext* cx, size_t length, HandleObject proto); enum class ShouldUpdateTypes @@ -104,17 +104,13 @@ enum class ShouldUpdateTypes DontUpdate }; -extern bool -MaybeAnalyzeBeforeCreatingLargeArray(ExclusiveContext* cx, HandleObjectGroup group, - const Value* vp, size_t length); - -extern JSObject* +extern ArrayObject* NewCopiedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, const Value* vp, size_t length, NewObjectKind newKind = GenericObject, ShouldUpdateTypes updateTypes = ShouldUpdateTypes::Update); -extern JSObject* +extern ArrayObject* NewCopiedArrayForCallingAllocationSite(JSContext* cx, const Value* vp, size_t length, HandleObject proto = nullptr); @@ -202,7 +198,7 @@ array_splice(JSContext* cx, unsigned argc, js::Value* vp); extern bool NewbornArrayPush(JSContext* cx, HandleObject obj, const Value& v); -extern JSObject* +extern ArrayObject* ArrayConstructorOneArg(JSContext* cx, HandleObjectGroup group, int32_t lengthInt); #ifdef DEBUG diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index 7765b1197..d7db5129d 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -2369,7 +2369,7 @@ js::str_replace_string_raw(JSContext* cx, HandleString string, HandleString patt } // ES 2016 draft Mar 25, 2016 21.1.3.17 steps 4, 8, 12-18. -static JSObject* +static ArrayObject* SplitHelper(JSContext* cx, HandleLinearString str, uint32_t limit, HandleLinearString sep, HandleObjectGroup group) { @@ -2466,7 +2466,7 @@ SplitHelper(JSContext* cx, HandleLinearString str, uint32_t limit, HandleLinearS } // Fast-path for splitting a string into a character array via split(""). -static JSObject* +static ArrayObject* CharSplitHelper(JSContext* cx, HandleLinearString str, uint32_t limit, HandleObjectGroup group) { size_t strLength = str->length(); @@ -2491,7 +2491,7 @@ CharSplitHelper(JSContext* cx, HandleLinearString str, uint32_t limit, HandleObj } // ES 2016 draft Mar 25, 2016 21.1.3.17 steps 4, 8, 12-18. -JSObject* +ArrayObject* js::str_split_string(JSContext* cx, HandleObjectGroup group, HandleString str, HandleString sep, uint32_t limit) { diff --git a/js/src/jsstr.h b/js/src/jsstr.h index 38fbfa85e..68175c826 100644 --- a/js/src/jsstr.h +++ b/js/src/jsstr.h @@ -465,7 +465,7 @@ FileEscapedString(FILE* fp, const char* chars, size_t length, uint32_t quote) return res; } -JSObject* +ArrayObject* str_split_string(JSContext* cx, HandleObjectGroup group, HandleString str, HandleString sep, uint32_t limit); diff --git a/js/src/vm/JSONParser.cpp b/js/src/vm/JSONParser.cpp index 01883bb15..e50da3bc4 100644 --- a/js/src/vm/JSONParser.cpp +++ b/js/src/vm/JSONParser.cpp @@ -606,8 +606,8 @@ JSONParserBase::finishArray(MutableHandleValue vp, ElementVector& elements) { MOZ_ASSERT(&elements == &stack.back().elements()); - JSObject* obj = ObjectGroup::newArrayObject(cx, elements.begin(), elements.length(), - GenericObject); + ArrayObject* obj = ObjectGroup::newArrayObject(cx, elements.begin(), elements.length(), + GenericObject); if (!obj) return false; diff --git a/js/src/vm/ObjectGroup.cpp b/js/src/vm/ObjectGroup.cpp index a227b7c9c..c2866f5ae 100644 --- a/js/src/vm/ObjectGroup.cpp +++ b/js/src/vm/ObjectGroup.cpp @@ -774,7 +774,7 @@ GetValueTypeForTable(const Value& v) return type; } -/* static */ JSObject* +/* static */ ArrayObject* ObjectGroup::newArrayObject(ExclusiveContext* cx, const Value* vp, size_t length, NewObjectKind newKind, NewArrayKind arrayKind) @@ -854,11 +854,8 @@ ObjectGroup::newArrayObject(ExclusiveContext* cx, } // The type of the elements being added will already be reflected in type - // information, but make sure when creating an unboxed array that the - // common element type is suitable for the unboxed representation. + // information. ShouldUpdateTypes updateTypes = ShouldUpdateTypes::DontUpdate; - if (!MaybeAnalyzeBeforeCreatingLargeArray(cx, group, vp, length)) - return nullptr; if (group->maybePreliminaryObjects()) group->maybePreliminaryObjects()->maybeAnalyze(cx, group); diff --git a/js/src/vm/ObjectGroup.h b/js/src/vm/ObjectGroup.h index 4e24de9f1..553cb8366 100644 --- a/js/src/vm/ObjectGroup.h +++ b/js/src/vm/ObjectGroup.h @@ -505,11 +505,11 @@ class ObjectGroup : public gc::TenuredCell UnknownIndex // Make an array with an unknown element type. }; - // Create an ArrayObject or UnboxedArrayObject with the specified elements - // and a group specialized for the elements. - static JSObject* newArrayObject(ExclusiveContext* cx, const Value* vp, size_t length, - NewObjectKind newKind, - NewArrayKind arrayKind = NewArrayKind::Normal); + // Create an ArrayObject with the specified elements and a group specialized + // for the elements. + static ArrayObject* newArrayObject(ExclusiveContext* cx, const Value* vp, size_t length, + NewObjectKind newKind, + NewArrayKind arrayKind = NewArrayKind::Normal); // Create a PlainObject or UnboxedPlainObject with the specified properties // and a group specialized for those properties. diff --git a/js/src/vm/Stack.cpp b/js/src/vm/Stack.cpp index 87e95c893..c5f2cf5f3 100644 --- a/js/src/vm/Stack.cpp +++ b/js/src/vm/Stack.cpp @@ -82,7 +82,7 @@ InterpreterFrame::isNonGlobalEvalFrame() const return isEvalFrame() && script()->bodyScope()->as().isNonGlobal(); } -JSObject* +ArrayObject* InterpreterFrame::createRestParameter(JSContext* cx) { MOZ_ASSERT(script()->hasRest()); diff --git a/js/src/vm/Stack.h b/js/src/vm/Stack.h index 552738d89..dc9306c99 100644 --- a/js/src/vm/Stack.h +++ b/js/src/vm/Stack.h @@ -523,7 +523,7 @@ class InterpreterFrame ArgumentsObject& argsObj() const; void initArgsObj(ArgumentsObject& argsobj); - JSObject* createRestParameter(JSContext* cx); + ArrayObject* createRestParameter(JSContext* cx); /* * Environment chain -- cgit v1.2.3