OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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" | 5 #include "vm/globals.h" |
6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
7 | 7 |
8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
9 #include "vm/code_generator.h" | 9 #include "vm/code_generator.h" |
10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
(...skipping 619 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
630 __ add(R9, R9, Operand(R3, LSL, 1)); // R3 is a Smi. | 630 __ add(R9, R9, Operand(R3, LSL, 1)); // R3 is a Smi. |
631 ASSERT(kSmiTagShift == 1); | 631 ASSERT(kSmiTagShift == 1); |
632 __ bic(R9, R9, Operand(kObjectAlignment - 1)); | 632 __ bic(R9, R9, Operand(kObjectAlignment - 1)); |
633 | 633 |
634 // R9: Allocation size. | 634 // R9: Allocation size. |
635 Heap::Space space = Heap::SpaceForAllocation(cid); | 635 Heap::Space space = Heap::SpaceForAllocation(cid); |
636 __ LoadIsolate(R8); | 636 __ LoadIsolate(R8); |
637 __ ldr(R8, Address(R8, Isolate::heap_offset())); | 637 __ ldr(R8, Address(R8, Isolate::heap_offset())); |
638 // Potential new object start. | 638 // Potential new object start. |
639 __ ldr(R0, Address(R8, Heap::TopOffset(space))); | 639 __ ldr(R0, Address(R8, Heap::TopOffset(space))); |
640 __ adds(R7, R0, Operand(R9)); // Potential next object start. | 640 __ adds(R711, R0, Operand(R9)); // Potential next object start. |
641 __ b(&slow_case, CS); // Branch if unsigned overflow. | 641 __ b(&slow_case, CS); // Branch if unsigned overflow. |
642 | 642 |
643 // Check if the allocation fits into the remaining space. | 643 // Check if the allocation fits into the remaining space. |
644 // R0: potential new object start. | 644 // R0: potential new object start. |
645 // R7: potential next object start. | 645 // R711: potential next object start. |
646 // R9: allocation size. | 646 // R9: allocation size. |
647 __ ldr(R3, Address(R8, Heap::EndOffset(space))); | 647 __ ldr(R3, Address(R8, Heap::EndOffset(space))); |
648 __ cmp(R7, Operand(R3)); | 648 __ cmp(R711, Operand(R3)); |
649 __ b(&slow_case, CS); | 649 __ b(&slow_case, CS); |
650 | 650 |
651 // Successfully allocated the object(s), now update top to point to | 651 // Successfully allocated the object(s), now update top to point to |
652 // next object start and initialize the object. | 652 // next object start and initialize the object. |
653 __ LoadAllocationStatsAddress(R3, cid, /* inline_isolate = */ false); | 653 __ LoadAllocationStatsAddress(R3, cid, /* inline_isolate = */ false); |
654 __ str(R7, Address(R8, Heap::TopOffset(space))); | 654 __ str(R711, Address(R8, Heap::TopOffset(space))); |
655 __ add(R0, R0, Operand(kHeapObjectTag)); | 655 __ add(R0, R0, Operand(kHeapObjectTag)); |
656 | 656 |
657 // Initialize the tags. | 657 // Initialize the tags. |
658 // R0: new object start as a tagged pointer. | 658 // R0: new object start as a tagged pointer. |
659 // R3: allocation stats address. | 659 // R3: allocation stats address. |
660 // R7: new object end address. | 660 // R711: new object end address. |
661 // R9: allocation size. | 661 // R9: allocation size. |
662 { | 662 { |
663 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2; | 663 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2; |
664 | 664 |
665 __ CompareImmediate(R9, RawObject::SizeTag::kMaxSizeTag); | 665 __ CompareImmediate(R9, RawObject::SizeTag::kMaxSizeTag); |
666 __ mov(R8, Operand(R9, LSL, shift), LS); | 666 __ mov(R8, Operand(R9, LSL, shift), LS); |
667 __ mov(R8, Operand(0), HI); | 667 __ mov(R8, Operand(0), HI); |
668 | 668 |
669 // Get the class index and insert it into the tags. | 669 // Get the class index and insert it into the tags. |
670 // R8: size and bit tags. | 670 // R8: size and bit tags. |
671 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cid)); | 671 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cid)); |
672 __ orr(R8, R8, Operand(TMP)); | 672 __ orr(R8, R8, Operand(TMP)); |
673 __ str(R8, FieldAddress(R0, Array::tags_offset())); // Store tags. | 673 __ str(R8, FieldAddress(R0, Array::tags_offset())); // Store tags. |
674 } | 674 } |
675 | 675 |
676 // R0: new object start as a tagged pointer. | 676 // R0: new object start as a tagged pointer. |
677 // R7: new object end address. | 677 // R711: new object end address. |
678 // Store the type argument field. | 678 // Store the type argument field. |
679 __ InitializeFieldNoBarrier(R0, | 679 __ InitializeFieldNoBarrier(R0, |
680 FieldAddress(R0, Array::type_arguments_offset()), | 680 FieldAddress(R0, Array::type_arguments_offset()), |
681 R1); | 681 R1); |
682 | 682 |
683 // Set the length field. | 683 // Set the length field. |
684 __ InitializeFieldNoBarrier(R0, | 684 __ InitializeFieldNoBarrier(R0, |
685 FieldAddress(R0, Array::length_offset()), | 685 FieldAddress(R0, Array::length_offset()), |
686 R2); | 686 R2); |
687 | 687 |
688 // Initialize all array elements to raw_null. | 688 // Initialize all array elements to raw_null. |
689 // R0: new object start as a tagged pointer. | 689 // R0: new object start as a tagged pointer. |
690 // R3: allocation stats address. | 690 // R3: allocation stats address. |
691 // R8, R9: null | 691 // R8, R9: null |
692 // R4: iterator which initially points to the start of the variable | 692 // R4: iterator which initially points to the start of the variable |
693 // data area to be initialized. | 693 // data area to be initialized. |
694 // R7: new object end address. | 694 // R711: new object end address. |
695 // R9: allocation size. | 695 // R9: allocation size. |
696 __ IncrementAllocationStatsWithSize(R3, R9, space); | 696 __ IncrementAllocationStatsWithSize(R3, R9, space); |
697 | 697 |
698 __ LoadObject(R8, Object::null_object()); | 698 __ LoadObject(R8, Object::null_object()); |
699 __ mov(R9, Operand(R8)); | 699 __ mov(R9, Operand(R8)); |
700 __ AddImmediate(R4, R0, sizeof(RawArray) - kHeapObjectTag); | 700 __ AddImmediate(R4, R0, sizeof(RawArray) - kHeapObjectTag); |
701 __ InitializeFieldsNoBarrier(R0, R4, R7, R8, R9); | 701 __ InitializeFieldsNoBarrier(R0, R4, R711, R8, R9); |
702 __ Ret(); // Returns the newly allocated object in R0. | 702 __ Ret(); // Returns the newly allocated object in R0. |
703 // Unable to allocate the array using the fast inline code, just call | 703 // Unable to allocate the array using the fast inline code, just call |
704 // into the runtime. | 704 // into the runtime. |
705 __ Bind(&slow_case); | 705 __ Bind(&slow_case); |
706 | 706 |
707 // Create a stub frame as we are pushing some objects on the stack before | 707 // Create a stub frame as we are pushing some objects on the stack before |
708 // calling into the runtime. | 708 // calling into the runtime. |
709 __ EnterStubFrame(); | 709 __ EnterStubFrame(); |
710 __ LoadObject(IP, Object::null_object()); | 710 __ LoadObject(IP, Object::null_object()); |
711 // Setup space on stack for return value. | 711 // Setup space on stack for return value. |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
763 // Save top resource and top exit frame info. Use R4-6 as temporary registers. | 763 // Save top resource and top exit frame info. Use R4-6 as temporary registers. |
764 // StackFrameIterator reads the top exit frame info saved in this frame. | 764 // StackFrameIterator reads the top exit frame info saved in this frame. |
765 __ LoadFromOffset(kWord, R9, THR, Thread::top_exit_frame_info_offset()); | 765 __ LoadFromOffset(kWord, R9, THR, Thread::top_exit_frame_info_offset()); |
766 __ LoadFromOffset(kWord, R4, THR, Thread::top_resource_offset()); | 766 __ LoadFromOffset(kWord, R4, THR, Thread::top_resource_offset()); |
767 __ LoadImmediate(R8, 0); | 767 __ LoadImmediate(R8, 0); |
768 __ StoreToOffset(kWord, R8, THR, Thread::top_resource_offset()); | 768 __ StoreToOffset(kWord, R8, THR, Thread::top_resource_offset()); |
769 __ StoreToOffset(kWord, R8, THR, Thread::top_exit_frame_info_offset()); | 769 __ StoreToOffset(kWord, R8, THR, Thread::top_exit_frame_info_offset()); |
770 | 770 |
771 // kExitLinkSlotFromEntryFp must be kept in sync with the code below. | 771 // kExitLinkSlotFromEntryFp must be kept in sync with the code below. |
772 __ Push(R4); | 772 __ Push(R4); |
| 773 #if defined(TARGET_OS_MAC) |
| 774 ASSERT(kExitLinkSlotFromEntryFp == -26); |
| 775 #else |
773 ASSERT(kExitLinkSlotFromEntryFp == -27); | 776 ASSERT(kExitLinkSlotFromEntryFp == -27); |
| 777 #endif |
774 __ Push(R9); | 778 __ Push(R9); |
775 | 779 |
776 // Load arguments descriptor array into R4, which is passed to Dart code. | 780 // Load arguments descriptor array into R4, which is passed to Dart code. |
777 __ ldr(R4, Address(R1, VMHandles::kOffsetOfRawPtrInHandle)); | 781 __ ldr(R4, Address(R1, VMHandles::kOffsetOfRawPtrInHandle)); |
778 | 782 |
779 // Load number of arguments into R9. | 783 // Load number of arguments into R9. |
780 __ ldr(R9, FieldAddress(R4, ArgumentsDescriptor::count_offset())); | 784 __ ldr(R9, FieldAddress(R4, ArgumentsDescriptor::count_offset())); |
781 __ SmiUntag(R9); | 785 __ SmiUntag(R9); |
782 | 786 |
783 // Compute address of 'arguments array' data area into R2. | 787 // Compute address of 'arguments array' data area into R2. |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
925 R8); | 929 R8); |
926 | 930 |
927 // Initialize the context variables. | 931 // Initialize the context variables. |
928 // R0: new object. | 932 // R0: new object. |
929 // R1: number of context variables. | 933 // R1: number of context variables. |
930 // R2: object size. | 934 // R2: object size. |
931 // R3: next object start. | 935 // R3: next object start. |
932 // R8, R9: raw null. | 936 // R8, R9: raw null. |
933 // R4: allocation stats address. | 937 // R4: allocation stats address. |
934 Label loop; | 938 Label loop; |
935 __ AddImmediate(R7, R0, Context::variable_offset(0) - kHeapObjectTag); | 939 __ AddImmediate(R711, R0, Context::variable_offset(0) - kHeapObjectTag); |
936 __ InitializeFieldsNoBarrier(R0, R7, R3, R8, R9); | 940 __ InitializeFieldsNoBarrier(R0, R711, R3, R8, R9); |
937 __ IncrementAllocationStatsWithSize(R4, R2, space); | 941 __ IncrementAllocationStatsWithSize(R4, R2, space); |
938 | 942 |
939 // Done allocating and initializing the context. | 943 // Done allocating and initializing the context. |
940 // R0: new object. | 944 // R0: new object. |
941 __ Ret(); | 945 __ Ret(); |
942 | 946 |
943 __ Bind(&slow_case); | 947 __ Bind(&slow_case); |
944 } | 948 } |
945 // Create a stub frame as we are pushing some objects on the stack before | 949 // Create a stub frame as we are pushing some objects on the stack before |
946 // calling into the runtime. | 950 // calling into the runtime. |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1032 } | 1036 } |
1033 | 1037 |
1034 | 1038 |
1035 // Called for inline allocation of objects. | 1039 // Called for inline allocation of objects. |
1036 // Input parameters: | 1040 // Input parameters: |
1037 // LR : return address. | 1041 // LR : return address. |
1038 // SP + 0 : type arguments object (only if class is parameterized). | 1042 // SP + 0 : type arguments object (only if class is parameterized). |
1039 void StubCode::GenerateAllocationStubForClass(Assembler* assembler, | 1043 void StubCode::GenerateAllocationStubForClass(Assembler* assembler, |
1040 const Class& cls) { | 1044 const Class& cls) { |
1041 // Must load pool pointer before being able to patch. | 1045 // Must load pool pointer before being able to patch. |
1042 Register new_pp = R7; | 1046 Register new_pp = R711; |
1043 __ LoadPoolPointer(new_pp); | 1047 __ LoadPoolPointer(new_pp); |
1044 // The generated code is different if the class is parameterized. | 1048 // The generated code is different if the class is parameterized. |
1045 const bool is_cls_parameterized = cls.NumTypeArguments() > 0; | 1049 const bool is_cls_parameterized = cls.NumTypeArguments() > 0; |
1046 ASSERT(!is_cls_parameterized || | 1050 ASSERT(!is_cls_parameterized || |
1047 (cls.type_arguments_field_offset() != Class::kNoTypeArguments)); | 1051 (cls.type_arguments_field_offset() != Class::kNoTypeArguments)); |
1048 // kInlineInstanceSize is a constant used as a threshold for determining | 1052 // kInlineInstanceSize is a constant used as a threshold for determining |
1049 // when the object initialization should be done as a loop or as | 1053 // when the object initialization should be done as a loop or as |
1050 // straight line code. | 1054 // straight line code. |
1051 const int kInlineInstanceSize = 12; | 1055 const int kInlineInstanceSize = 12; |
1052 const intptr_t instance_size = cls.instance_size(); | 1056 const intptr_t instance_size = cls.instance_size(); |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1210 if (FLAG_trace_optimized_ic_calls) { | 1214 if (FLAG_trace_optimized_ic_calls) { |
1211 __ EnterStubFrame(); | 1215 __ EnterStubFrame(); |
1212 __ PushList((1 << R9) | (1 << R8)); // Preserve. | 1216 __ PushList((1 << R9) | (1 << R8)); // Preserve. |
1213 __ Push(ic_reg); // Argument. | 1217 __ Push(ic_reg); // Argument. |
1214 __ Push(func_reg); // Argument. | 1218 __ Push(func_reg); // Argument. |
1215 __ CallRuntime(kTraceICCallRuntimeEntry, 2); | 1219 __ CallRuntime(kTraceICCallRuntimeEntry, 2); |
1216 __ Drop(2); // Discard argument; | 1220 __ Drop(2); // Discard argument; |
1217 __ PopList((1 << R9) | (1 << R8)); // Restore. | 1221 __ PopList((1 << R9) | (1 << R8)); // Restore. |
1218 __ LeaveStubFrame(); | 1222 __ LeaveStubFrame(); |
1219 } | 1223 } |
1220 __ ldr(R7, FieldAddress(func_reg, Function::usage_counter_offset())); | 1224 __ ldr(R711, FieldAddress(func_reg, Function::usage_counter_offset())); |
1221 __ add(R7, R7, Operand(1)); | 1225 __ add(R711, R711, Operand(1)); |
1222 __ str(R7, FieldAddress(func_reg, Function::usage_counter_offset())); | 1226 __ str(R711, FieldAddress(func_reg, Function::usage_counter_offset())); |
1223 } | 1227 } |
1224 | 1228 |
1225 | 1229 |
1226 // Loads function into 'temp_reg'. | 1230 // Loads function into 'temp_reg'. |
1227 void StubCode::GenerateUsageCounterIncrement(Assembler* assembler, | 1231 void StubCode::GenerateUsageCounterIncrement(Assembler* assembler, |
1228 Register temp_reg) { | 1232 Register temp_reg) { |
1229 if (FLAG_optimization_counter_threshold >= 0) { | 1233 if (FLAG_optimization_counter_threshold >= 0) { |
1230 Register ic_reg = R9; | 1234 Register ic_reg = R9; |
1231 Register func_reg = temp_reg; | 1235 Register func_reg = temp_reg; |
1232 ASSERT(temp_reg == R8); | 1236 ASSERT(temp_reg == R8); |
1233 __ Comment("Increment function counter"); | 1237 __ Comment("Increment function counter"); |
1234 __ ldr(func_reg, FieldAddress(ic_reg, ICData::owner_offset())); | 1238 __ ldr(func_reg, FieldAddress(ic_reg, ICData::owner_offset())); |
1235 __ ldr(R7, FieldAddress(func_reg, Function::usage_counter_offset())); | 1239 __ ldr(R711, FieldAddress(func_reg, Function::usage_counter_offset())); |
1236 __ add(R7, R7, Operand(1)); | 1240 __ add(R711, R711, Operand(1)); |
1237 __ str(R7, FieldAddress(func_reg, Function::usage_counter_offset())); | 1241 __ str(R711, FieldAddress(func_reg, Function::usage_counter_offset())); |
1238 } | 1242 } |
1239 } | 1243 } |
1240 | 1244 |
1241 | 1245 |
1242 // Note: R9 must be preserved. | 1246 // Note: R9 must be preserved. |
1243 // Attempt a quick Smi operation for known operations ('kind'). The ICData | 1247 // Attempt a quick Smi operation for known operations ('kind'). The ICData |
1244 // must have been primed with a Smi/Smi check that will be used for counting | 1248 // must have been primed with a Smi/Smi check that will be used for counting |
1245 // the invocations. | 1249 // the invocations. |
1246 static void EmitFastSmiOp(Assembler* assembler, | 1250 static void EmitFastSmiOp(Assembler* assembler, |
1247 Token::Kind kind, | 1251 Token::Kind kind, |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1369 // Loop that checks if there is an IC data match. | 1373 // Loop that checks if there is an IC data match. |
1370 Label loop, update, test, found; | 1374 Label loop, update, test, found; |
1371 // R9: IC data object (preserved). | 1375 // R9: IC data object (preserved). |
1372 __ ldr(R8, FieldAddress(R9, ICData::ic_data_offset())); | 1376 __ ldr(R8, FieldAddress(R9, ICData::ic_data_offset())); |
1373 // R8: ic_data_array with check entries: classes and target functions. | 1377 // R8: ic_data_array with check entries: classes and target functions. |
1374 __ AddImmediate(R8, R8, Array::data_offset() - kHeapObjectTag); | 1378 __ AddImmediate(R8, R8, Array::data_offset() - kHeapObjectTag); |
1375 // R8: points directly to the first ic data array element. | 1379 // R8: points directly to the first ic data array element. |
1376 | 1380 |
1377 // Get the receiver's class ID (first read number of arguments from | 1381 // Get the receiver's class ID (first read number of arguments from |
1378 // arguments descriptor array and then access the receiver from the stack). | 1382 // arguments descriptor array and then access the receiver from the stack). |
1379 __ ldr(R7, FieldAddress(R4, ArgumentsDescriptor::count_offset())); | 1383 __ ldr(R711, FieldAddress(R4, ArgumentsDescriptor::count_offset())); |
1380 __ sub(R7, R7, Operand(Smi::RawValue(1))); | 1384 __ sub(R711, R711, Operand(Smi::RawValue(1))); |
1381 __ ldr(R0, Address(SP, R7, LSL, 1)); // R7 (argument_count - 1) is smi. | 1385 __ ldr(R0, Address(SP, R711, LSL, 1)); // R711 (argument_count - 1) is smi. |
1382 __ LoadTaggedClassIdMayBeSmi(R0, R0); | 1386 __ LoadTaggedClassIdMayBeSmi(R0, R0); |
1383 // R7: argument_count - 1 (smi). | 1387 // R711: argument_count - 1 (smi). |
1384 // R0: receiver's class ID (smi). | 1388 // R0: receiver's class ID (smi). |
1385 __ ldr(R1, Address(R8, 0)); // First class id (smi) to check. | 1389 __ ldr(R1, Address(R8, 0)); // First class id (smi) to check. |
1386 __ b(&test); | 1390 __ b(&test); |
1387 | 1391 |
1388 __ Comment("ICData loop"); | 1392 __ Comment("ICData loop"); |
1389 __ Bind(&loop); | 1393 __ Bind(&loop); |
1390 for (int i = 0; i < num_args; i++) { | 1394 for (int i = 0; i < num_args; i++) { |
1391 if (i > 0) { | 1395 if (i > 0) { |
1392 // If not the first, load the next argument's class ID. | 1396 // If not the first, load the next argument's class ID. |
1393 __ AddImmediate(R0, R7, Smi::RawValue(-i)); | 1397 __ AddImmediate(R0, R711, Smi::RawValue(-i)); |
1394 __ ldr(R0, Address(SP, R0, LSL, 1)); | 1398 __ ldr(R0, Address(SP, R0, LSL, 1)); |
1395 __ LoadTaggedClassIdMayBeSmi(R0, R0); | 1399 __ LoadTaggedClassIdMayBeSmi(R0, R0); |
1396 // R0: next argument class ID (smi). | 1400 // R0: next argument class ID (smi). |
1397 __ LoadFromOffset(kWord, R1, R8, i * kWordSize); | 1401 __ LoadFromOffset(kWord, R1, R8, i * kWordSize); |
1398 // R1: next class ID to check (smi). | 1402 // R1: next class ID to check (smi). |
1399 } | 1403 } |
1400 __ cmp(R0, Operand(R1)); // Class id match? | 1404 __ cmp(R0, Operand(R1)); // Class id match? |
1401 if (i < (num_args - 1)) { | 1405 if (i < (num_args - 1)) { |
1402 __ b(&update, NE); // Continue. | 1406 __ b(&update, NE); // Continue. |
1403 } else { | 1407 } else { |
1404 // Last check, all checks before matched. | 1408 // Last check, all checks before matched. |
1405 __ b(&found, EQ); // Break. | 1409 __ b(&found, EQ); // Break. |
1406 } | 1410 } |
1407 } | 1411 } |
1408 __ Bind(&update); | 1412 __ Bind(&update); |
1409 // Reload receiver class ID. It has not been destroyed when num_args == 1. | 1413 // Reload receiver class ID. It has not been destroyed when num_args == 1. |
1410 if (num_args > 1) { | 1414 if (num_args > 1) { |
1411 __ ldr(R0, Address(SP, R7, LSL, 1)); | 1415 __ ldr(R0, Address(SP, R711, LSL, 1)); |
1412 __ LoadTaggedClassIdMayBeSmi(R0, R0); | 1416 __ LoadTaggedClassIdMayBeSmi(R0, R0); |
1413 } | 1417 } |
1414 | 1418 |
1415 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; | 1419 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; |
1416 __ AddImmediate(R8, entry_size); // Next entry. | 1420 __ AddImmediate(R8, entry_size); // Next entry. |
1417 __ ldr(R1, Address(R8, 0)); // Next class ID. | 1421 __ ldr(R1, Address(R8, 0)); // Next class ID. |
1418 | 1422 |
1419 __ Bind(&test); | 1423 __ Bind(&test); |
1420 __ CompareImmediate(R1, Smi::RawValue(kIllegalCid)); // Done? | 1424 __ CompareImmediate(R1, Smi::RawValue(kIllegalCid)); // Done? |
1421 __ b(&loop, NE); | 1425 __ b(&loop, NE); |
1422 | 1426 |
1423 __ Comment("IC miss"); | 1427 __ Comment("IC miss"); |
1424 // Compute address of arguments. | 1428 // Compute address of arguments. |
1425 // R7: argument_count - 1 (smi). | 1429 // R711: argument_count - 1 (smi). |
1426 __ add(R7, SP, Operand(R7, LSL, 1)); // R7 is Smi. | 1430 __ add(R711, SP, Operand(R711, LSL, 1)); // R711 is Smi. |
1427 // R7: address of receiver. | 1431 // R711: address of receiver. |
1428 // Create a stub frame as we are pushing some objects on the stack before | 1432 // Create a stub frame as we are pushing some objects on the stack before |
1429 // calling into the runtime. | 1433 // calling into the runtime. |
1430 __ EnterStubFrame(); | 1434 __ EnterStubFrame(); |
1431 __ LoadObject(R0, Object::null_object()); | 1435 __ LoadObject(R0, Object::null_object()); |
1432 // Preserve IC data object and arguments descriptor array and | 1436 // Preserve IC data object and arguments descriptor array and |
1433 // setup space on stack for result (target code object). | 1437 // setup space on stack for result (target code object). |
1434 __ PushList((1 << R0) | (1 << R4) | (1 << R9)); | 1438 __ PushList((1 << R0) | (1 << R4) | (1 << R9)); |
1435 // Push call arguments. | 1439 // Push call arguments. |
1436 for (intptr_t i = 0; i < num_args; i++) { | 1440 for (intptr_t i = 0; i < num_args; i++) { |
1437 __ LoadFromOffset(kWord, IP, R7, -i * kWordSize); | 1441 __ LoadFromOffset(kWord, IP, R711, -i * kWordSize); |
1438 __ Push(IP); | 1442 __ Push(IP); |
1439 } | 1443 } |
1440 // Pass IC data object. | 1444 // Pass IC data object. |
1441 __ Push(R9); | 1445 __ Push(R9); |
1442 __ CallRuntime(handle_ic_miss, num_args + 1); | 1446 __ CallRuntime(handle_ic_miss, num_args + 1); |
1443 // Remove the call arguments pushed earlier, including the IC data object. | 1447 // Remove the call arguments pushed earlier, including the IC data object. |
1444 __ Drop(num_args + 1); | 1448 __ Drop(num_args + 1); |
1445 // Pop returned function object into R0. | 1449 // Pop returned function object into R0. |
1446 // Restore arguments descriptor array and IC data array. | 1450 // Restore arguments descriptor array and IC data array. |
1447 __ PopList((1 << R0) | (1 << R4) | (1 << R9)); | 1451 __ PopList((1 << R0) | (1 << R4) | (1 << R9)); |
(...skipping 639 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2087 // Result: | 2091 // Result: |
2088 // R1: entry point. | 2092 // R1: entry point. |
2089 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { | 2093 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { |
2090 EmitMegamorphicLookup(assembler, R0, R1, R1); | 2094 EmitMegamorphicLookup(assembler, R0, R1, R1); |
2091 __ Ret(); | 2095 __ Ret(); |
2092 } | 2096 } |
2093 | 2097 |
2094 } // namespace dart | 2098 } // namespace dart |
2095 | 2099 |
2096 #endif // defined TARGET_ARCH_ARM | 2100 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |