Bug 989348 - BaselineCompiler: Optimize JSOP_ARRAYPUSH. r=djvj

This commit is contained in:
Sankha Narayan Guria 2014-07-04 13:54:34 +02:00
parent 22af9b2a16
commit 49b3d9bb1a
3 changed files with 183 additions and 9 deletions

View File

@ -1790,22 +1790,34 @@ BaselineCompiler::emit_JSOP_ENDINIT()
return true;
}
typedef bool (*NewbornArrayPushFn)(JSContext *, HandleObject, const Value &);
static const VMFunction NewbornArrayPushInfo = FunctionInfo<NewbornArrayPushFn>(NewbornArrayPush);
bool
BaselineCompiler::emit_JSOP_ARRAYPUSH()
{
// Keep value in R0, object in R1.
frame.popRegsAndSync(2);
#ifdef DEBUG
{
Label fail;
Label ok;
// Stub register is unused in mainline code, so we can use it as
// scratch
Register scratchReg = BaselineStubReg;
masm.branchTestObject(Assembler::NotEqual, R1, &fail);
Register objReg = masm.extractObject(R1, ExtractTemp0);
masm.branchTestObjClass(Assembler::Equal, objReg, scratchReg, &ArrayObject::class_, &ok);
masm.bind(&fail);
masm.assumeUnreachable("JSOP_ARRAYPUSH operand 1 is not an array.");
masm.bind(&ok);
}
#endif
// R1 is guaranteed to be a boxed Array object
masm.unboxObject(R1, R1.scratchReg());
prepareVMCall();
pushArg(R0);
pushArg(R1.scratchReg());
return callVM(NewbornArrayPushInfo);
// Call IC.
ICArrayPush_Fallback::Compiler stubCompiler(cx);
return emitOpIC(stubCompiler.getStub(&stubSpace_));
}
bool

View File

@ -9655,6 +9655,102 @@ ICTableSwitch::fixupJumpTable(JSScript *script, BaselineScript *baseline)
table_[i] = baseline->nativeCodeForPC(script, (jsbytecode *) table_[i]);
}
//
// ArrayPush_Fallback
//
static bool
DoArrayPushFallback(JSContext *cx, BaselineFrame *frame, ICArrayPush_Fallback *stub_,
HandleObject obj, HandleValue v)
{
// This fallback stub may trigger debug mode toggling.
DebugModeOSRVolatileStub<ICArrayPush_Fallback *> stub(frame, stub_);
FallbackICSpew(cx, stub, "ArrayPush");
if (!NewbornArrayPush(cx, obj, v))
return false;
// Check if debug mode toggling made the stub invalid.
if (stub.invalid())
return true;
if (!stub->hasStub(ICStub::ArrayPush_Native))
{
ICArrayPush_Native::Compiler compiler(cx);
ICStub *newStub = compiler.getStub(compiler.getStubSpace(frame->script()));
if (!newStub)
return false;
stub->addNewStub(newStub);
}
return true;
}
typedef bool (*DoArrayPushFallbackFn)(JSContext *, BaselineFrame *, ICArrayPush_Fallback *,
HandleObject, HandleValue);
static const VMFunction DoArrayPushFallbackInfo = FunctionInfo<DoArrayPushFallbackFn>(DoArrayPushFallback);
bool
ICArrayPush_Fallback::Compiler::generateStubCode(MacroAssembler &masm)
{
// Restore the tail call register.
EmitRestoreTailCallReg(masm);
// Push arguments.
masm.pushValue(R0);
masm.push(R1.scratchReg());
masm.push(BaselineStubReg);
masm.pushBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
return tailCallVM(DoArrayPushFallbackInfo, masm);
}
//
// ArrayPush_Native
//
bool
ICArrayPush_Native::Compiler::generateStubCode(MacroAssembler &masm)
{
Label failure;
Register obj = R1.scratchReg();
GeneralRegisterSet regs(availableGeneralRegs(1));
regs.take(obj);
Register elementsTemp = regs.takeAny();
Register length = regs.takeAny();
masm.loadPtr(Address(obj, JSObject::offsetOfElements()), elementsTemp);
masm.load32(Address(elementsTemp, ObjectElements::offsetOfLength()), length);
#ifdef DEBUG
{
Label ok;
masm.branch32(Assembler::Equal,
Address(elementsTemp,
ObjectElements::offsetOfInitializedLength()),
length,
&ok);
masm.assumeUnreachable("ArrayPush array length != initializedLength");
masm.bind(&ok);
}
#endif
masm.branch32(Assembler::BelowOrEqual,
Address(elementsTemp, ObjectElements::offsetOfCapacity()),
length, &failure);
Int32Key key = Int32Key(length);
JS_STATIC_ASSERT(sizeof(Value) == 8);
masm.storeValue(R0, BaseIndex(elementsTemp, length, TimesEight));
masm.bumpKey(&key, 1);
masm.store32(length, Address(elementsTemp, ObjectElements::offsetOfLength()));
masm.store32(length, Address(elementsTemp, ObjectElements::offsetOfInitializedLength()));
EmitReturnFromIC(masm);
masm.bind(&failure);
EmitStubGuardFailure(masm);
return true;
}
//
// IteratorNew_Fallback
//

View File

@ -377,6 +377,9 @@ class ICEntry
_(Call_ScriptedApplyArguments) \
_(Call_ScriptedFunCall) \
\
_(ArrayPush_Fallback) \
_(ArrayPush_Native) \
\
_(GetElem_Fallback) \
_(GetElem_NativeSlot) \
_(GetElem_NativePrototypeSlot) \
@ -2899,6 +2902,69 @@ class ICUnaryArith_Double : public ICStub
};
};
// ArrayPush
// JSOP_ARRAYPUSH
class ICArrayPush_Fallback : public ICFallbackStub
{
friend class ICStubSpace;
explicit ICArrayPush_Fallback(JitCode *stubCode)
: ICFallbackStub(ArrayPush_Fallback, stubCode)
{}
public:
static inline ICArrayPush_Fallback *New(ICStubSpace *space, JitCode *code) {
if (!code)
return nullptr;
return space->allocate<ICArrayPush_Fallback>(code);
}
class Compiler : public ICStubCompiler {
protected:
bool generateStubCode(MacroAssembler &masm);
public:
Compiler(JSContext *cx)
: ICStubCompiler(cx, ICStub::ArrayPush_Fallback)
{}
ICStub *getStub(ICStubSpace *space) {
return ICArrayPush_Fallback::New(space, getStubCode());
}
};
};
class ICArrayPush_Native : public ICStub
{
friend class ICStubSpace;
explicit ICArrayPush_Native(JitCode *stubCode)
: ICStub(ArrayPush_Native, stubCode)
{}
public:
static inline ICArrayPush_Native *New(ICStubSpace *space, JitCode *code) {
if (!code)
return nullptr;
return space->allocate<ICArrayPush_Native>(code);
}
class Compiler : public ICStubCompiler {
protected:
bool generateStubCode(MacroAssembler &masm);
public:
Compiler(JSContext *cx)
: ICStubCompiler(cx, ICStub::ArrayPush_Native)
{}
ICStub *getStub(ICStubSpace *space) {
return ICArrayPush_Native::New(space, getStubCode());
}
};
};
// GetElem
// JSOP_GETELEM