| 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 |