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