| 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 436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 447 // - RDX: instantiator type arguments or raw_null. | 447 // - RDX: instantiator type arguments or raw_null. |
| 448 // - RCX: instantiator or raw_null. | 448 // - RCX: instantiator or raw_null. |
| 449 // Clobbers RCX and RDX. | 449 // Clobbers RCX and RDX. |
| 450 // Returns: | 450 // Returns: |
| 451 // - true or false in RAX. | 451 // - true or false in RAX. |
| 452 void FlowGraphCompiler::GenerateInstanceOf(intptr_t deopt_id, | 452 void FlowGraphCompiler::GenerateInstanceOf(intptr_t deopt_id, |
| 453 intptr_t token_pos, | 453 intptr_t token_pos, |
| 454 intptr_t try_index, | 454 intptr_t try_index, |
| 455 const AbstractType& type, | 455 const AbstractType& type, |
| 456 bool negate_result, | 456 bool negate_result, |
| 457 BitmapBuilder* stack_bitmap) { | 457 LocationSummary* locs) { |
| 458 ASSERT(type.IsFinalized() && !type.IsMalformed()); | 458 ASSERT(type.IsFinalized() && !type.IsMalformed()); |
| 459 | 459 |
| 460 const Immediate raw_null = | 460 const Immediate raw_null = |
| 461 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 461 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 462 Label is_instance, is_not_instance; | 462 Label is_instance, is_not_instance; |
| 463 __ pushq(RCX); // Store instantiator on stack. | 463 __ pushq(RCX); // Store instantiator on stack. |
| 464 __ pushq(RDX); // Store instantiator type arguments. | 464 __ pushq(RDX); // Store instantiator type arguments. |
| 465 // If type is instantiated and non-parameterized, we can inline code | 465 // If type is instantiated and non-parameterized, we can inline code |
| 466 // checking whether the tested instance is a Smi. | 466 // checking whether the tested instance is a Smi. |
| 467 if (type.IsInstantiated()) { | 467 if (type.IsInstantiated()) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 488 __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments. | 488 __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments. |
| 489 __ movq(RCX, Address(RSP, kWordSize)); // Get instantiator. | 489 __ movq(RCX, Address(RSP, kWordSize)); // Get instantiator. |
| 490 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 490 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 491 __ pushq(RAX); // Push the instance. | 491 __ pushq(RAX); // Push the instance. |
| 492 __ PushObject(type); // Push the type. | 492 __ PushObject(type); // Push the type. |
| 493 __ pushq(RCX); // TODO(srdjan): Pass instantiator instead of null. | 493 __ pushq(RCX); // TODO(srdjan): Pass instantiator instead of null. |
| 494 __ pushq(RDX); // Instantiator type arguments. | 494 __ pushq(RDX); // Instantiator type arguments. |
| 495 __ LoadObject(RAX, test_cache); | 495 __ LoadObject(RAX, test_cache); |
| 496 __ pushq(RAX); | 496 __ pushq(RAX); |
| 497 GenerateCallRuntime(deopt_id, token_pos, try_index, | 497 GenerateCallRuntime(deopt_id, token_pos, try_index, |
| 498 kInstanceofRuntimeEntry, stack_bitmap); | 498 kInstanceofRuntimeEntry, locs); |
| 499 // Pop the parameters supplied to the runtime entry. The result of the | 499 // Pop the parameters supplied to the runtime entry. The result of the |
| 500 // instanceof runtime call will be left as the result of the operation. | 500 // instanceof runtime call will be left as the result of the operation. |
| 501 __ Drop(5); | 501 __ Drop(5); |
| 502 if (negate_result) { | 502 if (negate_result) { |
| 503 __ popq(RDX); | 503 __ popq(RDX); |
| 504 __ LoadObject(RAX, bool_true()); | 504 __ LoadObject(RAX, bool_true()); |
| 505 __ cmpq(RDX, RAX); | 505 __ cmpq(RDX, RAX); |
| 506 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 506 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
| 507 __ LoadObject(RAX, bool_false()); | 507 __ LoadObject(RAX, bool_false()); |
| 508 } else { | 508 } else { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 532 // - RCX: instantiator or raw_null. | 532 // - RCX: instantiator or raw_null. |
| 533 // Returns: | 533 // Returns: |
| 534 // - object in RAX for successful assignable check (or throws TypeError). | 534 // - object in RAX for successful assignable check (or throws TypeError). |
| 535 // Performance notes: positive checks must be quick, negative checks can be slow | 535 // Performance notes: positive checks must be quick, negative checks can be slow |
| 536 // as they throw an exception. | 536 // as they throw an exception. |
| 537 void FlowGraphCompiler::GenerateAssertAssignable(intptr_t deopt_id, | 537 void FlowGraphCompiler::GenerateAssertAssignable(intptr_t deopt_id, |
| 538 intptr_t token_pos, | 538 intptr_t token_pos, |
| 539 intptr_t try_index, | 539 intptr_t try_index, |
| 540 const AbstractType& dst_type, | 540 const AbstractType& dst_type, |
| 541 const String& dst_name, | 541 const String& dst_name, |
| 542 BitmapBuilder* stack_bitmap) { | 542 LocationSummary* locs) { |
| 543 ASSERT(token_pos >= 0); | 543 ASSERT(token_pos >= 0); |
| 544 ASSERT(!dst_type.IsNull()); | 544 ASSERT(!dst_type.IsNull()); |
| 545 ASSERT(dst_type.IsFinalized()); | 545 ASSERT(dst_type.IsFinalized()); |
| 546 // Assignable check is skipped in FlowGraphBuilder, not here. | 546 // Assignable check is skipped in FlowGraphBuilder, not here. |
| 547 ASSERT(dst_type.IsMalformed() || | 547 ASSERT(dst_type.IsMalformed() || |
| 548 (!dst_type.IsDynamicType() && !dst_type.IsObjectType())); | 548 (!dst_type.IsDynamicType() && !dst_type.IsObjectType())); |
| 549 __ pushq(RCX); // Store instantiator. | 549 __ pushq(RCX); // Store instantiator. |
| 550 __ pushq(RDX); // Store instantiator type arguments. | 550 __ pushq(RDX); // Store instantiator type arguments. |
| 551 // A null object is always assignable and is returned as result. | 551 // A null object is always assignable and is returned as result. |
| 552 const Immediate raw_null = | 552 const Immediate raw_null = |
| 553 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 553 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 554 Label is_assignable, runtime_call; | 554 Label is_assignable, runtime_call; |
| 555 __ cmpq(RAX, raw_null); | 555 __ cmpq(RAX, raw_null); |
| 556 __ j(EQUAL, &is_assignable); | 556 __ j(EQUAL, &is_assignable); |
| 557 | 557 |
| 558 // Generate throw new TypeError() if the type is malformed. | 558 // Generate throw new TypeError() if the type is malformed. |
| 559 if (dst_type.IsMalformed()) { | 559 if (dst_type.IsMalformed()) { |
| 560 const Error& error = Error::Handle(dst_type.malformed_error()); | 560 const Error& error = Error::Handle(dst_type.malformed_error()); |
| 561 const String& error_message = String::ZoneHandle( | 561 const String& error_message = String::ZoneHandle( |
| 562 Symbols::New(error.ToErrorCString())); | 562 Symbols::New(error.ToErrorCString())); |
| 563 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 563 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 564 __ pushq(RAX); // Push the source object. | 564 __ pushq(RAX); // Push the source object. |
| 565 __ PushObject(dst_name); // Push the name of the destination. | 565 __ PushObject(dst_name); // Push the name of the destination. |
| 566 __ PushObject(error_message); | 566 __ PushObject(error_message); |
| 567 GenerateCallRuntime(deopt_id, | 567 GenerateCallRuntime(deopt_id, |
| 568 token_pos, | 568 token_pos, |
| 569 try_index, | 569 try_index, |
| 570 kMalformedTypeErrorRuntimeEntry, | 570 kMalformedTypeErrorRuntimeEntry, |
| 571 stack_bitmap); | 571 locs); |
| 572 // We should never return here. | 572 // We should never return here. |
| 573 __ int3(); | 573 __ int3(); |
| 574 | 574 |
| 575 __ Bind(&is_assignable); // For a null object. | 575 __ Bind(&is_assignable); // For a null object. |
| 576 __ popq(RDX); // Remove pushed instantiator type arguments. | 576 __ popq(RDX); // Remove pushed instantiator type arguments. |
| 577 __ popq(RCX); // Remove pushed instantiator. | 577 __ popq(RCX); // Remove pushed instantiator. |
| 578 return; | 578 return; |
| 579 } | 579 } |
| 580 | 580 |
| 581 // Generate inline type check, linking to runtime call if not assignable. | 581 // Generate inline type check, linking to runtime call if not assignable. |
| 582 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(); | 582 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(); |
| 583 test_cache = GenerateInlineInstanceof(token_pos, dst_type, | 583 test_cache = GenerateInlineInstanceof(token_pos, dst_type, |
| 584 &is_assignable, &runtime_call); | 584 &is_assignable, &runtime_call); |
| 585 | 585 |
| 586 __ Bind(&runtime_call); | 586 __ Bind(&runtime_call); |
| 587 __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments. | 587 __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments. |
| 588 __ movq(RCX, Address(RSP, kWordSize)); // Get instantiator. | 588 __ movq(RCX, Address(RSP, kWordSize)); // Get instantiator. |
| 589 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 589 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 590 __ pushq(RAX); // Push the source object. | 590 __ pushq(RAX); // Push the source object. |
| 591 __ PushObject(dst_type); // Push the type of the destination. | 591 __ PushObject(dst_type); // Push the type of the destination. |
| 592 __ pushq(RCX); // Instantiator. | 592 __ pushq(RCX); // Instantiator. |
| 593 __ pushq(RDX); // Instantiator type arguments. | 593 __ pushq(RDX); // Instantiator type arguments. |
| 594 __ PushObject(dst_name); // Push the name of the destination. | 594 __ PushObject(dst_name); // Push the name of the destination. |
| 595 __ LoadObject(RAX, test_cache); | 595 __ LoadObject(RAX, test_cache); |
| 596 __ pushq(RAX); | 596 __ pushq(RAX); |
| 597 GenerateCallRuntime(deopt_id, | 597 GenerateCallRuntime(deopt_id, |
| 598 token_pos, | 598 token_pos, |
| 599 try_index, | 599 try_index, |
| 600 kTypeCheckRuntimeEntry, | 600 kTypeCheckRuntimeEntry, |
| 601 stack_bitmap); | 601 locs); |
| 602 // Pop the parameters supplied to the runtime entry. The result of the | 602 // Pop the parameters supplied to the runtime entry. The result of the |
| 603 // type check runtime call is the checked value. | 603 // type check runtime call is the checked value. |
| 604 __ Drop(6); | 604 __ Drop(6); |
| 605 __ popq(RAX); | 605 __ popq(RAX); |
| 606 | 606 |
| 607 __ Bind(&is_assignable); | 607 __ Bind(&is_assignable); |
| 608 __ popq(RDX); // Remove pushed instantiator type arguments. | 608 __ popq(RDX); // Remove pushed instantiator type arguments. |
| 609 __ popq(RCX); // Remove pushed instantiator. | 609 __ popq(RCX); // Remove pushed instantiator. |
| 610 } | 610 } |
| 611 | 611 |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 767 if (StackSize() != 0) { | 767 if (StackSize() != 0) { |
| 768 // We need to unwind the space we reserved for locals and copied parameters. | 768 // We need to unwind the space we reserved for locals and copied parameters. |
| 769 // The NoSuchMethodFunction stub does not expect to see that area on the | 769 // The NoSuchMethodFunction stub does not expect to see that area on the |
| 770 // stack. | 770 // stack. |
| 771 __ addq(RSP, Immediate(StackSize() * kWordSize)); | 771 __ addq(RSP, Immediate(StackSize() * kWordSize)); |
| 772 } | 772 } |
| 773 // The calls immediately below have empty stackmaps because we have just | 773 // The calls immediately below have empty stackmaps because we have just |
| 774 // dropped the spill slots. | 774 // dropped the spill slots. |
| 775 BitmapBuilder* empty_stack_bitmap = new BitmapBuilder(); | 775 BitmapBuilder* empty_stack_bitmap = new BitmapBuilder(); |
| 776 if (function.IsClosureFunction()) { | 776 if (function.IsClosureFunction()) { |
| 777 GenerateCallRuntime(Isolate::kNoDeoptId, | 777 // We do not use GenerateCallRuntime because of the non-standard (empty) |
| 778 0, | 778 // stackmap used here. |
| 779 CatchClauseNode::kInvalidTryIndex, | 779 __ CallRuntime(kClosureArgumentMismatchRuntimeEntry); |
| 780 kClosureArgumentMismatchRuntimeEntry, | 780 AddCurrentDescriptor(PcDescriptors::kOther, |
| 781 empty_stack_bitmap); | 781 Isolate::kNoDeoptId, |
| 782 0, // No token position. |
| 783 CatchClauseNode::kInvalidTryIndex); |
| 782 } else { | 784 } else { |
| 783 ASSERT(!IsLeaf()); | 785 ASSERT(!IsLeaf()); |
| 784 // Invoke noSuchMethod function. | 786 // Invoke noSuchMethod function. |
| 785 const int kNumArgsChecked = 1; | 787 const int kNumArgsChecked = 1; |
| 786 ICData& ic_data = ICData::ZoneHandle(); | 788 ICData& ic_data = ICData::ZoneHandle(); |
| 787 ic_data = ICData::New(function, | 789 ic_data = ICData::New(function, |
| 788 String::Handle(function.name()), | 790 String::Handle(function.name()), |
| 789 Isolate::kNoDeoptId, | 791 Isolate::kNoDeoptId, |
| 790 kNumArgsChecked); | 792 kNumArgsChecked); |
| 791 __ LoadObject(RBX, ic_data); | 793 __ LoadObject(RBX, ic_data); |
| 792 // RBP - 8 : PC marker, allows easy identification of RawInstruction obj. | 794 // RBP - 8 : PC marker, allows easy identification of RawInstruction obj. |
| 793 // RBP : points to previous frame pointer. | 795 // RBP : points to previous frame pointer. |
| 794 // RBP + 8 : points to return address. | 796 // RBP + 8 : points to return address. |
| 795 // RBP + 16 : address of last argument (arg n-1). | 797 // RBP + 16 : address of last argument (arg n-1). |
| 796 // RSP + 16 + 8*(n-1) : address of first argument (arg 0). | 798 // RSP + 16 + 8*(n-1) : address of first argument (arg 0). |
| 797 // RBX : ic-data. | 799 // RBX : ic-data. |
| 798 // R10 : arguments descriptor array. | 800 // R10 : arguments descriptor array. |
| 799 __ call(&StubCode::CallNoSuchMethodFunctionLabel()); | 801 __ call(&StubCode::CallNoSuchMethodFunctionLabel()); |
| 800 if (is_optimizing()) { | 802 } |
| 801 stackmap_table_builder_->AddEntry(assembler()->CodeSize(), | 803 if (is_optimizing()) { |
| 802 empty_stack_bitmap); | 804 stackmap_table_builder_->AddEntry(assembler()->CodeSize(), |
| 803 } | 805 empty_stack_bitmap); |
| 804 } | 806 } |
| 805 | 807 |
| 806 if (FLAG_trace_functions) { | 808 if (FLAG_trace_functions) { |
| 807 __ pushq(RAX); // Preserve result. | 809 __ pushq(RAX); // Preserve result. |
| 808 __ PushObject(Function::ZoneHandle(function.raw())); | 810 __ PushObject(Function::ZoneHandle(function.raw())); |
| 809 GenerateCallRuntime(Isolate::kNoDeoptId, | 811 // We do not use GenerateCallRuntime because of the non-standard (empty) |
| 810 0, | 812 // stackmap used here. |
| 811 CatchClauseNode::kInvalidTryIndex, | 813 __ CallRuntime(kTraceFunctionExitRuntimeEntry); |
| 812 kTraceFunctionExitRuntimeEntry, | 814 AddCurrentDescriptor(PcDescriptors::kOther, |
| 813 empty_stack_bitmap); | 815 Isolate::kNoDeoptId, |
| 816 0, // No token position. |
| 817 CatchClauseNode::kInvalidTryIndex); |
| 818 if (is_optimizing()) { |
| 819 stackmap_table_builder_->AddEntry(assembler()->CodeSize(), |
| 820 empty_stack_bitmap); |
| 821 } |
| 814 __ popq(RAX); // Remove argument. | 822 __ popq(RAX); // Remove argument. |
| 815 __ popq(RAX); // Restore result. | 823 __ popq(RAX); // Restore result. |
| 816 } | 824 } |
| 817 __ LeaveFrame(); | 825 __ LeaveFrame(); |
| 818 __ ret(); | 826 __ ret(); |
| 819 | 827 |
| 820 __ Bind(&all_arguments_processed); | 828 __ Bind(&all_arguments_processed); |
| 821 // Nullify originally passed arguments only after they have been copied and | 829 // Nullify originally passed arguments only after they have been copied and |
| 822 // checked, otherwise noSuchMethod would not see their original values. | 830 // checked, otherwise noSuchMethod would not see their original values. |
| 823 // This step can be skipped in case we decide that formal parameters are | 831 // This step can be skipped in case we decide that formal parameters are |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 908 const int local_count = parsed_function().stack_local_count(); | 916 const int local_count = parsed_function().stack_local_count(); |
| 909 __ Comment("Enter frame"); | 917 __ Comment("Enter frame"); |
| 910 if (IsLeaf()) { | 918 if (IsLeaf()) { |
| 911 AssemblerMacros::EnterDartLeafFrame(assembler(), (StackSize() * kWordSize)); | 919 AssemblerMacros::EnterDartLeafFrame(assembler(), (StackSize() * kWordSize)); |
| 912 } else { | 920 } else { |
| 913 AssemblerMacros::EnterDartFrame(assembler(), (StackSize() * kWordSize)); | 921 AssemblerMacros::EnterDartFrame(assembler(), (StackSize() * kWordSize)); |
| 914 } | 922 } |
| 915 | 923 |
| 916 // For optimized code, keep a bitmap of the frame in order to build | 924 // For optimized code, keep a bitmap of the frame in order to build |
| 917 // stackmaps for GC safepoints in the prologue. | 925 // stackmaps for GC safepoints in the prologue. |
| 918 BitmapBuilder* stack_bitmap = NULL; | 926 LocationSummary* prologue_locs = NULL; |
| 919 if (is_optimizing()) { | 927 if (is_optimizing()) { |
| 920 // Spill slots are allocated but not initialized. | 928 // Spill slots are allocated but not initialized. |
| 921 stack_bitmap = new BitmapBuilder(); | 929 prologue_locs = new LocationSummary(0, 0, LocationSummary::kCall); |
| 922 stack_bitmap->SetLength(StackSize()); | 930 prologue_locs->stack_bitmap()->SetLength(StackSize()); |
| 923 } | 931 } |
| 924 | 932 |
| 925 // We check the number of passed arguments when we have to copy them due to | 933 // We check the number of passed arguments when we have to copy them due to |
| 926 // the presence of optional named parameters. | 934 // the presence of optional named parameters. |
| 927 // No such checking code is generated if only fixed parameters are declared, | 935 // No such checking code is generated if only fixed parameters are declared, |
| 928 // unless we are debug mode or unless we are compiling a closure. | 936 // unless we are debug mode or unless we are compiling a closure. |
| 929 if (copied_parameter_count == 0) { | 937 if (copied_parameter_count == 0) { |
| 930 #ifdef DEBUG | 938 #ifdef DEBUG |
| 931 const bool check_arguments = true; | 939 const bool check_arguments = true; |
| 932 #else | 940 #else |
| 933 const bool check_arguments = function.IsClosureFunction(); | 941 const bool check_arguments = function.IsClosureFunction(); |
| 934 #endif | 942 #endif |
| 935 if (check_arguments) { | 943 if (check_arguments) { |
| 936 __ Comment("Check argument count"); | 944 __ Comment("Check argument count"); |
| 937 // Check that num_fixed <= argc <= num_params. | 945 // Check that num_fixed <= argc <= num_params. |
| 938 Label argc_in_range; | 946 Label argc_in_range; |
| 939 // Total number of args is the first Smi in args descriptor array (R10). | 947 // Total number of args is the first Smi in args descriptor array (R10). |
| 940 __ movq(RAX, FieldAddress(R10, Array::data_offset())); | 948 __ movq(RAX, FieldAddress(R10, Array::data_offset())); |
| 941 __ cmpq(RAX, Immediate(Smi::RawValue(parameter_count))); | 949 __ cmpq(RAX, Immediate(Smi::RawValue(parameter_count))); |
| 942 __ j(EQUAL, &argc_in_range, Assembler::kNearJump); | 950 __ j(EQUAL, &argc_in_range, Assembler::kNearJump); |
| 943 if (function.IsClosureFunction()) { | 951 if (function.IsClosureFunction()) { |
| 944 GenerateCallRuntime(Isolate::kNoDeoptId, | 952 GenerateCallRuntime(Isolate::kNoDeoptId, |
| 945 function.token_pos(), | 953 function.token_pos(), |
| 946 CatchClauseNode::kInvalidTryIndex, | 954 CatchClauseNode::kInvalidTryIndex, |
| 947 kClosureArgumentMismatchRuntimeEntry, | 955 kClosureArgumentMismatchRuntimeEntry, |
| 948 stack_bitmap); | 956 prologue_locs); |
| 949 } else { | 957 } else { |
| 950 __ Stop("Wrong number of arguments"); | 958 __ Stop("Wrong number of arguments"); |
| 951 } | 959 } |
| 952 __ Bind(&argc_in_range); | 960 __ Bind(&argc_in_range); |
| 953 } | 961 } |
| 954 } else { | 962 } else { |
| 955 CopyParameters(); | 963 CopyParameters(); |
| 956 } | 964 } |
| 957 | 965 |
| 958 // In unoptimized code, initialize (non-argument) stack allocated slots to | 966 // In unoptimized code, initialize (non-argument) stack allocated slots to |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 992 0, | 1000 0, |
| 993 -1); | 1001 -1); |
| 994 __ jmp(&StubCode::FixCallersTargetLabel()); | 1002 __ jmp(&StubCode::FixCallersTargetLabel()); |
| 995 } | 1003 } |
| 996 | 1004 |
| 997 | 1005 |
| 998 void FlowGraphCompiler::GenerateCall(intptr_t token_pos, | 1006 void FlowGraphCompiler::GenerateCall(intptr_t token_pos, |
| 999 intptr_t try_index, | 1007 intptr_t try_index, |
| 1000 const ExternalLabel* label, | 1008 const ExternalLabel* label, |
| 1001 PcDescriptors::Kind kind, | 1009 PcDescriptors::Kind kind, |
| 1002 BitmapBuilder* stack_bitmap) { | 1010 LocationSummary* locs) { |
| 1003 ASSERT(!IsLeaf()); | 1011 ASSERT(!IsLeaf()); |
| 1004 __ call(label); | 1012 __ call(label); |
| 1005 if (is_optimizing() && (stack_bitmap != NULL)) { | |
| 1006 stackmap_table_builder_->AddEntry(assembler()->CodeSize(), stack_bitmap); | |
| 1007 } | |
| 1008 AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos, try_index); | 1013 AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos, try_index); |
| 1014 RecordSafepoint(locs); |
| 1009 } | 1015 } |
| 1010 | 1016 |
| 1011 | 1017 |
| 1012 void FlowGraphCompiler::GenerateCallRuntime(intptr_t deopt_id, | 1018 void FlowGraphCompiler::GenerateCallRuntime(intptr_t deopt_id, |
| 1013 intptr_t token_pos, | 1019 intptr_t token_pos, |
| 1014 intptr_t try_index, | 1020 intptr_t try_index, |
| 1015 const RuntimeEntry& entry, | 1021 const RuntimeEntry& entry, |
| 1016 BitmapBuilder* stack_bitmap) { | 1022 LocationSummary* locs) { |
| 1017 ASSERT(!IsLeaf()); | 1023 ASSERT(!IsLeaf()); |
| 1018 ASSERT(!is_optimizing() || (stack_bitmap != NULL)); | |
| 1019 __ CallRuntime(entry); | 1024 __ CallRuntime(entry); |
| 1020 if (is_optimizing()) { | |
| 1021 stackmap_table_builder_->AddEntry(assembler()->CodeSize(), stack_bitmap); | |
| 1022 } | |
| 1023 AddCurrentDescriptor(PcDescriptors::kOther, deopt_id, token_pos, try_index); | 1025 AddCurrentDescriptor(PcDescriptors::kOther, deopt_id, token_pos, try_index); |
| 1026 RecordSafepoint(locs); |
| 1024 } | 1027 } |
| 1025 | 1028 |
| 1026 | 1029 |
| 1027 intptr_t FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label, | 1030 void FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label, |
| 1028 const ICData& ic_data, | 1031 const ICData& ic_data, |
| 1029 const Array& arguments_descriptor, | 1032 const Array& arguments_descriptor, |
| 1030 intptr_t argument_count) { | 1033 intptr_t argument_count, |
| 1034 intptr_t deopt_id, |
| 1035 intptr_t token_pos, |
| 1036 intptr_t try_index, |
| 1037 LocationSummary* locs) { |
| 1031 ASSERT(!IsLeaf()); | 1038 ASSERT(!IsLeaf()); |
| 1032 __ LoadObject(RBX, ic_data); | 1039 __ LoadObject(RBX, ic_data); |
| 1033 __ LoadObject(R10, arguments_descriptor); | 1040 __ LoadObject(R10, arguments_descriptor); |
| 1034 | 1041 |
| 1035 __ call(target_label); | 1042 __ call(target_label); |
| 1036 const intptr_t descr_offset = assembler()->CodeSize(); | 1043 AddCurrentDescriptor(PcDescriptors::kIcCall, deopt_id, token_pos, try_index); |
| 1044 RecordSafepoint(locs); |
| 1045 |
| 1037 __ Drop(argument_count); | 1046 __ Drop(argument_count); |
| 1038 return descr_offset; | |
| 1039 } | 1047 } |
| 1040 | 1048 |
| 1041 | 1049 |
| 1042 intptr_t FlowGraphCompiler::EmitStaticCall(const Function& function, | 1050 void FlowGraphCompiler::EmitStaticCall(const Function& function, |
| 1043 const Array& arguments_descriptor, | 1051 const Array& arguments_descriptor, |
| 1044 intptr_t argument_count) { | 1052 intptr_t argument_count, |
| 1053 intptr_t deopt_id, |
| 1054 intptr_t token_pos, |
| 1055 intptr_t try_index, |
| 1056 LocationSummary* locs) { |
| 1045 ASSERT(!IsLeaf()); | 1057 ASSERT(!IsLeaf()); |
| 1046 __ LoadObject(RBX, function); | 1058 __ LoadObject(RBX, function); |
| 1047 __ LoadObject(R10, arguments_descriptor); | 1059 __ LoadObject(R10, arguments_descriptor); |
| 1048 __ call(&StubCode::CallStaticFunctionLabel()); | 1060 __ call(&StubCode::CallStaticFunctionLabel()); |
| 1049 const intptr_t descr_offset = assembler()->CodeSize(); | 1061 AddCurrentDescriptor(PcDescriptors::kFuncCall, deopt_id, token_pos, |
| 1062 try_index); |
| 1063 RecordSafepoint(locs); |
| 1050 __ Drop(argument_count); | 1064 __ Drop(argument_count); |
| 1051 return descr_offset; | |
| 1052 } | 1065 } |
| 1053 | 1066 |
| 1054 | 1067 |
| 1055 // Checks class id of instance against all 'class_ids'. Jump to 'deopt' label | 1068 // Checks class id of instance against all 'class_ids'. Jump to 'deopt' label |
| 1056 // if no match or instance is Smi. | 1069 // if no match or instance is Smi. |
| 1057 void FlowGraphCompiler::EmitClassChecksNoSmi(const ICData& ic_data, | 1070 void FlowGraphCompiler::EmitClassChecksNoSmi(const ICData& ic_data, |
| 1058 Register instance_reg, | 1071 Register instance_reg, |
| 1059 Register temp_reg, | 1072 Register temp_reg, |
| 1060 Label* deopt) { | 1073 Label* deopt) { |
| 1061 Label ok; | 1074 Label ok; |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1207 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) { | 1220 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) { |
| 1208 __ Exchange(mem1, mem2); | 1221 __ Exchange(mem1, mem2); |
| 1209 } | 1222 } |
| 1210 | 1223 |
| 1211 | 1224 |
| 1212 #undef __ | 1225 #undef __ |
| 1213 | 1226 |
| 1214 } // namespace dart | 1227 } // namespace dart |
| 1215 | 1228 |
| 1216 #endif // defined TARGET_ARCH_X64 | 1229 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |