From 85aeff765ea921ea2c947fa9d68756eb989b6287 Mon Sep 17 00:00:00 2001 From: Gaming4JC Date: Sun, 14 Jul 2019 19:04:52 -0400 Subject: 1344477 - Part 2: Optimize Array.prototype.splice with JSOP_NORVCALL. --- js/src/jit/CodeGenerator.cpp | 13 ------------ js/src/jit/CodeGenerator.h | 1 - js/src/jit/InlinableNatives.h | 1 - js/src/jit/IonBuilder.h | 1 - js/src/jit/Lowering.cpp | 10 --------- js/src/jit/Lowering.h | 1 - js/src/jit/MCallOptimize.cpp | 42 ------------------------------------- js/src/jit/MIR.h | 21 ------------------- js/src/jit/MOpcodes.h | 1 - js/src/jit/VMFunctions.cpp | 12 ----------- js/src/jit/VMFunctions.h | 3 --- js/src/jit/shared/LIR-shared.h | 28 ------------------------- js/src/jit/shared/LOpcodes-shared.h | 1 - js/src/jsarray.cpp | 35 ++++++++++++++++++++++--------- js/src/jsarray.h | 5 ++--- js/src/vm/SelfHosting.cpp | 2 +- 16 files changed, 28 insertions(+), 149 deletions(-) (limited to 'js') diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp index 114fc96b3..205812942 100644 --- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -4440,19 +4440,6 @@ CodeGenerator::visitApplyArrayGeneric(LApplyArrayGeneric* apply) emitApplyGeneric(apply); } -typedef bool (*ArraySpliceDenseFn)(JSContext*, HandleObject, uint32_t, uint32_t); -static const VMFunction ArraySpliceDenseInfo = - FunctionInfo(ArraySpliceDense, "ArraySpliceDense"); - -void -CodeGenerator::visitArraySplice(LArraySplice* lir) -{ - pushArg(ToRegister(lir->getDeleteCount())); - pushArg(ToRegister(lir->getStart())); - pushArg(ToRegister(lir->getObject())); - callVM(ArraySpliceDenseInfo, lir); -} - void CodeGenerator::visitBail(LBail* lir) { diff --git a/js/src/jit/CodeGenerator.h b/js/src/jit/CodeGenerator.h index 1c9a7e89b..12f1238ef 100644 --- a/js/src/jit/CodeGenerator.h +++ b/js/src/jit/CodeGenerator.h @@ -251,7 +251,6 @@ class CodeGenerator final : public CodeGeneratorSpecific void emitSetPropertyPolymorphic(LInstruction* lir, Register obj, Register scratch, const ConstantOrRegister& value); void visitSetPropertyPolymorphicV(LSetPropertyPolymorphicV* ins); - void visitArraySplice(LArraySplice* splice); void visitSetPropertyPolymorphicT(LSetPropertyPolymorphicT* ins); void visitAbsI(LAbsI* lir); void visitAtan2D(LAtan2D* lir); diff --git a/js/src/jit/InlinableNatives.h b/js/src/jit/InlinableNatives.h index 18535389a..1d0506f74 100644 --- a/js/src/jit/InlinableNatives.h +++ b/js/src/jit/InlinableNatives.h @@ -15,7 +15,6 @@ _(ArrayShift) \ _(ArrayPush) \ _(ArraySlice) \ - _(ArraySplice) \ \ _(AtomicsCompareExchange) \ _(AtomicsExchange) \ diff --git a/js/src/jit/IonBuilder.h b/js/src/jit/IonBuilder.h index 9e40b3959..1f763a4f2 100644 --- a/js/src/jit/IonBuilder.h +++ b/js/src/jit/IonBuilder.h @@ -821,7 +821,6 @@ class IonBuilder InliningStatus inlineArrayPush(CallInfo& callInfo); InliningStatus inlineArraySlice(CallInfo& callInfo); InliningStatus inlineArrayJoin(CallInfo& callInfo); - InliningStatus inlineArraySplice(CallInfo& callInfo); // Math natives. InliningStatus inlineMathAbs(CallInfo& callInfo); diff --git a/js/src/jit/Lowering.cpp b/js/src/jit/Lowering.cpp index 68417138b..22f1d5f70 100644 --- a/js/src/jit/Lowering.cpp +++ b/js/src/jit/Lowering.cpp @@ -656,16 +656,6 @@ LIRGenerator::visitAssertRecoveredOnBailout(MAssertRecoveredOnBailout* assertion MOZ_CRASH("AssertRecoveredOnBailout nodes are always recovered on bailouts."); } -void -LIRGenerator::visitArraySplice(MArraySplice* ins) -{ - LArraySplice* lir = new(alloc()) LArraySplice(useRegisterAtStart(ins->object()), - useRegisterAtStart(ins->start()), - useRegisterAtStart(ins->deleteCount())); - add(lir, ins); - assignSafepoint(lir, ins); -} - void LIRGenerator::visitGetDynamicName(MGetDynamicName* ins) { diff --git a/js/src/jit/Lowering.h b/js/src/jit/Lowering.h index b096bb143..9342ef471 100644 --- a/js/src/jit/Lowering.h +++ b/js/src/jit/Lowering.h @@ -107,7 +107,6 @@ class LIRGenerator : public LIRGeneratorSpecific void visitCall(MCall* call); void visitApplyArgs(MApplyArgs* apply); void visitApplyArray(MApplyArray* apply); - void visitArraySplice(MArraySplice* splice); void visitBail(MBail* bail); void visitUnreachable(MUnreachable* unreachable); void visitEncodeSnapshot(MEncodeSnapshot* ins); diff --git a/js/src/jit/MCallOptimize.cpp b/js/src/jit/MCallOptimize.cpp index 359f04639..5eee30e49 100644 --- a/js/src/jit/MCallOptimize.cpp +++ b/js/src/jit/MCallOptimize.cpp @@ -85,8 +85,6 @@ IonBuilder::inlineNativeCall(CallInfo& callInfo, JSFunction* target) return inlineArrayPush(callInfo); case InlinableNative::ArraySlice: return inlineArraySlice(callInfo); - case InlinableNative::ArraySplice: - return inlineArraySplice(callInfo); // Atomic natives. case InlinableNative::AtomicsCompareExchange: @@ -653,46 +651,6 @@ IonBuilder::inlineArrayPopShift(CallInfo& callInfo, MArrayPopShift::Mode mode) return InliningStatus_Inlined; } -IonBuilder::InliningStatus -IonBuilder::inlineArraySplice(CallInfo& callInfo) -{ - if (callInfo.argc() != 2 || callInfo.constructing()) { - trackOptimizationOutcome(TrackedOutcome::CantInlineNativeBadForm); - return InliningStatus_NotInlined; - } - - // Ensure |this|, argument and result are objects. - if (getInlineReturnType() != MIRType::Object) - return InliningStatus_NotInlined; - if (callInfo.thisArg()->type() != MIRType::Object) - return InliningStatus_NotInlined; - if (callInfo.getArg(0)->type() != MIRType::Int32) - return InliningStatus_NotInlined; - if (callInfo.getArg(1)->type() != MIRType::Int32) - return InliningStatus_NotInlined; - - callInfo.setImplicitlyUsedUnchecked(); - - // Specialize arr.splice(start, deleteCount) with unused return value and - // avoid creating the result array in this case. - if (!BytecodeIsPopped(pc)) { - trackOptimizationOutcome(TrackedOutcome::CantInlineGeneric); - return InliningStatus_NotInlined; - } - - MArraySplice* ins = MArraySplice::New(alloc(), - callInfo.thisArg(), - callInfo.getArg(0), - callInfo.getArg(1)); - - current->add(ins); - pushConstant(UndefinedValue()); - - if (!resumeAfter(ins)) - return InliningStatus_Error; - return InliningStatus_Inlined; -} - IonBuilder::InliningStatus IonBuilder::inlineArrayJoin(CallInfo& callInfo) { diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h index ac55b1150..6c376d528 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -4186,27 +4186,6 @@ class MCallDOMNative : public MCall virtual void computeMovable() override; }; -// arr.splice(start, deleteCount) with unused return value. -class MArraySplice - : public MTernaryInstruction, - public Mix3Policy, IntPolicy<1>, IntPolicy<2> >::Data -{ - private: - - MArraySplice(MDefinition* object, MDefinition* start, MDefinition* deleteCount) - : MTernaryInstruction(object, start, deleteCount) - { } - - public: - INSTRUCTION_HEADER(ArraySplice) - TRIVIAL_NEW_WRAPPERS - NAMED_OPERANDS((0, object), (1, start), (2, deleteCount)) - - bool possiblyCalls() const override { - return true; - } -}; - // fun.apply(self, arguments) class MApplyArgs : public MAryInstruction<3>, diff --git a/js/src/jit/MOpcodes.h b/js/src/jit/MOpcodes.h index ab37604b4..9e460a2ba 100644 --- a/js/src/jit/MOpcodes.h +++ b/js/src/jit/MOpcodes.h @@ -69,7 +69,6 @@ namespace jit { _(Call) \ _(ApplyArgs) \ _(ApplyArray) \ - _(ArraySplice) \ _(Bail) \ _(Unreachable) \ _(EncodeSnapshot) \ diff --git a/js/src/jit/VMFunctions.cpp b/js/src/jit/VMFunctions.cpp index e58c3f570..1ff7adfd1 100644 --- a/js/src/jit/VMFunctions.cpp +++ b/js/src/jit/VMFunctions.cpp @@ -303,18 +303,6 @@ StringsEqual(JSContext* cx, HandleString lhs, HandleString rhs, bool* res) template bool StringsEqual(JSContext* cx, HandleString lhs, HandleString rhs, bool* res); template bool StringsEqual(JSContext* cx, HandleString lhs, HandleString rhs, bool* res); -bool -ArraySpliceDense(JSContext* cx, HandleObject obj, uint32_t start, uint32_t deleteCount) -{ - JS::AutoValueArray<4> argv(cx); - argv[0].setUndefined(); - argv[1].setObject(*obj); - argv[2].set(Int32Value(start)); - argv[3].set(Int32Value(deleteCount)); - - return js::array_splice_impl(cx, 2, argv.begin(), false); -} - bool ArrayPopDense(JSContext* cx, HandleObject obj, MutableHandleValue rval) { diff --git a/js/src/jit/VMFunctions.h b/js/src/jit/VMFunctions.h index bd65df134..94f741397 100644 --- a/js/src/jit/VMFunctions.h +++ b/js/src/jit/VMFunctions.h @@ -738,9 +738,6 @@ InitBaselineFrameForOsr(BaselineFrame* frame, InterpreterFrame* interpFrame, JSObject* CreateDerivedTypedObj(JSContext* cx, HandleObject descr, HandleObject owner, int32_t offset); -MOZ_MUST_USE bool -ArraySpliceDense(JSContext* cx, HandleObject obj, uint32_t start, uint32_t deleteCount); - MOZ_MUST_USE bool Recompile(JSContext* cx); MOZ_MUST_USE bool diff --git a/js/src/jit/shared/LIR-shared.h b/js/src/jit/shared/LIR-shared.h index 2b242d2e4..ecf02816e 100644 --- a/js/src/jit/shared/LIR-shared.h +++ b/js/src/jit/shared/LIR-shared.h @@ -2221,34 +2221,6 @@ class LApplyArrayGeneric : public LCallInstructionHelper -{ - public: - LIR_HEADER(ArraySplice) - - LArraySplice(const LAllocation& object, const LAllocation& start, - const LAllocation& deleteCount) - { - setOperand(0, object); - setOperand(1, start); - setOperand(2, deleteCount); - } - - MArraySplice* mir() const { - return mir_->toArraySplice(); - } - - const LAllocation* getObject() { - return getOperand(0); - } - const LAllocation* getStart() { - return getOperand(1); - } - const LAllocation* getDeleteCount() { - return getOperand(2); - } -}; - class LGetDynamicName : public LCallInstructionHelper { public: diff --git a/js/src/jit/shared/LOpcodes-shared.h b/js/src/jit/shared/LOpcodes-shared.h index deae92839..e260d7e94 100644 --- a/js/src/jit/shared/LOpcodes-shared.h +++ b/js/src/jit/shared/LOpcodes-shared.h @@ -69,7 +69,6 @@ _(NewArrayDynamicLength) \ _(NewTypedArray) \ _(NewTypedArrayDynamicLength) \ - _(ArraySplice) \ _(NewObject) \ _(NewTypedObject) \ _(NewNamedLambdaObject) \ diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index 33ff67f36..e618c319f 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -2380,13 +2380,6 @@ CopyDenseElements(JSContext* cx, NativeObject* dst, NativeObject* src, return DenseElementResult::Success; } -/* ES 2016 draft Mar 25, 2016 22.1.3.26. */ -bool -js::array_splice(JSContext* cx, unsigned argc, Value* vp) -{ - return array_splice_impl(cx, argc, vp, true); -} - static inline bool ArraySpliceCopy(JSContext* cx, HandleObject arr, HandleObject obj, uint32_t actualStart, uint32_t actualDeleteCount) @@ -2416,8 +2409,8 @@ ArraySpliceCopy(JSContext* cx, HandleObject arr, HandleObject obj, return SetLengthProperty(cx, arr, actualDeleteCount); } -bool -js::array_splice_impl(JSContext* cx, unsigned argc, Value* vp, bool returnValueIsUsed) +static bool +array_splice_impl(JSContext* cx, unsigned argc, Value* vp, bool returnValueIsUsed) { AutoSPSEntry pseudoFrame(cx->runtime(), "Array.prototype.splice"); CallArgs args = CallArgsFromVp(argc, vp); @@ -2667,6 +2660,19 @@ js::array_splice_impl(JSContext* cx, unsigned argc, Value* vp, bool returnValueI return true; } +/* ES 2016 draft Mar 25, 2016 22.1.3.26. */ +bool +js::array_splice(JSContext* cx, unsigned argc, Value* vp) +{ + return array_splice_impl(cx, argc, vp, true); +} + +static bool +array_splice_noRetVal(JSContext* cx, unsigned argc, Value* vp) +{ + return array_splice_impl(cx, argc, vp, false); +} + struct SortComparatorIndexes { bool operator()(uint32_t a, uint32_t b, bool* lessOrEqualp) { @@ -3084,6 +3090,15 @@ array_of(JSContext* cx, unsigned argc, Value* vp) return true; } +const JSJitInfo js::array_splice_info = { + { (JSJitGetterOp)array_splice_noRetVal }, + { 0 }, /* unused */ + { 0 }, /* unused */ + JSJitInfo::IgnoresReturnValueNative, + JSJitInfo::AliasEverything, + JSVAL_TYPE_UNDEFINED, +}; + static const JSFunctionSpec array_methods[] = { #if JS_HAS_TOSOURCE JS_FN(js_toSource_str, array_toSource, 0,0), @@ -3099,7 +3114,7 @@ static const JSFunctionSpec array_methods[] = { JS_INLINABLE_FN("pop", array_pop, 0,0, ArrayPop), JS_INLINABLE_FN("shift", array_shift, 0,0, ArrayShift), JS_FN("unshift", array_unshift, 1,0), - JS_INLINABLE_FN("splice", array_splice, 2,0, ArraySplice), + JS_FNINFO("splice", array_splice, &array_splice_info, 2,0), /* Pythonic sequence methods. */ JS_SELF_HOSTED_FN("concat", "ArrayConcat", 1,0), diff --git a/js/src/jsarray.h b/js/src/jsarray.h index 00b475a8e..d0084731f 100644 --- a/js/src/jsarray.h +++ b/js/src/jsarray.h @@ -146,9 +146,6 @@ array_push(JSContext* cx, unsigned argc, js::Value* vp); extern bool array_pop(JSContext* cx, unsigned argc, js::Value* vp); -extern bool -array_splice_impl(JSContext* cx, unsigned argc, js::Value* vp, bool pop); - extern bool array_join(JSContext* cx, unsigned argc, js::Value* vp); @@ -173,6 +170,8 @@ array_reverse(JSContext* cx, unsigned argc, js::Value* vp); extern bool array_splice(JSContext* cx, unsigned argc, js::Value* vp); +extern const JSJitInfo array_splice_info; + /* * Append the given (non-hole) value to the end of an array. The array must be * a newborn array -- that is, one which has not been exposed to script for diff --git a/js/src/vm/SelfHosting.cpp b/js/src/vm/SelfHosting.cpp index 2ff20cfea..792a00490 100644 --- a/js/src/vm/SelfHosting.cpp +++ b/js/src/vm/SelfHosting.cpp @@ -2154,7 +2154,7 @@ static const JSFunctionSpec intrinsic_functions[] = { JS_INLINABLE_FN("std_Array_slice", array_slice, 2,0, ArraySlice), JS_FN("std_Array_sort", array_sort, 1,0), JS_FN("std_Array_reverse", array_reverse, 0,0), - JS_INLINABLE_FN("std_Array_splice", array_splice, 2,0, ArraySplice), + JS_FNINFO("std_Array_splice", array_splice, &array_splice_info, 2,0), JS_FN("std_Date_now", date_now, 0,0), JS_FN("std_Date_valueOf", date_valueOf, 0,0), -- cgit v1.2.3