| 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 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 442 // - Class equality (only if class is not parameterized). | 442 // - Class equality (only if class is not parameterized). |
| 443 // Inputs: | 443 // Inputs: |
| 444 // - EAX: object. | 444 // - EAX: object. |
| 445 // - EDX: instantiator type arguments or raw_null. | 445 // - EDX: instantiator type arguments or raw_null. |
| 446 // - ECX: instantiator or raw_null. | 446 // - ECX: instantiator or raw_null. |
| 447 // Clobbers ECX and EDX. | 447 // Clobbers ECX and EDX. |
| 448 // Returns: | 448 // Returns: |
| 449 // - true or false in EAX. | 449 // - true or false in EAX. |
| 450 void FlowGraphCompiler::GenerateInstanceOf(intptr_t deopt_id, | 450 void FlowGraphCompiler::GenerateInstanceOf(intptr_t deopt_id, |
| 451 intptr_t token_pos, | 451 intptr_t token_pos, |
| 452 intptr_t try_index, | |
| 453 const AbstractType& type, | 452 const AbstractType& type, |
| 454 bool negate_result, | 453 bool negate_result, |
| 455 LocationSummary* locs) { | 454 LocationSummary* locs) { |
| 456 ASSERT(type.IsFinalized() && !type.IsMalformed()); | 455 ASSERT(type.IsFinalized() && !type.IsMalformed()); |
| 457 | 456 |
| 458 const Immediate raw_null = | 457 const Immediate raw_null = |
| 459 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 458 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 460 Label is_instance, is_not_instance; | 459 Label is_instance, is_not_instance; |
| 461 __ pushl(ECX); // Store instantiator on stack. | 460 __ pushl(ECX); // Store instantiator on stack. |
| 462 __ pushl(EDX); // Store instantiator type arguments. | 461 __ pushl(EDX); // Store instantiator type arguments. |
| (...skipping 22 matching lines...) Expand all Loading... |
| 485 // Generate runtime call. | 484 // Generate runtime call. |
| 486 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments. | 485 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments. |
| 487 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator. | 486 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator. |
| 488 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 487 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 489 __ pushl(EAX); // Push the instance. | 488 __ pushl(EAX); // Push the instance. |
| 490 __ PushObject(type); // Push the type. | 489 __ PushObject(type); // Push the type. |
| 491 __ pushl(ECX); // Instantiator. | 490 __ pushl(ECX); // Instantiator. |
| 492 __ pushl(EDX); // Instantiator type arguments. | 491 __ pushl(EDX); // Instantiator type arguments. |
| 493 __ LoadObject(EAX, test_cache); | 492 __ LoadObject(EAX, test_cache); |
| 494 __ pushl(EAX); | 493 __ pushl(EAX); |
| 495 GenerateCallRuntime(deopt_id, token_pos, try_index, | 494 GenerateCallRuntime(deopt_id, token_pos, kInstanceofRuntimeEntry, locs); |
| 496 kInstanceofRuntimeEntry, locs); | |
| 497 // Pop the parameters supplied to the runtime entry. The result of the | 495 // Pop the parameters supplied to the runtime entry. The result of the |
| 498 // instanceof runtime call will be left as the result of the operation. | 496 // instanceof runtime call will be left as the result of the operation. |
| 499 __ Drop(5); | 497 __ Drop(5); |
| 500 if (negate_result) { | 498 if (negate_result) { |
| 501 __ popl(EDX); | 499 __ popl(EDX); |
| 502 __ LoadObject(EAX, bool_true()); | 500 __ LoadObject(EAX, bool_true()); |
| 503 __ cmpl(EDX, EAX); | 501 __ cmpl(EDX, EAX); |
| 504 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 502 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
| 505 __ LoadObject(EAX, bool_false()); | 503 __ LoadObject(EAX, bool_false()); |
| 506 } else { | 504 } else { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 527 // Inputs: | 525 // Inputs: |
| 528 // - EAX: object. | 526 // - EAX: object. |
| 529 // - EDX: instantiator type arguments or raw_null. | 527 // - EDX: instantiator type arguments or raw_null. |
| 530 // - ECX: instantiator or raw_null. | 528 // - ECX: instantiator or raw_null. |
| 531 // Returns: | 529 // Returns: |
| 532 // - object in EAX for successful assignable check (or throws TypeError). | 530 // - object in EAX for successful assignable check (or throws TypeError). |
| 533 // Performance notes: positive checks must be quick, negative checks can be slow | 531 // Performance notes: positive checks must be quick, negative checks can be slow |
| 534 // as they throw an exception. | 532 // as they throw an exception. |
| 535 void FlowGraphCompiler::GenerateAssertAssignable(intptr_t deopt_id, | 533 void FlowGraphCompiler::GenerateAssertAssignable(intptr_t deopt_id, |
| 536 intptr_t token_pos, | 534 intptr_t token_pos, |
| 537 intptr_t try_index, | |
| 538 const AbstractType& dst_type, | 535 const AbstractType& dst_type, |
| 539 const String& dst_name, | 536 const String& dst_name, |
| 540 LocationSummary* locs) { | 537 LocationSummary* locs) { |
| 541 ASSERT(token_pos >= 0); | 538 ASSERT(token_pos >= 0); |
| 542 ASSERT(!dst_type.IsNull()); | 539 ASSERT(!dst_type.IsNull()); |
| 543 ASSERT(dst_type.IsFinalized()); | 540 ASSERT(dst_type.IsFinalized()); |
| 544 // Assignable check is skipped in FlowGraphBuilder, not here. | 541 // Assignable check is skipped in FlowGraphBuilder, not here. |
| 545 ASSERT(dst_type.IsMalformed() || | 542 ASSERT(dst_type.IsMalformed() || |
| 546 (!dst_type.IsDynamicType() && !dst_type.IsObjectType())); | 543 (!dst_type.IsDynamicType() && !dst_type.IsObjectType())); |
| 547 __ pushl(ECX); // Store instantiator. | 544 __ pushl(ECX); // Store instantiator. |
| 548 __ pushl(EDX); // Store instantiator type arguments. | 545 __ pushl(EDX); // Store instantiator type arguments. |
| 549 // A null object is always assignable and is returned as result. | 546 // A null object is always assignable and is returned as result. |
| 550 const Immediate raw_null = | 547 const Immediate raw_null = |
| 551 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 548 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 552 Label is_assignable, runtime_call; | 549 Label is_assignable, runtime_call; |
| 553 __ cmpl(EAX, raw_null); | 550 __ cmpl(EAX, raw_null); |
| 554 __ j(EQUAL, &is_assignable); | 551 __ j(EQUAL, &is_assignable); |
| 555 | 552 |
| 556 // Generate throw new TypeError() if the type is malformed. | 553 // Generate throw new TypeError() if the type is malformed. |
| 557 if (dst_type.IsMalformed()) { | 554 if (dst_type.IsMalformed()) { |
| 558 const Error& error = Error::Handle(dst_type.malformed_error()); | 555 const Error& error = Error::Handle(dst_type.malformed_error()); |
| 559 const String& error_message = String::ZoneHandle( | 556 const String& error_message = String::ZoneHandle( |
| 560 Symbols::New(error.ToErrorCString())); | 557 Symbols::New(error.ToErrorCString())); |
| 561 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 558 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 562 __ pushl(EAX); // Push the source object. | 559 __ pushl(EAX); // Push the source object. |
| 563 __ PushObject(dst_name); // Push the name of the destination. | 560 __ PushObject(dst_name); // Push the name of the destination. |
| 564 __ PushObject(error_message); | 561 __ PushObject(error_message); |
| 565 GenerateCallRuntime(deopt_id, | 562 GenerateCallRuntime(deopt_id, |
| 566 token_pos, | 563 token_pos, |
| 567 try_index, | |
| 568 kMalformedTypeErrorRuntimeEntry, | 564 kMalformedTypeErrorRuntimeEntry, |
| 569 locs); | 565 locs); |
| 570 // We should never return here. | 566 // We should never return here. |
| 571 __ int3(); | 567 __ int3(); |
| 572 | 568 |
| 573 __ Bind(&is_assignable); // For a null object. | 569 __ Bind(&is_assignable); // For a null object. |
| 574 __ popl(EDX); // Remove pushed instantiator type arguments. | 570 __ popl(EDX); // Remove pushed instantiator type arguments. |
| 575 __ popl(ECX); // Remove pushed instantiator. | 571 __ popl(ECX); // Remove pushed instantiator. |
| 576 return; | 572 return; |
| 577 } | 573 } |
| 578 | 574 |
| 579 // Generate inline type check, linking to runtime call if not assignable. | 575 // Generate inline type check, linking to runtime call if not assignable. |
| 580 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(); | 576 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(); |
| 581 test_cache = GenerateInlineInstanceof(token_pos, dst_type, | 577 test_cache = GenerateInlineInstanceof(token_pos, dst_type, |
| 582 &is_assignable, &runtime_call); | 578 &is_assignable, &runtime_call); |
| 583 | 579 |
| 584 __ Bind(&runtime_call); | 580 __ Bind(&runtime_call); |
| 585 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments. | 581 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments. |
| 586 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator. | 582 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator. |
| 587 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 583 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 588 __ pushl(EAX); // Push the source object. | 584 __ pushl(EAX); // Push the source object. |
| 589 __ PushObject(dst_type); // Push the type of the destination. | 585 __ PushObject(dst_type); // Push the type of the destination. |
| 590 __ pushl(ECX); // Instantiator. | 586 __ pushl(ECX); // Instantiator. |
| 591 __ pushl(EDX); // Instantiator type arguments. | 587 __ pushl(EDX); // Instantiator type arguments. |
| 592 __ PushObject(dst_name); // Push the name of the destination. | 588 __ PushObject(dst_name); // Push the name of the destination. |
| 593 __ LoadObject(EAX, test_cache); | 589 __ LoadObject(EAX, test_cache); |
| 594 __ pushl(EAX); | 590 __ pushl(EAX); |
| 595 GenerateCallRuntime(deopt_id, | 591 GenerateCallRuntime(deopt_id, token_pos, kTypeCheckRuntimeEntry, locs); |
| 596 token_pos, | |
| 597 try_index, | |
| 598 kTypeCheckRuntimeEntry, | |
| 599 locs); | |
| 600 // Pop the parameters supplied to the runtime entry. The result of the | 592 // Pop the parameters supplied to the runtime entry. The result of the |
| 601 // type check runtime call is the checked value. | 593 // type check runtime call is the checked value. |
| 602 __ Drop(6); | 594 __ Drop(6); |
| 603 __ popl(EAX); | 595 __ popl(EAX); |
| 604 | 596 |
| 605 __ Bind(&is_assignable); | 597 __ Bind(&is_assignable); |
| 606 __ popl(EDX); // Remove pushed instantiator type arguments. | 598 __ popl(EDX); // Remove pushed instantiator type arguments. |
| 607 __ popl(ECX); // Remove pushed instantiator. | 599 __ popl(ECX); // Remove pushed instantiator. |
| 608 } | 600 } |
| 609 | 601 |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 768 } | 760 } |
| 769 // The calls below have empty stackmaps because we have just dropped the | 761 // The calls below have empty stackmaps because we have just dropped the |
| 770 // spill slots. | 762 // spill slots. |
| 771 BitmapBuilder* empty_stack_bitmap = new BitmapBuilder(); | 763 BitmapBuilder* empty_stack_bitmap = new BitmapBuilder(); |
| 772 if (function.IsClosureFunction()) { | 764 if (function.IsClosureFunction()) { |
| 773 // We do not use GenerateCallRuntime because of the non-standard (empty) | 765 // We do not use GenerateCallRuntime because of the non-standard (empty) |
| 774 // stackmap used here. | 766 // stackmap used here. |
| 775 __ CallRuntime(kClosureArgumentMismatchRuntimeEntry); | 767 __ CallRuntime(kClosureArgumentMismatchRuntimeEntry); |
| 776 AddCurrentDescriptor(PcDescriptors::kOther, | 768 AddCurrentDescriptor(PcDescriptors::kOther, |
| 777 Isolate::kNoDeoptId, | 769 Isolate::kNoDeoptId, |
| 778 0, // No token position. | 770 0); // No token position. |
| 779 CatchClauseNode::kInvalidTryIndex); | |
| 780 } else { | 771 } else { |
| 781 ASSERT(!IsLeaf()); | 772 ASSERT(!IsLeaf()); |
| 782 // Invoke noSuchMethod function. | 773 // Invoke noSuchMethod function. |
| 783 const int kNumArgsChecked = 1; | 774 const int kNumArgsChecked = 1; |
| 784 ICData& ic_data = ICData::ZoneHandle(); | 775 ICData& ic_data = ICData::ZoneHandle(); |
| 785 ic_data = ICData::New(function, | 776 ic_data = ICData::New(function, |
| 786 String::Handle(function.name()), | 777 String::Handle(function.name()), |
| 787 Isolate::kNoDeoptId, | 778 Isolate::kNoDeoptId, |
| 788 kNumArgsChecked); | 779 kNumArgsChecked); |
| 789 __ LoadObject(ECX, ic_data); | 780 __ LoadObject(ECX, ic_data); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 803 | 794 |
| 804 | 795 |
| 805 if (FLAG_trace_functions) { | 796 if (FLAG_trace_functions) { |
| 806 __ pushl(EAX); // Preserve result. | 797 __ pushl(EAX); // Preserve result. |
| 807 __ PushObject(Function::ZoneHandle(function.raw())); | 798 __ PushObject(Function::ZoneHandle(function.raw())); |
| 808 // We do not use GenerateCallRuntime because of the non-standard (empty) | 799 // We do not use GenerateCallRuntime because of the non-standard (empty) |
| 809 // stackmap used here. | 800 // stackmap used here. |
| 810 __ CallRuntime(kTraceFunctionExitRuntimeEntry); | 801 __ CallRuntime(kTraceFunctionExitRuntimeEntry); |
| 811 AddCurrentDescriptor(PcDescriptors::kOther, | 802 AddCurrentDescriptor(PcDescriptors::kOther, |
| 812 Isolate::kNoDeoptId, | 803 Isolate::kNoDeoptId, |
| 813 0, // No token position. | 804 0); // No token position. |
| 814 CatchClauseNode::kInvalidTryIndex); | |
| 815 if (is_optimizing()) { | 805 if (is_optimizing()) { |
| 816 stackmap_table_builder_->AddEntry(assembler()->CodeSize(), | 806 stackmap_table_builder_->AddEntry(assembler()->CodeSize(), |
| 817 empty_stack_bitmap); | 807 empty_stack_bitmap); |
| 818 } | 808 } |
| 819 __ popl(EAX); // Remove argument. | 809 __ popl(EAX); // Remove argument. |
| 820 __ popl(EAX); // Restore result. | 810 __ popl(EAX); // Restore result. |
| 821 } | 811 } |
| 822 __ LeaveFrame(); | 812 __ LeaveFrame(); |
| 823 __ ret(); | 813 __ ret(); |
| 824 | 814 |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 941 __ Comment("Check argument count"); | 931 __ Comment("Check argument count"); |
| 942 // Check that num_fixed <= argc <= num_params. | 932 // Check that num_fixed <= argc <= num_params. |
| 943 Label argc_in_range; | 933 Label argc_in_range; |
| 944 // Total number of args is the first Smi in args descriptor array (EDX). | 934 // Total number of args is the first Smi in args descriptor array (EDX). |
| 945 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 935 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 946 __ cmpl(EAX, Immediate(Smi::RawValue(parameter_count))); | 936 __ cmpl(EAX, Immediate(Smi::RawValue(parameter_count))); |
| 947 __ j(EQUAL, &argc_in_range, Assembler::kNearJump); | 937 __ j(EQUAL, &argc_in_range, Assembler::kNearJump); |
| 948 if (function.IsClosureFunction()) { | 938 if (function.IsClosureFunction()) { |
| 949 GenerateCallRuntime(Isolate::kNoDeoptId, | 939 GenerateCallRuntime(Isolate::kNoDeoptId, |
| 950 function.token_pos(), | 940 function.token_pos(), |
| 951 CatchClauseNode::kInvalidTryIndex, | |
| 952 kClosureArgumentMismatchRuntimeEntry, | 941 kClosureArgumentMismatchRuntimeEntry, |
| 953 prologue_locs); | 942 prologue_locs); |
| 954 } else { | 943 } else { |
| 955 __ Stop("Wrong number of arguments"); | 944 __ Stop("Wrong number of arguments"); |
| 956 } | 945 } |
| 957 __ Bind(&argc_in_range); | 946 __ Bind(&argc_in_range); |
| 958 } | 947 } |
| 959 } else { | 948 } else { |
| 960 CopyParameters(); | 949 CopyParameters(); |
| 961 } | 950 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 985 } | 974 } |
| 986 | 975 |
| 987 VisitBlocks(); | 976 VisitBlocks(); |
| 988 | 977 |
| 989 __ int3(); | 978 __ int3(); |
| 990 GenerateDeferredCode(); | 979 GenerateDeferredCode(); |
| 991 // Emit function patching code. This will be swapped with the first 5 bytes | 980 // Emit function patching code. This will be swapped with the first 5 bytes |
| 992 // at entry point. | 981 // at entry point. |
| 993 AddCurrentDescriptor(PcDescriptors::kPatchCode, | 982 AddCurrentDescriptor(PcDescriptors::kPatchCode, |
| 994 Isolate::kNoDeoptId, | 983 Isolate::kNoDeoptId, |
| 995 0, // No token position. | 984 0); // No token position. |
| 996 CatchClauseNode::kInvalidTryIndex); | |
| 997 __ jmp(&StubCode::FixCallersTargetLabel()); | 985 __ jmp(&StubCode::FixCallersTargetLabel()); |
| 998 } | 986 } |
| 999 | 987 |
| 1000 | 988 |
| 1001 void FlowGraphCompiler::GenerateCall(intptr_t token_pos, | 989 void FlowGraphCompiler::GenerateCall(intptr_t token_pos, |
| 1002 intptr_t try_index, | |
| 1003 const ExternalLabel* label, | 990 const ExternalLabel* label, |
| 1004 PcDescriptors::Kind kind, | 991 PcDescriptors::Kind kind, |
| 1005 LocationSummary* locs) { | 992 LocationSummary* locs) { |
| 1006 ASSERT(!IsLeaf()); | 993 ASSERT(!IsLeaf()); |
| 1007 __ call(label); | 994 __ call(label); |
| 1008 AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos, try_index); | 995 AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos); |
| 1009 RecordSafepoint(locs); | 996 RecordSafepoint(locs); |
| 1010 } | 997 } |
| 1011 | 998 |
| 1012 | 999 |
| 1013 void FlowGraphCompiler::GenerateCallRuntime(intptr_t deopt_id, | 1000 void FlowGraphCompiler::GenerateCallRuntime(intptr_t deopt_id, |
| 1014 intptr_t token_pos, | 1001 intptr_t token_pos, |
| 1015 intptr_t try_index, | |
| 1016 const RuntimeEntry& entry, | 1002 const RuntimeEntry& entry, |
| 1017 LocationSummary* locs) { | 1003 LocationSummary* locs) { |
| 1018 ASSERT(!IsLeaf()); | 1004 ASSERT(!IsLeaf()); |
| 1019 __ CallRuntime(entry); | 1005 __ CallRuntime(entry); |
| 1020 AddCurrentDescriptor(PcDescriptors::kOther, deopt_id, token_pos, try_index); | 1006 AddCurrentDescriptor(PcDescriptors::kOther, deopt_id, token_pos); |
| 1021 RecordSafepoint(locs); | 1007 RecordSafepoint(locs); |
| 1022 } | 1008 } |
| 1023 | 1009 |
| 1024 | 1010 |
| 1025 void FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label, | 1011 void FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label, |
| 1026 const ICData& ic_data, | 1012 const ICData& ic_data, |
| 1027 const Array& arguments_descriptor, | 1013 const Array& arguments_descriptor, |
| 1028 intptr_t argument_count, | 1014 intptr_t argument_count, |
| 1029 intptr_t deopt_id, | 1015 intptr_t deopt_id, |
| 1030 intptr_t token_pos, | 1016 intptr_t token_pos, |
| 1031 intptr_t try_index, | |
| 1032 LocationSummary* locs) { | 1017 LocationSummary* locs) { |
| 1033 ASSERT(!IsLeaf()); | 1018 ASSERT(!IsLeaf()); |
| 1034 __ LoadObject(ECX, ic_data); | 1019 __ LoadObject(ECX, ic_data); |
| 1035 __ LoadObject(EDX, arguments_descriptor); | 1020 __ LoadObject(EDX, arguments_descriptor); |
| 1036 | 1021 |
| 1037 __ call(target_label); | 1022 __ call(target_label); |
| 1038 AddCurrentDescriptor(PcDescriptors::kIcCall, deopt_id, token_pos, try_index); | 1023 AddCurrentDescriptor(PcDescriptors::kIcCall, deopt_id, token_pos); |
| 1039 RecordSafepoint(locs); | 1024 RecordSafepoint(locs); |
| 1040 | 1025 |
| 1041 __ Drop(argument_count); | 1026 __ Drop(argument_count); |
| 1042 } | 1027 } |
| 1043 | 1028 |
| 1044 | 1029 |
| 1045 void FlowGraphCompiler::EmitStaticCall(const Function& function, | 1030 void FlowGraphCompiler::EmitStaticCall(const Function& function, |
| 1046 const Array& arguments_descriptor, | 1031 const Array& arguments_descriptor, |
| 1047 intptr_t argument_count, | 1032 intptr_t argument_count, |
| 1048 intptr_t deopt_id, | 1033 intptr_t deopt_id, |
| 1049 intptr_t token_pos, | 1034 intptr_t token_pos, |
| 1050 intptr_t try_index, | |
| 1051 LocationSummary* locs) { | 1035 LocationSummary* locs) { |
| 1052 ASSERT(!IsLeaf()); | 1036 ASSERT(!IsLeaf()); |
| 1053 __ LoadObject(ECX, function); | 1037 __ LoadObject(ECX, function); |
| 1054 __ LoadObject(EDX, arguments_descriptor); | 1038 __ LoadObject(EDX, arguments_descriptor); |
| 1055 __ call(&StubCode::CallStaticFunctionLabel()); | 1039 __ call(&StubCode::CallStaticFunctionLabel()); |
| 1056 AddCurrentDescriptor(PcDescriptors::kFuncCall, deopt_id, token_pos, | 1040 AddCurrentDescriptor(PcDescriptors::kFuncCall, deopt_id, token_pos); |
| 1057 try_index); | |
| 1058 RecordSafepoint(locs); | 1041 RecordSafepoint(locs); |
| 1059 if (is_optimizing()) { | 1042 if (is_optimizing()) { |
| 1060 AddDeoptIndexAtCall(deopt_id, token_pos); | 1043 AddDeoptIndexAtCall(deopt_id, token_pos); |
| 1061 } | 1044 } |
| 1062 __ Drop(argument_count); | 1045 __ Drop(argument_count); |
| 1063 } | 1046 } |
| 1064 | 1047 |
| 1065 | 1048 |
| 1066 // Checks class id of instance against all 'class_ids'. Jump to 'deopt' label | 1049 // Checks class id of instance against all 'class_ids'. Jump to 'deopt' label |
| 1067 // if no match or instance is Smi. | 1050 // if no match or instance is Smi. |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1315 __ popl(ECX); | 1298 __ popl(ECX); |
| 1316 __ popl(EAX); | 1299 __ popl(EAX); |
| 1317 } | 1300 } |
| 1318 | 1301 |
| 1319 | 1302 |
| 1320 #undef __ | 1303 #undef __ |
| 1321 | 1304 |
| 1322 } // namespace dart | 1305 } // namespace dart |
| 1323 | 1306 |
| 1324 #endif // defined TARGET_ARCH_IA32 | 1307 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |