Chromium Code Reviews| 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 681 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 692 // R3: allocation stats address. | 692 // R3: allocation stats address. |
| 693 // R4, R5: null | 693 // R4, R5: null |
| 694 // R6: iterator which initially points to the start of the variable | 694 // R6: iterator which initially points to the start of the variable |
| 695 // data area to be initialized. | 695 // data area to be initialized. |
| 696 // R7: new object end address. | 696 // R7: new object end address. |
| 697 // R8: allocation size. | 697 // R8: allocation size. |
| 698 | 698 |
| 699 __ LoadImmediate(R4, reinterpret_cast<intptr_t>(Object::null())); | 699 __ LoadImmediate(R4, reinterpret_cast<intptr_t>(Object::null())); |
| 700 __ mov(R5, Operand(R4)); | 700 __ mov(R5, Operand(R4)); |
| 701 __ AddImmediate(R6, R0, sizeof(RawArray) - kHeapObjectTag); | 701 __ AddImmediate(R6, R0, sizeof(RawArray) - kHeapObjectTag); |
| 702 | 702 __ InitializeFieldsNoBarrier(R0, R6, R7, R4, R5); |
| 703 Label init_loop; | |
| 704 __ Bind(&init_loop); | |
| 705 __ AddImmediate(R6, 2 * kWordSize); | |
| 706 __ cmp(R6, Operand(R7)); | |
| 707 __ strd(R4, Address(R6, -2 * kWordSize), LS); | |
| 708 __ b(&init_loop, CC); | |
| 709 __ str(R4, Address(R6, -2 * kWordSize), HI); | |
| 710 | |
| 711 __ IncrementAllocationStatsWithSize(R3, R8, cid, space); | 703 __ IncrementAllocationStatsWithSize(R3, R8, cid, space); |
| 712 __ Ret(); // Returns the newly allocated object in R0. | 704 __ Ret(); // Returns the newly allocated object in R0. |
| 713 // Unable to allocate the array using the fast inline code, just call | 705 // Unable to allocate the array using the fast inline code, just call |
| 714 // into the runtime. | 706 // into the runtime. |
| 715 __ Bind(&slow_case); | 707 __ Bind(&slow_case); |
| 716 | 708 |
| 717 // Create a stub frame as we are pushing some objects on the stack before | 709 // Create a stub frame as we are pushing some objects on the stack before |
| 718 // calling into the runtime. | 710 // calling into the runtime. |
| 719 __ EnterStubFrame(); | 711 __ EnterStubFrame(); |
| 720 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null())); | 712 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null())); |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 875 __ ldr(IP, Address(IP, 0)); | 867 __ ldr(IP, Address(IP, 0)); |
| 876 __ cmp(R3, Operand(IP)); | 868 __ cmp(R3, Operand(IP)); |
| 877 if (FLAG_use_slow_path) { | 869 if (FLAG_use_slow_path) { |
| 878 __ b(&slow_case); | 870 __ b(&slow_case); |
| 879 } else { | 871 } else { |
| 880 __ b(&slow_case, CS); // Branch if unsigned higher or equal. | 872 __ b(&slow_case, CS); // Branch if unsigned higher or equal. |
| 881 } | 873 } |
| 882 | 874 |
| 883 // Successfully allocated the object, now update top to point to | 875 // Successfully allocated the object, now update top to point to |
| 884 // next object start and initialize the object. | 876 // next object start and initialize the object. |
| 885 // R0: new object. | 877 // R0: new object start (untagged). |
| 886 // R1: number of context variables. | 878 // R1: number of context variables. |
| 887 // R2: object size. | 879 // R2: object size. |
| 888 // R3: next object start. | 880 // R3: next object start. |
| 889 // R5: top address. | 881 // R5: top address. |
| 890 __ LoadAllocationStatsAddress(R4, cid, space); | 882 __ LoadAllocationStatsAddress(R6, cid, space); |
| 891 __ str(R3, Address(R5, 0)); | 883 __ str(R3, Address(R5, 0)); |
| 892 __ add(R0, R0, Operand(kHeapObjectTag)); | 884 __ add(R0, R0, Operand(kHeapObjectTag)); |
| 893 | 885 |
| 894 // Calculate the size tag. | 886 // Calculate the size tag. |
| 895 // R0: new object. | 887 // R0: new object (tagged). |
| 896 // R1: number of context variables. | 888 // R1: number of context variables. |
| 897 // R2: object size. | 889 // R2: object size. |
| 898 // R4: allocation stats address. | 890 // R3: next object start. |
| 891 // R6: allocation stats address. | |
| 899 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2; | 892 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2; |
| 900 __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag); | 893 __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag); |
| 901 // If no size tag overflow, shift R2 left, else set R2 to zero. | 894 // If no size tag overflow, shift R2 left, else set R2 to zero. |
| 902 __ mov(R3, Operand(R2, LSL, shift), LS); | 895 __ mov(R5, Operand(R2, LSL, shift), LS); |
| 903 __ mov(R3, Operand(0), HI); | 896 __ mov(R5, Operand(0), HI); |
| 904 | 897 |
| 905 // Get the class index and insert it into the tags. | 898 // Get the class index and insert it into the tags. |
| 906 // R3: size and bit tags. | 899 // R5: size and bit tags. |
| 907 __ LoadImmediate(IP, RawObject::ClassIdTag::encode(cid)); | 900 __ LoadImmediate(IP, RawObject::ClassIdTag::encode(cid)); |
| 908 __ orr(R3, R3, Operand(IP)); | 901 __ orr(R5, R5, Operand(IP)); |
| 909 __ str(R3, FieldAddress(R0, Context::tags_offset())); | 902 __ str(R5, FieldAddress(R0, Context::tags_offset())); |
| 910 | 903 |
| 911 // Setup up number of context variables field. | 904 // Setup up number of context variables field. |
| 912 // R0: new object. | 905 // R0: new object. |
| 913 // R1: number of context variables as integer value (not object). | 906 // R1: number of context variables as integer value (not object). |
| 914 // R2: object size. | 907 // R2: object size. |
| 915 // R4: allocation stats address. | 908 // R3: next object start. |
| 909 // R6: allocation stats address. | |
| 916 __ str(R1, FieldAddress(R0, Context::num_variables_offset())); | 910 __ str(R1, FieldAddress(R0, Context::num_variables_offset())); |
| 917 | 911 |
| 918 // Setup the parent field. | 912 // Setup the parent field. |
| 919 // R0: new object. | 913 // R0: new object. |
| 920 // R1: number of context variables. | 914 // R1: number of context variables. |
| 921 // R2: object size. | 915 // R2: object size. |
| 922 // R4: allocation stats address. | 916 // R3: next object start. |
| 923 __ LoadImmediate(R3, reinterpret_cast<intptr_t>(Object::null())); | 917 // R6: allocation stats address. |
| 924 __ str(R3, FieldAddress(R0, Context::parent_offset())); | 918 __ LoadImmediate(R4, reinterpret_cast<intptr_t>(Object::null())); |
| 919 __ str(R4, FieldAddress(R0, Context::parent_offset())); | |
| 925 | 920 |
| 926 // Initialize the context variables. | 921 // Initialize the context variables. |
| 927 // R0: new object. | 922 // R0: new object. |
| 928 // R1: number of context variables. | 923 // R1: number of context variables. |
| 929 // R2: object size. | 924 // R2: object size. |
| 930 // R3: raw null. | 925 // R3: next object start. |
| 931 // R4: allocation stats address. | 926 // R4, R5: raw null. |
| 927 // R6: allocation stats address. | |
| 932 Label loop; | 928 Label loop; |
| 933 __ AddImmediate(R5, R0, Context::variable_offset(0) - kHeapObjectTag); | 929 __ AddImmediate(R7, R0, Context::variable_offset(0) - kHeapObjectTag); |
| 934 __ Bind(&loop); | 930 __ InitializeFieldsNoBarrier(R0, R7, R3, R4, R5); |
|
zra
2014/11/20 21:43:10
Keep an eye on benchmark numbers for any differenc
| |
| 935 __ subs(R1, R1, Operand(1)); | 931 __ IncrementAllocationStatsWithSize(R6, R2, cid, space); |
| 936 __ str(R3, Address(R5, R1, LSL, 2), PL); // Store if R1 positive or zero. | |
| 937 __ b(&loop, NE); // Loop if R1 not zero. | |
| 938 | |
| 939 __ IncrementAllocationStatsWithSize(R4, R2, cid, space); | |
| 940 | 932 |
| 941 // Done allocating and initializing the context. | 933 // Done allocating and initializing the context. |
| 942 // R0: new object. | 934 // R0: new object. |
| 943 __ Ret(); | 935 __ Ret(); |
| 944 | 936 |
| 945 __ Bind(&slow_case); | 937 __ Bind(&slow_case); |
| 946 } | 938 } |
| 947 // Create a stub frame as we are pushing some objects on the stack before | 939 // Create a stub frame as we are pushing some objects on the stack before |
| 948 // calling into the runtime. | 940 // calling into the runtime. |
| 949 __ EnterStubFrame(); | 941 __ EnterStubFrame(); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1060 const int kInlineInstanceSize = 12; | 1052 const int kInlineInstanceSize = 12; |
| 1061 const intptr_t instance_size = cls.instance_size(); | 1053 const intptr_t instance_size = cls.instance_size(); |
| 1062 ASSERT(instance_size > 0); | 1054 ASSERT(instance_size > 0); |
| 1063 if (FLAG_inline_alloc && Heap::IsAllocatableInNewSpace(instance_size)) { | 1055 if (FLAG_inline_alloc && Heap::IsAllocatableInNewSpace(instance_size)) { |
| 1064 Label slow_case; | 1056 Label slow_case; |
| 1065 // Allocate the object and update top to point to | 1057 // Allocate the object and update top to point to |
| 1066 // next object start and initialize the allocated object. | 1058 // next object start and initialize the allocated object. |
| 1067 Heap* heap = Isolate::Current()->heap(); | 1059 Heap* heap = Isolate::Current()->heap(); |
| 1068 Heap::Space space = heap->SpaceForAllocation(cls.id()); | 1060 Heap::Space space = heap->SpaceForAllocation(cls.id()); |
| 1069 __ LoadImmediate(R5, heap->TopAddress(space)); | 1061 __ LoadImmediate(R5, heap->TopAddress(space)); |
| 1070 __ ldr(R2, Address(R5, 0)); | 1062 __ ldr(R0, Address(R5, 0)); |
| 1071 __ AddImmediate(R3, R2, instance_size); | 1063 __ AddImmediate(R1, R0, instance_size); |
| 1072 // Check if the allocation fits into the remaining space. | 1064 // Check if the allocation fits into the remaining space. |
| 1073 // R2: potential new object start. | 1065 // R0: potential new object start. |
| 1074 // R3: potential next object start. | 1066 // R1: potential next object start. |
| 1075 __ LoadImmediate(IP, heap->EndAddress(space)); | 1067 __ LoadImmediate(IP, heap->EndAddress(space)); |
| 1076 __ ldr(IP, Address(IP, 0)); | 1068 __ ldr(IP, Address(IP, 0)); |
| 1077 __ cmp(R3, Operand(IP)); | 1069 __ cmp(R1, Operand(IP)); |
| 1078 if (FLAG_use_slow_path) { | 1070 if (FLAG_use_slow_path) { |
| 1079 __ b(&slow_case); | 1071 __ b(&slow_case); |
| 1080 } else { | 1072 } else { |
| 1081 __ b(&slow_case, CS); // Unsigned higher or equal. | 1073 __ b(&slow_case, CS); // Unsigned higher or equal. |
| 1082 } | 1074 } |
| 1083 __ str(R3, Address(R5, 0)); | 1075 __ str(R1, Address(R5, 0)); |
| 1084 | 1076 |
| 1085 // Load the address of the allocation stats table. We split up the load | 1077 // Load the address of the allocation stats table. We split up the load |
| 1086 // and the increment so that the dependent load is not too nearby. | 1078 // and the increment so that the dependent load is not too nearby. |
| 1087 __ LoadAllocationStatsAddress(R5, cls.id(), space); | 1079 __ LoadAllocationStatsAddress(R5, cls.id(), space); |
| 1088 | 1080 |
| 1089 // R2: new object start. | 1081 // R0: new object start. |
| 1090 // R3: next object start. | 1082 // R1: next object start. |
| 1091 // R5: allocation stats table. | 1083 // R5: allocation stats table. |
| 1092 // Set the tags. | 1084 // Set the tags. |
| 1093 uword tags = 0; | 1085 uword tags = 0; |
| 1094 tags = RawObject::SizeTag::update(instance_size, tags); | 1086 tags = RawObject::SizeTag::update(instance_size, tags); |
| 1095 ASSERT(cls.id() != kIllegalCid); | 1087 ASSERT(cls.id() != kIllegalCid); |
| 1096 tags = RawObject::ClassIdTag::update(cls.id(), tags); | 1088 tags = RawObject::ClassIdTag::update(cls.id(), tags); |
| 1097 __ LoadImmediate(R0, tags); | 1089 __ LoadImmediate(R2, tags); |
| 1098 __ str(R0, Address(R2, Instance::tags_offset())); | 1090 __ str(R2, Address(R0, Instance::tags_offset())); |
| 1091 __ add(R0, R0, Operand(kHeapObjectTag)); | |
| 1099 | 1092 |
| 1100 // Initialize the remaining words of the object. | 1093 // Initialize the remaining words of the object. |
| 1101 __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); | 1094 __ LoadImmediate(R2, reinterpret_cast<intptr_t>(Object::null())); |
| 1102 | 1095 |
| 1103 // R0: raw null. | 1096 // R2: raw null. |
| 1104 // R2: new object start. | 1097 // R0: new object (tagged). |
| 1105 // R3: next object start. | 1098 // R1: next object start. |
| 1106 // R5: allocation stats table. | 1099 // R5: allocation stats table. |
| 1107 // First try inlining the initialization without a loop. | 1100 // First try inlining the initialization without a loop. |
| 1108 if (instance_size < (kInlineInstanceSize * kWordSize)) { | 1101 if (instance_size < (kInlineInstanceSize * kWordSize)) { |
| 1109 // Check if the object contains any non-header fields. | 1102 // Check if the object contains any non-header fields. |
| 1110 // Small objects are initialized using a consecutive set of writes. | 1103 // Small objects are initialized using a consecutive set of writes. |
| 1111 intptr_t current_offset = Instance::NextFieldOffset(); | 1104 intptr_t current_offset = Instance::NextFieldOffset(); |
| 1112 // Write two nulls at a time. | 1105 // Write two nulls at a time. |
| 1113 if (instance_size >= 2 * kWordSize) { | 1106 if (instance_size >= 2 * kWordSize) { |
| 1114 __ mov(R1, Operand(R0)); | 1107 __ mov(R3, Operand(R2)); |
| 1115 while (current_offset + kWordSize < instance_size) { | 1108 while (current_offset + kWordSize < instance_size) { |
| 1116 __ StoreToOffset(kWordPair, R0, R2, current_offset); | 1109 __ StoreToOffset(kWordPair, R2, R0, current_offset - kHeapObjectTag); |
| 1117 current_offset += 2 * kWordSize; | 1110 current_offset += 2 * kWordSize; |
| 1118 } | 1111 } |
| 1119 } | 1112 } |
| 1120 // Write remainder. | 1113 // Write remainder. |
| 1121 while (current_offset < instance_size) { | 1114 while (current_offset < instance_size) { |
| 1122 __ StoreToOffset(kWord, R0, R2, current_offset); | 1115 __ StoreToOffset(kWord, R2, R0, current_offset - kHeapObjectTag); |
| 1123 current_offset += kWordSize; | 1116 current_offset += kWordSize; |
| 1124 } | 1117 } |
| 1125 } else { | 1118 } else { |
| 1126 // There are more than kInlineInstanceSize(12) fields | 1119 // There are more than kInlineInstanceSize(12) fields |
| 1127 __ add(R4, R2, Operand(Instance::NextFieldOffset())); | 1120 __ add(R4, R0, Operand(Instance::NextFieldOffset() - kHeapObjectTag)); |
| 1128 __ mov(R1, Operand(R0)); | 1121 __ mov(R3, Operand(R2)); |
| 1129 // Loop until the whole object is initialized. | 1122 // Loop until the whole object is initialized. |
| 1130 // R0: raw null. | 1123 // R2: raw null. |
| 1131 // R1: raw null. | 1124 // R3: raw null. |
| 1132 // R2: new object. | 1125 // R0: new object (tagged). |
| 1133 // R3: next object start. | 1126 // R1: next object start. |
| 1134 // R4: next word to be initialized. | 1127 // R4: next word to be initialized. |
| 1135 // R5: allocation stats table. | 1128 // R5: allocation stats table. |
| 1136 Label init_loop; | 1129 __ InitializeFieldsNoBarrier(R0, R4, R1, R2, R3); |
| 1137 __ Bind(&init_loop); | |
| 1138 __ AddImmediate(R4, 2 * kWordSize); | |
| 1139 __ cmp(R4, Operand(R3)); | |
| 1140 __ strd(R0, Address(R4, -2 * kWordSize), LS); | |
| 1141 __ b(&init_loop, CC); | |
| 1142 __ str(R0, Address(R4, -2 * kWordSize), HI); | |
| 1143 } | 1130 } |
| 1144 if (is_cls_parameterized) { | 1131 if (is_cls_parameterized) { |
| 1145 // Set the type arguments in the new object. | 1132 // Set the type arguments in the new object. |
| 1146 __ ldr(R4, Address(SP, 0)); | 1133 __ ldr(R4, Address(SP, 0)); |
| 1147 __ StoreToOffset(kWord, R4, R2, cls.type_arguments_field_offset()); | 1134 __ StoreToOffset(kWord, R4, |
| 1135 R0, cls.type_arguments_field_offset() - kHeapObjectTag); | |
| 1148 } | 1136 } |
| 1149 | 1137 |
| 1150 // Done allocating and initializing the instance. | 1138 // Done allocating and initializing the instance. |
| 1151 // R2: new object still missing its heap tag. | 1139 // R0: new object (tagged). |
| 1152 // R5: allocation stats table. | 1140 // R5: allocation stats table. |
| 1153 __ add(R0, R2, Operand(kHeapObjectTag)); | |
| 1154 | 1141 |
| 1155 // Update allocation stats. | 1142 // Update allocation stats. |
| 1156 __ IncrementAllocationStats(R5, cls.id(), space); | 1143 __ IncrementAllocationStats(R5, cls.id(), space); |
| 1157 | 1144 |
| 1158 // R0: new object. | 1145 // R0: new object (tagged). |
| 1159 __ Ret(); | 1146 __ Ret(); |
| 1160 | 1147 |
| 1161 __ Bind(&slow_case); | 1148 __ Bind(&slow_case); |
| 1162 } | 1149 } |
| 1163 if (is_cls_parameterized) { | 1150 if (is_cls_parameterized) { |
| 1164 // Load the type arguments. | 1151 // Load the type arguments. |
| 1165 __ ldr(R4, Address(SP, 0)); | 1152 __ ldr(R4, Address(SP, 0)); |
| 1166 } | 1153 } |
| 1167 // If is_cls_parameterized: | 1154 // If is_cls_parameterized: |
| 1168 // R4: new object type arguments. | 1155 // R4: new object type arguments. |
| (...skipping 820 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1989 const Register right = R0; | 1976 const Register right = R0; |
| 1990 __ ldr(left, Address(SP, 1 * kWordSize)); | 1977 __ ldr(left, Address(SP, 1 * kWordSize)); |
| 1991 __ ldr(right, Address(SP, 0 * kWordSize)); | 1978 __ ldr(right, Address(SP, 0 * kWordSize)); |
| 1992 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); | 1979 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); |
| 1993 __ Ret(); | 1980 __ Ret(); |
| 1994 } | 1981 } |
| 1995 | 1982 |
| 1996 } // namespace dart | 1983 } // namespace dart |
| 1997 | 1984 |
| 1998 #endif // defined TARGET_ARCH_ARM | 1985 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |