mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 11:25:00 +00:00
Bug 824473: IonMonkey: Enable inlining of JSOP_FUNAPPLY, r=dvander
This commit is contained in:
parent
8b45633296
commit
ceda8b6153
@ -179,7 +179,12 @@ StackFrame::initFromBailout(JSContext *cx, SnapshotIterator &iter)
|
||||
|
||||
IonSpew(IonSpew_Bailouts, " new PC is offset %u within script %p (line %d)",
|
||||
pcOff, (void *)script(), PCToLineNumber(script(), regs.pc));
|
||||
JS_ASSERT(exprStackSlots == js_ReconstructStackDepth(cx, script(), regs.pc));
|
||||
|
||||
// For fun.apply({}, arguments) the reconstructStackDepth will have stackdepth 4,
|
||||
// but it could be that we inlined the funapply. In that case exprStackSlots,
|
||||
// will have the real arguments in the slots and not be 4.
|
||||
JS_ASSERT_IF(JSOp(*regs.pc) != JSOP_FUNAPPLY,
|
||||
exprStackSlots == js_ReconstructStackDepth(cx, script(), regs.pc));
|
||||
}
|
||||
|
||||
static StackFrame *
|
||||
@ -192,8 +197,11 @@ PushInlinedFrame(JSContext *cx, StackFrame *callerFrame)
|
||||
// which will not be the case when we inline getters (in which case it would be a
|
||||
// JSOP_GETPROP). That will have to be handled differently.
|
||||
FrameRegs ®s = cx->regs();
|
||||
JS_ASSERT(JSOp(*regs.pc) == JSOP_CALL || JSOp(*regs.pc) == JSOP_NEW);
|
||||
JS_ASSERT(JSOp(*regs.pc) == JSOP_CALL || JSOp(*regs.pc) == JSOP_NEW ||
|
||||
JSOp(*regs.pc) == JSOP_FUNAPPLY);
|
||||
int callerArgc = GET_ARGC(regs.pc);
|
||||
if (JSOp(*regs.pc) == JSOP_FUNAPPLY)
|
||||
callerArgc = callerFrame->nactual();
|
||||
const Value &calleeVal = regs.sp[-callerArgc - 2];
|
||||
|
||||
RootedFunction fun(cx, calleeVal.toObject().toFunction());
|
||||
|
@ -46,6 +46,20 @@ class FixedList
|
||||
length_ -= num;
|
||||
}
|
||||
|
||||
bool increase(size_t num) {
|
||||
T *list = (T *)GetIonContext()->temp->allocate((length_ + num) * sizeof(T));
|
||||
if (list != NULL) {
|
||||
for (size_t i = 0; i < length_; i++)
|
||||
list[i] = list_[i];
|
||||
|
||||
length_ += num;
|
||||
list_ = list;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
T &operator[](size_t index) {
|
||||
JS_ASSERT(index < length_);
|
||||
return list_[index];
|
||||
|
@ -2856,6 +2856,11 @@ IonBuilder::inlineScriptedCall(HandleFunction target, CallInfo &callInfo)
|
||||
// Create resumepoint if not provided. This resume point collects outer variables only.
|
||||
// It is used to recover the stack state before the current bytecode.
|
||||
|
||||
// Make sure there is enough place in the slots
|
||||
uint32_t depth = current->stackDepth() + callInfo.argc() + 2;
|
||||
if (depth > current->nslots())
|
||||
current->increaseSlots(depth - current->nslots());
|
||||
|
||||
// Push formals to capture in the resumepoint
|
||||
callInfo.pushFormals(current);
|
||||
|
||||
@ -3984,8 +3989,22 @@ IonBuilder::jsop_funapplyarguments(uint32_t argc)
|
||||
// Pop apply function.
|
||||
current->pop();
|
||||
|
||||
// Set type information
|
||||
types::StackTypeSet *barrier;
|
||||
types::StackTypeSet *types = oracle->returnTypeSet(script(), pc, &barrier);
|
||||
callInfo.setTypeInfo(types, barrier);
|
||||
|
||||
// Try inlining call
|
||||
if (target != NULL) {
|
||||
AutoObjectVector targets(cx);
|
||||
targets.append(target);
|
||||
|
||||
if (makeInliningDecision(targets, argc))
|
||||
return inlineScriptedCall(target, callInfo);
|
||||
}
|
||||
|
||||
callInfo.wrapArgs(current);
|
||||
return makeCall(target, callInfo, funTypes, false);
|
||||
return makeCallBarrier(target, callInfo, funTypes, false);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -932,7 +932,10 @@ InlineFrameIterator::findNextFrame()
|
||||
JS_ASSERT(js_CodeSpec[*pc_].format & JOF_INVOKE);
|
||||
|
||||
// Recover the number of actual arguments from the script.
|
||||
numActualArgs_ = GET_ARGC(pc_);
|
||||
if (JSOp(*pc_) != JSOP_FUNAPPLY)
|
||||
numActualArgs_ = GET_ARGC(pc_);
|
||||
|
||||
JS_ASSERT(numActualArgs_ != 0xbad);
|
||||
|
||||
// Skip over non-argument slots, as well as |this|.
|
||||
unsigned skipCount = (si_.slots() - 1) - numActualArgs_ - 1;
|
||||
|
@ -155,6 +155,12 @@ MBasicBlock::init()
|
||||
return slots_.init(info_.nslots());
|
||||
}
|
||||
|
||||
bool
|
||||
MBasicBlock::increaseSlots(size_t num)
|
||||
{
|
||||
return slots_.increase(num);
|
||||
}
|
||||
|
||||
void
|
||||
MBasicBlock::copySlots(MBasicBlock *from)
|
||||
{
|
||||
@ -341,7 +347,7 @@ MBasicBlock::rewriteAtDepth(int32_t depth, MDefinition *ins)
|
||||
void
|
||||
MBasicBlock::push(MDefinition *ins)
|
||||
{
|
||||
JS_ASSERT(stackPosition_ < info_.nslots());
|
||||
JS_ASSERT(stackPosition_ < nslots());
|
||||
slots_[stackPosition_++] = ins;
|
||||
}
|
||||
|
||||
|
@ -105,6 +105,9 @@ class MBasicBlock : public TempObject, public InlineListNode<MBasicBlock>
|
||||
|
||||
MDefinition *scopeChain();
|
||||
|
||||
// Increase the number of slots available
|
||||
bool increaseSlots(size_t num);
|
||||
|
||||
// Initializes a slot value; must not be called for normal stack
|
||||
// operations, as it will not create new SSA names for copies.
|
||||
void initSlot(uint32_t index, MDefinition *ins);
|
||||
@ -220,6 +223,9 @@ class MBasicBlock : public TempObject, public InlineListNode<MBasicBlock>
|
||||
jsbytecode *pc() const {
|
||||
return pc_;
|
||||
}
|
||||
uint32_t nslots() const {
|
||||
return slots_.length();
|
||||
}
|
||||
uint32_t id() const {
|
||||
return id_;
|
||||
}
|
||||
|
@ -541,8 +541,12 @@ TypeInferenceOracle::canInlineCall(HandleScript caller, jsbytecode *pc)
|
||||
{
|
||||
JS_ASSERT(types::IsInlinableCall(pc));
|
||||
|
||||
JSOp op = JSOp(*pc);
|
||||
Bytecode *code = caller->analysis()->maybeCode(pc);
|
||||
if (code->monitoredTypes)
|
||||
|
||||
// For foo.apply(this, arguments), the caller is foo and not the js_fun_apply function.
|
||||
// Ignore code->monitoredTypes, as we know the caller is foo
|
||||
if (op != JSOP_FUNAPPLY && code->monitoredTypes)
|
||||
return false;
|
||||
|
||||
// Gets removed in Bug 796114
|
||||
|
@ -223,7 +223,11 @@ CodeGeneratorShared::encode(LSnapshot *snapshot)
|
||||
DebugOnly<jsbytecode *> bailPC = pc;
|
||||
if (mir->mode() == MResumePoint::ResumeAfter)
|
||||
bailPC = GetNextPc(pc);
|
||||
JS_ASSERT_IF(GetIonContext()->cx,
|
||||
|
||||
// For fun.apply({}, arguments) the reconstructStackDepth will have stackdepth 4,
|
||||
// but it could be that we inlined the funapply. In that case exprStackSlots,
|
||||
// will have the real arguments in the slots and not be 4.
|
||||
JS_ASSERT_IF(GetIonContext()->cx && JSOp(*bailPC) != JSOP_FUNAPPLY,
|
||||
exprStack == js_ReconstructStackDepth(GetIonContext()->cx, script, bailPC));
|
||||
|
||||
#ifdef TRACK_SNAPSHOTS
|
||||
|
@ -433,6 +433,7 @@ class StackFrame
|
||||
Value *base() const { return slots() + script()->nfixed; }
|
||||
Value *formals() const { return (Value *)this - fun()->nargs; }
|
||||
Value *actuals() const { return formals() - (flags_ & OVERFLOW_ARGS ? 2 + u.nactual : 0); }
|
||||
unsigned nactual() const { return u.nactual; }
|
||||
|
||||
private:
|
||||
friend class FrameRegs;
|
||||
|
Loading…
Reference in New Issue
Block a user