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 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 333 __ call(&target_label); | 333 __ call(&target_label); |
| 334 AddCurrentDescriptor(PcDescriptors::kIcCall, | 334 AddCurrentDescriptor(PcDescriptors::kIcCall, |
| 335 node_id, | 335 node_id, |
| 336 token_index); | 336 token_index); |
| 337 __ addl(ESP, Immediate(num_arguments * kWordSize)); | 337 __ addl(ESP, Immediate(num_arguments * kWordSize)); |
| 338 } | 338 } |
| 339 | 339 |
| 340 | 340 |
| 341 // Call to generate entry code: | 341 // Call to generate entry code: |
| 342 // - compute frame size and setup frame. | 342 // - compute frame size and setup frame. |
| 343 // - allocate local variables on stack. | 343 // - allocate local variables on stack. |
|
srdjan
2012/03/12 18:35:23
Remove this step. Maybe write as a comment that th
Kevin Millikin (Google)
2012/03/13 08:59:50
OK, removed. I thought it was referring to reserv
| |
| 344 // - optionally check if number of arguments match. | 344 // - optionally check if number of arguments match. |
| 345 // - initialize all non-argument locals to null. | 345 // - initialize all non-argument locals to null. |
| 346 // | 346 // |
| 347 // Input parameters: | 347 // Input parameters: |
| 348 // ESP : points to return address. | 348 // ESP : points to return address. |
| 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 = |
| 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 (EDX). | 412 // Total number of args is the first Smi in args descriptor array (EDX). |
| 442 __ movl(EBX, FieldAddress(EDX, Array::data_offset())); | 413 __ movl(EBX, FieldAddress(EDX, 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 __ cmpl(EBX, Immediate(Smi::RawValue(num_params))); | 416 __ cmpl(EBX, 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 (EDX). | 418 // Number of positional args is the second Smi in descriptor array (EDX). |
| 448 __ movl(ECX, FieldAddress(EDX, Array::data_offset() + (1 * kWordSize))); | 419 __ movl(ECX, FieldAddress(EDX, 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 __ movl(original_argument_addr, raw_null); | 570 __ movl(original_argument_addr, raw_null); |
| 600 __ Bind(&null_args_loop_condition); | 571 __ Bind(&null_args_loop_condition); |
| 601 __ decl(ECX); | 572 __ decl(ECX); |
| 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 __ movl(EAX, raw_null); | 583 __ movl(EAX, raw_null); |
| 612 } | 584 } |
| 613 __ movl(Address(EBP, index * kWordSize), EAX); | 585 __ movl(Address(EBP, (base - index) * kWordSize), EAX); |
| 614 } | 586 } |
| 615 | 587 |
| 616 // Generate stack overflow check. | 588 // Generate stack overflow check. |
| 617 __ cmpl(ESP, | 589 __ cmpl(ESP, |
| 618 Address::Absolute(Isolate::Current()->stack_limit_address())); | 590 Address::Absolute(Isolate::Current()->stack_limit_address())); |
| 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 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 758 node->type(), | 730 node->type(), |
| 759 node->dst_name()); | 731 node->dst_name()); |
| 760 if (IsResultNeeded(node)) { | 732 if (IsResultNeeded(node)) { |
| 761 __ pushl(EAX); | 733 __ pushl(EAX); |
| 762 } | 734 } |
| 763 } | 735 } |
| 764 | 736 |
| 765 | 737 |
| 766 void CodeGenerator::VisitClosureNode(ClosureNode* node) { | 738 void CodeGenerator::VisitClosureNode(ClosureNode* node) { |
| 767 const Function& function = node->function(); | 739 const Function& function = node->function(); |
| 768 if (function.IsNonImplicitClosureFunction()) { | 740 if (function.IsNonImplicitClosureFunction() && |
| 741 (function.context_scope() == ContextScope::null())) { | |
|
srdjan
2012/03/12 18:35:23
Why the changed condition? Previously we did not g
Kevin Millikin (Google)
2012/03/13 08:59:50
Now we can have both IsNonImplicitClosureFunction(
| |
| 769 const int current_context_level = state()->context_level(); | 742 const int current_context_level = state()->context_level(); |
| 770 const ContextScope& context_scope = ContextScope::ZoneHandle( | 743 const ContextScope& context_scope = ContextScope::ZoneHandle( |
| 771 node->scope()->PreserveOuterScope(current_context_level)); | 744 node->scope()->PreserveOuterScope(current_context_level)); |
| 772 ASSERT(!function.HasCode()); | 745 ASSERT(!function.HasCode()); |
| 773 ASSERT(function.context_scope() == ContextScope::null()); | |
| 774 function.set_context_scope(context_scope); | 746 function.set_context_scope(context_scope); |
| 775 } else { | 747 } else { |
| 776 ASSERT(function.context_scope() != ContextScope::null()); | |
| 777 if (function.IsImplicitInstanceClosureFunction()) { | 748 if (function.IsImplicitInstanceClosureFunction()) { |
| 778 node->receiver()->Visit(this); | 749 node->receiver()->Visit(this); |
| 779 } | 750 } |
| 780 } | 751 } |
| 752 ASSERT(function.context_scope() != ContextScope::null()); | |
| 753 | |
| 781 // The function type of a closure may have type arguments. In that case, pass | 754 // The function type of a closure may have type arguments. In that case, pass |
| 782 // the type arguments of the instantiator. | 755 // the type arguments of the instantiator. |
| 783 const Class& cls = Class::Handle(function.signature_class()); | 756 const Class& cls = Class::Handle(function.signature_class()); |
| 784 ASSERT(!cls.IsNull()); | 757 ASSERT(!cls.IsNull()); |
| 785 const bool requires_type_arguments = cls.HasTypeArguments(); | 758 const bool requires_type_arguments = cls.HasTypeArguments(); |
| 786 if (requires_type_arguments) { | 759 if (requires_type_arguments) { |
| 787 ASSERT(!function.IsImplicitStaticClosureFunction()); | 760 ASSERT(!function.IsImplicitStaticClosureFunction()); |
| 788 GenerateInstantiatorTypeArguments(node->token_index()); | 761 GenerateInstantiatorTypeArguments(node->token_index()); |
| 789 } | 762 } |
| 790 const Code& stub = Code::Handle( | 763 const Code& stub = Code::Handle( |
| (...skipping 1894 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2685 const Error& error = Error::Handle( | 2658 const Error& error = Error::Handle( |
| 2686 Parser::FormatError(script, token_index, "Error", format, args)); | 2659 Parser::FormatError(script, token_index, "Error", format, args)); |
| 2687 va_end(args); | 2660 va_end(args); |
| 2688 Isolate::Current()->long_jump_base()->Jump(1, error); | 2661 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 2689 UNREACHABLE(); | 2662 UNREACHABLE(); |
| 2690 } | 2663 } |
| 2691 | 2664 |
| 2692 } // namespace dart | 2665 } // namespace dart |
| 2693 | 2666 |
| 2694 #endif // defined TARGET_ARCH_IA32 | 2667 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |