LInstruction* LChunkBuilder::DoContext(HContext* instr) {
- return instr->HasNoUses() ? NULL : DefineAsRegister(new(zone()) LContext);
+ // If there is a non-return use, the context must be allocated in a register.
+ for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) {
+ if (!it.value()->IsReturn()) {
+ return DefineAsRegister(new(zone()) LContext);
+ }
+ }
+
+ return NULL;
}
__ ldm(ia_w, sp, fp.bit() | lr.bit());
__ add(sp, sp, Operand(sp_delta));
}
- if (info()->IsStub()) {
- __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
- }
__ Jump(lr);
}
class CodeStubGraphBuilderBase : public HGraphBuilder {
public:
CodeStubGraphBuilderBase(Isolate* isolate, HydrogenCodeStub* stub)
- : HGraphBuilder(&info_), info_(stub, isolate) {}
+ : HGraphBuilder(&info_), info_(stub, isolate), context_(NULL) {}
virtual bool BuildGraph();
protected:
virtual void BuildCodeStub() = 0;
HParameter* GetParameter(int parameter) { return parameters_[parameter]; }
HydrogenCodeStub* stub() { return info_.code_stub(); }
+ HContext* context() { return context_; }
private:
SmartArrayPointer<HParameter*> parameters_;
CompilationInfoWithZone info_;
+ HContext* context_;
};
graph()->entry_block()->Finish(jump);
set_current_block(next_block);
+ context_ = new(zone()) HContext();
+ AddInstruction(context_);
+
int major_key = stub()->MajorKey();
CodeStubInterfaceDescriptor* descriptor =
info_.isolate()->code_stub_interface_descriptor(major_key);
casted_stub()->is_js_array(), casted_stub()->elements_kind(), false);
AddInstruction(load);
- HReturn* ret = new(zone) HReturn(load);
+ HReturn* ret = new(zone) HReturn(load, context());
current_block()->Finish(ret);
}
};
-class HReturn: public HTemplateControlInstruction<0, 1> {
+class HReturn: public HTemplateControlInstruction<0, 2> {
public:
- explicit HReturn(HValue* value) {
+ HReturn(HValue* value, HValue* context) {
SetOperandAt(0, value);
+ SetOperandAt(1, context);
}
virtual Representation RequiredInputRepresentation(int index) {
virtual void PrintDataTo(StringStream* stream);
HValue* value() { return OperandAt(0); }
+ HValue* context() { return OperandAt(1); }
DECLARE_CONCRETE_INSTRUCTION(Return)
};
if (HasStackOverflow()) return false;
if (current_block() != NULL) {
- HReturn* instr = new(zone()) HReturn(graph()->GetConstantUndefined());
+ HReturn* instr = new(zone()) HReturn(graph()->GetConstantUndefined(),
+ context);
current_block()->FinishExit(instr);
set_current_block(NULL);
}
// Not an inlined return, so an actual one.
CHECK_ALIVE(VisitForValue(stmt->expression()));
HValue* result = environment()->Pop();
- current_block()->FinishExit(new(zone()) HReturn(result));
+ current_block()->FinishExit(new(zone()) HReturn(
+ result,
+ environment()->LookupContext()));
} else if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) {
// Return from an inlined construct call. In a test context the return value
// will always evaluate to true, in a value context the return value needs
ASSERT(environment->HasBeenRegistered());
int id = environment->deoptimization_index();
ASSERT(info()->IsOptimizing() || info()->IsStub());
- Deoptimizer::BailoutType bailout_type = frame_is_built_
- ? Deoptimizer::EAGER
- : Deoptimizer::LAZY;
+ Deoptimizer::BailoutType bailout_type = info()->IsStub()
+ ? Deoptimizer::LAZY
+ : Deoptimizer::EAGER;
Address entry = Deoptimizer::GetDeoptimizationEntry(id, bailout_type);
if (entry == NULL) {
Abort("bailout was not prepared");
__ bind(&no_padding);
}
if (info()->IsStub()) {
- __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
__ Ret();
} else {
__ Ret((GetParameterCount() + 1) * kPointerSize, ecx);
void LCodeGen::DoContext(LContext* instr) {
Register result = ToRegister(instr->result());
- __ mov(result, Operand(ebp, StandardFrameConstants::kContextOffset));
+ if (info()->IsOptimizing()) {
+ __ mov(result, Operand(ebp, StandardFrameConstants::kContextOffset));
+ } else {
+ // If there is no frame, the context must be in esi.
+ ASSERT(result.is(esi));
+ }
}
LInstruction* LChunkBuilder::DoContext(HContext* instr) {
- return instr->HasNoUses() ? NULL : DefineAsRegister(new(zone()) LContext);
+ if (instr->HasNoUses()) return NULL;
+
+ if (info()->IsStub()) {
+ return DefineFixed(new(zone()) LContext, esi);
+ }
+
+ return DefineAsRegister(new(zone()) LContext);
}
LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
- return new(zone()) LReturn(UseFixed(instr->value(), eax));
+ LOperand* context = info()->IsStub()
+ ? UseFixed(instr->context(), esi)
+ : NULL;
+ return new(zone()) LReturn(UseFixed(instr->value(), eax), context);
}
};
-class LReturn: public LTemplateInstruction<0, 1, 0> {
+class LReturn: public LTemplateInstruction<0, 2, 0> {
public:
- explicit LReturn(LOperand* value) {
+ explicit LReturn(LOperand* value, LOperand* context) {
inputs_[0] = value;
+ inputs_[1] = context;
}
DECLARE_CONCRETE_INSTRUCTION(Return, "return")
LOperand* InputIterator::Current() {
ASSERT(!Done());
+ ASSERT(instr_->InputAt(current_) != NULL);
return instr_->InputAt(current_);
}
void InputIterator::SkipUninteresting() {
- while (current_ < limit_ && instr_->InputAt(current_)->IsConstantOperand()) {
+ while (current_ < limit_) {
+ LOperand* current = instr_->InputAt(current_);
+ if (current != NULL && !current->IsConstantOperand()) break;
++current_;
}
}
LOperand* UseIterator::Current() {
ASSERT(!Done());
- return input_iterator_.Done()
+ LOperand* result = input_iterator_.Done()
? env_iterator_.Current()
: input_iterator_.Current();
+ ASSERT(result != NULL);
+ return result;
}
LOperand* Current() {
ASSERT(!Done());
+ ASSERT(env_->values()->at(current_) != NULL);
return env_->values()->at(current_);
}
LOperand* Current() {
ASSERT(!current_iterator_.Done());
+ ASSERT(current_iterator_.Current() != NULL);
return current_iterator_.Current();
}
__ pop(rbp);
}
if (info()->IsStub()) {
- __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
__ Ret(0, r10);
} else {
__ Ret((GetParameterCount() + 1) * kPointerSize, rcx);
LInstruction* LChunkBuilder::DoContext(HContext* instr) {
- return instr->HasNoUses() ? NULL : DefineAsRegister(new(zone()) LContext);
+ // If there is a non-return use, the context must be allocated in a register.
+ for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) {
+ if (!it.value()->IsReturn()) {
+ return DefineAsRegister(new(zone()) LContext);
+ }
+ }
+
+ return NULL;
}