| 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_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 7 | 7 |
| 8 #include "vm/flow_graph_compiler.h" | 8 #include "vm/flow_graph_compiler.h" |
| 9 | 9 |
| 10 #include "vm/ast_printer.h" | 10 #include "vm/ast_printer.h" |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 | 22 |
| 23 FlowGraphCompiler::FlowGraphCompiler( | 23 FlowGraphCompiler::FlowGraphCompiler( |
| 24 Assembler* assembler, | 24 Assembler* assembler, |
| 25 const ParsedFunction& parsed_function, | 25 const ParsedFunction& parsed_function, |
| 26 const GrowableArray<BlockEntryInstr*>* blocks) | 26 const GrowableArray<BlockEntryInstr*>* blocks) |
| 27 : assembler_(assembler), | 27 : assembler_(assembler), |
| 28 parsed_function_(parsed_function), | 28 parsed_function_(parsed_function), |
| 29 blocks_(blocks), | 29 blocks_(blocks), |
| 30 block_info_(blocks->length()), | 30 block_info_(blocks->length()), |
| 31 current_block_(NULL), | 31 current_block_(NULL), |
| 32 pc_descriptors_list_(new CodeGenerator::DescriptorList()), | 32 pc_descriptors_list_(new CodeGenerator::DescriptorList()) { |
| 33 stack_local_count_(0) { | |
| 34 for (int i = 0; i < blocks->length(); ++i) { | 33 for (int i = 0; i < blocks->length(); ++i) { |
| 35 block_info_.Add(new BlockInfo()); | 34 block_info_.Add(new BlockInfo()); |
| 36 } | 35 } |
| 37 } | 36 } |
| 38 | 37 |
| 39 | 38 |
| 40 FlowGraphCompiler::~FlowGraphCompiler() { | 39 FlowGraphCompiler::~FlowGraphCompiler() { |
| 41 // BlockInfos are zone-allocated, so their destructors are not called. | 40 // BlockInfos are zone-allocated, so their destructors are not called. |
| 42 // Verify the labels explicitly here. | 41 // Verify the labels explicitly here. |
| 43 for (int i = 0; i < block_info_.length(); ++i) { | 42 for (int i = 0; i < block_info_.length(); ++i) { |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 157 default: | 156 default: |
| 158 UNIMPLEMENTED(); | 157 UNIMPLEMENTED(); |
| 159 } | 158 } |
| 160 ExternalLabel target_label("InlineCache", label_address); | 159 ExternalLabel target_label("InlineCache", label_address); |
| 161 __ call(&target_label); | 160 __ call(&target_label); |
| 162 AddCurrentDescriptor(PcDescriptors::kIcCall, node_id, token_index); | 161 AddCurrentDescriptor(PcDescriptors::kIcCall, node_id, token_index); |
| 163 __ addq(RSP, Immediate(argument_count * kWordSize)); | 162 __ addq(RSP, Immediate(argument_count * kWordSize)); |
| 164 } | 163 } |
| 165 | 164 |
| 166 | 165 |
| 166 void FlowGraphCompiler::VisitCurrentContext(CurrentContextComp* comp) { |
| 167 __ movq(RAX, CTX); |
| 168 } |
| 169 |
| 170 |
| 171 void FlowGraphCompiler::VisitClosureCall(ClosureCallComp* comp) { |
| 172 ASSERT(comp->context()->IsTemp()); |
| 173 ASSERT(VerifyCallComputation(comp)); |
| 174 // The arguments to the stub include the closure. The arguments |
| 175 // descriptor describes the closure's arguments (and so does not include |
| 176 // the closure). |
| 177 int argument_count = comp->ArgumentCount(); |
| 178 const Array& arguments_descriptor = |
| 179 CodeGenerator::ArgumentsDescriptor(argument_count - 1, |
| 180 comp->argument_names()); |
| 181 __ LoadObject(R10, arguments_descriptor); |
| 182 |
| 183 GenerateCall(comp->token_index(), |
| 184 &StubCode::CallClosureFunctionLabel(), |
| 185 PcDescriptors::kOther); |
| 186 __ addq(RSP, Immediate(argument_count * kWordSize)); |
| 187 __ popq(CTX); |
| 188 } |
| 189 |
| 190 |
| 167 void FlowGraphCompiler::VisitInstanceCall(InstanceCallComp* comp) { | 191 void FlowGraphCompiler::VisitInstanceCall(InstanceCallComp* comp) { |
| 168 ASSERT(VerifyCallComputation(comp)); | 192 ASSERT(VerifyCallComputation(comp)); |
| 169 EmitInstanceCall(comp->node_id(), | 193 EmitInstanceCall(comp->node_id(), |
| 170 comp->token_index(), | 194 comp->token_index(), |
| 171 comp->function_name(), | 195 comp->function_name(), |
| 172 comp->ArgumentCount(), | 196 comp->ArgumentCount(), |
| 173 comp->argument_names(), | 197 comp->argument_names(), |
| 174 comp->checked_argument_count()); | 198 comp->checked_argument_count()); |
| 175 } | 199 } |
| 176 | 200 |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 359 if (comp->ElementAt(i)->IsTemp()) { | 383 if (comp->ElementAt(i)->IsTemp()) { |
| 360 __ popq(Address(RCX, i * kWordSize)); | 384 __ popq(Address(RCX, i * kWordSize)); |
| 361 } else { | 385 } else { |
| 362 LoadValue(RDX, comp->ElementAt(i)); | 386 LoadValue(RDX, comp->ElementAt(i)); |
| 363 __ movq(Address(RCX, i * kWordSize), RDX); | 387 __ movq(Address(RCX, i * kWordSize), RDX); |
| 364 } | 388 } |
| 365 } | 389 } |
| 366 } | 390 } |
| 367 | 391 |
| 368 | 392 |
| 393 void FlowGraphCompiler::VisitCreateClosure(CreateClosureComp* comp) { |
| 394 const Function& function = comp->function(); |
| 395 const Code& stub = Code::Handle( |
| 396 StubCode::GetAllocationStubForClosure(function)); |
| 397 const ExternalLabel label(function.ToCString(), stub.EntryPoint()); |
| 398 GenerateCall(comp->token_index(), &label, PcDescriptors::kOther); |
| 399 |
| 400 const Class& cls = Class::Handle(function.signature_class()); |
| 401 if (cls.HasTypeArguments()) { |
| 402 __ popq(RCX); // Discard type arguments. |
| 403 } |
| 404 if (function.IsImplicitInstanceClosureFunction()) { |
| 405 __ popq(RCX); // Discard receiver. |
| 406 } |
| 407 } |
| 408 |
| 409 |
| 369 void FlowGraphCompiler::VisitBlocks( | 410 void FlowGraphCompiler::VisitBlocks( |
| 370 const GrowableArray<BlockEntryInstr*>& blocks) { | 411 const GrowableArray<BlockEntryInstr*>& blocks) { |
| 371 for (intptr_t i = blocks.length() - 1; i >= 0; --i) { | 412 for (intptr_t i = blocks.length() - 1; i >= 0; --i) { |
| 372 // Compile the block entry. | 413 // Compile the block entry. |
| 373 current_block_ = blocks[i]; | 414 current_block_ = blocks[i]; |
| 374 Instruction* instr = current_block()->Accept(this); | 415 Instruction* instr = current_block()->Accept(this); |
| 375 // Compile all successors until an exit, branch, or a block entry. | 416 // Compile all successors until an exit, branch, or a block entry. |
| 376 while ((instr != NULL) && !instr->IsBlockEntry()) { | 417 while ((instr != NULL) && !instr->IsBlockEntry()) { |
| 377 instr = instr->Accept(this); | 418 instr = instr->Accept(this); |
| 378 } | 419 } |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 433 } | 474 } |
| 434 | 475 |
| 435 | 476 |
| 436 void FlowGraphCompiler::VisitReturn(ReturnInstr* instr) { | 477 void FlowGraphCompiler::VisitReturn(ReturnInstr* instr) { |
| 437 LoadValue(RAX, instr->value()); | 478 LoadValue(RAX, instr->value()); |
| 438 | 479 |
| 439 #ifdef DEBUG | 480 #ifdef DEBUG |
| 440 // Check that the entry stack size matches the exit stack size. | 481 // Check that the entry stack size matches the exit stack size. |
| 441 __ movq(R10, RBP); | 482 __ movq(R10, RBP); |
| 442 __ subq(R10, RSP); | 483 __ subq(R10, RSP); |
| 443 __ cmpq(R10, Immediate(stack_local_count() * kWordSize)); | 484 __ cmpq(R10, Immediate(parsed_function_.local_count() * kWordSize)); |
| 444 Label stack_ok; | 485 Label stack_ok; |
| 445 __ j(EQUAL, &stack_ok, Assembler::kNearJump); | 486 __ j(EQUAL, &stack_ok, Assembler::kNearJump); |
| 446 __ Stop("Exit stack size does not match the entry stack size."); | 487 __ Stop("Exit stack size does not match the entry stack size."); |
| 447 __ Bind(&stack_ok); | 488 __ Bind(&stack_ok); |
| 448 #endif // DEBUG. | 489 #endif // DEBUG. |
| 449 | 490 |
| 450 if (FLAG_trace_functions) { | 491 if (FLAG_trace_functions) { |
| 451 __ pushq(RAX); // Preserve result. | 492 __ pushq(RAX); // Preserve result. |
| 452 const Function& function = | 493 const Function& function = |
| 453 Function::ZoneHandle(parsed_function_.function().raw()); | 494 Function::ZoneHandle(parsed_function_.function().raw()); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 493 if (negated) { | 534 if (negated) { |
| 494 __ j(EQUAL, &block_info_[instr->true_successor()->block_number()]->label); | 535 __ j(EQUAL, &block_info_[instr->true_successor()->block_number()]->label); |
| 495 } else { | 536 } else { |
| 496 __ j(NOT_EQUAL, | 537 __ j(NOT_EQUAL, |
| 497 &block_info_[instr->false_successor()->block_number()]->label); | 538 &block_info_[instr->false_successor()->block_number()]->label); |
| 498 } | 539 } |
| 499 } | 540 } |
| 500 | 541 |
| 501 | 542 |
| 502 void FlowGraphCompiler::CompileGraph() { | 543 void FlowGraphCompiler::CompileGraph() { |
| 544 // Specialized version of entry code from CodeGenerator::GenerateEntryCode. |
| 503 const Function& function = parsed_function_.function(); | 545 const Function& function = parsed_function_.function(); |
| 504 if ((function.num_optional_parameters() != 0)) { | 546 |
| 505 Bailout("function has optional parameters"); | 547 // We don't implement copied parameters yet and should have bailed out |
| 506 } | 548 // from the graph builder. |
| 507 LocalScope* scope = parsed_function_.node_sequence()->scope(); | 549 ASSERT(function.num_optional_parameters() == 0); |
| 508 LocalScope* context_owner = NULL; | |
| 509 const int parameter_count = function.num_fixed_parameters(); | 550 const int parameter_count = function.num_fixed_parameters(); |
| 510 const int first_parameter_index = 1 + parameter_count; | 551 const int local_count = parsed_function_.local_count(); |
| 511 const int first_local_index = -1; | 552 __ EnterFrame(local_count * kWordSize); |
| 512 int first_free_frame_index = | |
| 513 scope->AllocateVariables(first_parameter_index, | |
| 514 parameter_count, | |
| 515 first_local_index, | |
| 516 scope, | |
| 517 &context_owner); | |
| 518 set_stack_local_count(first_local_index - first_free_frame_index); | |
| 519 | |
| 520 // Specialized version of entry code from CodeGenerator::GenerateEntryCode. | |
| 521 __ EnterFrame(stack_local_count() * kWordSize); | |
| 522 #ifdef DEBUG | 553 #ifdef DEBUG |
| 523 const bool check_arguments = true; | 554 const bool check_arguments = true; |
| 524 #else | 555 #else |
| 525 const bool check_arguments = function.IsClosureFunction(); | 556 const bool check_arguments = function.IsClosureFunction(); |
| 526 #endif | 557 #endif |
| 527 if (check_arguments) { | 558 if (check_arguments) { |
| 528 // Check that num_fixed <= argc <= num_params. | 559 // Check that num_fixed <= argc <= num_params. |
| 529 Label argc_in_range; | 560 Label argc_in_range; |
| 530 // Total number of args is the first Smi in args descriptor array (R10). | 561 // Total number of args is the first Smi in args descriptor array (R10). |
| 531 __ movq(RAX, FieldAddress(R10, Array::data_offset())); | 562 __ movq(RAX, FieldAddress(R10, Array::data_offset())); |
| 532 __ cmpq(RAX, Immediate(Smi::RawValue(parameter_count))); | 563 __ cmpq(RAX, Immediate(Smi::RawValue(parameter_count))); |
| 533 __ j(EQUAL, &argc_in_range, Assembler::kNearJump); | 564 __ j(EQUAL, &argc_in_range, Assembler::kNearJump); |
| 534 if (function.IsClosureFunction()) { | 565 if (function.IsClosureFunction()) { |
| 535 GenerateCallRuntime(AstNode::kNoId, | 566 GenerateCallRuntime(AstNode::kNoId, |
| 536 function.token_index(), | 567 function.token_index(), |
| 537 kClosureArgumentMismatchRuntimeEntry); | 568 kClosureArgumentMismatchRuntimeEntry); |
| 538 } else { | 569 } else { |
| 539 __ Stop("Wrong number of arguments"); | 570 __ Stop("Wrong number of arguments"); |
| 540 } | 571 } |
| 541 __ Bind(&argc_in_range); | 572 __ Bind(&argc_in_range); |
| 542 } | 573 } |
| 543 | 574 |
| 544 // Initialize locals to null. | 575 // Initialize locals to null. |
| 545 if (stack_local_count() > 0) { | 576 if (local_count > 0) { |
| 546 __ movq(RAX, Immediate(reinterpret_cast<intptr_t>(Object::null()))); | 577 __ movq(RAX, Immediate(reinterpret_cast<intptr_t>(Object::null()))); |
| 547 for (int i = 0; i < stack_local_count(); ++i) { | 578 const int base = parsed_function_.first_local_index(); |
| 579 for (int i = 0; i < local_count; ++i) { |
| 548 // Subtract index i (locals lie at lower addresses than RBP). | 580 // Subtract index i (locals lie at lower addresses than RBP). |
| 549 __ movq(Address(RBP, (first_local_index - i) * kWordSize), RAX); | 581 __ movq(Address(RBP, (base - i) * kWordSize), RAX); |
| 550 } | 582 } |
| 551 } | 583 } |
| 552 | 584 |
| 553 // Generate stack overflow check. | 585 // Generate stack overflow check. |
| 554 __ movq(TMP, Immediate(Isolate::Current()->stack_limit_address())); | 586 __ movq(TMP, Immediate(Isolate::Current()->stack_limit_address())); |
| 555 __ cmpq(RSP, Address(TMP, 0)); | 587 __ cmpq(RSP, Address(TMP, 0)); |
| 556 Label no_stack_overflow; | 588 Label no_stack_overflow; |
| 557 __ j(ABOVE, &no_stack_overflow, Assembler::kNearJump); | 589 __ j(ABOVE, &no_stack_overflow, Assembler::kNearJump); |
| 558 GenerateCallRuntime(AstNode::kNoId, | 590 GenerateCallRuntime(AstNode::kNoId, |
| 559 function.token_index(), | 591 function.token_index(), |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 632 void FlowGraphCompiler::FinalizeExceptionHandlers(const Code& code) { | 664 void FlowGraphCompiler::FinalizeExceptionHandlers(const Code& code) { |
| 633 // We don't compile exception handlers yet. | 665 // We don't compile exception handlers yet. |
| 634 code.set_exception_handlers( | 666 code.set_exception_handlers( |
| 635 ExceptionHandlers::Handle(ExceptionHandlers::New(0))); | 667 ExceptionHandlers::Handle(ExceptionHandlers::New(0))); |
| 636 } | 668 } |
| 637 | 669 |
| 638 | 670 |
| 639 } // namespace dart | 671 } // namespace dart |
| 640 | 672 |
| 641 #endif // defined TARGET_ARCH_X64 | 673 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |