mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-29 11:57:32 +09:00
1344477 - Part 2: Optimize Array.prototype.splice with JSOP_NORVCALL.
This commit is contained in:
parent
417aa02122
commit
4f51cc381d
16 changed files with 28 additions and 149 deletions
|
|
@ -4440,19 +4440,6 @@ CodeGenerator::visitApplyArrayGeneric(LApplyArrayGeneric* apply)
|
|||
emitApplyGeneric(apply);
|
||||
}
|
||||
|
||||
typedef bool (*ArraySpliceDenseFn)(JSContext*, HandleObject, uint32_t, uint32_t);
|
||||
static const VMFunction ArraySpliceDenseInfo =
|
||||
FunctionInfo<ArraySpliceDenseFn>(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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@
|
|||
_(ArrayShift) \
|
||||
_(ArrayPush) \
|
||||
_(ArraySlice) \
|
||||
_(ArraySplice) \
|
||||
\
|
||||
_(AtomicsCompareExchange) \
|
||||
_(AtomicsExchange) \
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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<ObjectPolicy<0>, 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>,
|
||||
|
|
|
|||
|
|
@ -69,7 +69,6 @@ namespace jit {
|
|||
_(Call) \
|
||||
_(ApplyArgs) \
|
||||
_(ApplyArray) \
|
||||
_(ArraySplice) \
|
||||
_(Bail) \
|
||||
_(Unreachable) \
|
||||
_(EncodeSnapshot) \
|
||||
|
|
|
|||
|
|
@ -303,18 +303,6 @@ StringsEqual(JSContext* cx, HandleString lhs, HandleString rhs, bool* res)
|
|||
template bool StringsEqual<true>(JSContext* cx, HandleString lhs, HandleString rhs, bool* res);
|
||||
template bool StringsEqual<false>(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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -2221,34 +2221,6 @@ class LApplyArrayGeneric : public LCallInstructionHelper<BOX_PIECES, BOX_PIECES
|
|||
}
|
||||
};
|
||||
|
||||
class LArraySplice : public LCallInstructionHelper<0, 3, 0>
|
||||
{
|
||||
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<BOX_PIECES, 2, 3>
|
||||
{
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -69,7 +69,6 @@
|
|||
_(NewArrayDynamicLength) \
|
||||
_(NewTypedArray) \
|
||||
_(NewTypedArrayDynamicLength) \
|
||||
_(ArraySplice) \
|
||||
_(NewObject) \
|
||||
_(NewTypedObject) \
|
||||
_(NewNamedLambdaObject) \
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue