| 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/code_generator.h" | 8 #include "vm/code_generator.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 349 // RSP + 8 : address of last argument (arg n-1). | 349 // RSP + 8 : address of last argument (arg n-1). |
| 350 // RSP + 8*n : address of first argument (arg 0). | 350 // RSP + 8*n : address of first argument (arg 0). |
| 351 // R10 : arguments descriptor array. | 351 // R10 : arguments descriptor array. |
| 352 void CodeGenerator::GenerateEntryCode() { | 352 void CodeGenerator::GenerateEntryCode() { |
| 353 const Immediate raw_null = | 353 const Immediate raw_null = |
| 354 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 354 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 355 const Function& function = parsed_function_.function(); | 355 const Function& function = parsed_function_.function(); |
| 356 LocalScope* scope = parsed_function_.node_sequence()->scope(); | 356 LocalScope* scope = parsed_function_.node_sequence()->scope(); |
| 357 const int num_fixed_params = function.num_fixed_parameters(); | 357 const int num_fixed_params = function.num_fixed_parameters(); |
| 358 const int num_opt_params = function.num_optional_parameters(); | 358 const int num_opt_params = function.num_optional_parameters(); |
| 359 const int num_params = num_fixed_params + num_opt_params; | 359 const int num_copied_params = parsed_function_.copied_parameter_count(); |
| 360 int first_param_index; | 360 const int stack_slot_count = |
| 361 int first_local_index; | 361 num_copied_params + parsed_function_.local_count(); |
| 362 int num_copied_params; | 362 set_locals_space_size(stack_slot_count * kWordSize); |
| 363 // Assign indices to parameters and locals. | |
| 364 if (num_params == num_fixed_params) { | |
| 365 // No need to copy incoming arguments. | |
| 366 // The body of the function will access parameter i at fp[1 + num_fixed - i] | |
| 367 // and local variable j at fp[-1 - j]. | |
| 368 first_param_index = 1 + num_params; | |
| 369 first_local_index = -1; | |
| 370 num_copied_params = 0; | |
| 371 } else { | |
| 372 // The body of the function will access copied parameter i at fp[-1 - i] | |
| 373 // and local j at fp[-1 - num_params - j]. | |
| 374 first_param_index = -1; | |
| 375 first_local_index = -1 - num_params; | |
| 376 num_copied_params = num_params; | |
| 377 ASSERT(num_copied_params > 0); | |
| 378 } | |
| 379 | |
| 380 // Allocate parameters and local variables, either in the local frame or in | |
| 381 // the context(s). | |
| 382 LocalScope* context_owner = NULL; // No context needed so far. | |
| 383 int first_free_frame_index = | |
| 384 scope->AllocateVariables(first_param_index, | |
| 385 num_params, | |
| 386 first_local_index, | |
| 387 scope, // Initial loop owner. | |
| 388 &context_owner); | |
| 389 // Frame indices are relative to the frame pointer and are decreasing. | |
| 390 ASSERT(first_free_frame_index <= first_local_index); | |
| 391 const int num_locals = first_local_index - first_free_frame_index; | |
| 392 | 363 |
| 393 // Reserve local space for copied incoming and default arguments and locals. | 364 // Reserve local space for copied incoming and default arguments and locals. |
| 394 // TODO(regis): We may give up reserving space on stack for args/locals | 365 // TODO(regis): We may give up reserving space on stack for args/locals |
| 395 // because pushes of initial values may be more effective than moves. | 366 // because pushes of initial values may be more effective than moves. |
| 396 set_locals_space_size((num_copied_params + num_locals) * kWordSize); | |
| 397 __ EnterFrame(locals_space_size()); | 367 __ EnterFrame(locals_space_size()); |
| 398 | 368 |
| 399 // We check the number of passed arguments when we have to copy them due to | 369 // We check the number of passed arguments when we have to copy them due to |
| 400 // the presence of optional named parameters. | 370 // the presence of optional named parameters. |
| 401 // No such checking code is generated if only fixed parameters are declared, | 371 // No such checking code is generated if only fixed parameters are declared, |
| 402 // unless we are debug mode or unless we are compiling a closure. | 372 // unless we are debug mode or unless we are compiling a closure. |
| 403 if (num_copied_params == 0) { | 373 if (num_copied_params == 0) { |
| 404 #if defined(DEBUG) | 374 #if defined(DEBUG) |
| 405 const bool check_arguments = true; // Always check arguments in debug mode. | 375 const bool check_arguments = true; // Always check arguments in debug mode. |
| 406 #else | 376 #else |
| (...skipping 18 matching lines...) Expand all Loading... |
| 425 if (function.IsClosureFunction()) { | 395 if (function.IsClosureFunction()) { |
| 426 GenerateCallRuntime(AstNode::kNoId, | 396 GenerateCallRuntime(AstNode::kNoId, |
| 427 0, | 397 0, |
| 428 kClosureArgumentMismatchRuntimeEntry); | 398 kClosureArgumentMismatchRuntimeEntry); |
| 429 } else { | 399 } else { |
| 430 __ Stop("Wrong number of arguments"); | 400 __ Stop("Wrong number of arguments"); |
| 431 } | 401 } |
| 432 __ Bind(&argc_in_range); | 402 __ Bind(&argc_in_range); |
| 433 } | 403 } |
| 434 } else { | 404 } else { |
| 435 ASSERT(first_param_index == -1); | 405 ASSERT(parsed_function_.first_parameter_index() == -1); |
| 436 // Copy positional arguments. | 406 // Copy positional arguments. |
| 437 // Check that no fewer than num_fixed_params positional arguments are passed | 407 // Check that no fewer than num_fixed_params positional arguments are passed |
| 438 // in and that no more than num_params arguments are passed in. | 408 // in and that no more than num_params arguments are passed in. |
| 439 // Passed argument i at fp[1 + argc - i] copied to fp[-1 - i]. | 409 // Passed argument i at fp[1 + argc - i] copied to fp[-1 - i]. |
| 410 const int num_params = num_fixed_params + num_opt_params; |
| 440 | 411 |
| 441 // Total number of args is the first Smi in args descriptor array (R10). | 412 // Total number of args is the first Smi in args descriptor array (R10). |
| 442 __ movq(RBX, FieldAddress(R10, Array::data_offset())); | 413 __ movq(RBX, FieldAddress(R10, Array::data_offset())); |
| 443 // Check that num_args <= num_params. | 414 // Check that num_args <= num_params. |
| 444 Label wrong_num_arguments; | 415 Label wrong_num_arguments; |
| 445 __ cmpq(RBX, Immediate(Smi::RawValue(num_params))); | 416 __ cmpq(RBX, Immediate(Smi::RawValue(num_params))); |
| 446 __ j(GREATER, &wrong_num_arguments); | 417 __ j(GREATER, &wrong_num_arguments); |
| 447 // Number of positional args is the second Smi in descriptor array (R10). | 418 // Number of positional args is the second Smi in descriptor array (R10). |
| 448 __ movq(RCX, FieldAddress(R10, Array::data_offset() + (1 * kWordSize))); | 419 __ movq(RCX, FieldAddress(R10, Array::data_offset() + (1 * kWordSize))); |
| 449 // Check that num_pos_args >= num_fixed_params. | 420 // Check that num_pos_args >= num_fixed_params. |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 599 __ movq(original_argument_addr, raw_null); | 570 __ movq(original_argument_addr, raw_null); |
| 600 __ Bind(&null_args_loop_condition); | 571 __ Bind(&null_args_loop_condition); |
| 601 __ decq(RCX); | 572 __ decq(RCX); |
| 602 __ j(POSITIVE, &null_args_loop, Assembler::kNearJump); | 573 __ j(POSITIVE, &null_args_loop, Assembler::kNearJump); |
| 603 } | 574 } |
| 604 | 575 |
| 605 // Initialize locals. | 576 // Initialize locals. |
| 606 // TODO(regis): For now, always unroll the init loop. Decide later above | 577 // TODO(regis): For now, always unroll the init loop. Decide later above |
| 607 // which threshold to implement a loop. | 578 // which threshold to implement a loop. |
| 608 // Consider emitting pushes instead of moves. | 579 // Consider emitting pushes instead of moves. |
| 609 for (int index = first_local_index; index > first_free_frame_index; index--) { | 580 const int base = parsed_function_.first_local_index(); |
| 610 if (index == first_local_index) { | 581 for (int index = 0; index < parsed_function_.local_count(); ++index) { |
| 582 if (index == 0) { |
| 611 __ movq(RAX, raw_null); | 583 __ movq(RAX, raw_null); |
| 612 } | 584 } |
| 613 __ movq(Address(RBP, index * kWordSize), RAX); | 585 __ movq(Address(RBP, (base - index) * kWordSize), RAX); |
| 614 } | 586 } |
| 615 | 587 |
| 616 // Generate stack overflow check. | 588 // Generate stack overflow check. |
| 617 __ movq(TMP, Immediate(Isolate::Current()->stack_limit_address())); | 589 __ movq(TMP, Immediate(Isolate::Current()->stack_limit_address())); |
| 618 __ cmpq(RSP, Address(TMP, 0)); | 590 __ cmpq(RSP, Address(TMP, 0)); |
| 619 Label no_stack_overflow; | 591 Label no_stack_overflow; |
| 620 __ j(ABOVE, &no_stack_overflow); | 592 __ j(ABOVE, &no_stack_overflow); |
| 621 GenerateCallRuntime(AstNode::kNoId, | 593 GenerateCallRuntime(AstNode::kNoId, |
| 622 0, | 594 0, |
| 623 kStackOverflowRuntimeEntry); | 595 kStackOverflowRuntimeEntry); |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 744 node->type(), | 716 node->type(), |
| 745 node->dst_name()); | 717 node->dst_name()); |
| 746 if (IsResultNeeded(node)) { | 718 if (IsResultNeeded(node)) { |
| 747 __ pushq(RAX); | 719 __ pushq(RAX); |
| 748 } | 720 } |
| 749 } | 721 } |
| 750 | 722 |
| 751 | 723 |
| 752 void CodeGenerator::VisitClosureNode(ClosureNode* node) { | 724 void CodeGenerator::VisitClosureNode(ClosureNode* node) { |
| 753 const Function& function = node->function(); | 725 const Function& function = node->function(); |
| 754 if (function.IsNonImplicitClosureFunction()) { | 726 if (function.IsNonImplicitClosureFunction() && |
| 727 (function.context_scope() == ContextScope::null())) { |
| 755 const int current_context_level = state()->context_level(); | 728 const int current_context_level = state()->context_level(); |
| 756 const ContextScope& context_scope = ContextScope::ZoneHandle( | 729 const ContextScope& context_scope = ContextScope::ZoneHandle( |
| 757 node->scope()->PreserveOuterScope(current_context_level)); | 730 node->scope()->PreserveOuterScope(current_context_level)); |
| 758 ASSERT(!function.HasCode()); | 731 ASSERT(!function.HasCode()); |
| 759 ASSERT(function.context_scope() == ContextScope::null()); | |
| 760 function.set_context_scope(context_scope); | 732 function.set_context_scope(context_scope); |
| 761 } else { | 733 } else { |
| 762 ASSERT(function.context_scope() != ContextScope::null()); | |
| 763 if (function.IsImplicitInstanceClosureFunction()) { | 734 if (function.IsImplicitInstanceClosureFunction()) { |
| 764 node->receiver()->Visit(this); | 735 node->receiver()->Visit(this); |
| 765 } | 736 } |
| 766 } | 737 } |
| 738 ASSERT(function.context_scope() != ContextScope::null()); |
| 739 |
| 767 // The function type of a closure may have type arguments. In that case, pass | 740 // The function type of a closure may have type arguments. In that case, pass |
| 768 // the type arguments of the instantiator. | 741 // the type arguments of the instantiator. |
| 769 const Class& cls = Class::Handle(function.signature_class()); | 742 const Class& cls = Class::Handle(function.signature_class()); |
| 770 ASSERT(!cls.IsNull()); | 743 ASSERT(!cls.IsNull()); |
| 771 const bool requires_type_arguments = cls.HasTypeArguments(); | 744 const bool requires_type_arguments = cls.HasTypeArguments(); |
| 772 if (requires_type_arguments) { | 745 if (requires_type_arguments) { |
| 773 ASSERT(!function.IsImplicitStaticClosureFunction()); | 746 ASSERT(!function.IsImplicitStaticClosureFunction()); |
| 774 GenerateInstantiatorTypeArguments(node->token_index()); | 747 GenerateInstantiatorTypeArguments(node->token_index()); |
| 775 } | 748 } |
| 776 const Code& stub = Code::Handle( | 749 const Code& stub = Code::Handle( |
| (...skipping 1896 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2673 const Error& error = Error::Handle( | 2646 const Error& error = Error::Handle( |
| 2674 Parser::FormatError(script, token_index, "Error", format, args)); | 2647 Parser::FormatError(script, token_index, "Error", format, args)); |
| 2675 va_end(args); | 2648 va_end(args); |
| 2676 Isolate::Current()->long_jump_base()->Jump(1, error); | 2649 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 2677 UNREACHABLE(); | 2650 UNREACHABLE(); |
| 2678 } | 2651 } |
| 2679 | 2652 |
| 2680 } // namespace dart | 2653 } // namespace dart |
| 2681 | 2654 |
| 2682 #endif // defined TARGET_ARCH_X64 | 2655 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |