Bug 1344477 - Part 2: Optimize Array.prototype.splice with JSOP_NORVCALL. r=jandem

This commit is contained in:
Tooru Fujisawa 2017-03-19 14:16:36 +09:00
Родитель 7f556ef14e
Коммит 32cff5d448
16 изменённых файлов: 28 добавлений и 148 удалений

Просмотреть файл

@ -4666,19 +4666,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)
{

Просмотреть файл

@ -258,7 +258,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) \

Просмотреть файл

@ -627,7 +627,6 @@ class IonBuilder
InliningResult inlineArrayPush(CallInfo& callInfo);
InliningResult inlineArraySlice(CallInfo& callInfo);
InliningResult inlineArrayJoin(CallInfo& callInfo);
InliningResult inlineArraySplice(CallInfo& callInfo);
// Math natives.
InliningResult inlineMathAbs(CallInfo& callInfo);

Просмотреть файл

@ -655,16 +655,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);

Просмотреть файл

@ -87,8 +87,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:
@ -667,45 +665,6 @@ IonBuilder::inlineArrayPopShift(CallInfo& callInfo, MArrayPopShift::Mode mode)
return InliningStatus_Inlined;
}
IonBuilder::InliningResult
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());
MOZ_TRY(resumeAfter(ins));
return InliningStatus_Inlined;
}
IonBuilder::InliningResult
IonBuilder::inlineArrayJoin(CallInfo& callInfo)
{

Просмотреть файл

@ -4224,27 +4224,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) \

Просмотреть файл

@ -323,18 +323,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)
{

Просмотреть файл

@ -767,9 +767,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

Просмотреть файл

@ -2233,34 +2233,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) \

Просмотреть файл

@ -2482,13 +2482,6 @@ CanOptimizeForDenseStorage(HandleObject arr, uint32_t startingIndex, uint32_t co
startingIndex + count <= GetAnyBoxedOrUnboxedInitializedLength(arr);
}
/* 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)
@ -2518,8 +2511,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)
{
AutoGeckoProfilerEntry pseudoFrame(cx->runtime(), "Array.prototype.splice");
CallArgs args = CallArgsFromVp(argc, vp);
@ -2763,6 +2756,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) {
@ -3177,6 +3183,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),
@ -3192,7 +3207,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),

Просмотреть файл

@ -165,9 +165,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);
@ -192,6 +189,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

Просмотреть файл

@ -2306,7 +2306,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),