Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(18)

Side by Side Diff: runtime/vm/stub_code_ia32.cc

Issue 154393003: Implement eager instantiation and canonicalization of type arguments at run (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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_IA32) 6 #if defined(TARGET_ARCH_IA32)
7 7
8 #include "vm/assembler.h" 8 #include "vm/assembler.h"
9 #include "vm/compiler.h" 9 #include "vm/compiler.h"
10 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
11 #include "vm/flow_graph_compiler.h" 11 #include "vm/flow_graph_compiler.h"
12 #include "vm/instructions.h" 12 #include "vm/instructions.h"
13 #include "vm/heap.h" 13 #include "vm/heap.h"
14 #include "vm/object_store.h" 14 #include "vm/object_store.h"
15 #include "vm/resolver.h" 15 #include "vm/resolver.h"
16 #include "vm/scavenger.h" 16 #include "vm/scavenger.h"
17 #include "vm/stack_frame.h" 17 #include "vm/stack_frame.h"
18 #include "vm/stub_code.h" 18 #include "vm/stub_code.h"
19 19
20 20
21 #define __ assembler-> 21 #define __ assembler->
22 22
23 namespace dart { 23 namespace dart {
24 24
25 DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects."); 25 DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects.");
26 DEFINE_FLAG(bool, use_slow_path, false, 26 DEFINE_FLAG(bool, use_slow_path, false,
27 "Set to true for debugging & verifying the slow paths."); 27 "Set to true for debugging & verifying the slow paths.");
28 DECLARE_FLAG(bool, trace_optimized_ic_calls);
28 DECLARE_FLAG(int, optimization_counter_threshold); 29 DECLARE_FLAG(int, optimization_counter_threshold);
29 DECLARE_FLAG(bool, trace_optimized_ic_calls); 30
30 31
31 // Input parameters: 32 // Input parameters:
32 // ESP : points to return address. 33 // ESP : points to return address.
33 // ESP + 4 : address of last argument in argument array. 34 // ESP + 4 : address of last argument in argument array.
34 // ESP + 4*EDX : address of first argument in argument array. 35 // ESP + 4*EDX : address of first argument in argument array.
35 // ESP + 4*EDX + 4 : address of return value. 36 // ESP + 4*EDX + 4 : address of return value.
36 // ECX : address of the runtime function to call. 37 // ECX : address of the runtime function to call.
37 // EDX : number of arguments to the call. 38 // EDX : number of arguments to the call.
38 // Must preserve callee saved registers EDI and EBX. 39 // Must preserve callee saved registers EDI and EBX.
39 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) { 40 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) {
(...skipping 1071 matching lines...) Expand 10 before | Expand all | Expand 10 after
1111 const intptr_t kInstantiatorTypeArgumentsOffset = 1 * kWordSize; 1112 const intptr_t kInstantiatorTypeArgumentsOffset = 1 * kWordSize;
1112 const Immediate& raw_null = 1113 const Immediate& raw_null =
1113 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1114 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1114 // The generated code is different if the class is parameterized. 1115 // The generated code is different if the class is parameterized.
1115 const bool is_cls_parameterized = cls.NumTypeArguments() > 0; 1116 const bool is_cls_parameterized = cls.NumTypeArguments() > 0;
1116 ASSERT(!is_cls_parameterized || 1117 ASSERT(!is_cls_parameterized ||
1117 (cls.type_arguments_field_offset() != Class::kNoTypeArguments)); 1118 (cls.type_arguments_field_offset() != Class::kNoTypeArguments));
1118 // kInlineInstanceSize is a constant used as a threshold for determining 1119 // kInlineInstanceSize is a constant used as a threshold for determining
1119 // when the object initialization should be done as a loop or as 1120 // when the object initialization should be done as a loop or as
1120 // straight line code. 1121 // straight line code.
1121 const int kInlineInstanceSize = 12; 1122 const int kInlineInstanceSize = 12; // In words.
1122 const intptr_t instance_size = cls.instance_size(); 1123 const intptr_t instance_size = cls.instance_size();
1123 ASSERT(instance_size > 0); 1124 ASSERT(instance_size > 0);
1124 const intptr_t type_args_size = InstantiatedTypeArguments::InstanceSize(); 1125 Label slow_case_with_type_arguments;
1125 if (FLAG_inline_alloc && 1126 if (FLAG_inline_alloc && Heap::IsAllocatableInNewSpace(instance_size)) {
1126 Heap::IsAllocatableInNewSpace(instance_size + type_args_size)) { 1127 Label slow_case_reload_type_arguments;
1127 Label slow_case; 1128 if (is_cls_parameterized) {
1129 // Instantiation of the type arguments vector is only required if an
1130 // instantiator is provided (not kNoInstantiator, but may be null).
1131 __ movl(EDX, Address(ESP, kObjectTypeArgumentsOffset));
1132 __ movl(EDI, Address(ESP, kInstantiatorTypeArgumentsOffset));
1133 Label type_arguments_ready;
1134 __ cmpl(EDI, Immediate(Smi::RawValue(StubCode::kNoInstantiator)));
1135 __ j(EQUAL, &type_arguments_ready, Assembler::kNearJump);
1136 // Lookup instantiator EDI in instantiations array of type arguments EDX
1137 // and, if found, use cached instantiated type arguments.
1138 __ movl(EAX, FieldAddress(EDX, TypeArguments::instantiations_offset()));
1139 __ movl(EBX, FieldAddress(EAX, Array::length_offset()));
1140 __ leal(EAX, FieldAddress(EAX, Array::data_offset()));
1141 __ leal(EBX, Address(EAX, EBX, TIMES_2, 0)); // EBX is smi.
1142 Label loop, found;
1143 __ Bind(&loop);
1144 __ cmpl(EAX, EBX);
1145 __ j(ABOVE_EQUAL, &slow_case_reload_type_arguments);
1146 __ movl(EDX, Address(EAX, 0 * kWordSize)); // Cached instantiator.
1147 __ cmpl(EDX, EDI);
1148 __ j(EQUAL, &found, Assembler::kNearJump);
1149 __ cmpl(EDX, Immediate(Smi::RawValue(StubCode::kNoInstantiator)));
1150 __ j(EQUAL, &slow_case_reload_type_arguments);
1151 __ addl(EAX, Immediate(2 * kWordSize));
1152 __ jmp(&loop, Assembler::kNearJump);
1153 __ Bind(&found);
1154 __ movl(EDX, Address(EAX, 1 * kWordSize)); // Cached instantiated args.
1155 __ movl(EDI, Immediate(Smi::RawValue(StubCode::kNoInstantiator)));
1156 __ Bind(&type_arguments_ready);
1157 // EDX: instantiated type arguments.
1158 // EDI: kNoInstantiator.
1159 }
1160 // Allocate the object and update top to point to
1161 // next object start and initialize the allocated object.
1162 // EDX: instantiated type arguments (if is_cls_parameterized).
1163 // EDI: kNoInstantiator (if is_cls_parameterized).
1128 Heap* heap = Isolate::Current()->heap(); 1164 Heap* heap = Isolate::Current()->heap();
1129 __ movl(EAX, Address::Absolute(heap->TopAddress())); 1165 __ movl(EAX, Address::Absolute(heap->TopAddress()));
1130 __ leal(EBX, Address(EAX, instance_size)); 1166 __ leal(EBX, Address(EAX, instance_size));
1131 if (is_cls_parameterized) {
1132 __ movl(ECX, EBX);
1133 // A new InstantiatedTypeArguments object only needs to be allocated if
1134 // the instantiator is provided (not kNoInstantiator, but may be null).
1135 Label no_instantiator;
1136 __ cmpl(Address(ESP, kInstantiatorTypeArgumentsOffset),
1137 Immediate(Smi::RawValue(StubCode::kNoInstantiator)));
1138 __ j(EQUAL, &no_instantiator, Assembler::kNearJump);
1139 __ addl(EBX, Immediate(type_args_size));
1140 __ Bind(&no_instantiator);
1141 // ECX: potential new object end and, if ECX != EBX, potential new
1142 // InstantiatedTypeArguments object start.
1143 }
1144 // Check if the allocation fits into the remaining space. 1167 // Check if the allocation fits into the remaining space.
1145 // EAX: potential new object start. 1168 // EAX: potential new object start.
1146 // EBX: potential next object start. 1169 // EBX: potential next object start.
1147 __ cmpl(EBX, Address::Absolute(heap->EndAddress())); 1170 __ cmpl(EBX, Address::Absolute(heap->EndAddress()));
1148 if (FLAG_use_slow_path) { 1171 if (FLAG_use_slow_path) {
1149 __ jmp(&slow_case); 1172 __ jmp(&slow_case_with_type_arguments);
1150 } else { 1173 } else {
1151 __ j(ABOVE_EQUAL, &slow_case); 1174 __ j(ABOVE_EQUAL, &slow_case_with_type_arguments);
1152 } 1175 }
1153
1154 // Successfully allocated the object(s), now update top to point to
1155 // next object start and initialize the object.
1156 __ movl(Address::Absolute(heap->TopAddress()), EBX); 1176 __ movl(Address::Absolute(heap->TopAddress()), EBX);
1157 __ UpdateAllocationStats(cls.id(), EDI); 1177 __ UpdateAllocationStats(cls.id(), ECX);
1158
1159 if (is_cls_parameterized) {
1160 // Initialize the type arguments field in the object.
1161 // EAX: new object start.
1162 // ECX: potential new object end and, if ECX != EBX, potential new
1163 // InstantiatedTypeArguments object start.
1164 // EBX: next object start.
1165 Label type_arguments_ready;
1166 __ movl(EDI, Address(ESP, kObjectTypeArgumentsOffset));
1167 __ cmpl(ECX, EBX);
1168 __ j(EQUAL, &type_arguments_ready, Assembler::kNearJump);
1169 // Initialize InstantiatedTypeArguments object at ECX.
1170 __ movl(Address(ECX,
1171 InstantiatedTypeArguments::uninstantiated_type_arguments_offset()),
1172 EDI);
1173 __ movl(EDX, Address(ESP, kInstantiatorTypeArgumentsOffset));
1174 __ movl(Address(ECX,
1175 InstantiatedTypeArguments::instantiator_type_arguments_offset()),
1176 EDX);
1177 const Class& ita_cls =
1178 Class::ZoneHandle(Object::instantiated_type_arguments_class());
1179 // Set the tags.
1180 uword tags = 0;
1181 tags = RawObject::SizeTag::update(type_args_size, tags);
1182 tags = RawObject::ClassIdTag::update(ita_cls.id(), tags);
1183 __ movl(Address(ECX, Instance::tags_offset()), Immediate(tags));
1184 // Set the new InstantiatedTypeArguments object (ECX) as the type
1185 // arguments (EDI) of the new object (EAX).
1186 __ movl(EDI, ECX);
1187 __ addl(EDI, Immediate(kHeapObjectTag));
1188 // Set EBX to new object end.
1189 __ movl(EBX, ECX);
1190 __ Bind(&type_arguments_ready);
1191 // EAX: new object.
1192 // EDI: new object type arguments.
1193 }
1194 1178
1195 // EAX: new object start. 1179 // EAX: new object start.
1196 // EBX: next object start. 1180 // EBX: next object start.
1197 // EDI: new object type arguments (if is_cls_parameterized). 1181 // EDX: new object type arguments (if is_cls_parameterized).
1198 // Set the tags. 1182 // Set the tags.
1199 uword tags = 0; 1183 uword tags = 0;
1200 tags = RawObject::SizeTag::update(instance_size, tags); 1184 tags = RawObject::SizeTag::update(instance_size, tags);
1201 ASSERT(cls.id() != kIllegalCid); 1185 ASSERT(cls.id() != kIllegalCid);
1202 tags = RawObject::ClassIdTag::update(cls.id(), tags); 1186 tags = RawObject::ClassIdTag::update(cls.id(), tags);
1203 __ movl(Address(EAX, Instance::tags_offset()), Immediate(tags)); 1187 __ movl(Address(EAX, Instance::tags_offset()), Immediate(tags));
1204 1188
1205 // Initialize the remaining words of the object. 1189 // Initialize the remaining words of the object.
1206 const Immediate& raw_null = 1190 const Immediate& raw_null =
1207 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1191 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1208 1192
1209 // EAX: new object start. 1193 // EAX: new object start.
1210 // EBX: next object start. 1194 // EBX: next object start.
1211 // EDI: new object type arguments (if is_cls_parameterized). 1195 // EDX: new object type arguments (if is_cls_parameterized).
1212 // First try inlining the initialization without a loop. 1196 // First try inlining the initialization without a loop.
1213 if (instance_size < (kInlineInstanceSize * kWordSize)) { 1197 if (instance_size < (kInlineInstanceSize * kWordSize)) {
1214 // Check if the object contains any non-header fields. 1198 // Check if the object contains any non-header fields.
1215 // Small objects are initialized using a consecutive set of writes. 1199 // Small objects are initialized using a consecutive set of writes.
1216 for (intptr_t current_offset = Instance::NextFieldOffset(); 1200 for (intptr_t current_offset = Instance::NextFieldOffset();
1217 current_offset < instance_size; 1201 current_offset < instance_size;
1218 current_offset += kWordSize) { 1202 current_offset += kWordSize) {
1219 __ movl(Address(EAX, current_offset), raw_null); 1203 __ movl(Address(EAX, current_offset), raw_null);
1220 } 1204 }
1221 } else { 1205 } else {
1222 __ leal(ECX, Address(EAX, Instance::NextFieldOffset())); 1206 __ leal(ECX, Address(EAX, Instance::NextFieldOffset()));
1223 // Loop until the whole object is initialized. 1207 // Loop until the whole object is initialized.
1224 // EAX: new object. 1208 // EAX: new object.
1225 // EBX: next object start. 1209 // EBX: next object start.
1226 // ECX: next word to be initialized. 1210 // ECX: next word to be initialized.
1227 // EDI: new object type arguments (if is_cls_parameterized). 1211 // EDX: new object type arguments (if is_cls_parameterized).
1228 Label init_loop; 1212 Label init_loop;
1229 Label done; 1213 Label done;
1230 __ Bind(&init_loop); 1214 __ Bind(&init_loop);
1231 __ cmpl(ECX, EBX); 1215 __ cmpl(ECX, EBX);
1232 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); 1216 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump);
1233 __ movl(Address(ECX, 0), raw_null); 1217 __ movl(Address(ECX, 0), raw_null);
1234 __ addl(ECX, Immediate(kWordSize)); 1218 __ addl(ECX, Immediate(kWordSize));
1235 __ jmp(&init_loop, Assembler::kNearJump); 1219 __ jmp(&init_loop, Assembler::kNearJump);
1236 __ Bind(&done); 1220 __ Bind(&done);
1237 } 1221 }
1238 if (is_cls_parameterized) { 1222 if (is_cls_parameterized) {
1239 // EDI: new object type arguments. 1223 // EDX: new object type arguments.
1240 // Set the type arguments in the new object. 1224 // Set the type arguments in the new object.
1241 __ movl(Address(EAX, cls.type_arguments_field_offset()), EDI); 1225 __ movl(Address(EAX, cls.type_arguments_field_offset()), EDX);
1242 } 1226 }
1243 // Done allocating and initializing the instance. 1227 // Done allocating and initializing the instance.
1244 // EAX: new object. 1228 // EAX: new object.
1245 __ addl(EAX, Immediate(kHeapObjectTag)); 1229 __ addl(EAX, Immediate(kHeapObjectTag));
1246 __ ret(); 1230 __ ret();
1247 1231
1248 __ Bind(&slow_case); 1232 __ Bind(&slow_case_reload_type_arguments);
1249 } 1233 }
1250 if (is_cls_parameterized) { 1234 if (is_cls_parameterized) {
1251 __ movl(EAX, Address(ESP, kObjectTypeArgumentsOffset)); 1235 __ movl(EDX, Address(ESP, kObjectTypeArgumentsOffset));
1252 __ movl(EDX, Address(ESP, kInstantiatorTypeArgumentsOffset)); 1236 __ movl(EDI, Address(ESP, kInstantiatorTypeArgumentsOffset));
1253 } 1237 }
1238 __ Bind(&slow_case_with_type_arguments);
1239 // If is_cls_parameterized:
1240 // EDX: new object type arguments (instantiated or not).
1241 // EDI: instantiator type arguments or kNoInstantiator.
1254 // Create a stub frame as we are pushing some objects on the stack before 1242 // Create a stub frame as we are pushing some objects on the stack before
1255 // calling into the runtime. 1243 // calling into the runtime.
1256 __ EnterStubFrame(); 1244 __ EnterStubFrame();
1257 __ pushl(raw_null); // Setup space on stack for return value. 1245 __ pushl(raw_null); // Setup space on stack for return value.
1258 __ PushObject(cls); // Push class of object to be allocated. 1246 __ PushObject(cls); // Push class of object to be allocated.
1259 if (is_cls_parameterized) { 1247 if (is_cls_parameterized) {
1260 __ pushl(EAX); // Push type arguments of object to be allocated. 1248 __ pushl(EDX); // Push type arguments of object to be allocated.
1261 __ pushl(EDX); // Push type arguments of instantiator. 1249 __ pushl(EDI); // Push type arguments of instantiator.
1262 } else { 1250 } else {
1263 __ pushl(raw_null); // Push null type arguments. 1251 __ pushl(raw_null); // Push null type arguments.
1264 __ pushl(Immediate(Smi::RawValue(StubCode::kNoInstantiator))); 1252 __ pushl(Immediate(Smi::RawValue(StubCode::kNoInstantiator)));
1265 } 1253 }
1266 __ CallRuntime(kAllocateObjectRuntimeEntry, 3); // Allocate object. 1254 __ CallRuntime(kAllocateObjectRuntimeEntry, 3); // Allocate object.
1267 __ popl(EAX); // Pop argument (instantiator). 1255 __ popl(EAX); // Pop argument (instantiator).
1268 __ popl(EAX); // Pop argument (type arguments of object). 1256 __ popl(EAX); // Pop argument (type arguments of object).
1269 __ popl(EAX); // Pop argument (class of object). 1257 __ popl(EAX); // Pop argument (class of object).
1270 __ popl(EAX); // Pop result (newly allocated object). 1258 __ popl(EAX); // Pop result (newly allocated object).
1271 // EAX: new object 1259 // EAX: new object
(...skipping 897 matching lines...) Expand 10 before | Expand all | Expand 10 after
2169 const Register temp = ECX; 2157 const Register temp = ECX;
2170 __ movl(left, Address(ESP, 2 * kWordSize)); 2158 __ movl(left, Address(ESP, 2 * kWordSize));
2171 __ movl(right, Address(ESP, 1 * kWordSize)); 2159 __ movl(right, Address(ESP, 1 * kWordSize));
2172 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); 2160 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp);
2173 __ ret(); 2161 __ ret();
2174 } 2162 }
2175 2163
2176 } // namespace dart 2164 } // namespace dart
2177 2165
2178 #endif // defined TARGET_ARCH_IA32 2166 #endif // defined TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698