Chromium Code Reviews| 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_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
| 6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
| 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 // ESP + 4 : address of last argument (arg n-1). | 349 // ESP + 4 : address of last argument (arg n-1). |
| 350 // ESP + 4*n : address of first argument (arg 0). | 350 // ESP + 4*n : address of first argument (arg 0). |
| 351 // EDX : arguments descriptor array. | 351 // EDX : 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 = parsed_function_.local_count(); |
| 361 int first_local_index; | 361 set_locals_space_size(stack_slot_count * kWordSize); |
| 362 int num_copied_params; | |
| 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 | 362 |
| 393 // Reserve local space for copied incoming and default arguments and locals. | 363 // 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 | 364 // 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. | 365 // 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()); | 366 __ EnterFrame(locals_space_size()); |
| 398 | 367 |
| 399 // We check the number of passed arguments when we have to copy them due to | 368 // We check the number of passed arguments when we have to copy them due to |
| 400 // the presence of optional named parameters. | 369 // the presence of optional named parameters. |
| 401 // No such checking code is generated if only fixed parameters are declared, | 370 // 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. | 371 // unless we are debug mode or unless we are compiling a closure. |
| 403 if (num_copied_params == 0) { | 372 if (num_copied_params == 0) { |
| 373 ASSERT(num_opt_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 |
| 407 // The number of arguments passed to closure functions must always be | 377 // The number of arguments passed to closure functions must always be |
| 408 // checked here, because no resolving stub (normally responsible for the | 378 // checked here, because no resolving stub (normally responsible for the |
| 409 // check) is involved in closure calls. | 379 // check) is involved in closure calls. |
| 410 const bool check_arguments = function.IsClosureFunction(); | 380 const bool check_arguments = function.IsClosureFunction(); |
| 411 #endif | 381 #endif |
| 412 if (check_arguments) { | 382 if (check_arguments) { |
| 413 // Check that num_fixed <= argc <= num_params. | 383 // Check that num_fixed <= argc <= num_params. |
| 414 Label argc_in_range; | 384 Label argc_in_range; |
| 415 // Total number of args is the first Smi in args descriptor array (EDX). | 385 // Total number of args is the first Smi in args descriptor array (EDX). |
| 416 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 386 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 417 if (num_opt_params == 0) { | 387 __ cmpl(EAX, Immediate(Smi::RawValue(num_fixed_params))); |
| 418 __ cmpl(EAX, Immediate(Smi::RawValue(num_fixed_params))); | 388 __ j(EQUAL, &argc_in_range, Assembler::kNearJump); |
| 419 __ j(EQUAL, &argc_in_range, Assembler::kNearJump); | |
| 420 } else { | |
| 421 __ subl(EAX, Immediate(Smi::RawValue(num_fixed_params))); | |
| 422 __ cmpl(EAX, Immediate(Smi::RawValue(num_opt_params))); | |
| 423 __ j(BELOW_EQUAL, &argc_in_range, Assembler::kNearJump); | |
| 424 } | |
| 425 if (function.IsClosureFunction()) { | 389 if (function.IsClosureFunction()) { |
| 426 GenerateCallRuntime(AstNode::kNoId, | 390 GenerateCallRuntime(AstNode::kNoId, |
| 427 0, | 391 0, |
| 428 kClosureArgumentMismatchRuntimeEntry); | 392 kClosureArgumentMismatchRuntimeEntry); |
| 429 } else { | 393 } else { |
| 430 __ Stop("Wrong number of arguments"); | 394 __ Stop("Wrong number of arguments"); |
| 431 } | 395 } |
| 432 __ Bind(&argc_in_range); | 396 __ Bind(&argc_in_range); |
| 433 } | 397 } |
| 434 } else { | 398 } else { |
| 435 ASSERT(first_param_index == -1); | 399 ASSERT(parsed_function_.first_parameter_index() == -1); |
| 436 // Copy positional arguments. | 400 // Copy positional arguments. |
| 437 // Check that no fewer than num_fixed_params positional arguments are passed | 401 // 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. | 402 // 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]. | 403 // Passed argument i at fp[1 + argc - i] copied to fp[-1 - i]. |
| 404 const int num_params = num_fixed_params + num_opt_params; | |
| 440 | 405 |
| 441 // Total number of args is the first Smi in args descriptor array (EDX). | 406 // Total number of args is the first Smi in args descriptor array (EDX). |
| 442 __ movl(EBX, FieldAddress(EDX, Array::data_offset())); | 407 __ movl(EBX, FieldAddress(EDX, Array::data_offset())); |
| 443 // Check that num_args <= num_params. | 408 // Check that num_args <= num_params. |
| 444 Label wrong_num_arguments; | 409 Label wrong_num_arguments; |
| 445 __ cmpl(EBX, Immediate(Smi::RawValue(num_params))); | 410 __ cmpl(EBX, Immediate(Smi::RawValue(num_params))); |
| 446 __ j(GREATER, &wrong_num_arguments); | 411 __ j(GREATER, &wrong_num_arguments); |
| 447 // Number of positional args is the second Smi in descriptor array (EDX). | 412 // Number of positional args is the second Smi in descriptor array (EDX). |
| 448 __ movl(ECX, FieldAddress(EDX, Array::data_offset() + (1 * kWordSize))); | 413 __ movl(ECX, FieldAddress(EDX, Array::data_offset() + (1 * kWordSize))); |
| 449 // Check that num_pos_args >= num_fixed_params. | 414 // Check that num_pos_args >= num_fixed_params. |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 599 __ movl(original_argument_addr, raw_null); | 564 __ movl(original_argument_addr, raw_null); |
| 600 __ Bind(&null_args_loop_condition); | 565 __ Bind(&null_args_loop_condition); |
| 601 __ decl(ECX); | 566 __ decl(ECX); |
| 602 __ j(POSITIVE, &null_args_loop, Assembler::kNearJump); | 567 __ j(POSITIVE, &null_args_loop, Assembler::kNearJump); |
| 603 } | 568 } |
| 604 | 569 |
| 605 // Initialize locals. | 570 // Initialize locals. |
| 606 // TODO(regis): For now, always unroll the init loop. Decide later above | 571 // TODO(regis): For now, always unroll the init loop. Decide later above |
| 607 // which threshold to implement a loop. | 572 // which threshold to implement a loop. |
| 608 // Consider emitting pushes instead of moves. | 573 // Consider emitting pushes instead of moves. |
| 609 for (int index = first_local_index; index > first_free_frame_index; index--) { | 574 const int base = parsed_function_.first_local_index(); |
|
Kevin Millikin (Google)
2012/03/13 12:31:08
I think with your change to make local_count() inc
srdjan
2012/03/13 16:57:00
Excluding num_copied_parameters from stack_local_c
| |
| 610 if (index == first_local_index) { | 575 for (int index = 0; index < parsed_function_.local_count(); ++index) { |
| 576 if (index == 0) { | |
| 611 __ movl(EAX, raw_null); | 577 __ movl(EAX, raw_null); |
| 612 } | 578 } |
| 613 __ movl(Address(EBP, index * kWordSize), EAX); | 579 __ movl(Address(EBP, (base - index) * kWordSize), EAX); |
| 614 } | 580 } |
| 615 | 581 |
| 616 // Generate stack overflow check. | 582 // Generate stack overflow check. |
| 617 __ cmpl(ESP, | 583 __ cmpl(ESP, |
| 618 Address::Absolute(Isolate::Current()->stack_limit_address())); | 584 Address::Absolute(Isolate::Current()->stack_limit_address())); |
| 619 Label no_stack_overflow; | 585 Label no_stack_overflow; |
| 620 __ j(ABOVE, &no_stack_overflow); | 586 __ j(ABOVE, &no_stack_overflow); |
| 621 GenerateCallRuntime(AstNode::kNoId, | 587 GenerateCallRuntime(AstNode::kNoId, |
| 622 0, | 588 0, |
| 623 kStackOverflowRuntimeEntry); | 589 kStackOverflowRuntimeEntry); |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 758 node->type(), | 724 node->type(), |
| 759 node->dst_name()); | 725 node->dst_name()); |
| 760 if (IsResultNeeded(node)) { | 726 if (IsResultNeeded(node)) { |
| 761 __ pushl(EAX); | 727 __ pushl(EAX); |
| 762 } | 728 } |
| 763 } | 729 } |
| 764 | 730 |
| 765 | 731 |
| 766 void CodeGenerator::VisitClosureNode(ClosureNode* node) { | 732 void CodeGenerator::VisitClosureNode(ClosureNode* node) { |
| 767 const Function& function = node->function(); | 733 const Function& function = node->function(); |
| 768 if (function.IsNonImplicitClosureFunction()) { | 734 if (function.IsNonImplicitClosureFunction() && |
| 735 (function.context_scope() == ContextScope::null())) { | |
| 769 const int current_context_level = state()->context_level(); | 736 const int current_context_level = state()->context_level(); |
| 770 const ContextScope& context_scope = ContextScope::ZoneHandle( | 737 const ContextScope& context_scope = ContextScope::ZoneHandle( |
| 771 node->scope()->PreserveOuterScope(current_context_level)); | 738 node->scope()->PreserveOuterScope(current_context_level)); |
| 772 ASSERT(!function.HasCode()); | 739 ASSERT(!function.HasCode()); |
| 773 ASSERT(function.context_scope() == ContextScope::null()); | |
| 774 function.set_context_scope(context_scope); | 740 function.set_context_scope(context_scope); |
| 775 } else { | 741 } else { |
| 776 ASSERT(function.context_scope() != ContextScope::null()); | |
| 777 if (function.IsImplicitInstanceClosureFunction()) { | 742 if (function.IsImplicitInstanceClosureFunction()) { |
| 778 node->receiver()->Visit(this); | 743 node->receiver()->Visit(this); |
| 779 } | 744 } |
| 780 } | 745 } |
| 746 ASSERT(function.context_scope() != ContextScope::null()); | |
| 747 | |
| 781 // The function type of a closure may have type arguments. In that case, pass | 748 // The function type of a closure may have type arguments. In that case, pass |
| 782 // the type arguments of the instantiator. | 749 // the type arguments of the instantiator. |
| 783 const Class& cls = Class::Handle(function.signature_class()); | 750 const Class& cls = Class::Handle(function.signature_class()); |
| 784 ASSERT(!cls.IsNull()); | 751 ASSERT(!cls.IsNull()); |
| 785 const bool requires_type_arguments = cls.HasTypeArguments(); | 752 const bool requires_type_arguments = cls.HasTypeArguments(); |
| 786 if (requires_type_arguments) { | 753 if (requires_type_arguments) { |
| 787 ASSERT(!function.IsImplicitStaticClosureFunction()); | 754 ASSERT(!function.IsImplicitStaticClosureFunction()); |
| 788 GenerateInstantiatorTypeArguments(node->token_index()); | 755 GenerateInstantiatorTypeArguments(node->token_index()); |
| 789 } | 756 } |
| 790 const Code& stub = Code::Handle( | 757 const Code& stub = Code::Handle( |
| (...skipping 1894 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2685 const Error& error = Error::Handle( | 2652 const Error& error = Error::Handle( |
| 2686 Parser::FormatError(script, token_index, "Error", format, args)); | 2653 Parser::FormatError(script, token_index, "Error", format, args)); |
| 2687 va_end(args); | 2654 va_end(args); |
| 2688 Isolate::Current()->long_jump_base()->Jump(1, error); | 2655 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 2689 UNREACHABLE(); | 2656 UNREACHABLE(); |
| 2690 } | 2657 } |
| 2691 | 2658 |
| 2692 } // namespace dart | 2659 } // namespace dart |
| 2693 | 2660 |
| 2694 #endif // defined TARGET_ARCH_IA32 | 2661 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |