Index: src/compiler/code-generator.cc |
diff --git a/src/compiler/code-generator.cc b/src/compiler/code-generator.cc |
index edfdaa79caa440022756e017347eda6c750a7b98..8fbefe0276c1bb385b824ffcef96db63b6eab1e6 100644 |
--- a/src/compiler/code-generator.cc |
+++ b/src/compiler/code-generator.cc |
@@ -19,12 +19,10 @@ CodeGenerator::CodeGenerator(InstructionSequence* code) |
masm_(code->zone()->isolate(), NULL, 0), |
resolver_(this), |
safepoints_(code->zone()), |
- lazy_deoptimization_entries_(code->zone()), |
+ deoptimization_points_(code->zone()), |
deoptimization_states_(code->zone()), |
deoptimization_literals_(code->zone()), |
- translations_(code->zone()) { |
- deoptimization_states_.resize(code->GetDeoptimizationEntryCount(), NULL); |
-} |
+ translations_(code->zone()) {} |
Handle<Code> CodeGenerator::GenerateCode() { |
@@ -49,9 +47,10 @@ Handle<Code> CodeGenerator::GenerateCode() { |
AssembleInstruction(*i); |
} |
+ EmitLazyDeoptimizationCallTable(); |
+ |
FinishCode(masm()); |
- UpdateSafepointsWithDeoptimizationPc(); |
safepoints()->Emit(masm(), frame()->GetSpillSlotCount()); |
// TODO(titzer): what are the right code flags here? |
@@ -173,23 +172,23 @@ void CodeGenerator::AssembleGap(GapInstruction* instr) { |
} |
-void CodeGenerator::UpdateSafepointsWithDeoptimizationPc() { |
- int patch_count = static_cast<int>(lazy_deoptimization_entries_.size()); |
- for (int i = 0; i < patch_count; ++i) { |
- LazyDeoptimizationEntry entry = lazy_deoptimization_entries_[i]; |
- // TODO(jarin) make sure that there is no code (other than nops) |
- // between the call position and the continuation position. |
- safepoints()->SetDeoptimizationPc(entry.safepoint_id(), |
- entry.deoptimization()->pos()); |
+void CodeGenerator::EmitLazyDeoptimizationCallTable() { |
+ // ZoneDeque<DeoptimizationPoint*>::iterator iter; |
+ int i = 0; |
+ for (ZoneDeque<DeoptimizationPoint*>::iterator |
+ iter = deoptimization_points_.begin(); |
+ iter != deoptimization_points_.end(); iter++, i++) { |
+ int pc_offset = masm()->pc_offset(); |
+ AssembleDeoptimizerCall((*iter)->lazy_state_id()); |
+ safepoints()->SetDeoptimizationPc((*iter)->safepoint(), pc_offset); |
} |
} |
void CodeGenerator::PopulateDeoptimizationData(Handle<Code> code_object) { |
CompilationInfo* info = linkage()->info(); |
- int deopt_count = code()->GetDeoptimizationEntryCount(); |
- int patch_count = static_cast<int>(lazy_deoptimization_entries_.size()); |
- if (patch_count == 0 && deopt_count == 0) return; |
+ int deopt_count = static_cast<int>(deoptimization_states_.size()); |
+ if (deopt_count == 0) return; |
Handle<DeoptimizationInputData> data = |
DeoptimizationInputData::New(isolate(), deopt_count, TENURED); |
@@ -226,11 +225,11 @@ void CodeGenerator::PopulateDeoptimizationData(Handle<Code> code_object) { |
// Populate deoptimization entries. |
for (int i = 0; i < deopt_count; i++) { |
- FrameStateDescriptor* descriptor = code()->GetDeoptimizationEntry(i); |
- data->SetAstId(i, descriptor->bailout_id()); |
+ DeoptimizationState* deoptimization_state = deoptimization_states_[i]; |
+ data->SetAstId(i, deoptimization_state->bailout_id()); |
CHECK_NE(NULL, deoptimization_states_[i]); |
data->SetTranslationIndex( |
- i, Smi::FromInt(deoptimization_states_[i]->translation_id_)); |
+ i, Smi::FromInt(deoptimization_states_[i]->translation_id())); |
data->SetArgumentsStackHeight(i, Smi::FromInt(0)); |
data->SetPc(i, Smi::FromInt(-1)); |
} |
@@ -248,29 +247,33 @@ void CodeGenerator::AddSafepointAndDeopt(Instruction* instr) { |
instr->pointer_map(), Safepoint::kSimple, 0, |
needs_frame_state ? Safepoint::kLazyDeopt : Safepoint::kNoLazyDeopt); |
- if (flags & CallDescriptor::kLazyDeoptimization) { |
- RecordLazyDeoptimizationEntry(instr, safepoint_id); |
- } |
- |
if (needs_frame_state) { |
// If the frame state is present, it starts at argument 1 |
// (just after the code address). |
InstructionOperandConverter converter(this, instr); |
// Deoptimization info starts at argument 1 |
int frame_state_offset = 1; |
- int deoptimization_id = BuildTranslation(instr, frame_state_offset); |
+ FrameStateDescriptor* descriptor = |
+ GetFrameStateDescriptor(instr, frame_state_offset); |
+ int deopt_state_id = |
+ BuildTranslation(instr, frame_state_offset, kIgnoreOutput); |
+ int lazy_deopt_state_id = deopt_state_id; |
+ if (descriptor->state_combine() != kIgnoreOutput) { |
+ lazy_deopt_state_id = BuildTranslation(instr, frame_state_offset, |
+ descriptor->state_combine()); |
+ } |
+ deoptimization_points_.push_back(new (zone()) DeoptimizationPoint( |
+ deopt_state_id, lazy_deopt_state_id, descriptor, safepoint_id)); |
#if DEBUG |
// Make sure all the values live in stack slots or they are immediates. |
// (The values should not live in register because registers are clobbered |
// by calls.) |
- FrameStateDescriptor* descriptor = |
- code()->GetDeoptimizationEntry(deoptimization_id); |
for (int i = 0; i < descriptor->size(); i++) { |
InstructionOperand* op = instr->InputAt(frame_state_offset + 1 + i); |
CHECK(op->IsStackSlot() || op->IsImmediate()); |
} |
#endif |
- safepoints()->RecordLazyDeoptimizationIndex(deoptimization_id); |
+ safepoints()->RecordLazyDeoptimizationIndex(lazy_deopt_state_id); |
} |
if (flags & CallDescriptor::kNeedsNopAfterCall) { |
@@ -279,27 +282,6 @@ void CodeGenerator::AddSafepointAndDeopt(Instruction* instr) { |
} |
-void CodeGenerator::RecordLazyDeoptimizationEntry(Instruction* instr, |
- Safepoint::Id safepoint_id) { |
- InstructionOperandConverter i(this, instr); |
- |
- Label after_call; |
- masm()->bind(&after_call); |
- |
- // The continuation and deoptimization are the last two inputs: |
- BasicBlock* cont_block = |
- i.InputBlock(static_cast<int>(instr->InputCount()) - 2); |
- BasicBlock* deopt_block = |
- i.InputBlock(static_cast<int>(instr->InputCount()) - 1); |
- |
- Label* cont_label = code_->GetLabel(cont_block); |
- Label* deopt_label = code_->GetLabel(deopt_block); |
- |
- lazy_deoptimization_entries_.push_back(LazyDeoptimizationEntry( |
- after_call.pos(), cont_label, deopt_label, safepoint_id)); |
-} |
- |
- |
int CodeGenerator::DefineDeoptimizationLiteral(Handle<Object> literal) { |
int result = static_cast<int>(deoptimization_literals_.size()); |
for (unsigned i = 0; i < deoptimization_literals_.size(); ++i) { |
@@ -310,29 +292,53 @@ int CodeGenerator::DefineDeoptimizationLiteral(Handle<Object> literal) { |
} |
-int CodeGenerator::BuildTranslation(Instruction* instr, |
- int frame_state_offset) { |
+FrameStateDescriptor* CodeGenerator::GetFrameStateDescriptor( |
+ Instruction* instr, int frame_state_offset) { |
InstructionOperandConverter i(this, instr); |
- int deoptimization_id = i.InputInt32(frame_state_offset); |
- frame_state_offset++; |
+ InstructionSequence::StateId state_id = |
+ InstructionSequence::StateId::FromInt(i.InputInt32(frame_state_offset)); |
+ return code()->GetFrameStateDescriptor(state_id); |
+} |
- // We should build translation only once. |
- DCHECK_EQ(NULL, deoptimization_states_[deoptimization_id]); |
+int CodeGenerator::BuildTranslation(Instruction* instr, int frame_state_offset, |
+ OutputFrameStateCombine state_combine) { |
FrameStateDescriptor* descriptor = |
- code()->GetDeoptimizationEntry(deoptimization_id); |
+ GetFrameStateDescriptor(instr, frame_state_offset); |
+ frame_state_offset++; |
+ |
+ int height = descriptor->size() - descriptor->parameters_count(); |
+ switch (state_combine) { |
+ case kPushOutput: |
+ height++; |
+ break; |
+ case kIgnoreOutput: |
+ break; |
+ } |
+ |
+ |
Translation translation(&translations_, 1, 1, zone()); |
translation.BeginJSFrame(descriptor->bailout_id(), |
- Translation::kSelfLiteralId, |
- descriptor->size() - descriptor->parameters_count()); |
+ Translation::kSelfLiteralId, height); |
for (int i = 0; i < descriptor->size(); i++) { |
AddTranslationForOperand(&translation, instr, |
instr->InputAt(i + frame_state_offset)); |
} |
- deoptimization_states_[deoptimization_id] = |
- new (zone()) DeoptimizationState(translation.index()); |
+ switch (state_combine) { |
+ case kPushOutput: |
+ DCHECK(instr->OutputCount() == 1); |
+ AddTranslationForOperand(&translation, instr, instr->OutputAt(0)); |
+ break; |
+ case kIgnoreOutput: |
+ break; |
+ } |
+ |
+ int deoptimization_id = static_cast<int>(deoptimization_states_.size()); |
+ |
+ deoptimization_states_.push_back(new (zone()) DeoptimizationState( |
+ descriptor->bailout_id(), translation.index())); |
return deoptimization_id; |
} |