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 |