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_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 "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 452 // - RAX: object. | 452 // - RAX: object. |
| 453 // - RDX: instantiator type arguments or raw_null. | 453 // - RDX: instantiator type arguments or raw_null. |
| 454 // - RCX: instantiator or raw_null. | 454 // - RCX: instantiator or raw_null. |
| 455 // Clobbers RCX and RDX. | 455 // Clobbers RCX and RDX. |
| 456 // Returns: | 456 // Returns: |
| 457 // - true or false in RAX. | 457 // - true or false in RAX. |
| 458 void FlowGraphCompiler::GenerateInstanceOf(intptr_t deopt_id, | 458 void FlowGraphCompiler::GenerateInstanceOf(intptr_t deopt_id, |
| 459 intptr_t token_pos, | 459 intptr_t token_pos, |
| 460 intptr_t try_index, | 460 intptr_t try_index, |
| 461 const AbstractType& type, | 461 const AbstractType& type, |
| 462 bool negate_result) { | 462 bool negate_result, |
| 463 BitmapBuilder* stack_bitmap) { | |
| 463 ASSERT(type.IsFinalized() && !type.IsMalformed()); | 464 ASSERT(type.IsFinalized() && !type.IsMalformed()); |
| 464 | 465 |
| 465 const Immediate raw_null = | 466 const Immediate raw_null = |
| 466 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 467 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 467 Label is_instance, is_not_instance; | 468 Label is_instance, is_not_instance; |
| 468 __ pushq(RCX); // Store instantiator on stack. | 469 __ pushq(RCX); // Store instantiator on stack. |
| 469 __ pushq(RDX); // Store instantiator type arguments. | 470 __ pushq(RDX); // Store instantiator type arguments. |
| 470 // If type is instantiated and non-parameterized, we can inline code | 471 // If type is instantiated and non-parameterized, we can inline code |
| 471 // checking whether the tested instance is a Smi. | 472 // checking whether the tested instance is a Smi. |
| 472 if (type.IsInstantiated()) { | 473 if (type.IsInstantiated()) { |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 493 __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments. | 494 __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments. |
| 494 __ movq(RCX, Address(RSP, kWordSize)); // Get instantiator. | 495 __ movq(RCX, Address(RSP, kWordSize)); // Get instantiator. |
| 495 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 496 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 496 __ pushq(RAX); // Push the instance. | 497 __ pushq(RAX); // Push the instance. |
| 497 __ PushObject(type); // Push the type. | 498 __ PushObject(type); // Push the type. |
| 498 __ pushq(RCX); // TODO(srdjan): Pass instantiator instead of null. | 499 __ pushq(RCX); // TODO(srdjan): Pass instantiator instead of null. |
| 499 __ pushq(RDX); // Instantiator type arguments. | 500 __ pushq(RDX); // Instantiator type arguments. |
| 500 __ LoadObject(RAX, test_cache); | 501 __ LoadObject(RAX, test_cache); |
| 501 __ pushq(RAX); | 502 __ pushq(RAX); |
| 502 GenerateCallRuntime(deopt_id, token_pos, try_index, | 503 GenerateCallRuntime(deopt_id, token_pos, try_index, |
| 503 kInstanceofRuntimeEntry); | 504 kInstanceofRuntimeEntry, stack_bitmap); |
| 504 // Pop the parameters supplied to the runtime entry. The result of the | 505 // Pop the parameters supplied to the runtime entry. The result of the |
| 505 // instanceof runtime call will be left as the result of the operation. | 506 // instanceof runtime call will be left as the result of the operation. |
| 506 __ Drop(5); | 507 __ Drop(5); |
| 507 if (negate_result) { | 508 if (negate_result) { |
| 508 __ popq(RDX); | 509 __ popq(RDX); |
| 509 __ LoadObject(RAX, bool_true()); | 510 __ LoadObject(RAX, bool_true()); |
| 510 __ cmpq(RDX, RAX); | 511 __ cmpq(RDX, RAX); |
| 511 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 512 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
| 512 __ LoadObject(RAX, bool_false()); | 513 __ LoadObject(RAX, bool_false()); |
| 513 } else { | 514 } else { |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 536 // - RDX: instantiator type arguments or raw_null. | 537 // - RDX: instantiator type arguments or raw_null. |
| 537 // - RCX: instantiator or raw_null. | 538 // - RCX: instantiator or raw_null. |
| 538 // Returns: | 539 // Returns: |
| 539 // - object in RAX for successful assignable check (or throws TypeError). | 540 // - object in RAX for successful assignable check (or throws TypeError). |
| 540 // Performance notes: positive checks must be quick, negative checks can be slow | 541 // Performance notes: positive checks must be quick, negative checks can be slow |
| 541 // as they throw an exception. | 542 // as they throw an exception. |
| 542 void FlowGraphCompiler::GenerateAssertAssignable(intptr_t deopt_id, | 543 void FlowGraphCompiler::GenerateAssertAssignable(intptr_t deopt_id, |
| 543 intptr_t token_pos, | 544 intptr_t token_pos, |
| 544 intptr_t try_index, | 545 intptr_t try_index, |
| 545 const AbstractType& dst_type, | 546 const AbstractType& dst_type, |
| 546 const String& dst_name) { | 547 const String& dst_name, |
| 548 BitmapBuilder* stack_bitmap) { | |
| 547 ASSERT(token_pos >= 0); | 549 ASSERT(token_pos >= 0); |
| 548 ASSERT(!dst_type.IsNull()); | 550 ASSERT(!dst_type.IsNull()); |
| 549 ASSERT(dst_type.IsFinalized()); | 551 ASSERT(dst_type.IsFinalized()); |
| 550 // Assignable check is skipped in FlowGraphBuilder, not here. | 552 // Assignable check is skipped in FlowGraphBuilder, not here. |
| 551 ASSERT(dst_type.IsMalformed() || | 553 ASSERT(dst_type.IsMalformed() || |
| 552 (!dst_type.IsDynamicType() && !dst_type.IsObjectType())); | 554 (!dst_type.IsDynamicType() && !dst_type.IsObjectType())); |
| 553 __ pushq(RCX); // Store instantiator. | 555 __ pushq(RCX); // Store instantiator. |
| 554 __ pushq(RDX); // Store instantiator type arguments. | 556 __ pushq(RDX); // Store instantiator type arguments. |
| 555 // A null object is always assignable and is returned as result. | 557 // A null object is always assignable and is returned as result. |
| 556 const Immediate raw_null = | 558 const Immediate raw_null = |
| 557 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 559 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 558 Label is_assignable, runtime_call; | 560 Label is_assignable, runtime_call; |
| 559 __ cmpq(RAX, raw_null); | 561 __ cmpq(RAX, raw_null); |
| 560 __ j(EQUAL, &is_assignable); | 562 __ j(EQUAL, &is_assignable); |
| 561 | 563 |
| 562 // Generate throw new TypeError() if the type is malformed. | 564 // Generate throw new TypeError() if the type is malformed. |
| 563 if (dst_type.IsMalformed()) { | 565 if (dst_type.IsMalformed()) { |
| 564 const Error& error = Error::Handle(dst_type.malformed_error()); | 566 const Error& error = Error::Handle(dst_type.malformed_error()); |
| 565 const String& error_message = String::ZoneHandle( | 567 const String& error_message = String::ZoneHandle( |
| 566 Symbols::New(error.ToErrorCString())); | 568 Symbols::New(error.ToErrorCString())); |
| 567 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 569 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 568 __ pushq(RAX); // Push the source object. | 570 __ pushq(RAX); // Push the source object. |
| 569 __ PushObject(dst_name); // Push the name of the destination. | 571 __ PushObject(dst_name); // Push the name of the destination. |
| 570 __ PushObject(error_message); | 572 __ PushObject(error_message); |
| 571 GenerateCallRuntime(deopt_id, | 573 GenerateCallRuntime(deopt_id, |
| 572 token_pos, | 574 token_pos, |
| 573 try_index, | 575 try_index, |
| 574 kMalformedTypeErrorRuntimeEntry); | 576 kMalformedTypeErrorRuntimeEntry, |
| 577 stack_bitmap); | |
| 575 // We should never return here. | 578 // We should never return here. |
| 576 __ int3(); | 579 __ int3(); |
| 577 | 580 |
| 578 __ Bind(&is_assignable); // For a null object. | 581 __ Bind(&is_assignable); // For a null object. |
| 579 __ popq(RDX); // Remove pushed instantiator type arguments. | 582 __ popq(RDX); // Remove pushed instantiator type arguments. |
| 580 __ popq(RCX); // Remove pushed instantiator. | 583 __ popq(RCX); // Remove pushed instantiator. |
| 581 return; | 584 return; |
| 582 } | 585 } |
| 583 | 586 |
| 584 // Generate inline type check, linking to runtime call if not assignable. | 587 // Generate inline type check, linking to runtime call if not assignable. |
| 585 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(); | 588 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(); |
| 586 test_cache = GenerateInlineInstanceof(token_pos, dst_type, | 589 test_cache = GenerateInlineInstanceof(token_pos, dst_type, |
| 587 &is_assignable, &runtime_call); | 590 &is_assignable, &runtime_call); |
| 588 | 591 |
| 589 __ Bind(&runtime_call); | 592 __ Bind(&runtime_call); |
| 590 __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments. | 593 __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments. |
| 591 __ movq(RCX, Address(RSP, kWordSize)); // Get instantiator. | 594 __ movq(RCX, Address(RSP, kWordSize)); // Get instantiator. |
| 592 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 595 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 593 __ pushq(RAX); // Push the source object. | 596 __ pushq(RAX); // Push the source object. |
| 594 __ PushObject(dst_type); // Push the type of the destination. | 597 __ PushObject(dst_type); // Push the type of the destination. |
| 595 __ pushq(RCX); // Instantiator. | 598 __ pushq(RCX); // Instantiator. |
| 596 __ pushq(RDX); // Instantiator type arguments. | 599 __ pushq(RDX); // Instantiator type arguments. |
| 597 __ PushObject(dst_name); // Push the name of the destination. | 600 __ PushObject(dst_name); // Push the name of the destination. |
| 598 __ LoadObject(RAX, test_cache); | 601 __ LoadObject(RAX, test_cache); |
| 599 __ pushq(RAX); | 602 __ pushq(RAX); |
| 600 GenerateCallRuntime(deopt_id, | 603 GenerateCallRuntime(deopt_id, |
| 601 token_pos, | 604 token_pos, |
| 602 try_index, | 605 try_index, |
| 603 kTypeCheckRuntimeEntry); | 606 kTypeCheckRuntimeEntry, |
| 607 stack_bitmap); | |
| 604 // Pop the parameters supplied to the runtime entry. The result of the | 608 // Pop the parameters supplied to the runtime entry. The result of the |
| 605 // type check runtime call is the checked value. | 609 // type check runtime call is the checked value. |
| 606 __ Drop(6); | 610 __ Drop(6); |
| 607 __ popq(RAX); | 611 __ popq(RAX); |
| 608 | 612 |
| 609 __ Bind(&is_assignable); | 613 __ Bind(&is_assignable); |
| 610 __ popq(RDX); // Remove pushed instantiator type arguments. | 614 __ popq(RDX); // Remove pushed instantiator type arguments. |
| 611 __ popq(RCX); // Remove pushed instantiator. | 615 __ popq(RCX); // Remove pushed instantiator. |
| 612 } | 616 } |
| 613 | 617 |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 775 if (StackSize() != 0) { | 779 if (StackSize() != 0) { |
| 776 // We need to unwind the space we reserved for locals and copied parameters. | 780 // We need to unwind the space we reserved for locals and copied parameters. |
| 777 // The NoSuchMethodFunction stub does not expect to see that area on the | 781 // The NoSuchMethodFunction stub does not expect to see that area on the |
| 778 // stack. | 782 // stack. |
| 779 __ addq(RSP, Immediate(StackSize() * kWordSize)); | 783 __ addq(RSP, Immediate(StackSize() * kWordSize)); |
| 780 } | 784 } |
| 781 if (function.IsClosureFunction()) { | 785 if (function.IsClosureFunction()) { |
| 782 GenerateCallRuntime(Isolate::kNoDeoptId, | 786 GenerateCallRuntime(Isolate::kNoDeoptId, |
| 783 0, | 787 0, |
| 784 CatchClauseNode::kInvalidTryIndex, | 788 CatchClauseNode::kInvalidTryIndex, |
| 785 kClosureArgumentMismatchRuntimeEntry); | 789 kClosureArgumentMismatchRuntimeEntry, |
| 790 NULL); | |
|
Vyacheslav Egorov (Google)
2012/08/13 12:54:46
This NULL looks suspicious to me because we alread
| |
| 786 } else { | 791 } else { |
| 787 ASSERT(!IsLeaf()); | 792 ASSERT(!IsLeaf()); |
| 788 // Invoke noSuchMethod function. | 793 // Invoke noSuchMethod function. |
| 789 const int kNumArgsChecked = 1; | 794 const int kNumArgsChecked = 1; |
| 790 ICData& ic_data = ICData::ZoneHandle(); | 795 ICData& ic_data = ICData::ZoneHandle(); |
| 791 ic_data = ICData::New(function, | 796 ic_data = ICData::New(function, |
| 792 String::Handle(function.name()), | 797 String::Handle(function.name()), |
| 793 Isolate::kNoDeoptId, | 798 Isolate::kNoDeoptId, |
| 794 kNumArgsChecked); | 799 kNumArgsChecked); |
| 795 __ LoadObject(RBX, ic_data); | 800 __ LoadObject(RBX, ic_data); |
| 796 // RBP - 8 : PC marker, allows easy identification of RawInstruction obj. | 801 // RBP - 8 : PC marker, allows easy identification of RawInstruction obj. |
| 797 // RBP : points to previous frame pointer. | 802 // RBP : points to previous frame pointer. |
| 798 // RBP + 8 : points to return address. | 803 // RBP + 8 : points to return address. |
| 799 // RBP + 16 : address of last argument (arg n-1). | 804 // RBP + 16 : address of last argument (arg n-1). |
| 800 // RSP + 16 + 8*(n-1) : address of first argument (arg 0). | 805 // RSP + 16 + 8*(n-1) : address of first argument (arg 0). |
| 801 // RBX : ic-data. | 806 // RBX : ic-data. |
| 802 // R10 : arguments descriptor array. | 807 // R10 : arguments descriptor array. |
| 803 __ call(&StubCode::CallNoSuchMethodFunctionLabel()); | 808 __ call(&StubCode::CallNoSuchMethodFunctionLabel()); |
| 804 } | 809 } |
| 805 | 810 |
| 806 if (FLAG_trace_functions) { | 811 if (FLAG_trace_functions) { |
| 807 __ pushq(RAX); // Preserve result. | 812 __ pushq(RAX); // Preserve result. |
| 808 __ PushObject(Function::ZoneHandle(function.raw())); | 813 __ PushObject(Function::ZoneHandle(function.raw())); |
| 809 GenerateCallRuntime(Isolate::kNoDeoptId, | 814 GenerateCallRuntime(Isolate::kNoDeoptId, |
| 810 0, | 815 0, |
| 811 CatchClauseNode::kInvalidTryIndex, | 816 CatchClauseNode::kInvalidTryIndex, |
| 812 kTraceFunctionExitRuntimeEntry); | 817 kTraceFunctionExitRuntimeEntry, |
| 818 NULL); | |
|
Vyacheslav Egorov (Google)
2012/08/13 12:54:46
This NULL looks suspicious to me because we alread
| |
| 813 __ popq(RAX); // Remove argument. | 819 __ popq(RAX); // Remove argument. |
| 814 __ popq(RAX); // Restore result. | 820 __ popq(RAX); // Restore result. |
| 815 } | 821 } |
| 816 __ LeaveFrame(); | 822 __ LeaveFrame(); |
| 817 __ ret(); | 823 __ ret(); |
| 818 | 824 |
| 819 __ Bind(&all_arguments_processed); | 825 __ Bind(&all_arguments_processed); |
| 820 // Nullify originally passed arguments only after they have been copied and | 826 // Nullify originally passed arguments only after they have been copied and |
| 821 // checked, otherwise noSuchMethod would not see their original values. | 827 // checked, otherwise noSuchMethod would not see their original values. |
| 822 // This step can be skipped in case we decide that formal parameters are | 828 // This step can be skipped in case we decide that formal parameters are |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 896 // code size, and nop(2) increases the minimum code size appropriately. | 902 // code size, and nop(2) increases the minimum code size appropriately. |
| 897 __ nop(2); | 903 __ nop(2); |
| 898 __ int3(); | 904 __ int3(); |
| 899 __ jmp(&StubCode::FixCallersTargetLabel()); | 905 __ jmp(&StubCode::FixCallersTargetLabel()); |
| 900 return; | 906 return; |
| 901 } | 907 } |
| 902 // Specialized version of entry code from CodeGenerator::GenerateEntryCode. | 908 // Specialized version of entry code from CodeGenerator::GenerateEntryCode. |
| 903 const Function& function = parsed_function().function(); | 909 const Function& function = parsed_function().function(); |
| 904 | 910 |
| 905 const int parameter_count = function.num_fixed_parameters(); | 911 const int parameter_count = function.num_fixed_parameters(); |
| 906 const int num_copied_params = parsed_function().copied_parameter_count(); | 912 const int copied_parameter_count = parsed_function().copied_parameter_count(); |
| 907 const int local_count = parsed_function().stack_local_count(); | 913 const int local_count = parsed_function().stack_local_count(); |
| 908 __ Comment("Enter frame"); | 914 __ Comment("Enter frame"); |
| 909 if (IsLeaf()) { | 915 if (IsLeaf()) { |
| 910 AssemblerMacros::EnterDartLeafFrame(assembler(), (StackSize() * kWordSize)); | 916 AssemblerMacros::EnterDartLeafFrame(assembler(), (StackSize() * kWordSize)); |
| 911 } else { | 917 } else { |
| 912 AssemblerMacros::EnterDartFrame(assembler(), (StackSize() * kWordSize)); | 918 AssemblerMacros::EnterDartFrame(assembler(), (StackSize() * kWordSize)); |
| 913 } | 919 } |
| 914 // We check the number of passed arguments when we have to copy them due to | 920 // We check the number of passed arguments when we have to copy them due to |
| 915 // the presence of optional named parameters. | 921 // the presence of optional named parameters. |
| 916 // No such checking code is generated if only fixed parameters are declared, | 922 // No such checking code is generated if only fixed parameters are declared, |
| 917 // unless we are debug mode or unless we are compiling a closure. | 923 // unless we are debug mode or unless we are compiling a closure. |
| 918 if (num_copied_params == 0) { | 924 if (copied_parameter_count == 0) { |
| 919 #ifdef DEBUG | 925 #ifdef DEBUG |
| 920 const bool check_arguments = true; | 926 const bool check_arguments = true; |
| 921 #else | 927 #else |
| 922 const bool check_arguments = function.IsClosureFunction(); | 928 const bool check_arguments = function.IsClosureFunction(); |
| 923 #endif | 929 #endif |
| 924 if (check_arguments) { | 930 if (check_arguments) { |
| 925 __ Comment("Check argument count"); | 931 __ Comment("Check argument count"); |
| 926 // Check that num_fixed <= argc <= num_params. | 932 // Check that num_fixed <= argc <= num_params. |
| 927 Label argc_in_range; | 933 Label argc_in_range; |
| 928 // Total number of args is the first Smi in args descriptor array (R10). | 934 // Total number of args is the first Smi in args descriptor array (R10). |
| 929 __ movq(RAX, FieldAddress(R10, Array::data_offset())); | 935 __ movq(RAX, FieldAddress(R10, Array::data_offset())); |
| 930 __ cmpq(RAX, Immediate(Smi::RawValue(parameter_count))); | 936 __ cmpq(RAX, Immediate(Smi::RawValue(parameter_count))); |
| 931 __ j(EQUAL, &argc_in_range, Assembler::kNearJump); | 937 __ j(EQUAL, &argc_in_range, Assembler::kNearJump); |
| 932 if (function.IsClosureFunction()) { | 938 if (function.IsClosureFunction()) { |
| 933 GenerateCallRuntime(Isolate::kNoDeoptId, | 939 GenerateCallRuntime(Isolate::kNoDeoptId, |
| 934 function.token_pos(), | 940 function.token_pos(), |
| 935 CatchClauseNode::kInvalidTryIndex, | 941 CatchClauseNode::kInvalidTryIndex, |
| 936 kClosureArgumentMismatchRuntimeEntry); | 942 kClosureArgumentMismatchRuntimeEntry, |
| 943 NULL); | |
|
Vyacheslav Egorov (Google)
2012/08/13 12:54:46
This NULL looks suspicious to me because we alread
| |
| 937 } else { | 944 } else { |
| 938 __ Stop("Wrong number of arguments"); | 945 __ Stop("Wrong number of arguments"); |
| 939 } | 946 } |
| 940 __ Bind(&argc_in_range); | 947 __ Bind(&argc_in_range); |
| 941 } | 948 } |
| 942 } else { | 949 } else { |
| 943 CopyParameters(); | 950 CopyParameters(); |
| 944 } | 951 } |
| 945 | 952 |
| 953 // Initialize (non-argument) stack allocated slots to null. | |
| 954 // | |
| 946 // TODO(vegorov): introduce stack maps and stop initializing all spill slots | 955 // TODO(vegorov): introduce stack maps and stop initializing all spill slots |
| 947 // with null. | 956 // with null. |
| 948 const intptr_t stack_slot_count = | 957 intptr_t uninitialized_slot_count; |
| 949 is_ssa_ ? block_order_[0]->AsGraphEntry()->spill_slot_count() | 958 if (is_ssa_) { |
| 950 : local_count; | 959 GraphEntryInstr* entry = block_order_[0]->AsGraphEntry(); |
| 951 | 960 uninitialized_slot_count = |
| 961 entry->spill_slot_count() - copied_parameter_count; | |
| 962 } else { | |
| 963 uninitialized_slot_count = local_count; | |
| 964 } | |
| 952 const intptr_t slot_base = parsed_function().first_stack_local_index(); | 965 const intptr_t slot_base = parsed_function().first_stack_local_index(); |
| 953 | 966 |
| 954 // Initialize (non-argument) stack allocated locals to null. | 967 if (uninitialized_slot_count > 0) { |
| 955 if (stack_slot_count > 0) { | |
| 956 __ Comment("Initialize spill slots"); | 968 __ Comment("Initialize spill slots"); |
| 957 const Immediate raw_null = | 969 const Immediate raw_null = |
| 958 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 970 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 959 __ movq(RAX, raw_null); | 971 __ movq(RAX, raw_null); |
| 960 for (intptr_t i = 0; i < stack_slot_count; ++i) { | 972 for (intptr_t i = 0; i < uninitialized_slot_count; ++i) { |
| 961 // Subtract index i (locals lie at lower addresses than RBP). | 973 // Subtract index i (locals lie at lower addresses than RBP). |
| 962 __ movq(Address(RBP, (slot_base - i) * kWordSize), RAX); | 974 __ movq(Address(RBP, (slot_base - i) * kWordSize), RAX); |
| 963 } | 975 } |
| 964 } | 976 } |
| 965 | 977 |
| 966 if (FLAG_print_scopes) { | 978 if (FLAG_print_scopes) { |
| 967 // Print the function scope (again) after generating the prologue in order | 979 // Print the function scope (again) after generating the prologue in order |
| 968 // to see annotations such as allocation indices of locals. | 980 // to see annotations such as allocation indices of locals. |
| 969 if (FLAG_print_ast) { | 981 if (FLAG_print_ast) { |
| 970 // Second printing. | 982 // Second printing. |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 984 Isolate::kNoDeoptId, | 996 Isolate::kNoDeoptId, |
| 985 0, | 997 0, |
| 986 -1); | 998 -1); |
| 987 __ jmp(&StubCode::FixCallersTargetLabel()); | 999 __ jmp(&StubCode::FixCallersTargetLabel()); |
| 988 } | 1000 } |
| 989 | 1001 |
| 990 | 1002 |
| 991 void FlowGraphCompiler::GenerateCall(intptr_t token_pos, | 1003 void FlowGraphCompiler::GenerateCall(intptr_t token_pos, |
| 992 intptr_t try_index, | 1004 intptr_t try_index, |
| 993 const ExternalLabel* label, | 1005 const ExternalLabel* label, |
| 994 PcDescriptors::Kind kind) { | 1006 PcDescriptors::Kind kind, |
| 1007 BitmapBuilder* stack_bitmap) { | |
| 995 ASSERT(!IsLeaf()); | 1008 ASSERT(!IsLeaf()); |
| 996 ASSERT(frame_register_allocator()->IsSpilled()); | 1009 ASSERT(frame_register_allocator()->IsSpilled()); |
| 997 __ call(label); | 1010 __ call(label); |
| 1011 if (is_ssa() && (stack_bitmap != NULL)) { | |
|
Vyacheslav Egorov (Google)
2012/08/13 12:54:46
I would prefer to have stack_bitmap always not equ
Kevin Millikin (Google)
2012/08/13 15:10:37
I agree completely. With this change we fall back
| |
| 1012 stackmap_table_builder_->AddEntry(assembler()->CodeSize(), stack_bitmap); | |
| 1013 } | |
| 998 AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos, try_index); | 1014 AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos, try_index); |
| 999 } | 1015 } |
| 1000 | 1016 |
| 1001 | 1017 |
| 1002 void FlowGraphCompiler::GenerateCallRuntime(intptr_t deopt_id, | 1018 void FlowGraphCompiler::GenerateCallRuntime(intptr_t deopt_id, |
| 1003 intptr_t token_pos, | 1019 intptr_t token_pos, |
| 1004 intptr_t try_index, | 1020 intptr_t try_index, |
| 1005 const RuntimeEntry& entry) { | 1021 const RuntimeEntry& entry, |
| 1022 BitmapBuilder* stack_bitmap) { | |
| 1006 ASSERT(!IsLeaf()); | 1023 ASSERT(!IsLeaf()); |
| 1007 ASSERT(frame_register_allocator()->IsSpilled()); | 1024 ASSERT(frame_register_allocator()->IsSpilled()); |
| 1008 __ CallRuntime(entry); | 1025 __ CallRuntime(entry); |
| 1026 if (is_ssa() && (stack_bitmap != NULL)) { | |
| 1027 stackmap_table_builder_->AddEntry(assembler()->CodeSize(), stack_bitmap); | |
| 1028 } | |
| 1009 AddCurrentDescriptor(PcDescriptors::kOther, deopt_id, token_pos, try_index); | 1029 AddCurrentDescriptor(PcDescriptors::kOther, deopt_id, token_pos, try_index); |
| 1010 } | 1030 } |
| 1011 | 1031 |
| 1012 | 1032 |
| 1013 intptr_t FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label, | 1033 intptr_t FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label, |
| 1014 const ICData& ic_data, | 1034 const ICData& ic_data, |
| 1015 const Array& arguments_descriptor, | 1035 const Array& arguments_descriptor, |
| 1016 intptr_t argument_count) { | 1036 intptr_t argument_count) { |
| 1017 ASSERT(!IsLeaf()); | 1037 ASSERT(!IsLeaf()); |
| 1018 __ LoadObject(RBX, ic_data); | 1038 __ LoadObject(RBX, ic_data); |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1193 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) { | 1213 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) { |
| 1194 __ Exchange(mem1, mem2); | 1214 __ Exchange(mem1, mem2); |
| 1195 } | 1215 } |
| 1196 | 1216 |
| 1197 | 1217 |
| 1198 #undef __ | 1218 #undef __ |
| 1199 | 1219 |
| 1200 } // namespace dart | 1220 } // namespace dart |
| 1201 | 1221 |
| 1202 #endif // defined TARGET_ARCH_X64 | 1222 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |