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/base/adapters.h" | 8 #include "src/base/adapters.h" |
9 #include "src/compiler/code-generator-impl.h" | 9 #include "src/compiler/code-generator-impl.h" |
10 #include "src/compiler/linkage.h" | 10 #include "src/compiler/linkage.h" |
(...skipping 14 matching lines...) Expand all Loading... |
25 Label** targets() const { return targets_; } | 25 Label** targets() const { return targets_; } |
26 size_t target_count() const { return target_count_; } | 26 size_t target_count() const { return target_count_; } |
27 | 27 |
28 private: | 28 private: |
29 Label label_; | 29 Label label_; |
30 JumpTable* const next_; | 30 JumpTable* const next_; |
31 Label** const targets_; | 31 Label** const targets_; |
32 size_t const target_count_; | 32 size_t const target_count_; |
33 }; | 33 }; |
34 | 34 |
35 CodeGenerator::CodeGenerator(Zone* zone, CompilationInfo* info) | 35 CodeGenerator::CodeGenerator(Frame* frame, Linkage* linkage, |
| 36 InstructionSequence* code, CompilationInfo* info) |
36 : frame_access_state_(nullptr), | 37 : frame_access_state_(nullptr), |
37 linkage_(nullptr), | 38 linkage_(linkage), |
38 code_(nullptr), | 39 code_(code), |
39 unwinding_info_writer_(zone), | 40 unwinding_info_writer_(zone()), |
40 info_(info), | 41 info_(info), |
41 labels_(nullptr), | 42 labels_(zone()->NewArray<Label>(code->InstructionBlockCount())), |
42 current_block_(RpoNumber::Invalid()), | 43 current_block_(RpoNumber::Invalid()), |
43 current_source_position_(SourcePosition::Unknown()), | 44 current_source_position_(SourcePosition::Unknown()), |
44 masm_(info->isolate(), nullptr, 0, CodeObjectRequired::kNo), | 45 masm_(info->isolate(), nullptr, 0, CodeObjectRequired::kNo), |
45 resolver_(this), | 46 resolver_(this), |
46 safepoints_(zone), | 47 safepoints_(code->zone()), |
47 handlers_(zone), | 48 handlers_(code->zone()), |
48 deoptimization_exits_(zone), | 49 deoptimization_exits_(code->zone()), |
49 deoptimization_states_(zone), | 50 deoptimization_states_(code->zone()), |
50 deoptimization_literals_(zone), | 51 deoptimization_literals_(code->zone()), |
51 inlined_function_count_(0), | 52 inlined_function_count_(0), |
52 translations_(zone), | 53 translations_(code->zone()), |
53 last_lazy_deopt_pc_(0), | 54 last_lazy_deopt_pc_(0), |
54 jump_tables_(nullptr), | 55 jump_tables_(nullptr), |
55 ools_(nullptr), | 56 ools_(nullptr), |
56 osr_pc_offset_(-1), | 57 osr_pc_offset_(-1), |
57 source_position_table_builder_(info->isolate(), zone, | 58 source_position_table_builder_(info->isolate(), code->zone(), |
58 info->SourcePositionRecordingMode()), | 59 info->SourcePositionRecordingMode()) { |
59 assemble_code_successful_(false) {} | |
60 | |
61 void CodeGenerator::Initialize(Frame* frame, Linkage* linkage, | |
62 InstructionSequence* code) { | |
63 linkage_ = linkage; | |
64 code_ = code; | |
65 labels_ = zone()->NewArray<Label>(code->InstructionBlockCount()); | |
66 for (int i = 0; i < code->InstructionBlockCount(); ++i) { | 60 for (int i = 0; i < code->InstructionBlockCount(); ++i) { |
67 new (&labels_[i]) Label; | 61 new (&labels_[i]) Label; |
68 } | 62 } |
69 | 63 CreateFrameAccessState(frame); |
70 // Create the FrameAccessState object. The Frame is immutable from here on. | |
71 FinishFrame(frame); | |
72 frame_access_state_ = new (code->zone()) FrameAccessState(frame); | |
73 } | 64 } |
74 | 65 |
75 bool CodeGenerator::AssembleCode() { | 66 void CodeGenerator::CreateFrameAccessState(Frame* frame) { |
76 DCHECK(!assemble_code_successful()); | 67 FinishFrame(frame); |
| 68 frame_access_state_ = new (code()->zone()) FrameAccessState(frame); |
| 69 } |
| 70 |
| 71 Handle<Code> CodeGenerator::GenerateCode() { |
| 72 CompilationInfo* info = this->info(); |
77 | 73 |
78 // Open a frame scope to indicate that there is a frame on the stack. The | 74 // Open a frame scope to indicate that there is a frame on the stack. The |
79 // MANUAL indicates that the scope shouldn't actually generate code to set up | 75 // MANUAL indicates that the scope shouldn't actually generate code to set up |
80 // the frame (that is done in AssemblePrologue). | 76 // the frame (that is done in AssemblePrologue). |
81 FrameScope frame_scope(masm(), StackFrame::MANUAL); | 77 FrameScope frame_scope(masm(), StackFrame::MANUAL); |
82 | 78 |
83 // Place function entry hook if requested to do so. | 79 // Place function entry hook if requested to do so. |
84 if (linkage()->GetIncomingDescriptor()->IsJSFunctionCall()) { | 80 if (linkage()->GetIncomingDescriptor()->IsJSFunctionCall()) { |
85 ProfileEntryHookStub::MaybeCallEntryHook(masm()); | 81 ProfileEntryHookStub::MaybeCallEntryHook(masm()); |
86 } | 82 } |
87 // Architecture-specific, linkage-specific prologue. | 83 // Architecture-specific, linkage-specific prologue. |
88 info()->set_prologue_offset(masm()->pc_offset()); | 84 info->set_prologue_offset(masm()->pc_offset()); |
89 | 85 |
90 // Define deoptimization literals for all inlined functions. | 86 // Define deoptimization literals for all inlined functions. |
91 DCHECK_EQ(0u, deoptimization_literals_.size()); | 87 DCHECK_EQ(0u, deoptimization_literals_.size()); |
92 for (const CompilationInfo::InlinedFunctionHolder& inlined : | 88 for (const CompilationInfo::InlinedFunctionHolder& inlined : |
93 info()->inlined_functions()) { | 89 info->inlined_functions()) { |
94 if (!inlined.shared_info.is_identical_to(info()->shared_info())) { | 90 if (!inlined.shared_info.is_identical_to(info->shared_info())) { |
95 DefineDeoptimizationLiteral(inlined.shared_info); | 91 DefineDeoptimizationLiteral(inlined.shared_info); |
96 } | 92 } |
97 } | 93 } |
98 inlined_function_count_ = deoptimization_literals_.size(); | 94 inlined_function_count_ = deoptimization_literals_.size(); |
99 | 95 |
100 // Define deoptimization literals for all unoptimized code objects of inlined | 96 // Define deoptimization literals for all unoptimized code objects of inlined |
101 // functions. This ensures unoptimized code is kept alive by optimized code. | 97 // functions. This ensures unoptimized code is kept alive by optimized code. |
102 for (const CompilationInfo::InlinedFunctionHolder& inlined : | 98 for (const CompilationInfo::InlinedFunctionHolder& inlined : |
103 info()->inlined_functions()) { | 99 info->inlined_functions()) { |
104 if (!inlined.shared_info.is_identical_to(info()->shared_info())) { | 100 if (!inlined.shared_info.is_identical_to(info->shared_info())) { |
105 DefineDeoptimizationLiteral(inlined.inlined_code_object_root); | 101 DefineDeoptimizationLiteral(inlined.inlined_code_object_root); |
106 } | 102 } |
107 } | 103 } |
108 | 104 |
109 unwinding_info_writer_.SetNumberOfInstructionBlocks( | 105 unwinding_info_writer_.SetNumberOfInstructionBlocks( |
110 code()->InstructionBlockCount()); | 106 code()->InstructionBlockCount()); |
111 | 107 |
112 // Assemble all non-deferred blocks, followed by deferred ones. | 108 // Assemble all non-deferred blocks, followed by deferred ones. |
113 for (int deferred = 0; deferred < 2; ++deferred) { | 109 for (int deferred = 0; deferred < 2; ++deferred) { |
114 for (const InstructionBlock* block : code()->instruction_blocks()) { | 110 for (const InstructionBlock* block : code()->instruction_blocks()) { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
164 } | 160 } |
165 } | 161 } |
166 | 162 |
167 CodeGenResult result; | 163 CodeGenResult result; |
168 if (FLAG_enable_embedded_constant_pool && !block->needs_frame()) { | 164 if (FLAG_enable_embedded_constant_pool && !block->needs_frame()) { |
169 ConstantPoolUnavailableScope constant_pool_unavailable(masm()); | 165 ConstantPoolUnavailableScope constant_pool_unavailable(masm()); |
170 result = AssembleBlock(block); | 166 result = AssembleBlock(block); |
171 } else { | 167 } else { |
172 result = AssembleBlock(block); | 168 result = AssembleBlock(block); |
173 } | 169 } |
174 if (result != kSuccess) { | 170 if (result != kSuccess) return Handle<Code>(); |
175 assemble_code_successful_ = false; | |
176 return false; | |
177 } | |
178 unwinding_info_writer_.EndInstructionBlock(block); | 171 unwinding_info_writer_.EndInstructionBlock(block); |
179 } | 172 } |
180 } | 173 } |
181 | 174 |
182 assemble_code_successful_ = true; | |
183 return true; | |
184 } | |
185 | |
186 Handle<Code> CodeGenerator::FinishCodeObject() { | |
187 if (!assemble_code_successful_) { | |
188 return Handle<Code>::null(); | |
189 } | |
190 | |
191 // Assemble all out-of-line code. | 175 // Assemble all out-of-line code. |
192 if (ools_) { | 176 if (ools_) { |
193 masm()->RecordComment("-- Out of line code --"); | 177 masm()->RecordComment("-- Out of line code --"); |
194 for (OutOfLineCode* ool = ools_; ool; ool = ool->next()) { | 178 for (OutOfLineCode* ool = ools_; ool; ool = ool->next()) { |
195 masm()->bind(ool->entry()); | 179 masm()->bind(ool->entry()); |
196 ool->Generate(); | 180 ool->Generate(); |
197 if (ool->exit()->is_bound()) masm()->jmp(ool->exit()); | 181 if (ool->exit()->is_bound()) masm()->jmp(ool->exit()); |
198 } | 182 } |
199 } | 183 } |
200 | 184 |
201 // Assemble all eager deoptimization exits. | 185 // Assemble all eager deoptimization exits. |
202 for (DeoptimizationExit* exit : deoptimization_exits_) { | 186 for (DeoptimizationExit* exit : deoptimization_exits_) { |
203 masm()->bind(exit->label()); | 187 masm()->bind(exit->label()); |
204 AssembleDeoptimizerCall(exit->deoptimization_id(), Deoptimizer::EAGER); | 188 AssembleDeoptimizerCall(exit->deoptimization_id(), Deoptimizer::EAGER); |
205 } | 189 } |
206 | 190 |
207 // Ensure there is space for lazy deoptimization in the code. | 191 // Ensure there is space for lazy deoptimization in the code. |
208 if (info()->ShouldEnsureSpaceForLazyDeopt()) { | 192 if (info->ShouldEnsureSpaceForLazyDeopt()) { |
209 int target_offset = masm()->pc_offset() + Deoptimizer::patch_size(); | 193 int target_offset = masm()->pc_offset() + Deoptimizer::patch_size(); |
210 while (masm()->pc_offset() < target_offset) { | 194 while (masm()->pc_offset() < target_offset) { |
211 masm()->nop(); | 195 masm()->nop(); |
212 } | 196 } |
213 } | 197 } |
214 | 198 |
215 FinishCode(masm()); | 199 FinishCode(masm()); |
216 | 200 |
217 // Emit the jump tables. | 201 // Emit the jump tables. |
218 if (jump_tables_) { | 202 if (jump_tables_) { |
219 masm()->Align(kPointerSize); | 203 masm()->Align(kPointerSize); |
220 for (JumpTable* table = jump_tables_; table; table = table->next()) { | 204 for (JumpTable* table = jump_tables_; table; table = table->next()) { |
221 masm()->bind(table->label()); | 205 masm()->bind(table->label()); |
222 AssembleJumpTable(table->targets(), table->target_count()); | 206 AssembleJumpTable(table->targets(), table->target_count()); |
223 } | 207 } |
224 } | 208 } |
225 | 209 |
226 safepoints()->Emit(masm(), frame()->GetTotalFrameSlotCount()); | 210 safepoints()->Emit(masm(), frame()->GetTotalFrameSlotCount()); |
227 | 211 |
228 unwinding_info_writer_.Finish(masm()->pc_offset()); | 212 unwinding_info_writer_.Finish(masm()->pc_offset()); |
229 | 213 |
230 Handle<Code> result = v8::internal::CodeGenerator::MakeCodeEpilogue( | 214 Handle<Code> result = v8::internal::CodeGenerator::MakeCodeEpilogue( |
231 masm(), unwinding_info_writer_.eh_frame_writer(), info(), | 215 masm(), unwinding_info_writer_.eh_frame_writer(), info, Handle<Object>()); |
232 Handle<Object>()); | |
233 result->set_is_turbofanned(true); | 216 result->set_is_turbofanned(true); |
234 result->set_stack_slots(frame()->GetTotalFrameSlotCount()); | 217 result->set_stack_slots(frame()->GetTotalFrameSlotCount()); |
235 result->set_safepoint_table_offset(safepoints()->GetCodeOffset()); | 218 result->set_safepoint_table_offset(safepoints()->GetCodeOffset()); |
236 Handle<ByteArray> source_positions = | 219 Handle<ByteArray> source_positions = |
237 source_position_table_builder_.ToSourcePositionTable(); | 220 source_position_table_builder_.ToSourcePositionTable(); |
238 result->set_source_position_table(*source_positions); | 221 result->set_source_position_table(*source_positions); |
239 source_position_table_builder_.EndJitLogging(AbstractCode::cast(*result)); | 222 source_position_table_builder_.EndJitLogging(AbstractCode::cast(*result)); |
240 | 223 |
241 // Emit exception handler table. | 224 // Emit exception handler table. |
242 if (!handlers_.empty()) { | 225 if (!handlers_.empty()) { |
243 Handle<HandlerTable> table = | 226 Handle<HandlerTable> table = |
244 Handle<HandlerTable>::cast(isolate()->factory()->NewFixedArray( | 227 Handle<HandlerTable>::cast(isolate()->factory()->NewFixedArray( |
245 HandlerTable::LengthForReturn(static_cast<int>(handlers_.size())), | 228 HandlerTable::LengthForReturn(static_cast<int>(handlers_.size())), |
246 TENURED)); | 229 TENURED)); |
247 for (size_t i = 0; i < handlers_.size(); ++i) { | 230 for (size_t i = 0; i < handlers_.size(); ++i) { |
248 table->SetReturnOffset(static_cast<int>(i), handlers_[i].pc_offset); | 231 table->SetReturnOffset(static_cast<int>(i), handlers_[i].pc_offset); |
249 table->SetReturnHandler(static_cast<int>(i), handlers_[i].handler->pos()); | 232 table->SetReturnHandler(static_cast<int>(i), handlers_[i].handler->pos()); |
250 } | 233 } |
251 result->set_handler_table(*table); | 234 result->set_handler_table(*table); |
252 } | 235 } |
253 | 236 |
254 PopulateDeoptimizationData(result); | 237 PopulateDeoptimizationData(result); |
255 | 238 |
256 // Ensure there is space for lazy deoptimization in the relocation info. | 239 // Ensure there is space for lazy deoptimization in the relocation info. |
257 if (info()->ShouldEnsureSpaceForLazyDeopt()) { | 240 if (info->ShouldEnsureSpaceForLazyDeopt()) { |
258 Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(result); | 241 Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(result); |
259 } | 242 } |
260 | 243 |
261 return result; | 244 return result; |
262 } | 245 } |
263 | 246 |
| 247 |
264 bool CodeGenerator::IsNextInAssemblyOrder(RpoNumber block) const { | 248 bool CodeGenerator::IsNextInAssemblyOrder(RpoNumber block) const { |
265 return code() | 249 return code() |
266 ->InstructionBlockAt(current_block_) | 250 ->InstructionBlockAt(current_block_) |
267 ->ao_number() | 251 ->ao_number() |
268 .IsNext(code()->InstructionBlockAt(block)->ao_number()); | 252 .IsNext(code()->InstructionBlockAt(block)->ao_number()); |
269 } | 253 } |
270 | 254 |
271 | 255 |
272 void CodeGenerator::RecordSafepoint(ReferenceMap* references, | 256 void CodeGenerator::RecordSafepoint(ReferenceMap* references, |
273 Safepoint::Kind kind, int arguments, | 257 Safepoint::Kind kind, int arguments, |
(...skipping 678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
952 : frame_(gen->frame()), masm_(gen->masm()), next_(gen->ools_) { | 936 : frame_(gen->frame()), masm_(gen->masm()), next_(gen->ools_) { |
953 gen->ools_ = this; | 937 gen->ools_ = this; |
954 } | 938 } |
955 | 939 |
956 | 940 |
957 OutOfLineCode::~OutOfLineCode() {} | 941 OutOfLineCode::~OutOfLineCode() {} |
958 | 942 |
959 } // namespace compiler | 943 } // namespace compiler |
960 } // namespace internal | 944 } // namespace internal |
961 } // namespace v8 | 945 } // namespace v8 |
OLD | NEW |