Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/compiler/code-generator.h" | 5 #include "src/compiler/code-generator.h" |
| 6 | 6 |
| 7 #include "src/address-map.h" | 7 #include "src/address-map.h" |
| 8 #include "src/compiler/code-generator-impl.h" | 8 #include "src/compiler/code-generator-impl.h" |
| 9 #include "src/compiler/linkage.h" | 9 #include "src/compiler/linkage.h" |
| 10 #include "src/compiler/pipeline.h" | 10 #include "src/compiler/pipeline.h" |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 49 deoptimization_literals_(code->zone()), | 49 deoptimization_literals_(code->zone()), |
| 50 inlined_function_count_(0), | 50 inlined_function_count_(0), |
| 51 translations_(code->zone()), | 51 translations_(code->zone()), |
| 52 last_lazy_deopt_pc_(0), | 52 last_lazy_deopt_pc_(0), |
| 53 jump_tables_(nullptr), | 53 jump_tables_(nullptr), |
| 54 ools_(nullptr), | 54 ools_(nullptr), |
| 55 osr_pc_offset_(-1) { | 55 osr_pc_offset_(-1) { |
| 56 for (int i = 0; i < code->InstructionBlockCount(); ++i) { | 56 for (int i = 0; i < code->InstructionBlockCount(); ++i) { |
| 57 new (&labels_[i]) Label; | 57 new (&labels_[i]) Label; |
| 58 } | 58 } |
| 59 if (code->ContainsCall()) { | |
| 60 frame->MarkNeedsFrame(); | |
| 61 } | |
| 62 } | 59 } |
| 63 | 60 |
| 64 | |
| 65 Handle<Code> CodeGenerator::GenerateCode() { | 61 Handle<Code> CodeGenerator::GenerateCode() { |
| 66 CompilationInfo* info = this->info(); | 62 CompilationInfo* info = this->info(); |
| 67 | 63 |
| 68 // Open a frame scope to indicate that there is a frame on the stack. The | 64 // Open a frame scope to indicate that there is a frame on the stack. The |
| 69 // MANUAL indicates that the scope shouldn't actually generate code to set up | 65 // MANUAL indicates that the scope shouldn't actually generate code to set up |
| 70 // the frame (that is done in AssemblePrologue). | 66 // the frame (that is done in AssemblePrologue). |
| 71 FrameScope frame_scope(masm(), StackFrame::MANUAL); | 67 FrameScope frame_scope(masm(), StackFrame::MANUAL); |
| 72 | 68 |
| 73 // Emit a code line info recording start event. | 69 // Emit a code line info recording start event. |
| 74 PositionsRecorder* recorder = masm()->positions_recorder(); | 70 PositionsRecorder* recorder = masm()->positions_recorder(); |
| 75 LOG_CODE_EVENT(isolate(), CodeStartLinePosInfoRecordEvent(recorder)); | 71 LOG_CODE_EVENT(isolate(), CodeStartLinePosInfoRecordEvent(recorder)); |
| 76 | 72 |
| 77 // Place function entry hook if requested to do so. | 73 // Place function entry hook if requested to do so. |
| 78 if (linkage()->GetIncomingDescriptor()->IsJSFunctionCall()) { | 74 if (linkage()->GetIncomingDescriptor()->IsJSFunctionCall()) { |
| 79 ProfileEntryHookStub::MaybeCallEntryHook(masm()); | 75 ProfileEntryHookStub::MaybeCallEntryHook(masm()); |
| 80 } | 76 } |
| 81 // Architecture-specific, linkage-specific prologue. | 77 // Architecture-specific, linkage-specific prologue. |
| 82 info->set_prologue_offset(masm()->pc_offset()); | 78 info->set_prologue_offset(masm()->pc_offset()); |
| 83 AssemblePrologue(); | |
| 84 if (linkage()->GetIncomingDescriptor()->InitializeRootRegister()) { | 79 if (linkage()->GetIncomingDescriptor()->InitializeRootRegister()) { |
| 85 masm()->InitializeRootRegister(); | 80 masm()->InitializeRootRegister(); |
| 86 } | 81 } |
| 87 | 82 |
| 88 // Define deoptimization literals for all inlined functions. | 83 // Define deoptimization literals for all inlined functions. |
| 89 DCHECK_EQ(0u, deoptimization_literals_.size()); | 84 DCHECK_EQ(0u, deoptimization_literals_.size()); |
| 90 for (const CompilationInfo::InlinedFunctionHolder& inlined : | 85 for (const CompilationInfo::InlinedFunctionHolder& inlined : |
| 91 info->inlined_functions()) { | 86 info->inlined_functions()) { |
| 92 if (!inlined.shared_info.is_identical_to(info->shared_info())) { | 87 if (!inlined.shared_info.is_identical_to(info->shared_info())) { |
| 93 DefineDeoptimizationLiteral(inlined.shared_info); | 88 DefineDeoptimizationLiteral(inlined.shared_info); |
| 94 } | 89 } |
| 95 } | 90 } |
| 96 inlined_function_count_ = deoptimization_literals_.size(); | 91 inlined_function_count_ = deoptimization_literals_.size(); |
| 97 | 92 |
| 98 // Define deoptimization literals for all unoptimized code objects of inlined | 93 // Define deoptimization literals for all unoptimized code objects of inlined |
| 99 // functions. This ensures unoptimized code is kept alive by optimized code. | 94 // functions. This ensures unoptimized code is kept alive by optimized code. |
| 100 for (const CompilationInfo::InlinedFunctionHolder& inlined : | 95 for (const CompilationInfo::InlinedFunctionHolder& inlined : |
| 101 info->inlined_functions()) { | 96 info->inlined_functions()) { |
| 102 if (!inlined.shared_info.is_identical_to(info->shared_info())) { | 97 if (!inlined.shared_info.is_identical_to(info->shared_info())) { |
| 103 DefineDeoptimizationLiteral(inlined.inlined_code_object_root); | 98 DefineDeoptimizationLiteral(inlined.inlined_code_object_root); |
| 104 } | 99 } |
| 105 } | 100 } |
| 106 | 101 |
| 102 // Finish the Frame | |
| 103 frame()->AlignFrame(kFrameAlignmentInBytes); | |
| 104 AssembleSetupStackPointer(); | |
| 107 // Assemble all non-deferred blocks, followed by deferred ones. | 105 // Assemble all non-deferred blocks, followed by deferred ones. |
| 108 for (int deferred = 0; deferred < 2; ++deferred) { | 106 for (int deferred = 0; deferred < 2; ++deferred) { |
| 109 for (const InstructionBlock* block : code()->instruction_blocks()) { | 107 for (const InstructionBlock* block : code()->instruction_blocks()) { |
| 110 if (block->IsDeferred() == (deferred == 0)) { | 108 if (block->IsDeferred() == (deferred == 0)) { |
| 111 continue; | 109 continue; |
| 112 } | 110 } |
| 113 // Align loop headers on 16-byte boundaries. | 111 // Align loop headers on 16-byte boundaries. |
| 114 if (block->IsLoopHeader()) masm()->Align(16); | 112 if (block->IsLoopHeader()) masm()->Align(16); |
| 115 // Ensure lazy deopt doesn't patch handler entry points. | 113 // Ensure lazy deopt doesn't patch handler entry points. |
| 116 if (block->IsHandler()) EnsureSpaceForLazyDeopt(); | 114 if (block->IsHandler()) EnsureSpaceForLazyDeopt(); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 136 buffer = buffer.SubVector(next, buffer.length()); | 134 buffer = buffer.SubVector(next, buffer.length()); |
| 137 } | 135 } |
| 138 if (block->loop_header().IsValid()) { | 136 if (block->loop_header().IsValid()) { |
| 139 next = | 137 next = |
| 140 SNPrintF(buffer, " (in loop %d)", block->loop_header().ToInt()); | 138 SNPrintF(buffer, " (in loop %d)", block->loop_header().ToInt()); |
| 141 buffer = buffer.SubVector(next, buffer.length()); | 139 buffer = buffer.SubVector(next, buffer.length()); |
| 142 } | 140 } |
| 143 SNPrintF(buffer, " --"); | 141 SNPrintF(buffer, " --"); |
| 144 masm()->RecordComment(buffer_start); | 142 masm()->RecordComment(buffer_start); |
| 145 } | 143 } |
| 144 | |
| 145 frame_access_state()->MarkHasFrame(block->needs_frame()); | |
| 146 | |
| 146 masm()->bind(GetLabel(current_block_)); | 147 masm()->bind(GetLabel(current_block_)); |
| 148 if (block->must_construct_frame()) { | |
| 149 AssemblePrologue(); | |
|
Benedikt Meurer
2016/03/30 04:00:25
Maybe we should rename AssemblePrologue to Assembl
Mircea Trofin
2016/03/30 04:13:27
I want to do that, but together with separating fr
Benedikt Meurer
2016/03/30 04:34:08
Acknowledged.
| |
| 150 } | |
| 151 | |
| 147 for (int i = block->code_start(); i < block->code_end(); ++i) { | 152 for (int i = block->code_start(); i < block->code_end(); ++i) { |
| 148 AssembleInstruction(code()->InstructionAt(i)); | 153 Instruction* instr = code()->InstructionAt(i); |
|
Benedikt Meurer
2016/03/30 04:00:25
Please put all of this into AssembleInstruction be
Mircea Trofin
2016/03/30 04:13:27
We need the operands involved in the gap to be emi
Benedikt Meurer
2016/03/30 04:34:08
Sure, but that can all be done inside AssembleInst
Mircea Trofin
2016/03/30 05:58:20
Done.
| |
| 154 AssembleGaps(instr); | |
| 155 if (block->must_deconstruct_frame() && | |
|
Benedikt Meurer
2016/03/30 04:00:25
This condition looks unnecessarily complex. Isn't
Mircea Trofin
2016/03/30 04:13:27
That's true for ret, and I plan to address that se
Benedikt Meurer
2016/03/30 04:34:08
Acknowledged.
| |
| 156 i == block->last_instruction_index() && !instr->IsRet()) { | |
| 157 DCHECK(instr->IsJump()); | |
| 158 AssembleDeconstructFrame(); | |
| 159 } | |
| 160 AssembleInstruction(instr); | |
| 149 } | 161 } |
| 150 } | 162 } |
| 151 } | 163 } |
| 152 | 164 |
| 153 // Assemble all out-of-line code. | 165 // Assemble all out-of-line code. |
| 154 if (ools_) { | 166 if (ools_) { |
| 155 masm()->RecordComment("-- Out of line code --"); | 167 masm()->RecordComment("-- Out of line code --"); |
| 156 for (OutOfLineCode* ool = ools_; ool; ool = ool->next()) { | 168 for (OutOfLineCode* ool = ools_; ool; ool = ool->next()) { |
| 157 masm()->bind(ool->entry()); | 169 masm()->bind(ool->entry()); |
| 158 ool->Generate(); | 170 ool->Generate(); |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 283 RootIndexMap map(isolate()); | 295 RootIndexMap map(isolate()); |
| 284 int root_index = map.Lookup(*object); | 296 int root_index = map.Lookup(*object); |
| 285 if (root_index != RootIndexMap::kInvalidRootIndex) { | 297 if (root_index != RootIndexMap::kInvalidRootIndex) { |
| 286 *index_return = static_cast<Heap::RootListIndex>(root_index); | 298 *index_return = static_cast<Heap::RootListIndex>(root_index); |
| 287 return true; | 299 return true; |
| 288 } | 300 } |
| 289 } | 301 } |
| 290 return false; | 302 return false; |
| 291 } | 303 } |
| 292 | 304 |
| 293 | |
| 294 void CodeGenerator::AssembleInstruction(Instruction* instr) { | 305 void CodeGenerator::AssembleInstruction(Instruction* instr) { |
| 295 AssembleGaps(instr); | |
| 296 AssembleSourcePosition(instr); | 306 AssembleSourcePosition(instr); |
| 297 // Assemble architecture-specific code for the instruction. | 307 // Assemble architecture-specific code for the instruction. |
| 298 AssembleArchInstruction(instr); | 308 AssembleArchInstruction(instr); |
| 299 | 309 |
| 300 FlagsMode mode = FlagsModeField::decode(instr->opcode()); | 310 FlagsMode mode = FlagsModeField::decode(instr->opcode()); |
| 301 FlagsCondition condition = FlagsConditionField::decode(instr->opcode()); | 311 FlagsCondition condition = FlagsConditionField::decode(instr->opcode()); |
| 302 switch (mode) { | 312 switch (mode) { |
| 303 case kFlags_branch: { | 313 case kFlags_branch: { |
| 304 // Assemble a branch after this instruction. | 314 // Assemble a branch after this instruction. |
| 305 InstructionOperandConverter i(this, instr); | 315 InstructionOperandConverter i(this, instr); |
| (...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 754 Instruction* instr, size_t frame_state_offset) { | 764 Instruction* instr, size_t frame_state_offset) { |
| 755 int const deoptimization_id = BuildTranslation( | 765 int const deoptimization_id = BuildTranslation( |
| 756 instr, -1, frame_state_offset, OutputFrameStateCombine::Ignore()); | 766 instr, -1, frame_state_offset, OutputFrameStateCombine::Ignore()); |
| 757 DeoptimizationExit* const exit = | 767 DeoptimizationExit* const exit = |
| 758 new (zone()) DeoptimizationExit(deoptimization_id); | 768 new (zone()) DeoptimizationExit(deoptimization_id); |
| 759 deoptimization_exits_.push_back(exit); | 769 deoptimization_exits_.push_back(exit); |
| 760 return exit; | 770 return exit; |
| 761 } | 771 } |
| 762 | 772 |
| 763 int CodeGenerator::TailCallFrameStackSlotDelta(int stack_param_delta) { | 773 int CodeGenerator::TailCallFrameStackSlotDelta(int stack_param_delta) { |
| 764 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); | |
| 765 int spill_slots = frame()->GetSpillSlotCount(); | |
| 766 bool has_frame = descriptor->IsJSFunctionCall() || spill_slots > 0; | |
| 767 // Leave the PC on the stack on platforms that have that as part of their ABI | 774 // Leave the PC on the stack on platforms that have that as part of their ABI |
| 768 int pc_slots = V8_TARGET_ARCH_STORES_RETURN_ADDRESS_ON_STACK ? 1 : 0; | 775 int pc_slots = V8_TARGET_ARCH_STORES_RETURN_ADDRESS_ON_STACK ? 1 : 0; |
| 769 int sp_slot_delta = | 776 int sp_slot_delta = frame_access_state()->has_frame() |
| 770 has_frame ? (frame()->GetTotalFrameSlotCount() - pc_slots) : 0; | 777 ? (frame()->GetTotalFrameSlotCount() - pc_slots) |
| 778 : 0; | |
| 771 // Discard only slots that won't be used by new parameters. | 779 // Discard only slots that won't be used by new parameters. |
| 772 sp_slot_delta += stack_param_delta; | 780 sp_slot_delta += stack_param_delta; |
| 773 return sp_slot_delta; | 781 return sp_slot_delta; |
| 774 } | 782 } |
| 775 | 783 |
| 776 | |
| 777 OutOfLineCode::OutOfLineCode(CodeGenerator* gen) | 784 OutOfLineCode::OutOfLineCode(CodeGenerator* gen) |
| 778 : frame_(gen->frame()), masm_(gen->masm()), next_(gen->ools_) { | 785 : frame_(gen->frame()), masm_(gen->masm()), next_(gen->ools_) { |
| 779 gen->ools_ = this; | 786 gen->ools_ = this; |
| 780 } | 787 } |
| 781 | 788 |
| 782 | 789 |
| 783 OutOfLineCode::~OutOfLineCode() {} | 790 OutOfLineCode::~OutOfLineCode() {} |
| 784 | 791 |
| 785 } // namespace compiler | 792 } // namespace compiler |
| 786 } // namespace internal | 793 } // namespace internal |
| 787 } // namespace v8 | 794 } // namespace v8 |
| OLD | NEW |