| 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 29 matching lines...) Expand all Loading... |
| 40 const intptr_t offset = assem->CodeSize(); | 40 const intptr_t offset = assem->CodeSize(); |
| 41 __ Bind(&L); | 41 __ Bind(&L); |
| 42 __ popl(EAX); | 42 __ popl(EAX); |
| 43 __ subl(EAX, | 43 __ subl(EAX, |
| 44 Immediate(offset - AssemblerMacros::kOffsetOfSavedPCfromEntrypoint)); | 44 Immediate(offset - AssemblerMacros::kOffsetOfSavedPCfromEntrypoint)); |
| 45 __ movl(Address(EBP, -kWordSize), EAX); | 45 __ movl(Address(EBP, -kWordSize), EAX); |
| 46 __ popl(EAX); | 46 __ popl(EAX); |
| 47 } | 47 } |
| 48 __ call(&StubCode::DeoptimizeLabel()); | 48 __ call(&StubCode::DeoptimizeLabel()); |
| 49 const intptr_t deopt_info_index = stub_ix; | 49 const intptr_t deopt_info_index = stub_ix; |
| 50 compiler->pc_descriptors_list()-> AddDeoptInfo( | 50 compiler->pc_descriptors_list()->AddDeoptInfo( |
| 51 compiler->assembler()->CodeSize(), | 51 compiler->assembler()->CodeSize(), |
| 52 deopt_id_, | 52 deopt_id_, |
| 53 reason_, | 53 reason_, |
| 54 deopt_info_index); | 54 deopt_info_index); |
| 55 #undef __ | 55 #undef __ |
| 56 } | 56 } |
| 57 | 57 |
| 58 | 58 |
| 59 #define __ assembler()-> | 59 #define __ assembler()-> |
| 60 | 60 |
| (...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 443 // - EDX: instantiator type arguments or raw_null. | 443 // - EDX: instantiator type arguments or raw_null. |
| 444 // - ECX: instantiator or raw_null. | 444 // - ECX: instantiator or raw_null. |
| 445 // Clobbers ECX and EDX. | 445 // Clobbers ECX and EDX. |
| 446 // Returns: | 446 // Returns: |
| 447 // - true or false in EAX. | 447 // - true or false in EAX. |
| 448 void FlowGraphCompiler::GenerateInstanceOf(intptr_t deopt_id, | 448 void FlowGraphCompiler::GenerateInstanceOf(intptr_t deopt_id, |
| 449 intptr_t token_pos, | 449 intptr_t token_pos, |
| 450 intptr_t try_index, | 450 intptr_t try_index, |
| 451 const AbstractType& type, | 451 const AbstractType& type, |
| 452 bool negate_result, | 452 bool negate_result, |
| 453 BitmapBuilder* stack_bitmap) { | 453 LocationSummary* locs) { |
| 454 ASSERT(type.IsFinalized() && !type.IsMalformed()); | 454 ASSERT(type.IsFinalized() && !type.IsMalformed()); |
| 455 | 455 |
| 456 const Immediate raw_null = | 456 const Immediate raw_null = |
| 457 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 457 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 458 Label is_instance, is_not_instance; | 458 Label is_instance, is_not_instance; |
| 459 __ pushl(ECX); // Store instantiator on stack. | 459 __ pushl(ECX); // Store instantiator on stack. |
| 460 __ pushl(EDX); // Store instantiator type arguments. | 460 __ pushl(EDX); // Store instantiator type arguments. |
| 461 // If type is instantiated and non-parameterized, we can inline code | 461 // If type is instantiated and non-parameterized, we can inline code |
| 462 // checking whether the tested instance is a Smi. | 462 // checking whether the tested instance is a Smi. |
| 463 if (type.IsInstantiated()) { | 463 if (type.IsInstantiated()) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 484 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments. | 484 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments. |
| 485 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator. | 485 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator. |
| 486 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 486 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 487 __ pushl(EAX); // Push the instance. | 487 __ pushl(EAX); // Push the instance. |
| 488 __ PushObject(type); // Push the type. | 488 __ PushObject(type); // Push the type. |
| 489 __ pushl(ECX); // Instantiator. | 489 __ pushl(ECX); // Instantiator. |
| 490 __ pushl(EDX); // Instantiator type arguments. | 490 __ pushl(EDX); // Instantiator type arguments. |
| 491 __ LoadObject(EAX, test_cache); | 491 __ LoadObject(EAX, test_cache); |
| 492 __ pushl(EAX); | 492 __ pushl(EAX); |
| 493 GenerateCallRuntime(deopt_id, token_pos, try_index, | 493 GenerateCallRuntime(deopt_id, token_pos, try_index, |
| 494 kInstanceofRuntimeEntry, stack_bitmap); | 494 kInstanceofRuntimeEntry, locs); |
| 495 // 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 |
| 496 // 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. |
| 497 __ Drop(5); | 497 __ Drop(5); |
| 498 if (negate_result) { | 498 if (negate_result) { |
| 499 __ popl(EDX); | 499 __ popl(EDX); |
| 500 __ LoadObject(EAX, bool_true()); | 500 __ LoadObject(EAX, bool_true()); |
| 501 __ cmpl(EDX, EAX); | 501 __ cmpl(EDX, EAX); |
| 502 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 502 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
| 503 __ LoadObject(EAX, bool_false()); | 503 __ LoadObject(EAX, bool_false()); |
| 504 } else { | 504 } else { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 528 // - ECX: instantiator or raw_null. | 528 // - ECX: instantiator or raw_null. |
| 529 // Returns: | 529 // Returns: |
| 530 // - object in EAX for successful assignable check (or throws TypeError). | 530 // - object in EAX for successful assignable check (or throws TypeError). |
| 531 // 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 |
| 532 // as they throw an exception. | 532 // as they throw an exception. |
| 533 void FlowGraphCompiler::GenerateAssertAssignable(intptr_t deopt_id, | 533 void FlowGraphCompiler::GenerateAssertAssignable(intptr_t deopt_id, |
| 534 intptr_t token_pos, | 534 intptr_t token_pos, |
| 535 intptr_t try_index, | 535 intptr_t try_index, |
| 536 const AbstractType& dst_type, | 536 const AbstractType& dst_type, |
| 537 const String& dst_name, | 537 const String& dst_name, |
| 538 BitmapBuilder* stack_bitmap) { | 538 LocationSummary* locs) { |
| 539 ASSERT(token_pos >= 0); | 539 ASSERT(token_pos >= 0); |
| 540 ASSERT(!dst_type.IsNull()); | 540 ASSERT(!dst_type.IsNull()); |
| 541 ASSERT(dst_type.IsFinalized()); | 541 ASSERT(dst_type.IsFinalized()); |
| 542 // Assignable check is skipped in FlowGraphBuilder, not here. | 542 // Assignable check is skipped in FlowGraphBuilder, not here. |
| 543 ASSERT(dst_type.IsMalformed() || | 543 ASSERT(dst_type.IsMalformed() || |
| 544 (!dst_type.IsDynamicType() && !dst_type.IsObjectType())); | 544 (!dst_type.IsDynamicType() && !dst_type.IsObjectType())); |
| 545 __ pushl(ECX); // Store instantiator. | 545 __ pushl(ECX); // Store instantiator. |
| 546 __ pushl(EDX); // Store instantiator type arguments. | 546 __ pushl(EDX); // Store instantiator type arguments. |
| 547 // A null object is always assignable and is returned as result. | 547 // A null object is always assignable and is returned as result. |
| 548 const Immediate raw_null = | 548 const Immediate raw_null = |
| 549 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 549 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 550 Label is_assignable, runtime_call; | 550 Label is_assignable, runtime_call; |
| 551 __ cmpl(EAX, raw_null); | 551 __ cmpl(EAX, raw_null); |
| 552 __ j(EQUAL, &is_assignable); | 552 __ j(EQUAL, &is_assignable); |
| 553 | 553 |
| 554 // Generate throw new TypeError() if the type is malformed. | 554 // Generate throw new TypeError() if the type is malformed. |
| 555 if (dst_type.IsMalformed()) { | 555 if (dst_type.IsMalformed()) { |
| 556 const Error& error = Error::Handle(dst_type.malformed_error()); | 556 const Error& error = Error::Handle(dst_type.malformed_error()); |
| 557 const String& error_message = String::ZoneHandle( | 557 const String& error_message = String::ZoneHandle( |
| 558 Symbols::New(error.ToErrorCString())); | 558 Symbols::New(error.ToErrorCString())); |
| 559 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 559 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 560 __ pushl(EAX); // Push the source object. | 560 __ pushl(EAX); // Push the source object. |
| 561 __ PushObject(dst_name); // Push the name of the destination. | 561 __ PushObject(dst_name); // Push the name of the destination. |
| 562 __ PushObject(error_message); | 562 __ PushObject(error_message); |
| 563 GenerateCallRuntime(deopt_id, | 563 GenerateCallRuntime(deopt_id, |
| 564 token_pos, | 564 token_pos, |
| 565 try_index, | 565 try_index, |
| 566 kMalformedTypeErrorRuntimeEntry, | 566 kMalformedTypeErrorRuntimeEntry, |
| 567 stack_bitmap); | 567 locs); |
| 568 // We should never return here. | 568 // We should never return here. |
| 569 __ int3(); | 569 __ int3(); |
| 570 | 570 |
| 571 __ Bind(&is_assignable); // For a null object. | 571 __ Bind(&is_assignable); // For a null object. |
| 572 __ popl(EDX); // Remove pushed instantiator type arguments. | 572 __ popl(EDX); // Remove pushed instantiator type arguments. |
| 573 __ popl(ECX); // Remove pushed instantiator. | 573 __ popl(ECX); // Remove pushed instantiator. |
| 574 return; | 574 return; |
| 575 } | 575 } |
| 576 | 576 |
| 577 // Generate inline type check, linking to runtime call if not assignable. | 577 // Generate inline type check, linking to runtime call if not assignable. |
| 578 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(); | 578 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(); |
| 579 test_cache = GenerateInlineInstanceof(token_pos, dst_type, | 579 test_cache = GenerateInlineInstanceof(token_pos, dst_type, |
| 580 &is_assignable, &runtime_call); | 580 &is_assignable, &runtime_call); |
| 581 | 581 |
| 582 __ Bind(&runtime_call); | 582 __ Bind(&runtime_call); |
| 583 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments. | 583 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments. |
| 584 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator. | 584 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator. |
| 585 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 585 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 586 __ pushl(EAX); // Push the source object. | 586 __ pushl(EAX); // Push the source object. |
| 587 __ PushObject(dst_type); // Push the type of the destination. | 587 __ PushObject(dst_type); // Push the type of the destination. |
| 588 __ pushl(ECX); // Instantiator. | 588 __ pushl(ECX); // Instantiator. |
| 589 __ pushl(EDX); // Instantiator type arguments. | 589 __ pushl(EDX); // Instantiator type arguments. |
| 590 __ PushObject(dst_name); // Push the name of the destination. | 590 __ PushObject(dst_name); // Push the name of the destination. |
| 591 __ LoadObject(EAX, test_cache); | 591 __ LoadObject(EAX, test_cache); |
| 592 __ pushl(EAX); | 592 __ pushl(EAX); |
| 593 GenerateCallRuntime(deopt_id, | 593 GenerateCallRuntime(deopt_id, |
| 594 token_pos, | 594 token_pos, |
| 595 try_index, | 595 try_index, |
| 596 kTypeCheckRuntimeEntry, | 596 kTypeCheckRuntimeEntry, |
| 597 stack_bitmap); | 597 locs); |
| 598 // Pop the parameters supplied to the runtime entry. The result of the | 598 // Pop the parameters supplied to the runtime entry. The result of the |
| 599 // type check runtime call is the checked value. | 599 // type check runtime call is the checked value. |
| 600 __ Drop(6); | 600 __ Drop(6); |
| 601 __ popl(EAX); | 601 __ popl(EAX); |
| 602 | 602 |
| 603 __ Bind(&is_assignable); | 603 __ Bind(&is_assignable); |
| 604 __ popl(EDX); // Remove pushed instantiator type arguments. | 604 __ popl(EDX); // Remove pushed instantiator type arguments. |
| 605 __ popl(ECX); // Remove pushed instantiator. | 605 __ popl(ECX); // Remove pushed instantiator. |
| 606 } | 606 } |
| 607 | 607 |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 761 if (StackSize() != 0) { | 761 if (StackSize() != 0) { |
| 762 // We need to unwind the space we reserved for locals and copied parameters. | 762 // We need to unwind the space we reserved for locals and copied parameters. |
| 763 // The NoSuchMethodFunction stub does not expect to see that area on the | 763 // The NoSuchMethodFunction stub does not expect to see that area on the |
| 764 // stack. | 764 // stack. |
| 765 __ addl(ESP, Immediate(StackSize() * kWordSize)); | 765 __ addl(ESP, Immediate(StackSize() * kWordSize)); |
| 766 } | 766 } |
| 767 // The calls below have empty stackmaps because we have just dropped the | 767 // The calls below have empty stackmaps because we have just dropped the |
| 768 // spill slots. | 768 // spill slots. |
| 769 BitmapBuilder* empty_stack_bitmap = new BitmapBuilder(); | 769 BitmapBuilder* empty_stack_bitmap = new BitmapBuilder(); |
| 770 if (function.IsClosureFunction()) { | 770 if (function.IsClosureFunction()) { |
| 771 GenerateCallRuntime(Isolate::kNoDeoptId, | 771 // We do not use GenerateCallRuntime because of the non-standard (empty) |
| 772 0, | 772 // stackmap used here. |
| 773 CatchClauseNode::kInvalidTryIndex, | 773 __ CallRuntime(kClosureArgumentMismatchRuntimeEntry); |
| 774 kClosureArgumentMismatchRuntimeEntry, | 774 AddCurrentDescriptor(PcDescriptors::kOther, |
| 775 empty_stack_bitmap); | 775 Isolate::kNoDeoptId, |
| 776 0, // No token position. |
| 777 CatchClauseNode::kInvalidTryIndex); |
| 776 } else { | 778 } else { |
| 777 ASSERT(!IsLeaf()); | 779 ASSERT(!IsLeaf()); |
| 778 // Invoke noSuchMethod function. | 780 // Invoke noSuchMethod function. |
| 779 const int kNumArgsChecked = 1; | 781 const int kNumArgsChecked = 1; |
| 780 ICData& ic_data = ICData::ZoneHandle(); | 782 ICData& ic_data = ICData::ZoneHandle(); |
| 781 ic_data = ICData::New(function, | 783 ic_data = ICData::New(function, |
| 782 String::Handle(function.name()), | 784 String::Handle(function.name()), |
| 783 Isolate::kNoDeoptId, | 785 Isolate::kNoDeoptId, |
| 784 kNumArgsChecked); | 786 kNumArgsChecked); |
| 785 __ LoadObject(ECX, ic_data); | 787 __ LoadObject(ECX, ic_data); |
| 786 // EBP - 4 : PC marker, allows easy identification of RawInstruction obj. | 788 // EBP - 4 : PC marker, allows easy identification of RawInstruction obj. |
| 787 // EBP : points to previous frame pointer. | 789 // EBP : points to previous frame pointer. |
| 788 // EBP + 4 : points to return address. | 790 // EBP + 4 : points to return address. |
| 789 // EBP + 8 : address of last argument (arg n-1). | 791 // EBP + 8 : address of last argument (arg n-1). |
| 790 // ESP + 8 + 4*(n-1) : address of first argument (arg 0). | 792 // ESP + 8 + 4*(n-1) : address of first argument (arg 0). |
| 791 // ECX : ic-data. | 793 // ECX : ic-data. |
| 792 // EDX : arguments descriptor array. | 794 // EDX : arguments descriptor array. |
| 793 __ call(&StubCode::CallNoSuchMethodFunctionLabel()); | 795 __ call(&StubCode::CallNoSuchMethodFunctionLabel()); |
| 796 } |
| 797 if (is_optimizing()) { |
| 798 stackmap_table_builder_->AddEntry(assembler()->CodeSize(), |
| 799 empty_stack_bitmap); |
| 800 } |
| 801 |
| 802 |
| 803 if (FLAG_trace_functions) { |
| 804 __ pushl(EAX); // Preserve result. |
| 805 __ PushObject(Function::ZoneHandle(function.raw())); |
| 806 // We do not use GenerateCallRuntime because of the non-standard (empty) |
| 807 // stackmap used here. |
| 808 __ CallRuntime(kTraceFunctionExitRuntimeEntry); |
| 809 AddCurrentDescriptor(PcDescriptors::kOther, |
| 810 Isolate::kNoDeoptId, |
| 811 0, // No token position. |
| 812 CatchClauseNode::kInvalidTryIndex); |
| 794 if (is_optimizing()) { | 813 if (is_optimizing()) { |
| 795 stackmap_table_builder_->AddEntry(assembler()->CodeSize(), | 814 stackmap_table_builder_->AddEntry(assembler()->CodeSize(), |
| 796 empty_stack_bitmap); | 815 empty_stack_bitmap); |
| 797 } | 816 } |
| 798 } | |
| 799 | |
| 800 if (FLAG_trace_functions) { | |
| 801 __ pushl(EAX); // Preserve result. | |
| 802 __ PushObject(Function::ZoneHandle(function.raw())); | |
| 803 GenerateCallRuntime(Isolate::kNoDeoptId, | |
| 804 0, | |
| 805 CatchClauseNode::kInvalidTryIndex, | |
| 806 kTraceFunctionExitRuntimeEntry, | |
| 807 empty_stack_bitmap); | |
| 808 __ popl(EAX); // Remove argument. | 817 __ popl(EAX); // Remove argument. |
| 809 __ popl(EAX); // Restore result. | 818 __ popl(EAX); // Restore result. |
| 810 } | 819 } |
| 811 __ LeaveFrame(); | 820 __ LeaveFrame(); |
| 812 __ ret(); | 821 __ ret(); |
| 813 | 822 |
| 814 __ Bind(&all_arguments_processed); | 823 __ Bind(&all_arguments_processed); |
| 815 // Nullify originally passed arguments only after they have been copied and | 824 // Nullify originally passed arguments only after they have been copied and |
| 816 // checked, otherwise noSuchMethod would not see their original values. | 825 // checked, otherwise noSuchMethod would not see their original values. |
| 817 // This step can be skipped in case we decide that formal parameters are | 826 // This step can be skipped in case we decide that formal parameters are |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 901 const int local_count = parsed_function().stack_local_count(); | 910 const int local_count = parsed_function().stack_local_count(); |
| 902 __ Comment("Enter frame"); | 911 __ Comment("Enter frame"); |
| 903 if (IsLeaf()) { | 912 if (IsLeaf()) { |
| 904 AssemblerMacros::EnterDartLeafFrame(assembler(), (StackSize() * kWordSize)); | 913 AssemblerMacros::EnterDartLeafFrame(assembler(), (StackSize() * kWordSize)); |
| 905 } else { | 914 } else { |
| 906 AssemblerMacros::EnterDartFrame(assembler(), (StackSize() * kWordSize)); | 915 AssemblerMacros::EnterDartFrame(assembler(), (StackSize() * kWordSize)); |
| 907 } | 916 } |
| 908 | 917 |
| 909 // For optimized code, keep a bitmap of the frame in order to build | 918 // For optimized code, keep a bitmap of the frame in order to build |
| 910 // stackmaps for GC safepoints in the prologue. | 919 // stackmaps for GC safepoints in the prologue. |
| 911 BitmapBuilder* stack_bitmap = NULL; | 920 LocationSummary* prologue_locs = NULL; |
| 912 if (is_optimizing()) { | 921 if (is_optimizing()) { |
| 913 // Spill slots are allocated but not initialized. | 922 // Spill slots are allocated but not initialized. |
| 914 stack_bitmap = new BitmapBuilder(); | 923 prologue_locs = new LocationSummary(0, 0, LocationSummary::kCall); |
| 915 stack_bitmap->SetLength(StackSize()); | 924 prologue_locs->stack_bitmap()->SetLength(StackSize()); |
| 916 } | 925 } |
| 917 | 926 |
| 918 // We check the number of passed arguments when we have to copy them due to | 927 // We check the number of passed arguments when we have to copy them due to |
| 919 // the presence of optional named parameters. | 928 // the presence of optional named parameters. |
| 920 // No such checking code is generated if only fixed parameters are declared, | 929 // No such checking code is generated if only fixed parameters are declared, |
| 921 // unless we are debug mode or unless we are compiling a closure. | 930 // unless we are debug mode or unless we are compiling a closure. |
| 922 if (copied_parameter_count == 0) { | 931 if (copied_parameter_count == 0) { |
| 923 #ifdef DEBUG | 932 #ifdef DEBUG |
| 924 const bool check_arguments = true; | 933 const bool check_arguments = true; |
| 925 #else | 934 #else |
| 926 const bool check_arguments = function.IsClosureFunction(); | 935 const bool check_arguments = function.IsClosureFunction(); |
| 927 #endif | 936 #endif |
| 928 if (check_arguments) { | 937 if (check_arguments) { |
| 929 __ Comment("Check argument count"); | 938 __ Comment("Check argument count"); |
| 930 // Check that num_fixed <= argc <= num_params. | 939 // Check that num_fixed <= argc <= num_params. |
| 931 Label argc_in_range; | 940 Label argc_in_range; |
| 932 // Total number of args is the first Smi in args descriptor array (EDX). | 941 // Total number of args is the first Smi in args descriptor array (EDX). |
| 933 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 942 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 934 __ cmpl(EAX, Immediate(Smi::RawValue(parameter_count))); | 943 __ cmpl(EAX, Immediate(Smi::RawValue(parameter_count))); |
| 935 __ j(EQUAL, &argc_in_range, Assembler::kNearJump); | 944 __ j(EQUAL, &argc_in_range, Assembler::kNearJump); |
| 936 if (function.IsClosureFunction()) { | 945 if (function.IsClosureFunction()) { |
| 937 GenerateCallRuntime(Isolate::kNoDeoptId, | 946 GenerateCallRuntime(Isolate::kNoDeoptId, |
| 938 function.token_pos(), | 947 function.token_pos(), |
| 939 CatchClauseNode::kInvalidTryIndex, | 948 CatchClauseNode::kInvalidTryIndex, |
| 940 kClosureArgumentMismatchRuntimeEntry, | 949 kClosureArgumentMismatchRuntimeEntry, |
| 941 stack_bitmap); | 950 prologue_locs); |
| 942 } else { | 951 } else { |
| 943 __ Stop("Wrong number of arguments"); | 952 __ Stop("Wrong number of arguments"); |
| 944 } | 953 } |
| 945 __ Bind(&argc_in_range); | 954 __ Bind(&argc_in_range); |
| 946 } | 955 } |
| 947 } else { | 956 } else { |
| 948 CopyParameters(); | 957 CopyParameters(); |
| 949 } | 958 } |
| 950 | 959 |
| 951 // In unoptimized code, initialize (non-argument) stack allocated slots to | 960 // In unoptimized code, initialize (non-argument) stack allocated slots to |
| (...skipping 19 matching lines...) Expand all Loading... |
| 971 } | 980 } |
| 972 AstPrinter::PrintFunctionScope(parsed_function()); | 981 AstPrinter::PrintFunctionScope(parsed_function()); |
| 973 } | 982 } |
| 974 | 983 |
| 975 VisitBlocks(); | 984 VisitBlocks(); |
| 976 | 985 |
| 977 __ int3(); | 986 __ int3(); |
| 978 GenerateDeferredCode(); | 987 GenerateDeferredCode(); |
| 979 // Emit function patching code. This will be swapped with the first 5 bytes | 988 // Emit function patching code. This will be swapped with the first 5 bytes |
| 980 // at entry point. | 989 // at entry point. |
| 981 pc_descriptors_list()->AddDescriptor(PcDescriptors::kPatchCode, | 990 AddCurrentDescriptor(PcDescriptors::kPatchCode, |
| 982 assembler()->CodeSize(), | 991 Isolate::kNoDeoptId, |
| 983 Isolate::kNoDeoptId, | 992 0, // No token position. |
| 984 0, | 993 CatchClauseNode::kInvalidTryIndex); |
| 985 -1); | |
| 986 __ jmp(&StubCode::FixCallersTargetLabel()); | 994 __ jmp(&StubCode::FixCallersTargetLabel()); |
| 987 } | 995 } |
| 988 | 996 |
| 989 | 997 |
| 990 void FlowGraphCompiler::GenerateCall(intptr_t token_pos, | 998 void FlowGraphCompiler::GenerateCall(intptr_t token_pos, |
| 991 intptr_t try_index, | 999 intptr_t try_index, |
| 992 const ExternalLabel* label, | 1000 const ExternalLabel* label, |
| 993 PcDescriptors::Kind kind, | 1001 PcDescriptors::Kind kind, |
| 994 BitmapBuilder* stack_bitmap) { | 1002 LocationSummary* locs) { |
| 995 ASSERT(!IsLeaf()); | 1003 ASSERT(!IsLeaf()); |
| 996 __ call(label); | 1004 __ call(label); |
| 997 if (is_optimizing() && (stack_bitmap != NULL)) { | |
| 998 stackmap_table_builder_->AddEntry(assembler()->CodeSize(), stack_bitmap); | |
| 999 } | |
| 1000 AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos, try_index); | 1005 AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos, try_index); |
| 1006 RecordSafepoint(locs); |
| 1001 } | 1007 } |
| 1002 | 1008 |
| 1003 | 1009 |
| 1004 void FlowGraphCompiler::GenerateCallRuntime(intptr_t deopt_id, | 1010 void FlowGraphCompiler::GenerateCallRuntime(intptr_t deopt_id, |
| 1005 intptr_t token_pos, | 1011 intptr_t token_pos, |
| 1006 intptr_t try_index, | 1012 intptr_t try_index, |
| 1007 const RuntimeEntry& entry, | 1013 const RuntimeEntry& entry, |
| 1008 BitmapBuilder* stack_bitmap) { | 1014 LocationSummary* locs) { |
| 1009 ASSERT(!IsLeaf()); | 1015 ASSERT(!IsLeaf()); |
| 1010 ASSERT(!is_optimizing() || (stack_bitmap != NULL)); | |
| 1011 __ CallRuntime(entry); | 1016 __ CallRuntime(entry); |
| 1012 if (is_optimizing()) { | |
| 1013 stackmap_table_builder_->AddEntry(assembler()->CodeSize(), stack_bitmap); | |
| 1014 } | |
| 1015 AddCurrentDescriptor(PcDescriptors::kOther, deopt_id, token_pos, try_index); | 1017 AddCurrentDescriptor(PcDescriptors::kOther, deopt_id, token_pos, try_index); |
| 1018 RecordSafepoint(locs); |
| 1016 } | 1019 } |
| 1017 | 1020 |
| 1018 | 1021 |
| 1019 intptr_t FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label, | 1022 void FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label, |
| 1020 const ICData& ic_data, | 1023 const ICData& ic_data, |
| 1021 const Array& arguments_descriptor, | 1024 const Array& arguments_descriptor, |
| 1022 intptr_t argument_count) { | 1025 intptr_t argument_count, |
| 1026 intptr_t deopt_id, |
| 1027 intptr_t token_pos, |
| 1028 intptr_t try_index, |
| 1029 LocationSummary* locs) { |
| 1023 ASSERT(!IsLeaf()); | 1030 ASSERT(!IsLeaf()); |
| 1024 __ LoadObject(ECX, ic_data); | 1031 __ LoadObject(ECX, ic_data); |
| 1025 __ LoadObject(EDX, arguments_descriptor); | 1032 __ LoadObject(EDX, arguments_descriptor); |
| 1026 | 1033 |
| 1027 __ call(target_label); | 1034 __ call(target_label); |
| 1028 const intptr_t descr_offset = assembler()->CodeSize(); | 1035 AddCurrentDescriptor(PcDescriptors::kIcCall, deopt_id, token_pos, try_index); |
| 1036 RecordSafepoint(locs); |
| 1037 |
| 1029 __ Drop(argument_count); | 1038 __ Drop(argument_count); |
| 1030 return descr_offset; | |
| 1031 } | 1039 } |
| 1032 | 1040 |
| 1033 | 1041 |
| 1034 intptr_t FlowGraphCompiler::EmitStaticCall(const Function& function, | 1042 void FlowGraphCompiler::EmitStaticCall(const Function& function, |
| 1035 const Array& arguments_descriptor, | 1043 const Array& arguments_descriptor, |
| 1036 intptr_t argument_count) { | 1044 intptr_t argument_count, |
| 1045 intptr_t deopt_id, |
| 1046 intptr_t token_pos, |
| 1047 intptr_t try_index, |
| 1048 LocationSummary* locs) { |
| 1037 ASSERT(!IsLeaf()); | 1049 ASSERT(!IsLeaf()); |
| 1038 __ LoadObject(ECX, function); | 1050 __ LoadObject(ECX, function); |
| 1039 __ LoadObject(EDX, arguments_descriptor); | 1051 __ LoadObject(EDX, arguments_descriptor); |
| 1040 __ call(&StubCode::CallStaticFunctionLabel()); | 1052 __ call(&StubCode::CallStaticFunctionLabel()); |
| 1041 const intptr_t descr_offset = assembler()->CodeSize(); | 1053 AddCurrentDescriptor(PcDescriptors::kFuncCall, deopt_id, token_pos, |
| 1054 try_index); |
| 1055 RecordSafepoint(locs); |
| 1042 __ Drop(argument_count); | 1056 __ Drop(argument_count); |
| 1043 return descr_offset; | |
| 1044 } | 1057 } |
| 1045 | 1058 |
| 1046 | 1059 |
| 1047 // Checks class id of instance against all 'class_ids'. Jump to 'deopt' label | 1060 // Checks class id of instance against all 'class_ids'. Jump to 'deopt' label |
| 1048 // if no match or instance is Smi. | 1061 // if no match or instance is Smi. |
| 1049 void FlowGraphCompiler::EmitClassChecksNoSmi(const ICData& ic_data, | 1062 void FlowGraphCompiler::EmitClassChecksNoSmi(const ICData& ic_data, |
| 1050 Register instance_reg, | 1063 Register instance_reg, |
| 1051 Register temp_reg, | 1064 Register temp_reg, |
| 1052 Label* deopt) { | 1065 Label* deopt) { |
| 1053 Label ok; | 1066 Label ok; |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1221 __ popl(ECX); | 1234 __ popl(ECX); |
| 1222 __ popl(EAX); | 1235 __ popl(EAX); |
| 1223 } | 1236 } |
| 1224 | 1237 |
| 1225 | 1238 |
| 1226 #undef __ | 1239 #undef __ |
| 1227 | 1240 |
| 1228 } // namespace dart | 1241 } // namespace dart |
| 1229 | 1242 |
| 1230 #endif // defined TARGET_ARCH_IA32 | 1243 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |