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