| 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;
|
| }
|
|
|