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

Side by Side Diff: runtime/vm/stub_code_x64.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_X64) 6 #if defined(TARGET_ARCH_X64)
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/heap.h" 12 #include "vm/heap.h"
13 #include "vm/instructions.h" 13 #include "vm/instructions.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
32 // Input parameters: 32 // Input parameters:
33 // RSP : points to return address. 33 // RSP : points to return address.
34 // RSP + 8 : address of last argument in argument array. 34 // RSP + 8 : address of last argument in argument array.
35 // RSP + 8*R10 : address of first argument in argument array. 35 // RSP + 8*R10 : address of first argument in argument array.
36 // RSP + 8*R10 + 8 : address of return value. 36 // RSP + 8*R10 + 8 : address of return value.
37 // RBX : address of the runtime function to call. 37 // RBX : address of the runtime function to call.
38 // R10 : number of arguments to the call. 38 // R10 : number of arguments to the call.
39 // Must preserve callee saved registers R12 and R13. 39 // Must preserve callee saved registers R12 and R13.
(...skipping 1067 matching lines...) Expand 10 before | Expand all | Expand 10 after
1107 // The generated code is different if the class is parameterized. 1107 // The generated code is different if the class is parameterized.
1108 const bool is_cls_parameterized = cls.NumTypeArguments() > 0; 1108 const bool is_cls_parameterized = cls.NumTypeArguments() > 0;
1109 ASSERT(!is_cls_parameterized || 1109 ASSERT(!is_cls_parameterized ||
1110 (cls.type_arguments_field_offset() != Class::kNoTypeArguments)); 1110 (cls.type_arguments_field_offset() != Class::kNoTypeArguments));
1111 // kInlineInstanceSize is a constant used as a threshold for determining 1111 // kInlineInstanceSize is a constant used as a threshold for determining
1112 // when the object initialization should be done as a loop or as 1112 // when the object initialization should be done as a loop or as
1113 // straight line code. 1113 // straight line code.
1114 const int kInlineInstanceSize = 12; // In words. 1114 const int kInlineInstanceSize = 12; // In words.
1115 const intptr_t instance_size = cls.instance_size(); 1115 const intptr_t instance_size = cls.instance_size();
1116 ASSERT(instance_size > 0); 1116 ASSERT(instance_size > 0);
1117 const intptr_t type_args_size = InstantiatedTypeArguments::InstanceSize();
1118 __ LoadObject(R12, Object::null_object(), PP); 1117 __ LoadObject(R12, Object::null_object(), PP);
1119 if (FLAG_inline_alloc && 1118 Label slow_case_with_type_arguments;
1120 Heap::IsAllocatableInNewSpace(instance_size + type_args_size)) { 1119 if (FLAG_inline_alloc && Heap::IsAllocatableInNewSpace(instance_size)) {
1121 Label slow_case; 1120 Label slow_case_reload_type_arguments;
1121 if (is_cls_parameterized) {
1122 // Instantiation of the type arguments vector is only required if an
1123 // instantiator is provided (not kNoInstantiator, but may be null).
1124 __ movq(RDX, Address(RSP, kObjectTypeArgumentsOffset));
1125 __ movq(RDI, Address(RSP, kInstantiatorTypeArgumentsOffset));
1126 Label type_arguments_ready;
1127 __ cmpq(RDI, Immediate(Smi::RawValue(StubCode::kNoInstantiator)));
1128 __ j(EQUAL, &type_arguments_ready, Assembler::kNearJump);
1129 // Lookup instantiator RDI in instantiations array of type arguments RDX
1130 // and, if found, use cached instantiated type arguments.
1131 __ movq(RAX, FieldAddress(RDX, TypeArguments::instantiations_offset()));
1132 __ movq(RBX, FieldAddress(RAX, Array::length_offset()));
1133 __ leaq(RAX, FieldAddress(RAX, Array::data_offset()));
1134 __ leaq(RBX, Address(RAX, RBX, TIMES_4, 0)); // RBX is smi.
1135 Label loop, found;
1136 __ Bind(&loop);
1137 __ cmpq(RAX, RBX);
1138 __ j(ABOVE_EQUAL, &slow_case_reload_type_arguments);
1139 __ movq(RDX, Address(RAX, 0 * kWordSize)); // Cached instantiator.
1140 __ cmpq(RDX, RDI);
1141 __ j(EQUAL, &found, Assembler::kNearJump);
1142 __ cmpq(RDX, Immediate(Smi::RawValue(StubCode::kNoInstantiator)));
1143 __ j(EQUAL, &slow_case_reload_type_arguments);
1144 __ addq(RAX, Immediate(2 * kWordSize));
1145 __ jmp(&loop, Assembler::kNearJump);
1146 __ Bind(&found);
1147 __ movq(RDX, Address(RAX, 1 * kWordSize)); // Cached instantiated args.
1148 __ movq(RDI, Immediate(Smi::RawValue(StubCode::kNoInstantiator)));
1149 __ Bind(&type_arguments_ready);
1150 // RDX: instantiated type arguments.
1151 // RDI: kNoInstantiator.
1152 }
1153 // Allocate the object and update top to point to
1154 // next object start and initialize the allocated object.
1155 // RDX: instantiated type arguments (if is_cls_parameterized).
1156 // RDI: kNoInstantiator (if is_cls_parameterized).
1122 Heap* heap = Isolate::Current()->heap(); 1157 Heap* heap = Isolate::Current()->heap();
1123 __ movq(RAX, Immediate(heap->TopAddress())); 1158 __ movq(RCX, Immediate(heap->TopAddress()));
1124 __ movq(RAX, Address(RAX, 0)); 1159 __ movq(RAX, Address(RCX, 0));
1125 __ leaq(RBX, Address(RAX, instance_size)); 1160 __ leaq(RBX, Address(RAX, instance_size));
1126 if (is_cls_parameterized) {
1127 __ movq(RCX, RBX);
1128 // A new InstantiatedTypeArguments object only needs to be allocated if
1129 // the instantiator is provided (not kNoInstantiator, but may be null).
1130 Label no_instantiator;
1131 __ cmpq(Address(RSP, kInstantiatorTypeArgumentsOffset),
1132 Immediate(Smi::RawValue(StubCode::kNoInstantiator)));
1133 __ j(EQUAL, &no_instantiator, Assembler::kNearJump);
1134 __ addq(RBX, Immediate(type_args_size));
1135 __ Bind(&no_instantiator);
1136 // RCX: potential new object end and, if RCX != RBX, potential new
1137 // InstantiatedTypeArguments object start.
1138 }
1139 // Check if the allocation fits into the remaining space. 1161 // Check if the allocation fits into the remaining space.
1140 // RAX: potential new object start. 1162 // RAX: potential new object start.
1141 // RBX: potential next object start. 1163 // RBX: potential next object start.
1142 __ movq(RDI, Immediate(heap->EndAddress())); 1164 // RCX: heap top address.
1143 __ cmpq(RBX, Address(RDI, 0)); 1165 __ movq(R13, Immediate(heap->EndAddress()));
1166 __ cmpq(RBX, Address(R13, 0));
1144 if (FLAG_use_slow_path) { 1167 if (FLAG_use_slow_path) {
1145 __ jmp(&slow_case); 1168 __ jmp(&slow_case_with_type_arguments);
1146 } else { 1169 } else {
1147 __ j(ABOVE_EQUAL, &slow_case); 1170 __ j(ABOVE_EQUAL, &slow_case_with_type_arguments);
1148 } 1171 }
1149 1172 __ movq(Address(RCX, 0), RBX);
1150 // Successfully allocated the object(s), now update top to point to
1151 // next object start and initialize the object.
1152 __ movq(RDI, Immediate(heap->TopAddress()));
1153 __ movq(Address(RDI, 0), RBX);
1154 __ UpdateAllocationStats(cls.id()); 1173 __ UpdateAllocationStats(cls.id());
1155 1174
1156 if (is_cls_parameterized) {
1157 // Initialize the type arguments field in the object.
1158 // RAX: new object start.
1159 // RCX: potential new object end and, if RCX != RBX, potential new
1160 // InstantiatedTypeArguments object start.
1161 // RBX: next object start.
1162 Label type_arguments_ready;
1163 __ movq(RDI, Address(RSP, kObjectTypeArgumentsOffset));
1164 __ cmpq(RCX, RBX);
1165 __ j(EQUAL, &type_arguments_ready, Assembler::kNearJump);
1166 // Initialize InstantiatedTypeArguments object at RCX.
1167 __ movq(Address(RCX,
1168 InstantiatedTypeArguments::uninstantiated_type_arguments_offset()),
1169 RDI);
1170 __ movq(RDX, Address(RSP, kInstantiatorTypeArgumentsOffset));
1171 __ movq(Address(RCX,
1172 InstantiatedTypeArguments::instantiator_type_arguments_offset()),
1173 RDX);
1174 const Class& ita_cls =
1175 Class::ZoneHandle(Object::instantiated_type_arguments_class());
1176 // Set the tags.
1177 uword tags = 0;
1178 tags = RawObject::SizeTag::update(type_args_size, tags);
1179 tags = RawObject::ClassIdTag::update(ita_cls.id(), tags);
1180 __ movq(Address(RCX, Instance::tags_offset()), Immediate(tags));
1181 // Set the new InstantiatedTypeArguments object (RCX) as the type
1182 // arguments (RDI) of the new object (RAX).
1183 __ movq(RDI, RCX);
1184 __ addq(RDI, Immediate(kHeapObjectTag));
1185 // Set RBX to new object end.
1186 __ movq(RBX, RCX);
1187 __ Bind(&type_arguments_ready);
1188 // RAX: new object.
1189 // RDI: new object type arguments.
1190 }
1191
1192 // RAX: new object start. 1175 // RAX: new object start.
1193 // RBX: next object start. 1176 // RBX: next object start.
1194 // RDI: new object type arguments (if is_cls_parameterized). 1177 // RDX: new object type arguments (if is_cls_parameterized).
1195 // Set the tags. 1178 // Set the tags.
1196 uword tags = 0; 1179 uword tags = 0;
1197 tags = RawObject::SizeTag::update(instance_size, tags); 1180 tags = RawObject::SizeTag::update(instance_size, tags);
1198 ASSERT(cls.id() != kIllegalCid); 1181 ASSERT(cls.id() != kIllegalCid);
1199 tags = RawObject::ClassIdTag::update(cls.id(), tags); 1182 tags = RawObject::ClassIdTag::update(cls.id(), tags);
1200 __ movq(Address(RAX, Instance::tags_offset()), Immediate(tags)); 1183 __ movq(Address(RAX, Instance::tags_offset()), Immediate(tags));
1201 1184
1202 // Initialize the remaining words of the object. 1185 // Initialize the remaining words of the object.
1203 // RAX: new object start. 1186 // RAX: new object start.
1204 // RBX: next object start. 1187 // RBX: next object start.
1205 // RDI: new object type arguments (if is_cls_parameterized). 1188 // RDX: new object type arguments (if is_cls_parameterized).
1189 // R12: raw null.
1206 // First try inlining the initialization without a loop. 1190 // First try inlining the initialization without a loop.
1207 if (instance_size < (kInlineInstanceSize * kWordSize)) { 1191 if (instance_size < (kInlineInstanceSize * kWordSize)) {
1208 // Check if the object contains any non-header fields. 1192 // Check if the object contains any non-header fields.
1209 // Small objects are initialized using a consecutive set of writes. 1193 // Small objects are initialized using a consecutive set of writes.
1210 for (intptr_t current_offset = Instance::NextFieldOffset(); 1194 for (intptr_t current_offset = Instance::NextFieldOffset();
1211 current_offset < instance_size; 1195 current_offset < instance_size;
1212 current_offset += kWordSize) { 1196 current_offset += kWordSize) {
1213 __ movq(Address(RAX, current_offset), R12); 1197 __ movq(Address(RAX, current_offset), R12);
1214 } 1198 }
1215 } else { 1199 } else {
1216 __ leaq(RCX, Address(RAX, Instance::NextFieldOffset())); 1200 __ leaq(RCX, Address(RAX, Instance::NextFieldOffset()));
1217 // Loop until the whole object is initialized. 1201 // Loop until the whole object is initialized.
1218 // RAX: new object. 1202 // RAX: new object.
1219 // RBX: next object start. 1203 // RBX: next object start.
1220 // RCX: next word to be initialized. 1204 // RCX: next word to be initialized.
1221 // RDI: new object type arguments (if is_cls_parameterized). 1205 // RDX: new object type arguments (if is_cls_parameterized).
1222 Label init_loop; 1206 Label init_loop;
1223 Label done; 1207 Label done;
1224 __ Bind(&init_loop); 1208 __ Bind(&init_loop);
1225 __ cmpq(RCX, RBX); 1209 __ cmpq(RCX, RBX);
1226 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); 1210 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump);
1227 __ movq(Address(RCX, 0), R12); 1211 __ movq(Address(RCX, 0), R12);
1228 __ addq(RCX, Immediate(kWordSize)); 1212 __ addq(RCX, Immediate(kWordSize));
1229 __ jmp(&init_loop, Assembler::kNearJump); 1213 __ jmp(&init_loop, Assembler::kNearJump);
1230 __ Bind(&done); 1214 __ Bind(&done);
1231 } 1215 }
1232 if (is_cls_parameterized) { 1216 if (is_cls_parameterized) {
1233 // RDI: new object type arguments. 1217 // RDX: new object type arguments.
1234 // Set the type arguments in the new object. 1218 // Set the type arguments in the new object.
1235 __ movq(Address(RAX, cls.type_arguments_field_offset()), RDI); 1219 __ movq(Address(RAX, cls.type_arguments_field_offset()), RDX);
1236 } 1220 }
1237 // Done allocating and initializing the instance. 1221 // Done allocating and initializing the instance.
1238 // RAX: new object. 1222 // RAX: new object.
1239 __ addq(RAX, Immediate(kHeapObjectTag)); 1223 __ addq(RAX, Immediate(kHeapObjectTag));
1240 __ ret(); 1224 __ ret();
1241 1225
1242 __ Bind(&slow_case); 1226 __ Bind(&slow_case_reload_type_arguments);
1243 } 1227 }
1244 if (is_cls_parameterized) { 1228 if (is_cls_parameterized) {
1245 __ movq(RAX, Address(RSP, kObjectTypeArgumentsOffset)); 1229 __ movq(RDX, Address(RSP, kObjectTypeArgumentsOffset));
1246 __ movq(RDX, Address(RSP, kInstantiatorTypeArgumentsOffset)); 1230 __ movq(RDI, Address(RSP, kInstantiatorTypeArgumentsOffset));
1247 } 1231 }
1232 __ Bind(&slow_case_with_type_arguments);
1233 // If is_cls_parameterized:
1234 // RDX: new object type arguments (instantiated or not).
1235 // RDI: instantiator type arguments or kNoInstantiator.
1248 // Create a stub frame. 1236 // Create a stub frame.
1249 __ EnterStubFrame(true); // Uses PP to access class object. 1237 __ EnterStubFrame(true); // Uses PP to access class object.
1250 __ pushq(R12); // Setup space on stack for return value. 1238 __ pushq(R12); // Setup space on stack for return value.
1251 __ PushObject(cls, PP); // Push class of object to be allocated. 1239 __ PushObject(cls, PP); // Push class of object to be allocated.
1252 if (is_cls_parameterized) { 1240 if (is_cls_parameterized) {
1253 __ pushq(RAX); // Push type arguments of object to be allocated. 1241 __ pushq(RDX); // Push type arguments of object to be allocated.
1254 __ pushq(RDX); // Push type arguments of instantiator. 1242 __ pushq(RDI); // Push type arguments of instantiator.
1255 } else { 1243 } else {
1256 __ pushq(R12); // Push null type arguments. 1244 __ pushq(R12); // Push null type arguments.
1257 __ pushq(Immediate(Smi::RawValue(StubCode::kNoInstantiator))); 1245 __ pushq(Immediate(Smi::RawValue(StubCode::kNoInstantiator)));
1258 } 1246 }
1259 __ CallRuntime(kAllocateObjectRuntimeEntry, 3); // Allocate object. 1247 __ CallRuntime(kAllocateObjectRuntimeEntry, 3); // Allocate object.
1260 __ popq(RAX); // Pop argument (instantiator). 1248 __ popq(RAX); // Pop argument (instantiator).
1261 __ popq(RAX); // Pop argument (type arguments of object). 1249 __ popq(RAX); // Pop argument (type arguments of object).
1262 __ popq(RAX); // Pop argument (class of object). 1250 __ popq(RAX); // Pop argument (class of object).
1263 __ popq(RAX); // Pop result (newly allocated object). 1251 __ popq(RAX); // Pop result (newly allocated object).
1264 // RAX: new object 1252 // RAX: new object
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after
1627 __ addq(Address(R12, count_offset), Immediate(Smi::RawValue(1))); 1615 __ addq(Address(R12, count_offset), Immediate(Smi::RawValue(1)));
1628 __ j(NO_OVERFLOW, &call_target_function, Assembler::kNearJump); 1616 __ j(NO_OVERFLOW, &call_target_function, Assembler::kNearJump);
1629 __ movq(Address(R12, count_offset), 1617 __ movq(Address(R12, count_offset),
1630 Immediate(Smi::RawValue(Smi::kMaxValue))); 1618 Immediate(Smi::RawValue(Smi::kMaxValue)));
1631 1619
1632 __ Bind(&call_target_function); 1620 __ Bind(&call_target_function);
1633 // RAX: Target function. 1621 // RAX: Target function.
1634 Label is_compiled; 1622 Label is_compiled;
1635 __ movq(RCX, FieldAddress(RAX, Function::code_offset())); 1623 __ movq(RCX, FieldAddress(RAX, Function::code_offset()));
1636 if (FLAG_collect_code) { 1624 if (FLAG_collect_code) {
1637 // If code might be GC'd, then EBX might be null. If it is, recompile. 1625 // If code might be GC'd, then RBX might be null. If it is, recompile.
1638 __ CompareObject(RCX, Object::null_object(), PP); 1626 __ CompareObject(RCX, Object::null_object(), PP);
1639 __ j(NOT_EQUAL, &is_compiled, Assembler::kNearJump); 1627 __ j(NOT_EQUAL, &is_compiled, Assembler::kNearJump);
1640 __ EnterStubFrame(); 1628 __ EnterStubFrame();
1641 __ pushq(R10); // Preserve arguments descriptor array. 1629 __ pushq(R10); // Preserve arguments descriptor array.
1642 __ pushq(RBX); // Preserve IC data object. 1630 __ pushq(RBX); // Preserve IC data object.
1643 __ pushq(RAX); // Pass function. 1631 __ pushq(RAX); // Pass function.
1644 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); 1632 __ CallRuntime(kCompileFunctionRuntimeEntry, 1);
1645 __ popq(RAX); // Restore function. 1633 __ popq(RAX); // Restore function.
1646 __ popq(RBX); // Restore IC data array. 1634 __ popq(RBX); // Restore IC data array.
1647 __ popq(R10); // Restore arguments descriptor array. 1635 __ popq(R10); // Restore arguments descriptor array.
(...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after
2148 2136
2149 __ movq(left, Address(RSP, 2 * kWordSize)); 2137 __ movq(left, Address(RSP, 2 * kWordSize));
2150 __ movq(right, Address(RSP, 1 * kWordSize)); 2138 __ movq(right, Address(RSP, 1 * kWordSize));
2151 GenerateIdenticalWithNumberCheckStub(assembler, left, right); 2139 GenerateIdenticalWithNumberCheckStub(assembler, left, right);
2152 __ ret(); 2140 __ ret();
2153 } 2141 }
2154 2142
2155 } // namespace dart 2143 } // namespace dart
2156 2144
2157 #endif // defined TARGET_ARCH_X64 2145 #endif // defined TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698