| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_XXX. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_XXX. |
| 6 | 6 |
| 7 #include "vm/flow_graph_compiler.h" | 7 #include "vm/flow_graph_compiler.h" |
| 8 | 8 |
| 9 #include "vm/dart_entry.h" | 9 #include "vm/dart_entry.h" |
| 10 #include "vm/debugger.h" | 10 #include "vm/debugger.h" |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 70 } | 70 } |
| 71 | 71 |
| 72 const DeoptInfo& deopt_info = DeoptInfo::Handle(builder.CreateDeoptInfo()); | 72 const DeoptInfo& deopt_info = DeoptInfo::Handle(builder.CreateDeoptInfo()); |
| 73 return deopt_info.raw(); | 73 return deopt_info.raw(); |
| 74 } | 74 } |
| 75 | 75 |
| 76 | 76 |
| 77 FlowGraphCompiler::FlowGraphCompiler(Assembler* assembler, | 77 FlowGraphCompiler::FlowGraphCompiler(Assembler* assembler, |
| 78 const FlowGraph& flow_graph, | 78 const FlowGraph& flow_graph, |
| 79 bool is_optimizing, | 79 bool is_optimizing, |
| 80 bool is_ssa, | |
| 81 bool is_leaf) | 80 bool is_leaf) |
| 82 : assembler_(assembler), | 81 : assembler_(assembler), |
| 83 parsed_function_(flow_graph.parsed_function()), | 82 parsed_function_(flow_graph.parsed_function()), |
| 84 block_order_(flow_graph.reverse_postorder()), | 83 block_order_(flow_graph.reverse_postorder()), |
| 85 current_block_(NULL), | 84 current_block_(NULL), |
| 86 exception_handlers_list_(NULL), | 85 exception_handlers_list_(NULL), |
| 87 pc_descriptors_list_(NULL), | 86 pc_descriptors_list_(NULL), |
| 88 stackmap_table_builder_(NULL), | 87 stackmap_table_builder_(NULL), |
| 89 block_info_(block_order_.length()), | 88 block_info_(block_order_.length()), |
| 90 deopt_stubs_(), | 89 deopt_stubs_(), |
| 91 object_table_(GrowableObjectArray::Handle(GrowableObjectArray::New())), | 90 object_table_(GrowableObjectArray::Handle(GrowableObjectArray::New())), |
| 92 is_optimizing_(is_optimizing), | 91 is_optimizing_(is_optimizing), |
| 93 is_ssa_(is_ssa), | |
| 94 is_dart_leaf_(is_leaf), | 92 is_dart_leaf_(is_leaf), |
| 95 bool_true_(Bool::ZoneHandle(Bool::True())), | 93 bool_true_(Bool::ZoneHandle(Bool::True())), |
| 96 bool_false_(Bool::ZoneHandle(Bool::False())), | 94 bool_false_(Bool::ZoneHandle(Bool::False())), |
| 97 double_class_(Class::ZoneHandle( | 95 double_class_(Class::ZoneHandle( |
| 98 Isolate::Current()->object_store()->double_class())), | 96 Isolate::Current()->object_store()->double_class())), |
| 99 frame_register_allocator_(this, is_optimizing, is_ssa), | |
| 100 parallel_move_resolver_(this) { | 97 parallel_move_resolver_(this) { |
| 101 ASSERT(assembler != NULL); | 98 ASSERT(assembler != NULL); |
| 102 ASSERT(is_optimizing_ || !is_ssa_); | 99 if (is_optimizing_) { |
| 103 if (is_ssa_) { | |
| 104 stackmap_table_builder_ = new StackmapTableBuilder(StackSize()); | 100 stackmap_table_builder_ = new StackmapTableBuilder(StackSize()); |
| 105 } | 101 } |
| 106 } | 102 } |
| 107 | 103 |
| 108 | 104 |
| 109 FlowGraphCompiler::~FlowGraphCompiler() { | 105 FlowGraphCompiler::~FlowGraphCompiler() { |
| 110 // BlockInfos are zone-allocated, so their destructors are not called. | 106 // BlockInfos are zone-allocated, so their destructors are not called. |
| 111 // Verify the labels explicitly here. | 107 // Verify the labels explicitly here. |
| 112 for (int i = 0; i < block_info_.length(); ++i) { | 108 for (int i = 0; i < block_info_.length(); ++i) { |
| 113 ASSERT(!block_info_[i]->label.IsLinked()); | 109 ASSERT(!block_info_[i]->label.IsLinked()); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 140 | 136 |
| 141 bool FlowGraphCompiler::CanOptimize() { | 137 bool FlowGraphCompiler::CanOptimize() { |
| 142 return !FLAG_report_usage_count && | 138 return !FLAG_report_usage_count && |
| 143 (FLAG_optimization_counter_threshold >= 0) && | 139 (FLAG_optimization_counter_threshold >= 0) && |
| 144 !Isolate::Current()->debugger()->IsActive(); | 140 !Isolate::Current()->debugger()->IsActive(); |
| 145 } | 141 } |
| 146 | 142 |
| 147 | 143 |
| 148 void FlowGraphCompiler::VisitBlocks() { | 144 void FlowGraphCompiler::VisitBlocks() { |
| 149 for (intptr_t i = 0; i < block_order().length(); ++i) { | 145 for (intptr_t i = 0; i < block_order().length(); ++i) { |
| 150 ASSERT(frame_register_allocator()->IsSpilled()); | |
| 151 assembler()->Comment("B%d", i); | 146 assembler()->Comment("B%d", i); |
| 152 // Compile the block entry. | 147 // Compile the block entry. |
| 153 BlockEntryInstr* entry = block_order()[i]; | 148 BlockEntryInstr* entry = block_order()[i]; |
| 154 set_current_block(entry); | 149 set_current_block(entry); |
| 155 entry->PrepareEntry(this); | 150 entry->PrepareEntry(this); |
| 156 // Compile all successors until an exit, branch, or a block entry. | 151 // Compile all successors until an exit, branch, or a block entry. |
| 157 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { | 152 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { |
| 158 Instruction* instr = it.Current(); | 153 Instruction* instr = it.Current(); |
| 159 if (FLAG_code_comments) EmitComment(instr); | 154 if (FLAG_code_comments) EmitComment(instr); |
| 160 if (instr->IsParallelMove()) { | 155 if (instr->IsParallelMove()) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 176 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; | 171 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; |
| 177 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); | 172 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); |
| 178 OS::SNPrint(chars, len, kFormat, function_name, reason); | 173 OS::SNPrint(chars, len, kFormat, function_name, reason); |
| 179 const Error& error = Error::Handle( | 174 const Error& error = Error::Handle( |
| 180 LanguageError::New(String::Handle(String::New(chars)))); | 175 LanguageError::New(String::Handle(String::New(chars)))); |
| 181 Isolate::Current()->long_jump_base()->Jump(1, error); | 176 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 182 } | 177 } |
| 183 | 178 |
| 184 | 179 |
| 185 intptr_t FlowGraphCompiler::StackSize() const { | 180 intptr_t FlowGraphCompiler::StackSize() const { |
| 186 if (is_ssa_) { | 181 if (is_optimizing_) { |
| 187 return block_order_[0]->AsGraphEntry()->spill_slot_count(); | 182 return block_order_[0]->AsGraphEntry()->spill_slot_count(); |
| 188 } else { | 183 } else { |
| 189 return parsed_function_.stack_local_count() + | 184 return parsed_function_.stack_local_count() + |
| 190 parsed_function_.copied_parameter_count(); | 185 parsed_function_.copied_parameter_count(); |
| 191 } | 186 } |
| 192 } | 187 } |
| 193 | 188 |
| 194 | 189 |
| 195 Label* FlowGraphCompiler::GetBlockLabel( | 190 Label* FlowGraphCompiler::GetBlockLabel( |
| 196 BlockEntryInstr* block_entry) const { | 191 BlockEntryInstr* block_entry) const { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 246 intptr_t pc_offset) { | 241 intptr_t pc_offset) { |
| 247 exception_handlers_list_->AddHandler(try_index, pc_offset); | 242 exception_handlers_list_->AddHandler(try_index, pc_offset); |
| 248 } | 243 } |
| 249 | 244 |
| 250 | 245 |
| 251 // Uses current pc position and try-index. | 246 // Uses current pc position and try-index. |
| 252 void FlowGraphCompiler::AddCurrentDescriptor(PcDescriptors::Kind kind, | 247 void FlowGraphCompiler::AddCurrentDescriptor(PcDescriptors::Kind kind, |
| 253 intptr_t deopt_id, | 248 intptr_t deopt_id, |
| 254 intptr_t token_pos, | 249 intptr_t token_pos, |
| 255 intptr_t try_index) { | 250 intptr_t try_index) { |
| 256 ASSERT((kind != PcDescriptors::kDeopt) || | |
| 257 frame_register_allocator()->IsSpilled()); | |
| 258 pc_descriptors_list()->AddDescriptor(kind, | 251 pc_descriptors_list()->AddDescriptor(kind, |
| 259 assembler()->CodeSize(), | 252 assembler()->CodeSize(), |
| 260 deopt_id, | 253 deopt_id, |
| 261 token_pos, | 254 token_pos, |
| 262 try_index); | 255 try_index); |
| 263 } | 256 } |
| 264 | 257 |
| 265 | 258 |
| 266 Label* FlowGraphCompiler::AddDeoptStub(intptr_t deopt_id, | 259 Label* FlowGraphCompiler::AddDeoptStub(intptr_t deopt_id, |
| 267 intptr_t try_index, | 260 intptr_t try_index, |
| 268 DeoptReasonId reason, | 261 DeoptReasonId reason) { |
| 269 Register reg1, | |
| 270 Register reg2, | |
| 271 Register reg3) { | |
| 272 DeoptimizationStub* stub = | 262 DeoptimizationStub* stub = |
| 273 new DeoptimizationStub(deopt_id, try_index, reason); | 263 new DeoptimizationStub(deopt_id, try_index, reason); |
| 274 if (pending_deoptimization_env_ == NULL) { | 264 ASSERT(is_optimizing_); |
| 275 ASSERT(!is_ssa_); | 265 ASSERT(pending_deoptimization_env_ != NULL); |
| 276 frame_register_allocator()->SpillInDeoptStub(stub); | 266 stub->set_deoptimization_env(pending_deoptimization_env_); |
| 277 if (reg1 != kNoRegister) stub->Push(reg1); | |
| 278 if (reg2 != kNoRegister) stub->Push(reg2); | |
| 279 if (reg3 != kNoRegister) stub->Push(reg3); | |
| 280 } else { | |
| 281 ASSERT(pending_deoptimization_env_ != NULL); | |
| 282 stub->set_deoptimization_env(pending_deoptimization_env_); | |
| 283 } | |
| 284 deopt_stubs_.Add(stub); | 267 deopt_stubs_.Add(stub); |
| 285 return stub->entry_label(); | 268 return stub->entry_label(); |
| 286 } | 269 } |
| 287 | 270 |
| 288 | 271 |
| 289 void FlowGraphCompiler::FinalizeExceptionHandlers(const Code& code) { | 272 void FlowGraphCompiler::FinalizeExceptionHandlers(const Code& code) { |
| 290 ASSERT(exception_handlers_list_ != NULL); | 273 ASSERT(exception_handlers_list_ != NULL); |
| 291 const ExceptionHandlers& handlers = ExceptionHandlers::Handle( | 274 const ExceptionHandlers& handlers = ExceptionHandlers::Handle( |
| 292 exception_handlers_list_->FinalizeExceptionHandlers(code.EntryPoint())); | 275 exception_handlers_list_->FinalizeExceptionHandlers(code.EntryPoint())); |
| 293 code.set_exception_handlers(handlers); | 276 code.set_exception_handlers(handlers); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 318 | 301 |
| 319 | 302 |
| 320 void FlowGraphCompiler::FinalizeStackmaps(const Code& code) { | 303 void FlowGraphCompiler::FinalizeStackmaps(const Code& code) { |
| 321 if (stackmap_table_builder_ == NULL) { | 304 if (stackmap_table_builder_ == NULL) { |
| 322 // The unoptimizing compiler has no stack maps. | 305 // The unoptimizing compiler has no stack maps. |
| 323 code.set_stackmaps(Array::Handle()); | 306 code.set_stackmaps(Array::Handle()); |
| 324 } else { | 307 } else { |
| 325 // Finalize the stack map array and add it to the code object. | 308 // Finalize the stack map array and add it to the code object. |
| 326 code.set_stackmaps( | 309 code.set_stackmaps( |
| 327 Array::Handle(stackmap_table_builder_->FinalizeStackmaps(code))); | 310 Array::Handle(stackmap_table_builder_->FinalizeStackmaps(code))); |
| 328 ASSERT(is_ssa() && is_optimizing()); | 311 ASSERT(is_optimizing()); |
| 329 } | 312 } |
| 330 } | 313 } |
| 331 | 314 |
| 332 | 315 |
| 333 void FlowGraphCompiler::FinalizeVarDescriptors(const Code& code) { | 316 void FlowGraphCompiler::FinalizeVarDescriptors(const Code& code) { |
| 334 const LocalVarDescriptors& var_descs = LocalVarDescriptors::Handle( | 317 const LocalVarDescriptors& var_descs = LocalVarDescriptors::Handle( |
| 335 parsed_function_.node_sequence()->scope()->GetVarDescriptors( | 318 parsed_function_.node_sequence()->scope()->GetVarDescriptors( |
| 336 parsed_function_.function())); | 319 parsed_function_.function())); |
| 337 code.set_var_descriptors(var_descs); | 320 code.set_var_descriptors(var_descs); |
| 338 } | 321 } |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 387 void FlowGraphCompiler::GenerateInstanceCall( | 370 void FlowGraphCompiler::GenerateInstanceCall( |
| 388 intptr_t deopt_id, | 371 intptr_t deopt_id, |
| 389 intptr_t token_pos, | 372 intptr_t token_pos, |
| 390 intptr_t try_index, | 373 intptr_t try_index, |
| 391 const String& function_name, | 374 const String& function_name, |
| 392 intptr_t argument_count, | 375 intptr_t argument_count, |
| 393 const Array& argument_names, | 376 const Array& argument_names, |
| 394 intptr_t checked_argument_count, | 377 intptr_t checked_argument_count, |
| 395 BitmapBuilder* stack_bitmap) { | 378 BitmapBuilder* stack_bitmap) { |
| 396 ASSERT(!IsLeaf()); | 379 ASSERT(!IsLeaf()); |
| 397 ASSERT(frame_register_allocator()->IsSpilled()); | |
| 398 ICData& ic_data = | 380 ICData& ic_data = |
| 399 ICData::ZoneHandle(ICData::New(parsed_function().function(), | 381 ICData::ZoneHandle(ICData::New(parsed_function().function(), |
| 400 function_name, | 382 function_name, |
| 401 deopt_id, | 383 deopt_id, |
| 402 checked_argument_count)); | 384 checked_argument_count)); |
| 403 const Array& arguments_descriptor = | 385 const Array& arguments_descriptor = |
| 404 DartEntry::ArgumentsDescriptor(argument_count, argument_names); | 386 DartEntry::ArgumentsDescriptor(argument_count, argument_names); |
| 405 uword label_address = 0; | 387 uword label_address = 0; |
| 406 switch (checked_argument_count) { | 388 switch (checked_argument_count) { |
| 407 case 1: | 389 case 1: |
| 408 label_address = StubCode::OneArgCheckInlineCacheEntryPoint(); | 390 label_address = StubCode::OneArgCheckInlineCacheEntryPoint(); |
| 409 break; | 391 break; |
| 410 case 2: | 392 case 2: |
| 411 label_address = StubCode::TwoArgsCheckInlineCacheEntryPoint(); | 393 label_address = StubCode::TwoArgsCheckInlineCacheEntryPoint(); |
| 412 break; | 394 break; |
| 413 default: | 395 default: |
| 414 UNIMPLEMENTED(); | 396 UNIMPLEMENTED(); |
| 415 } | 397 } |
| 416 ExternalLabel target_label("InlineCache", label_address); | 398 ExternalLabel target_label("InlineCache", label_address); |
| 417 | 399 |
| 418 const intptr_t descr_offset = EmitInstanceCall(&target_label, | 400 const intptr_t descr_offset = EmitInstanceCall(&target_label, |
| 419 ic_data, | 401 ic_data, |
| 420 arguments_descriptor, | 402 arguments_descriptor, |
| 421 argument_count); | 403 argument_count); |
| 422 if (is_ssa() && (stack_bitmap != NULL)) { | 404 if (is_optimizing() && (stack_bitmap != NULL)) { |
| 423 stackmap_table_builder_->AddEntry(descr_offset, stack_bitmap); | 405 stackmap_table_builder_->AddEntry(descr_offset, stack_bitmap); |
| 424 } | 406 } |
| 425 pc_descriptors_list()->AddDescriptor(PcDescriptors::kIcCall, | 407 pc_descriptors_list()->AddDescriptor(PcDescriptors::kIcCall, |
| 426 descr_offset, | 408 descr_offset, |
| 427 deopt_id, | 409 deopt_id, |
| 428 token_pos, | 410 token_pos, |
| 429 try_index); | 411 try_index); |
| 430 } | 412 } |
| 431 | 413 |
| 432 | 414 |
| 433 void FlowGraphCompiler::GenerateStaticCall(intptr_t deopt_id, | 415 void FlowGraphCompiler::GenerateStaticCall(intptr_t deopt_id, |
| 434 intptr_t token_pos, | 416 intptr_t token_pos, |
| 435 intptr_t try_index, | 417 intptr_t try_index, |
| 436 const Function& function, | 418 const Function& function, |
| 437 intptr_t argument_count, | 419 intptr_t argument_count, |
| 438 const Array& argument_names, | 420 const Array& argument_names, |
| 439 BitmapBuilder* stack_bitmap) { | 421 BitmapBuilder* stack_bitmap) { |
| 440 ASSERT(frame_register_allocator()->IsSpilled()); | |
| 441 | |
| 442 const Array& arguments_descriptor = | 422 const Array& arguments_descriptor = |
| 443 DartEntry::ArgumentsDescriptor(argument_count, argument_names); | 423 DartEntry::ArgumentsDescriptor(argument_count, argument_names); |
| 444 const intptr_t descr_offset = EmitStaticCall(function, | 424 const intptr_t descr_offset = EmitStaticCall(function, |
| 445 arguments_descriptor, | 425 arguments_descriptor, |
| 446 argument_count); | 426 argument_count); |
| 447 if (is_ssa() && (stack_bitmap != NULL)) { | 427 if (is_optimizing() && (stack_bitmap != NULL)) { |
| 448 stackmap_table_builder_->AddEntry(descr_offset, stack_bitmap); | 428 stackmap_table_builder_->AddEntry(descr_offset, stack_bitmap); |
| 449 } | 429 } |
| 450 pc_descriptors_list()->AddDescriptor(PcDescriptors::kFuncCall, | 430 pc_descriptors_list()->AddDescriptor(PcDescriptors::kFuncCall, |
| 451 descr_offset, | 431 descr_offset, |
| 452 deopt_id, | 432 deopt_id, |
| 453 token_pos, | 433 token_pos, |
| 454 try_index); | 434 try_index); |
| 455 } | 435 } |
| 456 | 436 |
| 457 | 437 |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 573 assembler()->j(true_condition, &is_true, Assembler::kNearJump); | 553 assembler()->j(true_condition, &is_true, Assembler::kNearJump); |
| 574 assembler()->Bind(&is_false); | 554 assembler()->Bind(&is_false); |
| 575 assembler()->LoadObject(result, bool_false()); | 555 assembler()->LoadObject(result, bool_false()); |
| 576 assembler()->jmp(&done); | 556 assembler()->jmp(&done); |
| 577 assembler()->Bind(&is_true); | 557 assembler()->Bind(&is_true); |
| 578 assembler()->LoadObject(result, bool_true()); | 558 assembler()->LoadObject(result, bool_true()); |
| 579 assembler()->Bind(&done); | 559 assembler()->Bind(&done); |
| 580 } | 560 } |
| 581 | 561 |
| 582 | 562 |
| 583 Register FrameRegisterAllocator::AllocateFreeRegister(bool* blocked_registers) { | 563 // Allocate a register that is not explicitly blocked. |
| 564 static Register AllocateFreeRegister(bool* blocked_registers) { |
| 584 for (intptr_t regno = 0; regno < kNumberOfCpuRegisters; regno++) { | 565 for (intptr_t regno = 0; regno < kNumberOfCpuRegisters; regno++) { |
| 585 if (!blocked_registers[regno] && (registers_[regno] == NULL)) { | 566 if (!blocked_registers[regno]) { |
| 586 blocked_registers[regno] = true; | 567 blocked_registers[regno] = true; |
| 587 return static_cast<Register>(regno); | 568 return static_cast<Register>(regno); |
| 588 } | 569 } |
| 589 } | 570 } |
| 590 return SpillFirst(); | 571 UNREACHABLE(); |
| 572 return kNoRegister; |
| 591 } | 573 } |
| 592 | 574 |
| 593 | 575 |
| 594 Register FrameRegisterAllocator::SpillFirst() { | 576 void FlowGraphCompiler::AllocateRegistersLocally(Instruction* instr) { |
| 595 ASSERT(!stack_.is_empty()); | 577 ASSERT(!is_optimizing()); |
| 596 Register reg = stack_[0]; | |
| 597 stack_.RemoveFirst(); | |
| 598 compiler()->assembler()->PushRegister(reg); | |
| 599 registers_[reg] = NULL; | |
| 600 return reg; | |
| 601 } | |
| 602 | |
| 603 | |
| 604 void FrameRegisterAllocator::SpillRegister(Register reg) { | |
| 605 while (registers_[reg] != NULL) SpillFirst(); | |
| 606 } | |
| 607 | |
| 608 | |
| 609 void FrameRegisterAllocator::AllocateRegisters(Instruction* instr) { | |
| 610 if (is_ssa_) return; | |
| 611 | 578 |
| 612 LocationSummary* locs = instr->locs(); | 579 LocationSummary* locs = instr->locs(); |
| 613 | 580 |
| 614 bool blocked_registers[kNumberOfCpuRegisters]; | 581 bool blocked_registers[kNumberOfCpuRegisters]; |
| 615 bool blocked_temp_registers[kNumberOfCpuRegisters]; | |
| 616 | |
| 617 bool spill = false; | |
| 618 | 582 |
| 619 // Mark all available registers free. | 583 // Mark all available registers free. |
| 620 for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) { | 584 for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) { |
| 621 blocked_registers[i] = false; | 585 blocked_registers[i] = false; |
| 622 blocked_temp_registers[i] = false; | |
| 623 } | 586 } |
| 624 | 587 |
| 625 // Mark all fixed input, temp and output registers as used. | 588 // Mark all fixed input, temp and output registers as used. |
| 626 for (intptr_t i = 0; i < locs->input_count(); i++) { | 589 for (intptr_t i = 0; i < locs->input_count(); i++) { |
| 627 Location loc = locs->in(i); | 590 Location loc = locs->in(i); |
| 628 if (loc.IsRegister()) { | 591 if (loc.IsRegister()) { |
| 629 ASSERT(!blocked_registers[loc.reg()]); | 592 ASSERT(!blocked_registers[loc.reg()]); |
| 630 blocked_registers[loc.reg()] = true; | 593 blocked_registers[loc.reg()] = true; |
| 631 if (registers_[loc.reg()] != NULL) { | |
| 632 intptr_t stack_index = stack_.length() - (locs->input_count() - i); | |
| 633 if ((stack_index < 0) || (stack_[stack_index] != loc.reg())) { | |
| 634 spill = true; | |
| 635 } | |
| 636 } | |
| 637 } | 594 } |
| 638 } | 595 } |
| 639 | 596 |
| 640 if (spill) Spill(); | |
| 641 | |
| 642 for (intptr_t i = 0; i < locs->temp_count(); i++) { | 597 for (intptr_t i = 0; i < locs->temp_count(); i++) { |
| 643 Location loc = locs->temp(i); | 598 Location loc = locs->temp(i); |
| 644 if (loc.IsRegister()) { | 599 if (loc.IsRegister()) { |
| 645 ASSERT(!blocked_registers[loc.reg()]); | 600 ASSERT(!blocked_registers[loc.reg()]); |
| 646 blocked_registers[loc.reg()] = true; | 601 blocked_registers[loc.reg()] = true; |
| 647 blocked_temp_registers[loc.reg()] = true; | |
| 648 } | 602 } |
| 649 } | 603 } |
| 650 | 604 |
| 651 if (locs->out().IsRegister()) { | 605 if (locs->out().IsRegister()) { |
| 652 // Fixed output registers are allowed to overlap with | 606 // Fixed output registers are allowed to overlap with |
| 653 // temps and inputs. | 607 // temps and inputs. |
| 654 blocked_registers[locs->out().reg()] = true; | 608 blocked_registers[locs->out().reg()] = true; |
| 655 } | 609 } |
| 656 | 610 |
| 657 // Do not allocate known registers. | 611 // Do not allocate known registers. |
| 658 blocked_registers[CTX] = true; | 612 blocked_registers[CTX] = true; |
| 659 blocked_registers[SPREG] = true; | 613 blocked_registers[SPREG] = true; |
| 660 blocked_registers[FPREG] = true; | 614 blocked_registers[FPREG] = true; |
| 661 if (TMP != kNoRegister) { | 615 if (TMP != kNoRegister) { |
| 662 blocked_registers[TMP] = true; | 616 blocked_registers[TMP] = true; |
| 663 } | 617 } |
| 664 | 618 |
| 665 // Allocate all unallocated input locations. | 619 // Allocate all unallocated input locations. |
| 620 const bool should_pop = !instr->IsPushArgument(); |
| 666 for (intptr_t i = locs->input_count() - 1; i >= 0; i--) { | 621 for (intptr_t i = locs->input_count() - 1; i >= 0; i--) { |
| 667 Location loc = locs->in(i); | 622 Location loc = locs->in(i); |
| 668 Register reg = kNoRegister; | 623 Register reg = kNoRegister; |
| 669 if (loc.IsRegister()) { | 624 if (loc.IsRegister()) { |
| 670 reg = loc.reg(); | 625 reg = loc.reg(); |
| 671 } else if (loc.IsUnallocated()) { | 626 } else if (loc.IsUnallocated()) { |
| 672 ASSERT(loc.policy() == Location::kRequiresRegister); | 627 ASSERT(loc.policy() == Location::kRequiresRegister); |
| 673 if (!stack_.is_empty() && !blocked_temp_registers[stack_.Last()]) { | 628 reg = AllocateFreeRegister(blocked_registers); |
| 674 reg = stack_.Last(); | |
| 675 blocked_registers[reg] = true; | |
| 676 } else { | |
| 677 reg = AllocateFreeRegister(blocked_registers); | |
| 678 } | |
| 679 locs->set_in(i, Location::RegisterLocation(reg)); | 629 locs->set_in(i, Location::RegisterLocation(reg)); |
| 680 } | 630 } |
| 681 | 631 |
| 682 // Inputs are consumed from the simulated frame. In case of a call argument | 632 // Inputs are consumed from the simulated frame. In case of a call argument |
| 683 // we leave it until the call instruction. | 633 // we leave it until the call instruction. |
| 684 if (!instr->IsPushArgument()) Pop(reg, instr->InputAt(i)); | 634 if (should_pop) { |
| 685 } | 635 assembler()->PopRegister(reg); |
| 686 | 636 } |
| 687 // If this instruction is call spill everything that was not consumed by | |
| 688 // input locations. | |
| 689 if (locs->can_call() || instr->IsBranch() || instr->IsGoto()) { | |
| 690 Spill(); | |
| 691 } | 637 } |
| 692 | 638 |
| 693 // Allocate all unallocated temp locations. | 639 // Allocate all unallocated temp locations. |
| 694 for (intptr_t i = 0; i < locs->temp_count(); i++) { | 640 for (intptr_t i = 0; i < locs->temp_count(); i++) { |
| 695 Location loc = locs->temp(i); | 641 Location loc = locs->temp(i); |
| 696 if (loc.IsUnallocated()) { | 642 if (loc.IsUnallocated()) { |
| 697 ASSERT(loc.policy() == Location::kRequiresRegister); | 643 ASSERT(loc.policy() == Location::kRequiresRegister); |
| 698 loc = Location::RegisterLocation( | 644 loc = Location::RegisterLocation( |
| 699 AllocateFreeRegister(blocked_registers)); | 645 AllocateFreeRegister(blocked_registers)); |
| 700 locs->set_temp(i, loc); | 646 locs->set_temp(i, loc); |
| 701 } | 647 } |
| 702 SpillRegister(loc.reg()); | |
| 703 } | 648 } |
| 704 | 649 |
| 705 Location result_location = locs->out(); | 650 Location result_location = locs->out(); |
| 706 if (result_location.IsUnallocated()) { | 651 if (result_location.IsUnallocated()) { |
| 707 switch (result_location.policy()) { | 652 switch (result_location.policy()) { |
| 708 case Location::kAny: | 653 case Location::kAny: |
| 709 case Location::kPrefersRegister: | 654 case Location::kPrefersRegister: |
| 710 case Location::kRequiresRegister: | 655 case Location::kRequiresRegister: |
| 711 result_location = Location::RegisterLocation( | 656 result_location = Location::RegisterLocation( |
| 712 AllocateFreeRegister(blocked_registers)); | 657 AllocateFreeRegister(blocked_registers)); |
| 713 break; | 658 break; |
| 714 case Location::kSameAsFirstInput: | 659 case Location::kSameAsFirstInput: |
| 715 result_location = locs->in(0); | 660 result_location = locs->in(0); |
| 716 break; | 661 break; |
| 717 } | 662 } |
| 718 locs->set_out(result_location); | 663 locs->set_out(result_location); |
| 719 } | 664 } |
| 720 | |
| 721 if (result_location.IsRegister()) { | |
| 722 SpillRegister(result_location.reg()); | |
| 723 } | |
| 724 } | 665 } |
| 725 | 666 |
| 726 | 667 |
| 727 void FrameRegisterAllocator::Pop(Register dst, Value* val) { | |
| 728 if (is_ssa_) return; | |
| 729 | |
| 730 if (!stack_.is_empty()) { | |
| 731 ASSERT(keep_values_in_registers_); | |
| 732 Register src = stack_.Last(); | |
| 733 ASSERT(val->AsUse()->definition() == registers_[src]); | |
| 734 stack_.RemoveLast(); | |
| 735 registers_[src] = NULL; | |
| 736 compiler()->assembler()->MoveRegister(dst, src); | |
| 737 } else { | |
| 738 compiler()->assembler()->PopRegister(dst); | |
| 739 } | |
| 740 } | |
| 741 | |
| 742 | |
| 743 void FrameRegisterAllocator::Push(Register reg, BindInstr* val) { | |
| 744 if (is_ssa_) return; | |
| 745 | |
| 746 ASSERT(registers_[reg] == NULL); | |
| 747 if (keep_values_in_registers_) { | |
| 748 registers_[reg] = val; | |
| 749 stack_.Add(reg); | |
| 750 } else { | |
| 751 compiler()->assembler()->PushRegister(reg); | |
| 752 } | |
| 753 } | |
| 754 | |
| 755 | |
| 756 void FrameRegisterAllocator::Spill() { | |
| 757 if (is_ssa_) return; | |
| 758 | |
| 759 for (int i = 0; i < stack_.length(); i++) { | |
| 760 Register r = stack_[i]; | |
| 761 registers_[r] = NULL; | |
| 762 compiler()->assembler()->PushRegister(r); | |
| 763 } | |
| 764 stack_.Clear(); | |
| 765 } | |
| 766 | |
| 767 | |
| 768 void FrameRegisterAllocator::SpillInDeoptStub(DeoptimizationStub* stub) { | |
| 769 if (is_ssa_) return; | |
| 770 | |
| 771 for (int i = 0; i < stack_.length(); i++) { | |
| 772 stub->Push(stack_[i]); | |
| 773 } | |
| 774 } | |
| 775 | |
| 776 | |
| 777 ParallelMoveResolver::ParallelMoveResolver(FlowGraphCompiler* compiler) | 668 ParallelMoveResolver::ParallelMoveResolver(FlowGraphCompiler* compiler) |
| 778 : compiler_(compiler), moves_(32) {} | 669 : compiler_(compiler), moves_(32) {} |
| 779 | 670 |
| 780 | 671 |
| 781 void ParallelMoveResolver::EmitNativeCode(ParallelMoveInstr* parallel_move) { | 672 void ParallelMoveResolver::EmitNativeCode(ParallelMoveInstr* parallel_move) { |
| 782 ASSERT(moves_.is_empty()); | 673 ASSERT(moves_.is_empty()); |
| 783 // Build up a worklist of moves. | 674 // Build up a worklist of moves. |
| 784 BuildInitialMoveList(parallel_move); | 675 BuildInitialMoveList(parallel_move); |
| 785 | 676 |
| 786 for (int i = 0; i < moves_.length(); ++i) { | 677 for (int i = 0; i < moves_.length(); ++i) { |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 876 return; | 767 return; |
| 877 } | 768 } |
| 878 } | 769 } |
| 879 | 770 |
| 880 // This move is not blocked. | 771 // This move is not blocked. |
| 881 EmitMove(index); | 772 EmitMove(index); |
| 882 } | 773 } |
| 883 | 774 |
| 884 | 775 |
| 885 } // namespace dart | 776 } // namespace dart |
| OLD | NEW |