| 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 679 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 690 // R0: potential new object start. | 690 // R0: potential new object start. |
| 691 // R7: potential next object start. | 691 // R7: potential next object start. |
| 692 // R8: allocation size. | 692 // R8: allocation size. |
| 693 __ LoadImmediate(R3, heap->EndAddress(space)); | 693 __ LoadImmediate(R3, heap->EndAddress(space)); |
| 694 __ ldr(R3, Address(R3, 0)); | 694 __ ldr(R3, Address(R3, 0)); |
| 695 __ cmp(R7, Operand(R3)); | 695 __ cmp(R7, Operand(R3)); |
| 696 __ b(&slow_case, CS); | 696 __ b(&slow_case, CS); |
| 697 | 697 |
| 698 // Successfully allocated the object(s), now update top to point to | 698 // Successfully allocated the object(s), now update top to point to |
| 699 // next object start and initialize the object. | 699 // next object start and initialize the object. |
| 700 __ LoadAllocationStatsAddress(R3, cid, space); |
| 700 __ str(R7, Address(R6, 0)); | 701 __ str(R7, Address(R6, 0)); |
| 701 __ add(R0, R0, Operand(kHeapObjectTag)); | 702 __ add(R0, R0, Operand(kHeapObjectTag)); |
| 702 __ UpdateAllocationStatsWithSize(cid, R8, R4, space); | |
| 703 | 703 |
| 704 // Initialize the tags. | 704 // Initialize the tags. |
| 705 // R0: new object start as a tagged pointer. | 705 // R0: new object start as a tagged pointer. |
| 706 // R3: allocation stats address. |
| 706 // R7: new object end address. | 707 // R7: new object end address. |
| 707 // R8: allocation size. | 708 // R8: allocation size. |
| 708 { | 709 { |
| 709 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2; | 710 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2; |
| 710 | 711 |
| 711 __ CompareImmediate(R8, RawObject::SizeTag::kMaxSizeTag); | 712 __ CompareImmediate(R8, RawObject::SizeTag::kMaxSizeTag); |
| 712 __ mov(R8, Operand(R8, LSL, shift), LS); | 713 __ mov(R6, Operand(R8, LSL, shift), LS); |
| 713 __ mov(R8, Operand(0), HI); | 714 __ mov(R6, Operand(0), HI); |
| 714 | 715 |
| 715 // Get the class index and insert it into the tags. | 716 // Get the class index and insert it into the tags. |
| 716 // R8: size and bit tags. | 717 // R6: size and bit tags. |
| 717 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cid)); | 718 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cid)); |
| 718 __ orr(R8, R8, Operand(TMP)); | 719 __ orr(R6, R6, Operand(TMP)); |
| 719 __ str(R8, FieldAddress(R0, Array::tags_offset())); // Store tags. | 720 __ str(R6, FieldAddress(R0, Array::tags_offset())); // Store tags. |
| 720 } | 721 } |
| 721 | 722 |
| 722 // R0: new object start as a tagged pointer. | 723 // R0: new object start as a tagged pointer. |
| 723 // R7: new object end address. | 724 // R7: new object end address. |
| 724 // Store the type argument field. | 725 // Store the type argument field. |
| 725 __ StoreIntoObjectNoBarrier(R0, | 726 __ StoreIntoObjectNoBarrier(R0, |
| 726 FieldAddress(R0, Array::type_arguments_offset()), | 727 FieldAddress(R0, Array::type_arguments_offset()), |
| 727 R1); | 728 R1); |
| 728 | 729 |
| 729 // Set the length field. | 730 // Set the length field. |
| 730 __ StoreIntoObjectNoBarrier(R0, | 731 __ StoreIntoObjectNoBarrier(R0, |
| 731 FieldAddress(R0, Array::length_offset()), | 732 FieldAddress(R0, Array::length_offset()), |
| 732 R2); | 733 R2); |
| 733 | 734 |
| 734 // Initialize all array elements to raw_null. | 735 // Initialize all array elements to raw_null. |
| 735 // R0: new object start as a tagged pointer. | 736 // R0: new object start as a tagged pointer. |
| 737 // R3: allocation stats address. |
| 736 // R7: new object end address. | 738 // R7: new object end address. |
| 737 // R8: iterator which initially points to the start of the variable | 739 // R8: iterator which initially points to the start of the variable |
| 738 // data area to be initialized. | 740 // data area to be initialized. |
| 739 // R3: null | 741 // R4, R5: null |
| 740 __ LoadImmediate(R3, reinterpret_cast<intptr_t>(Object::null())); | 742 __ LoadImmediate(R4, reinterpret_cast<intptr_t>(Object::null())); |
| 743 __ mov(R5, Operand(R4)); |
| 741 __ AddImmediate(R8, R0, sizeof(RawArray) - kHeapObjectTag); | 744 __ AddImmediate(R8, R0, sizeof(RawArray) - kHeapObjectTag); |
| 742 | 745 |
| 743 Label init_loop; | 746 Label init_loop; |
| 744 __ Bind(&init_loop); | 747 __ Bind(&init_loop); |
| 748 __ AddImmediate(R8, 2 * kWordSize); |
| 745 __ cmp(R8, Operand(R7)); | 749 __ cmp(R8, Operand(R7)); |
| 746 __ str(R3, Address(R8, 0), CC); | 750 __ strd(R4, Address(R8, -2 * kWordSize), LS); |
| 747 __ AddImmediate(R8, kWordSize, CC); | |
| 748 __ b(&init_loop, CC); | 751 __ b(&init_loop, CC); |
| 752 __ str(R4, Address(R8, -2 * kWordSize), HI); |
| 749 | 753 |
| 754 __ IncrementAllocationStatsWithSize(R3, R8, cid, space); |
| 750 __ Ret(); // Returns the newly allocated object in R0. | 755 __ Ret(); // Returns the newly allocated object in R0. |
| 751 // Unable to allocate the array using the fast inline code, just call | 756 // Unable to allocate the array using the fast inline code, just call |
| 752 // into the runtime. | 757 // into the runtime. |
| 753 __ Bind(&slow_case); | 758 __ Bind(&slow_case); |
| 754 | 759 |
| 755 // Create a stub frame as we are pushing some objects on the stack before | 760 // Create a stub frame as we are pushing some objects on the stack before |
| 756 // calling into the runtime. | 761 // calling into the runtime. |
| 757 __ EnterStubFrame(); | 762 __ EnterStubFrame(); |
| 758 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null())); | 763 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null())); |
| 759 // Setup space on stack for return value. | 764 // Setup space on stack for return value. |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 931 const intptr_t cid = kContextCid; | 936 const intptr_t cid = kContextCid; |
| 932 Heap::Space space = heap->SpaceForAllocation(cid); | 937 Heap::Space space = heap->SpaceForAllocation(cid); |
| 933 __ LoadImmediate(R5, heap->TopAddress(space)); | 938 __ LoadImmediate(R5, heap->TopAddress(space)); |
| 934 __ ldr(R0, Address(R5, 0)); | 939 __ ldr(R0, Address(R5, 0)); |
| 935 __ add(R3, R2, Operand(R0)); | 940 __ add(R3, R2, Operand(R0)); |
| 936 // Check if the allocation fits into the remaining space. | 941 // Check if the allocation fits into the remaining space. |
| 937 // R0: potential new object. | 942 // R0: potential new object. |
| 938 // R1: number of context variables. | 943 // R1: number of context variables. |
| 939 // R2: object size. | 944 // R2: object size. |
| 940 // R3: potential next object start. | 945 // R3: potential next object start. |
| 946 // R5: top address. |
| 941 __ LoadImmediate(IP, heap->EndAddress(space)); | 947 __ LoadImmediate(IP, heap->EndAddress(space)); |
| 942 __ ldr(IP, Address(IP, 0)); | 948 __ ldr(IP, Address(IP, 0)); |
| 943 __ cmp(R3, Operand(IP)); | 949 __ cmp(R3, Operand(IP)); |
| 944 if (FLAG_use_slow_path) { | 950 if (FLAG_use_slow_path) { |
| 945 __ b(&slow_case); | 951 __ b(&slow_case); |
| 946 } else { | 952 } else { |
| 947 __ b(&slow_case, CS); // Branch if unsigned higher or equal. | 953 __ b(&slow_case, CS); // Branch if unsigned higher or equal. |
| 948 } | 954 } |
| 949 | 955 |
| 950 // Successfully allocated the object, now update top to point to | 956 // Successfully allocated the object, now update top to point to |
| 951 // next object start and initialize the object. | 957 // next object start and initialize the object. |
| 952 // R0: new object. | 958 // R0: new object. |
| 953 // R1: number of context variables. | 959 // R1: number of context variables. |
| 954 // R2: object size. | 960 // R2: object size. |
| 955 // R3: next object start. | 961 // R3: next object start. |
| 962 // R5: top address. |
| 963 __ LoadAllocationStatsAddress(R4, cid, space); |
| 956 __ str(R3, Address(R5, 0)); | 964 __ str(R3, Address(R5, 0)); |
| 957 __ add(R0, R0, Operand(kHeapObjectTag)); | 965 __ add(R0, R0, Operand(kHeapObjectTag)); |
| 958 __ UpdateAllocationStatsWithSize(cid, R2, R5, space); | |
| 959 | 966 |
| 960 // Calculate the size tag. | 967 // Calculate the size tag. |
| 961 // R0: new object. | 968 // R0: new object. |
| 962 // R1: number of context variables. | 969 // R1: number of context variables. |
| 963 // R2: object size. | 970 // R2: object size. |
| 971 // R4: allocation stats address. |
| 964 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2; | 972 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2; |
| 965 __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag); | 973 __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag); |
| 966 // If no size tag overflow, shift R2 left, else set R2 to zero. | 974 // If no size tag overflow, shift R2 left, else set R2 to zero. |
| 967 __ mov(R2, Operand(R2, LSL, shift), LS); | 975 __ mov(R3, Operand(R2, LSL, shift), LS); |
| 968 __ mov(R2, Operand(0), HI); | 976 __ mov(R3, Operand(0), HI); |
| 969 | 977 |
| 970 // Get the class index and insert it into the tags. | 978 // Get the class index and insert it into the tags. |
| 971 // R2: size and bit tags. | 979 // R3: size and bit tags. |
| 972 __ LoadImmediate(IP, RawObject::ClassIdTag::encode(cid)); | 980 __ LoadImmediate(IP, RawObject::ClassIdTag::encode(cid)); |
| 973 __ orr(R2, R2, Operand(IP)); | 981 __ orr(R3, R3, Operand(IP)); |
| 974 __ str(R2, FieldAddress(R0, Context::tags_offset())); | 982 __ str(R3, FieldAddress(R0, Context::tags_offset())); |
| 975 | 983 |
| 976 // Setup up number of context variables field. | 984 // Setup up number of context variables field. |
| 977 // R0: new object. | 985 // R0: new object. |
| 978 // R1: number of context variables as integer value (not object). | 986 // R1: number of context variables as integer value (not object). |
| 987 // R2: object size. |
| 988 // R4: allocation stats address. |
| 979 __ str(R1, FieldAddress(R0, Context::num_variables_offset())); | 989 __ str(R1, FieldAddress(R0, Context::num_variables_offset())); |
| 980 | 990 |
| 981 // Setup isolate field. | 991 // Setup isolate field. |
| 982 // Load Isolate pointer into R2. | 992 // Load Isolate pointer into R3. |
| 983 // R0: new object. | 993 // R0: new object. |
| 984 // R1: number of context variables. | 994 // R1: number of context variables. |
| 985 __ LoadIsolate(R2); | 995 // R2: object size. |
| 986 // R2: isolate, not an object. | 996 // R4: allocation stats address. |
| 987 __ str(R2, FieldAddress(R0, Context::isolate_offset())); | 997 __ LoadIsolate(R3); |
| 998 // R3: isolate, not an object. |
| 999 __ str(R3, FieldAddress(R0, Context::isolate_offset())); |
| 988 | 1000 |
| 989 // Setup the parent field. | 1001 // Setup the parent field. |
| 990 // R0: new object. | 1002 // R0: new object. |
| 991 // R1: number of context variables. | 1003 // R1: number of context variables. |
| 992 __ LoadImmediate(R2, reinterpret_cast<intptr_t>(Object::null())); | 1004 // R2: object size. |
| 993 __ str(R2, FieldAddress(R0, Context::parent_offset())); | 1005 // R4: allocation stats address. |
| 1006 __ LoadImmediate(R3, reinterpret_cast<intptr_t>(Object::null())); |
| 1007 __ str(R3, FieldAddress(R0, Context::parent_offset())); |
| 994 | 1008 |
| 995 // Initialize the context variables. | 1009 // Initialize the context variables. |
| 996 // R0: new object. | 1010 // R0: new object. |
| 997 // R1: number of context variables. | 1011 // R1: number of context variables. |
| 998 // R2: raw null. | 1012 // R2: object size. |
| 1013 // R3: raw null. |
| 1014 // R4: allocation stats address. |
| 999 Label loop; | 1015 Label loop; |
| 1000 __ AddImmediate(R3, R0, Context::variable_offset(0) - kHeapObjectTag); | 1016 __ AddImmediate(R5, R0, Context::variable_offset(0) - kHeapObjectTag); |
| 1001 __ Bind(&loop); | 1017 __ Bind(&loop); |
| 1002 __ subs(R1, R1, Operand(1)); | 1018 __ subs(R1, R1, Operand(1)); |
| 1003 __ str(R2, Address(R3, R1, LSL, 2), PL); // Store if R1 positive or zero. | 1019 __ str(R3, Address(R5, R1, LSL, 2), PL); // Store if R1 positive or zero. |
| 1004 __ b(&loop, NE); // Loop if R1 not zero. | 1020 __ b(&loop, NE); // Loop if R1 not zero. |
| 1005 | 1021 |
| 1022 __ IncrementAllocationStatsWithSize(R4, R2, cid, space); |
| 1023 |
| 1006 // Done allocating and initializing the context. | 1024 // Done allocating and initializing the context. |
| 1007 // R0: new object. | 1025 // R0: new object. |
| 1008 __ Ret(); | 1026 __ Ret(); |
| 1009 | 1027 |
| 1010 __ Bind(&slow_case); | 1028 __ Bind(&slow_case); |
| 1011 } | 1029 } |
| 1012 // Create a stub frame as we are pushing some objects on the stack before | 1030 // Create a stub frame as we are pushing some objects on the stack before |
| 1013 // calling into the runtime. | 1031 // calling into the runtime. |
| 1014 __ EnterStubFrame(); | 1032 __ EnterStubFrame(); |
| 1015 // Setup space on stack for return value. | 1033 // Setup space on stack for return value. |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1101 // The generated code is different if the class is parameterized. | 1119 // The generated code is different if the class is parameterized. |
| 1102 const bool is_cls_parameterized = cls.NumTypeArguments() > 0; | 1120 const bool is_cls_parameterized = cls.NumTypeArguments() > 0; |
| 1103 ASSERT(!is_cls_parameterized || | 1121 ASSERT(!is_cls_parameterized || |
| 1104 (cls.type_arguments_field_offset() != Class::kNoTypeArguments)); | 1122 (cls.type_arguments_field_offset() != Class::kNoTypeArguments)); |
| 1105 // kInlineInstanceSize is a constant used as a threshold for determining | 1123 // kInlineInstanceSize is a constant used as a threshold for determining |
| 1106 // when the object initialization should be done as a loop or as | 1124 // when the object initialization should be done as a loop or as |
| 1107 // straight line code. | 1125 // straight line code. |
| 1108 const int kInlineInstanceSize = 12; | 1126 const int kInlineInstanceSize = 12; |
| 1109 const intptr_t instance_size = cls.instance_size(); | 1127 const intptr_t instance_size = cls.instance_size(); |
| 1110 ASSERT(instance_size > 0); | 1128 ASSERT(instance_size > 0); |
| 1111 if (is_cls_parameterized) { | |
| 1112 __ ldr(R1, Address(SP, 0)); | |
| 1113 // R1: instantiated type arguments. | |
| 1114 } | |
| 1115 if (FLAG_inline_alloc && Heap::IsAllocatableInNewSpace(instance_size)) { | 1129 if (FLAG_inline_alloc && Heap::IsAllocatableInNewSpace(instance_size)) { |
| 1116 Label slow_case; | 1130 Label slow_case; |
| 1117 // Allocate the object and update top to point to | 1131 // Allocate the object and update top to point to |
| 1118 // next object start and initialize the allocated object. | 1132 // next object start and initialize the allocated object. |
| 1119 // R1: instantiated type arguments (if is_cls_parameterized). | |
| 1120 Heap* heap = Isolate::Current()->heap(); | 1133 Heap* heap = Isolate::Current()->heap(); |
| 1121 Heap::Space space = heap->SpaceForAllocation(cls.id()); | 1134 Heap::Space space = heap->SpaceForAllocation(cls.id()); |
| 1122 __ LoadImmediate(R5, heap->TopAddress(space)); | 1135 __ LoadImmediate(R5, heap->TopAddress(space)); |
| 1123 __ ldr(R2, Address(R5, 0)); | 1136 __ ldr(R2, Address(R5, 0)); |
| 1124 __ AddImmediate(R3, R2, instance_size); | 1137 __ AddImmediate(R3, R2, instance_size); |
| 1125 // Check if the allocation fits into the remaining space. | 1138 // Check if the allocation fits into the remaining space. |
| 1126 // R2: potential new object start. | 1139 // R2: potential new object start. |
| 1127 // R3: potential next object start. | 1140 // R3: potential next object start. |
| 1128 __ LoadImmediate(IP, heap->EndAddress(space)); | 1141 __ LoadImmediate(IP, heap->EndAddress(space)); |
| 1129 __ ldr(IP, Address(IP, 0)); | 1142 __ ldr(IP, Address(IP, 0)); |
| 1130 __ cmp(R3, Operand(IP)); | 1143 __ cmp(R3, Operand(IP)); |
| 1131 if (FLAG_use_slow_path) { | 1144 if (FLAG_use_slow_path) { |
| 1132 __ b(&slow_case); | 1145 __ b(&slow_case); |
| 1133 } else { | 1146 } else { |
| 1134 __ b(&slow_case, CS); // Unsigned higher or equal. | 1147 __ b(&slow_case, CS); // Unsigned higher or equal. |
| 1135 } | 1148 } |
| 1136 __ str(R3, Address(R5, 0)); | 1149 __ str(R3, Address(R5, 0)); |
| 1137 __ UpdateAllocationStats(cls.id(), R5, space); | 1150 |
| 1151 // Load the address of the allocation stats table. We split up the load |
| 1152 // and the increment so that the dependent load is not too nearby. |
| 1153 __ LoadAllocationStatsAddress(R5, cls.id(), space); |
| 1138 | 1154 |
| 1139 // R2: new object start. | 1155 // R2: new object start. |
| 1140 // R3: next object start. | 1156 // R3: next object start. |
| 1141 // R1: new object type arguments (if is_cls_parameterized). | 1157 // R5: allocation stats table. |
| 1142 // Set the tags. | 1158 // Set the tags. |
| 1143 uword tags = 0; | 1159 uword tags = 0; |
| 1144 tags = RawObject::SizeTag::update(instance_size, tags); | 1160 tags = RawObject::SizeTag::update(instance_size, tags); |
| 1145 ASSERT(cls.id() != kIllegalCid); | 1161 ASSERT(cls.id() != kIllegalCid); |
| 1146 tags = RawObject::ClassIdTag::update(cls.id(), tags); | 1162 tags = RawObject::ClassIdTag::update(cls.id(), tags); |
| 1147 __ LoadImmediate(R0, tags); | 1163 __ LoadImmediate(R0, tags); |
| 1148 __ str(R0, Address(R2, Instance::tags_offset())); | 1164 __ str(R0, Address(R2, Instance::tags_offset())); |
| 1149 | 1165 |
| 1150 // Initialize the remaining words of the object. | 1166 // Initialize the remaining words of the object. |
| 1151 __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); | 1167 __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); |
| 1152 | 1168 |
| 1153 // R0: raw null. | 1169 // R0: raw null. |
| 1154 // R2: new object start. | 1170 // R2: new object start. |
| 1155 // R3: next object start. | 1171 // R3: next object start. |
| 1156 // R1: new object type arguments (if is_cls_parameterized). | 1172 // R5: allocation stats table. |
| 1157 // First try inlining the initialization without a loop. | 1173 // First try inlining the initialization without a loop. |
| 1158 if (instance_size < (kInlineInstanceSize * kWordSize)) { | 1174 if (instance_size < (kInlineInstanceSize * kWordSize)) { |
| 1159 // Check if the object contains any non-header fields. | 1175 // Check if the object contains any non-header fields. |
| 1160 // Small objects are initialized using a consecutive set of writes. | 1176 // Small objects are initialized using a consecutive set of writes. |
| 1161 for (intptr_t current_offset = Instance::NextFieldOffset(); | 1177 intptr_t current_offset = Instance::NextFieldOffset(); |
| 1162 current_offset < instance_size; | 1178 // Write two nulls at a time. |
| 1163 current_offset += kWordSize) { | 1179 if (instance_size >= 2 * kWordSize) { |
| 1180 __ mov(R1, Operand(R0)); |
| 1181 while (current_offset + kWordSize < instance_size) { |
| 1182 __ StoreToOffset(kWordPair, R0, R2, current_offset); |
| 1183 current_offset += 2 * kWordSize; |
| 1184 } |
| 1185 } |
| 1186 // Write remainder. |
| 1187 while (current_offset < instance_size) { |
| 1164 __ StoreToOffset(kWord, R0, R2, current_offset); | 1188 __ StoreToOffset(kWord, R0, R2, current_offset); |
| 1189 current_offset += kWordSize; |
| 1165 } | 1190 } |
| 1166 } else { | 1191 } else { |
| 1192 // There are more than kInlineInstanceSize(12) fields |
| 1167 __ add(R4, R2, Operand(Instance::NextFieldOffset())); | 1193 __ add(R4, R2, Operand(Instance::NextFieldOffset())); |
| 1194 __ mov(R1, Operand(R0)); |
| 1168 // Loop until the whole object is initialized. | 1195 // Loop until the whole object is initialized. |
| 1169 // R0: raw null. | 1196 // R0: raw null. |
| 1197 // R1: raw null. |
| 1170 // R2: new object. | 1198 // R2: new object. |
| 1171 // R3: next object start. | 1199 // R3: next object start. |
| 1172 // R4: next word to be initialized. | 1200 // R4: next word to be initialized. |
| 1173 // R1: new object type arguments (if is_cls_parameterized). | 1201 // R5: allocation stats table. |
| 1174 Label init_loop; | 1202 Label init_loop; |
| 1175 Label done; | |
| 1176 __ Bind(&init_loop); | 1203 __ Bind(&init_loop); |
| 1204 __ AddImmediate(R4, 2 * kWordSize); |
| 1177 __ cmp(R4, Operand(R3)); | 1205 __ cmp(R4, Operand(R3)); |
| 1178 __ b(&done, CS); | 1206 __ strd(R0, Address(R4, -2 * kWordSize), LS); |
| 1179 __ str(R0, Address(R4, 0)); | 1207 __ b(&init_loop, CC); |
| 1180 __ AddImmediate(R4, kWordSize); | 1208 __ str(R0, Address(R4, -2 * kWordSize), HI); |
| 1181 __ b(&init_loop); | |
| 1182 __ Bind(&done); | |
| 1183 } | 1209 } |
| 1184 if (is_cls_parameterized) { | 1210 if (is_cls_parameterized) { |
| 1185 // R1: new object type arguments. | |
| 1186 // Set the type arguments in the new object. | 1211 // Set the type arguments in the new object. |
| 1187 __ StoreToOffset(kWord, R1, R2, cls.type_arguments_field_offset()); | 1212 __ ldr(R4, Address(SP, 0)); |
| 1213 __ StoreToOffset(kWord, R4, R2, cls.type_arguments_field_offset()); |
| 1188 } | 1214 } |
| 1215 |
| 1189 // Done allocating and initializing the instance. | 1216 // Done allocating and initializing the instance. |
| 1190 // R2: new object still missing its heap tag. | 1217 // R2: new object still missing its heap tag. |
| 1218 // R5: allocation stats table. |
| 1191 __ add(R0, R2, Operand(kHeapObjectTag)); | 1219 __ add(R0, R2, Operand(kHeapObjectTag)); |
| 1220 |
| 1221 // Update allocation stats. |
| 1222 __ IncrementAllocationStats(R5, cls.id(), space); |
| 1223 |
| 1192 // R0: new object. | 1224 // R0: new object. |
| 1193 __ Ret(); | 1225 __ Ret(); |
| 1194 | 1226 |
| 1195 __ Bind(&slow_case); | 1227 __ Bind(&slow_case); |
| 1196 } | 1228 } |
| 1229 if (is_cls_parameterized) { |
| 1230 // Load the type arguments. |
| 1231 __ ldr(R4, Address(SP, 0)); |
| 1232 } |
| 1197 // If is_cls_parameterized: | 1233 // If is_cls_parameterized: |
| 1198 // R1: new object type arguments. | 1234 // R4: new object type arguments. |
| 1199 // Create a stub frame as we are pushing some objects on the stack before | 1235 // Create a stub frame as we are pushing some objects on the stack before |
| 1200 // calling into the runtime. | 1236 // calling into the runtime. |
| 1201 __ EnterStubFrame(true); // Uses pool pointer to pass cls to runtime. | 1237 __ EnterStubFrame(true); // Uses pool pointer to pass cls to runtime. |
| 1202 __ LoadImmediate(R2, reinterpret_cast<intptr_t>(Object::null())); | 1238 __ LoadImmediate(R2, reinterpret_cast<intptr_t>(Object::null())); |
| 1203 __ Push(R2); // Setup space on stack for return value. | 1239 __ Push(R2); // Setup space on stack for return value. |
| 1204 __ PushObject(cls); // Push class of object to be allocated. | 1240 __ PushObject(cls); // Push class of object to be allocated. |
| 1205 if (is_cls_parameterized) { | 1241 if (is_cls_parameterized) { |
| 1206 // Push type arguments. | 1242 // Push type arguments. |
| 1207 __ Push(R1); | 1243 __ Push(R4); |
| 1208 } else { | 1244 } else { |
| 1209 // Push null type arguments. | 1245 // Push null type arguments. |
| 1210 __ Push(R2); | 1246 __ Push(R2); |
| 1211 } | 1247 } |
| 1212 __ CallRuntime(kAllocateObjectRuntimeEntry, 2); // Allocate object. | 1248 __ CallRuntime(kAllocateObjectRuntimeEntry, 2); // Allocate object. |
| 1213 __ Drop(2); // Pop arguments. | 1249 __ Drop(2); // Pop arguments. |
| 1214 __ Pop(R0); // Pop result (newly allocated object). | 1250 __ Pop(R0); // Pop result (newly allocated object). |
| 1215 // R0: new object | 1251 // R0: new object |
| 1216 // Restore the frame pointer. | 1252 // Restore the frame pointer. |
| 1217 __ LeaveStubFrame(); | 1253 __ LeaveStubFrame(); |
| (...skipping 801 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2019 const Register right = R0; | 2055 const Register right = R0; |
| 2020 __ ldr(left, Address(SP, 1 * kWordSize)); | 2056 __ ldr(left, Address(SP, 1 * kWordSize)); |
| 2021 __ ldr(right, Address(SP, 0 * kWordSize)); | 2057 __ ldr(right, Address(SP, 0 * kWordSize)); |
| 2022 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); | 2058 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); |
| 2023 __ Ret(); | 2059 __ Ret(); |
| 2024 } | 2060 } |
| 2025 | 2061 |
| 2026 } // namespace dart | 2062 } // namespace dart |
| 2027 | 2063 |
| 2028 #endif // defined TARGET_ARCH_ARM | 2064 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |