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