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

Side by Side Diff: runtime/vm/code_generator.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/code_generator.h" 5 #include "vm/code_generator.h"
6 6
7 #include "vm/assembler.h" 7 #include "vm/assembler.h"
8 #include "vm/ast.h" 8 #include "vm/ast.h"
9 #include "vm/bigint_operations.h" 9 #include "vm/bigint_operations.h"
10 #include "vm/code_patcher.h" 10 #include "vm/code_patcher.h"
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
84 // Allocation of a fixed length array of given element type. 84 // Allocation of a fixed length array of given element type.
85 // This runtime entry is never called for allocating a List of a generic type, 85 // This runtime entry is never called for allocating a List of a generic type,
86 // because a prior run time call instantiates the element type if necessary. 86 // because a prior run time call instantiates the element type if necessary.
87 // Arg0: array length. 87 // Arg0: array length.
88 // Arg1: array type arguments, i.e. vector of 1 type, the element type. 88 // Arg1: array type arguments, i.e. vector of 1 type, the element type.
89 // Return value: newly allocated array of length arg0. 89 // Return value: newly allocated array of length arg0.
90 DEFINE_RUNTIME_ENTRY(AllocateArray, 2) { 90 DEFINE_RUNTIME_ENTRY(AllocateArray, 2) {
91 const Smi& length = Smi::CheckedHandle(arguments.ArgAt(0)); 91 const Smi& length = Smi::CheckedHandle(arguments.ArgAt(0));
92 const Array& array = Array::Handle(Array::New(length.Value())); 92 const Array& array = Array::Handle(Array::New(length.Value()));
93 arguments.SetReturn(array); 93 arguments.SetReturn(array);
94 AbstractTypeArguments& element_type = 94 TypeArguments& element_type =
95 AbstractTypeArguments::CheckedHandle(arguments.ArgAt(1)); 95 TypeArguments::CheckedHandle(arguments.ArgAt(1));
96 // An Array is raw or takes one type argument. However, its type argument 96 // An Array is raw or takes one type argument. However, its type argument
97 // vector may be longer than 1 due to a type optimization reusing the type 97 // vector may be longer than 1 due to a type optimization reusing the type
98 // argument vector of the instantiator. 98 // argument vector of the instantiator.
99 ASSERT(element_type.IsNull() || 99 ASSERT(element_type.IsNull() ||
100 ((element_type.Length() >= 1) && element_type.IsInstantiated())); 100 ((element_type.Length() >= 1) && element_type.IsInstantiated()));
101 array.SetTypeArguments(element_type); // May be null. 101 array.SetTypeArguments(element_type); // May be null.
102 } 102 }
103 103
104 104
105 // Helper returning the token position of the Dart caller.
106 static intptr_t GetCallerLocation() {
107 DartFrameIterator iterator;
108 StackFrame* caller_frame = iterator.NextFrame();
109 ASSERT(caller_frame != NULL);
110 return caller_frame->GetTokenPos();
111 }
112
113
105 // Allocate a new object. 114 // Allocate a new object.
106 // Arg0: class of the object that needs to be allocated. 115 // Arg0: class of the object that needs to be allocated.
107 // Arg1: type arguments of the object that needs to be allocated. 116 // Arg1: type arguments of the object that needs to be allocated.
108 // Arg2: type arguments of the instantiator or kNoInstantiator. 117 // Arg2: type arguments of the instantiator or kNoInstantiator.
109 // Return value: newly allocated object. 118 // Return value: newly allocated object.
110 DEFINE_RUNTIME_ENTRY(AllocateObject, 3) { 119 DEFINE_RUNTIME_ENTRY(AllocateObject, 3) {
111 const Class& cls = Class::CheckedHandle(arguments.ArgAt(0)); 120 const Class& cls = Class::CheckedHandle(arguments.ArgAt(0));
112 const Instance& instance = Instance::Handle(Instance::New(cls)); 121 const Instance& instance = Instance::Handle(Instance::New(cls));
113 arguments.SetReturn(instance); 122 arguments.SetReturn(instance);
114 if (cls.NumTypeArguments() == 0) { 123 if (cls.NumTypeArguments() == 0) {
115 // No type arguments required for a non-parameterized type. 124 // No type arguments required for a non-parameterized type.
116 ASSERT(Instance::CheckedHandle(arguments.ArgAt(1)).IsNull()); 125 ASSERT(Instance::CheckedHandle(arguments.ArgAt(1)).IsNull());
117 return; 126 return;
118 } 127 }
119 AbstractTypeArguments& type_arguments = 128 TypeArguments& type_arguments =
120 AbstractTypeArguments::CheckedHandle(arguments.ArgAt(1)); 129 TypeArguments::CheckedHandle(arguments.ArgAt(1));
121 // If no instantiator is provided, set the type arguments and return. 130 // If no instantiator is provided, set the type arguments and return.
122 if (Object::Handle(arguments.ArgAt(2)).IsSmi()) { 131 if (Object::Handle(arguments.ArgAt(2)).IsSmi()) {
123 ASSERT(Smi::CheckedHandle(arguments.ArgAt(2)).Value() == 132 ASSERT(Smi::CheckedHandle(arguments.ArgAt(2)).Value() ==
124 StubCode::kNoInstantiator); 133 StubCode::kNoInstantiator);
125 // Unless null (for a raw type), the type argument vector may be longer than 134 // Unless null (for a raw type), the type argument vector may be longer than
126 // necessary due to a type optimization reusing the type argument vector of 135 // necessary due to a type optimization reusing the type argument vector of
127 // the instantiator. 136 // the instantiator.
128 ASSERT(type_arguments.IsNull() || 137 ASSERT(type_arguments.IsNull() ||
129 (type_arguments.IsInstantiated() && 138 (type_arguments.IsInstantiated() &&
130 (type_arguments.Length() >= cls.NumTypeArguments()))); 139 (type_arguments.Length() >= cls.NumTypeArguments())));
131 instance.SetTypeArguments(type_arguments); // May be null. 140 instance.SetTypeArguments(type_arguments); // May be null.
132 return; 141 return;
133 } 142 }
134 // A still uninstantiated type argument vector must have the correct length. 143 // A still uninstantiated type argument vector must have the correct length.
135 ASSERT(!type_arguments.IsInstantiated() && 144 ASSERT(!type_arguments.IsInstantiated() &&
136 (type_arguments.Length() == cls.NumTypeArguments())); 145 (type_arguments.Length() == cls.NumTypeArguments()));
137 const AbstractTypeArguments& instantiator = 146 const TypeArguments& instantiator =
138 AbstractTypeArguments::CheckedHandle(arguments.ArgAt(2)); 147 TypeArguments::CheckedHandle(arguments.ArgAt(2));
139 ASSERT(instantiator.IsNull() || instantiator.IsInstantiated()); 148 ASSERT(instantiator.IsNull() || instantiator.IsInstantiated());
140 // Code inlined in the caller should have optimized the case where the 149 // Code inlined in the caller should have optimized the case where the
141 // instantiator can be reused as type argument vector. 150 // instantiator can be reused as type argument vector.
142 ASSERT(instantiator.IsNull() || !type_arguments.IsUninstantiatedIdentity()); 151 ASSERT(instantiator.IsNull() || !type_arguments.IsUninstantiatedIdentity());
143 type_arguments = InstantiatedTypeArguments::New(type_arguments, instantiator); 152 if (FLAG_enable_type_checks) {
144 instance.SetTypeArguments(type_arguments);
145 }
146
147
148 // Helper returning the token position of the Dart caller.
149 static intptr_t GetCallerLocation() {
150 DartFrameIterator iterator;
151 StackFrame* caller_frame = iterator.NextFrame();
152 ASSERT(caller_frame != NULL);
153 return caller_frame->GetTokenPos();
154 }
155
156
157 // Allocate a new object of a generic type and check that the instantiated type
158 // arguments are within the declared bounds or throw a dynamic type error.
159 // Arg0: class of the object that needs to be allocated.
160 // Arg1: type arguments of the object that needs to be allocated.
161 // Arg2: type arguments of the instantiator or kNoInstantiator.
162 // Return value: newly allocated object.
163 DEFINE_RUNTIME_ENTRY(AllocateObjectWithBoundsCheck, 3) {
164 ASSERT(FLAG_enable_type_checks);
165 const Class& cls = Class::CheckedHandle(arguments.ArgAt(0));
166 const Instance& instance = Instance::Handle(Instance::New(cls));
167 arguments.SetReturn(instance);
168 ASSERT(cls.NumTypeArguments() > 0);
169 AbstractTypeArguments& type_arguments =
170 AbstractTypeArguments::CheckedHandle(arguments.ArgAt(1));
171 if (Object::Handle(arguments.ArgAt(2)).IsSmi()) {
172 ASSERT(Smi::CheckedHandle(arguments.ArgAt(2)).Value() ==
173 StubCode::kNoInstantiator);
174 // Unless null (for a raw type), the type argument vector may be longer than
175 // necessary due to a type optimization reusing the type argument vector of
176 // the instantiator.
177 ASSERT(type_arguments.IsNull() ||
178 (type_arguments.IsInstantiated() &&
179 (type_arguments.Length() >= cls.NumTypeArguments())));
180 } else {
181 // A still uninstantiated type argument vector must have the correct length.
182 ASSERT(!type_arguments.IsInstantiated() &&
183 (type_arguments.Length() == cls.NumTypeArguments()));
184 const AbstractTypeArguments& instantiator =
185 AbstractTypeArguments::CheckedHandle(arguments.ArgAt(2));
186 ASSERT(instantiator.IsNull() || instantiator.IsInstantiated());
187 Error& bound_error = Error::Handle(); 153 Error& bound_error = Error::Handle();
188 // Code inlined in the caller should have optimized the case where the 154 type_arguments =
189 // instantiator can be reused as type argument vector. 155 type_arguments.InstantiateAndCanonicalizeFrom(instantiator,
190 ASSERT(instantiator.IsNull() || !type_arguments.IsUninstantiatedIdentity()); 156 &bound_error);
191 type_arguments = type_arguments.InstantiateFrom(instantiator, &bound_error);
192 if (!bound_error.IsNull()) { 157 if (!bound_error.IsNull()) {
193 // Throw a dynamic type error. 158 // Throw a dynamic type error.
194 const intptr_t location = GetCallerLocation(); 159 const intptr_t location = GetCallerLocation();
195 String& bound_error_message = String::Handle( 160 String& bound_error_message = String::Handle(
196 String::New(bound_error.ToErrorCString())); 161 String::New(bound_error.ToErrorCString()));
197 Exceptions::CreateAndThrowTypeError( 162 Exceptions::CreateAndThrowTypeError(
198 location, Symbols::Empty(), Symbols::Empty(), 163 location, Symbols::Empty(), Symbols::Empty(),
199 Symbols::Empty(), bound_error_message); 164 Symbols::Empty(), bound_error_message);
200 UNREACHABLE(); 165 UNREACHABLE();
201 } 166 }
167 } else {
168 type_arguments =
169 type_arguments.InstantiateAndCanonicalizeFrom(instantiator, NULL);
202 } 170 }
203 ASSERT(type_arguments.IsNull() || type_arguments.IsInstantiated()); 171 ASSERT(type_arguments.IsNull() || type_arguments.IsInstantiated());
204 instance.SetTypeArguments(type_arguments); 172 instance.SetTypeArguments(type_arguments);
205 } 173 }
206 174
207 175
208 // Instantiate type. 176 // Instantiate type.
209 // Arg0: uninstantiated type. 177 // Arg0: uninstantiated type.
210 // Arg1: instantiator type arguments. 178 // Arg1: instantiator type arguments.
211 // Return value: instantiated type. 179 // Return value: instantiated type.
212 DEFINE_RUNTIME_ENTRY(InstantiateType, 2) { 180 DEFINE_RUNTIME_ENTRY(InstantiateType, 2) {
213 AbstractType& type = AbstractType::CheckedHandle(arguments.ArgAt(0)); 181 AbstractType& type = AbstractType::CheckedHandle(arguments.ArgAt(0));
214 const AbstractTypeArguments& instantiator = 182 const TypeArguments& instantiator =
215 AbstractTypeArguments::CheckedHandle(arguments.ArgAt(1)); 183 TypeArguments::CheckedHandle(arguments.ArgAt(1));
216 ASSERT(!type.IsNull() && !type.IsInstantiated()); 184 ASSERT(!type.IsNull() && !type.IsInstantiated());
217 ASSERT(instantiator.IsNull() || instantiator.IsInstantiated()); 185 ASSERT(instantiator.IsNull() || instantiator.IsInstantiated());
218 Error& bound_error = Error::Handle(); 186 Error& bound_error = Error::Handle();
219 type = type.InstantiateFrom(instantiator, &bound_error); 187 type = type.InstantiateFrom(instantiator, &bound_error);
220 if (!bound_error.IsNull()) { 188 if (!bound_error.IsNull()) {
221 // Throw a dynamic type error. 189 // Throw a dynamic type error.
222 const intptr_t location = GetCallerLocation(); 190 const intptr_t location = GetCallerLocation();
223 String& bound_error_message = String::Handle( 191 String& bound_error_message = String::Handle(
224 String::New(bound_error.ToErrorCString())); 192 String::New(bound_error.ToErrorCString()));
225 Exceptions::CreateAndThrowTypeError( 193 Exceptions::CreateAndThrowTypeError(
226 location, Symbols::Empty(), Symbols::Empty(), 194 location, Symbols::Empty(), Symbols::Empty(),
227 Symbols::Empty(), bound_error_message); 195 Symbols::Empty(), bound_error_message);
228 UNREACHABLE(); 196 UNREACHABLE();
229 } 197 }
230 if (type.IsTypeRef()) { 198 if (type.IsTypeRef()) {
231 type = TypeRef::Cast(type).type(); 199 type = TypeRef::Cast(type).type();
232 ASSERT(!type.IsTypeRef()); 200 ASSERT(!type.IsTypeRef());
233 ASSERT(type.IsCanonical()); 201 ASSERT(type.IsCanonical());
234 } 202 }
235 ASSERT(!type.IsNull() && type.IsInstantiated()); 203 ASSERT(!type.IsNull() && type.IsInstantiated());
236 arguments.SetReturn(type); 204 arguments.SetReturn(type);
237 } 205 }
238 206
239 207
240 // Instantiate type arguments. 208 // Instantiate type arguments.
241 // Arg0: uninstantiated type arguments. 209 // Arg0: uninstantiated type arguments.
242 // Arg1: instantiator type arguments. 210 // Arg1: instantiator type arguments.
243 // Return value: instantiated type arguments. 211 // Return value: instantiated type arguments.
244 DEFINE_RUNTIME_ENTRY(InstantiateTypeArguments, 2) { 212 DEFINE_RUNTIME_ENTRY(InstantiateTypeArguments, 2) {
245 AbstractTypeArguments& type_arguments = 213 TypeArguments& type_arguments =
246 AbstractTypeArguments::CheckedHandle(arguments.ArgAt(0)); 214 TypeArguments::CheckedHandle(arguments.ArgAt(0));
247 const AbstractTypeArguments& instantiator = 215 const TypeArguments& instantiator =
248 AbstractTypeArguments::CheckedHandle(arguments.ArgAt(1)); 216 TypeArguments::CheckedHandle(arguments.ArgAt(1));
249 ASSERT(!type_arguments.IsNull() && !type_arguments.IsInstantiated()); 217 ASSERT(!type_arguments.IsNull() && !type_arguments.IsInstantiated());
250 ASSERT(instantiator.IsNull() || instantiator.IsInstantiated()); 218 ASSERT(instantiator.IsNull() || instantiator.IsInstantiated());
251 // Code inlined in the caller should have optimized the case where the 219 // Code inlined in the caller should have optimized the case where the
252 // instantiator can be reused as type argument vector. 220 // instantiator can be reused as type argument vector.
253 ASSERT(instantiator.IsNull() || !type_arguments.IsUninstantiatedIdentity()); 221 ASSERT(instantiator.IsNull() || !type_arguments.IsUninstantiatedIdentity());
254 type_arguments = InstantiatedTypeArguments::New(type_arguments, instantiator); 222 type_arguments =
223 type_arguments.InstantiateAndCanonicalizeFrom(instantiator, NULL);
255 ASSERT(type_arguments.IsInstantiated()); 224 ASSERT(type_arguments.IsInstantiated());
256 arguments.SetReturn(type_arguments); 225 arguments.SetReturn(type_arguments);
257 } 226 }
258 227
259 228
260 // Allocate a new closure. 229 // Allocate a new closure.
261 // The type argument vector of a closure is always the vector of type parameters 230 // The type argument vector of a closure is always the vector of type parameters
262 // of its signature class, i.e. an uninstantiated identity vector. Therefore, 231 // of its signature class, i.e. an uninstantiated identity vector. Therefore,
263 // the instantiator type arguments can be used as the instantiated closure type 232 // the instantiator type arguments can be used as the instantiated closure type
264 // arguments and is passed here as the type arguments. 233 // arguments and is passed here as the type arguments.
265 // Arg0: local function. 234 // Arg0: local function.
266 // Arg1: type arguments of the closure (i.e. instantiator). 235 // Arg1: type arguments of the closure (i.e. instantiator).
267 // Return value: newly allocated closure. 236 // Return value: newly allocated closure.
268 DEFINE_RUNTIME_ENTRY(AllocateClosure, 2) { 237 DEFINE_RUNTIME_ENTRY(AllocateClosure, 2) {
269 const Function& function = Function::CheckedHandle(arguments.ArgAt(0)); 238 const Function& function = Function::CheckedHandle(arguments.ArgAt(0));
270 ASSERT(function.IsClosureFunction() && !function.IsImplicitClosureFunction()); 239 ASSERT(function.IsClosureFunction() && !function.IsImplicitClosureFunction());
271 const AbstractTypeArguments& type_arguments = 240 const TypeArguments& type_arguments =
272 AbstractTypeArguments::CheckedHandle(arguments.ArgAt(1)); 241 TypeArguments::CheckedHandle(arguments.ArgAt(1));
273 ASSERT(type_arguments.IsNull() || type_arguments.IsInstantiated()); 242 ASSERT(type_arguments.IsNull() || type_arguments.IsInstantiated());
274 // The current context was saved in the Isolate structure when entering the 243 // The current context was saved in the Isolate structure when entering the
275 // runtime. 244 // runtime.
276 const Context& context = Context::Handle(isolate->top_context()); 245 const Context& context = Context::Handle(isolate->top_context());
277 ASSERT(!context.IsNull()); 246 ASSERT(!context.IsNull());
278 const Instance& closure = Instance::Handle(Closure::New(function, context)); 247 const Instance& closure = Instance::Handle(Closure::New(function, context));
279 Closure::SetTypeArguments(closure, type_arguments); 248 Closure::SetTypeArguments(closure, type_arguments);
280 arguments.SetReturn(closure); 249 arguments.SetReturn(closure);
281 } 250 }
282 251
283 252
284 // Allocate a new implicit instance closure. 253 // Allocate a new implicit instance closure.
285 // Arg0: local function. 254 // Arg0: local function.
286 // Arg1: receiver object. 255 // Arg1: receiver object.
287 // Arg2: type arguments of the closure. 256 // Arg2: type arguments of the closure.
288 // Return value: newly allocated closure. 257 // Return value: newly allocated closure.
289 DEFINE_RUNTIME_ENTRY(AllocateImplicitInstanceClosure, 3) { 258 DEFINE_RUNTIME_ENTRY(AllocateImplicitInstanceClosure, 3) {
290 const Function& function = Function::CheckedHandle(arguments.ArgAt(0)); 259 const Function& function = Function::CheckedHandle(arguments.ArgAt(0));
291 ASSERT(function.IsImplicitInstanceClosureFunction()); 260 ASSERT(function.IsImplicitInstanceClosureFunction());
292 const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(1)); 261 const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(1));
293 const AbstractTypeArguments& type_arguments = 262 const TypeArguments& type_arguments =
294 AbstractTypeArguments::CheckedHandle(arguments.ArgAt(2)); 263 TypeArguments::CheckedHandle(arguments.ArgAt(2));
295 ASSERT(type_arguments.IsNull() || type_arguments.IsInstantiated()); 264 ASSERT(type_arguments.IsNull() || type_arguments.IsInstantiated());
296 Context& context = Context::Handle(); 265 Context& context = Context::Handle();
297 context = Context::New(1); 266 context = Context::New(1);
298 context.SetAt(0, receiver); 267 context.SetAt(0, receiver);
299 const Instance& closure = Instance::Handle(Closure::New(function, context)); 268 const Instance& closure = Instance::Handle(Closure::New(function, context));
300 Closure::SetTypeArguments(closure, type_arguments); 269 Closure::SetTypeArguments(closure, type_arguments);
301 arguments.SetReturn(closure); 270 arguments.SetReturn(closure);
302 } 271 }
303 272
304 273
(...skipping 19 matching lines...) Expand all
324 } 293 }
325 arguments.SetReturn(cloned_ctx); 294 arguments.SetReturn(cloned_ctx);
326 } 295 }
327 296
328 297
329 // Helper routine for tracing a type check. 298 // Helper routine for tracing a type check.
330 static void PrintTypeCheck( 299 static void PrintTypeCheck(
331 const char* message, 300 const char* message,
332 const Instance& instance, 301 const Instance& instance,
333 const AbstractType& type, 302 const AbstractType& type,
334 const AbstractTypeArguments& instantiator_type_arguments, 303 const TypeArguments& instantiator_type_arguments,
335 const Bool& result) { 304 const Bool& result) {
336 DartFrameIterator iterator; 305 DartFrameIterator iterator;
337 StackFrame* caller_frame = iterator.NextFrame(); 306 StackFrame* caller_frame = iterator.NextFrame();
338 ASSERT(caller_frame != NULL); 307 ASSERT(caller_frame != NULL);
339 308
340 const Type& instance_type = Type::Handle(instance.GetType()); 309 const Type& instance_type = Type::Handle(instance.GetType());
341 ASSERT(instance_type.IsInstantiated()); 310 ASSERT(instance_type.IsInstantiated());
342 if (type.IsInstantiated()) { 311 if (type.IsInstantiated()) {
343 OS::PrintErr("%s: '%s' %" Pd " %s '%s' %" Pd " (pc: %#" Px ").\n", 312 OS::PrintErr("%s: '%s' %" Pd " %s '%s' %" Pd " (pc: %#" Px ").\n",
344 message, 313 message,
(...skipping 18 matching lines...) Expand all
363 if (!bound_error.IsNull()) { 332 if (!bound_error.IsNull()) {
364 OS::Print(" bound error: %s\n", bound_error.ToErrorCString()); 333 OS::Print(" bound error: %s\n", bound_error.ToErrorCString());
365 } 334 }
366 } 335 }
367 const Function& function = Function::Handle( 336 const Function& function = Function::Handle(
368 caller_frame->LookupDartFunction()); 337 caller_frame->LookupDartFunction());
369 OS::PrintErr(" -> Function %s\n", function.ToFullyQualifiedCString()); 338 OS::PrintErr(" -> Function %s\n", function.ToFullyQualifiedCString());
370 } 339 }
371 340
372 341
373 // Converts InstantiatedTypeArguments to TypeArguments and stores it
374 // into the instance. The assembly code can handle only type arguments of
375 // class TypeArguments. Because of the overhead, do it only when needed.
376 // Return true if type arguments have been replaced, false otherwise.
377 static bool OptimizeTypeArguments(const Instance& instance) {
378 const Class& type_class = Class::ZoneHandle(instance.clazz());
379 if (type_class.NumTypeArguments() == 0) {
380 return false;
381 }
382 AbstractTypeArguments& type_arguments =
383 AbstractTypeArguments::Handle(instance.GetTypeArguments());
384 if (type_arguments.IsNull()) {
385 return false;
386 }
387 bool replaced = false;
388 if (type_arguments.IsInstantiatedTypeArguments()) {
389 AbstractTypeArguments& uninstantiated = AbstractTypeArguments::Handle();
390 AbstractTypeArguments& instantiator = AbstractTypeArguments::Handle();
391 do {
392 const InstantiatedTypeArguments& instantiated_type_arguments =
393 InstantiatedTypeArguments::Cast(type_arguments);
394 uninstantiated =
395 instantiated_type_arguments.uninstantiated_type_arguments();
396 instantiator = instantiated_type_arguments.instantiator_type_arguments();
397 Error& bound_error = Error::Handle();
398 type_arguments = uninstantiated.InstantiateFrom(instantiator,
399 &bound_error);
400 ASSERT(bound_error.IsNull()); // Malbounded types are not optimized.
401 } while (type_arguments.IsInstantiatedTypeArguments());
402 AbstractTypeArguments& new_type_arguments = AbstractTypeArguments::Handle();
403 new_type_arguments = type_arguments.Canonicalize();
404 instance.SetTypeArguments(new_type_arguments);
405 replaced = true;
406 } else if (!type_arguments.IsCanonical()) {
407 AbstractTypeArguments& new_type_arguments = AbstractTypeArguments::Handle();
408 new_type_arguments = type_arguments.Canonicalize();
409 instance.SetTypeArguments(new_type_arguments);
410 replaced = true;
411 }
412 ASSERT(AbstractTypeArguments::Handle(
413 instance.GetTypeArguments()).IsTypeArguments());
414 return replaced;
415 }
416
417
418 // This updates the type test cache, an array containing 4-value elements 342 // This updates the type test cache, an array containing 4-value elements
419 // (instance class, instance type arguments, instantiator type arguments and 343 // (instance class, instance type arguments, instantiator type arguments and
420 // test_result). It can be applied to classes with type arguments in which 344 // test_result). It can be applied to classes with type arguments in which
421 // case it contains just the result of the class subtype test, not including 345 // case it contains just the result of the class subtype test, not including
422 // the evaluation of type arguments. 346 // the evaluation of type arguments.
423 // This operation is currently very slow (lookup of code is not efficient yet). 347 // This operation is currently very slow (lookup of code is not efficient yet).
424 // 'instantiator' can be null, in which case inst_targ 348 // 'instantiator' can be null, in which case inst_targ
425 static void UpdateTypeTestCache( 349 static void UpdateTypeTestCache(
426 const Instance& instance, 350 const Instance& instance,
427 const AbstractType& type, 351 const AbstractType& type,
428 const Instance& instantiator, 352 const Instance& instantiator,
429 const AbstractTypeArguments& incoming_instantiator_type_arguments, 353 const TypeArguments& instantiator_type_arguments,
430 const Bool& result, 354 const Bool& result,
431 const SubtypeTestCache& new_cache) { 355 const SubtypeTestCache& new_cache) {
432 // Since the test is expensive, don't do it unless necessary. 356 // Since the test is expensive, don't do it unless necessary.
433 // The list of disallowed cases will decrease as they are implemented in 357 // The list of disallowed cases will decrease as they are implemented in
434 // inlined assembly. 358 // inlined assembly.
435 if (new_cache.IsNull()) { 359 if (new_cache.IsNull()) {
436 if (FLAG_trace_type_checks) { 360 if (FLAG_trace_type_checks) {
437 OS::Print("UpdateTypeTestCache: cache is null\n"); 361 OS::Print("UpdateTypeTestCache: cache is null\n");
438 } 362 }
439 return; 363 return;
440 } 364 }
441 // Instantiator type arguments may be canonicalized later. 365 if (instance.IsSmi()) {
442 AbstractTypeArguments& instantiator_type_arguments = 366 if (FLAG_trace_type_checks) {
443 AbstractTypeArguments::Handle(incoming_instantiator_type_arguments.raw()); 367 OS::Print("UpdateTypeTestCache: instance is Smi\n");
444 AbstractTypeArguments& instance_type_arguments = 368 }
445 AbstractTypeArguments::Handle(); 369 return;
370 }
371 TypeArguments& instance_type_arguments =
372 TypeArguments::Handle();
srdjan 2014/02/07 21:59:47 This should fit on one line.
446 const Class& instance_class = Class::Handle(instance.clazz()); 373 const Class& instance_class = Class::Handle(instance.clazz());
447 374
448 // Canonicalize type arguments.
449 bool type_arguments_replaced = false;
450 if (instance_class.NumTypeArguments() > 0) { 375 if (instance_class.NumTypeArguments() > 0) {
451 // Canonicalize type arguments.
452 type_arguments_replaced = OptimizeTypeArguments(instance);
453 instance_type_arguments = instance.GetTypeArguments(); 376 instance_type_arguments = instance.GetTypeArguments();
454 } 377 }
455 if (!instantiator.IsNull()) {
456 if (OptimizeTypeArguments(instantiator)) {
457 type_arguments_replaced = true;
458 }
459 instantiator_type_arguments = instantiator.GetTypeArguments();
460 }
461 378
462 intptr_t last_instance_class_id = -1;
463 AbstractTypeArguments& last_instance_type_arguments =
464 AbstractTypeArguments::Handle();
465 AbstractTypeArguments& last_instantiator_type_arguments =
466 AbstractTypeArguments::Handle();
467 Bool& last_result = Bool::Handle();
468 const intptr_t len = new_cache.NumberOfChecks(); 379 const intptr_t len = new_cache.NumberOfChecks();
469 if (len >= FLAG_max_subtype_cache_entries) { 380 if (len >= FLAG_max_subtype_cache_entries) {
470 return; 381 return;
471 } 382 }
383 #if defined(DEBUG)
384 ASSERT(instance_type_arguments.IsNull() ||
385 instance_type_arguments.IsCanonical());
386 ASSERT(instantiator_type_arguments.IsNull() ||
387 instantiator_type_arguments.IsCanonical());
388 intptr_t last_instance_class_id = -1;
389 TypeArguments& last_instance_type_arguments =
390 TypeArguments::Handle();
391 TypeArguments& last_instantiator_type_arguments =
392 TypeArguments::Handle();
393 Bool& last_result = Bool::Handle();
472 for (intptr_t i = 0; i < len; ++i) { 394 for (intptr_t i = 0; i < len; ++i) {
473 new_cache.GetCheck( 395 new_cache.GetCheck(
474 i, 396 i,
475 &last_instance_class_id, 397 &last_instance_class_id,
476 &last_instance_type_arguments, 398 &last_instance_type_arguments,
477 &last_instantiator_type_arguments, 399 &last_instantiator_type_arguments,
478 &last_result); 400 &last_result);
479 if ((last_instance_class_id == instance_class.id()) && 401 if ((last_instance_class_id == instance_class.id()) &&
480 (last_instance_type_arguments.raw() == instance_type_arguments.raw()) && 402 (last_instance_type_arguments.raw() == instance_type_arguments.raw()) &&
481 (last_instantiator_type_arguments.raw() == 403 (last_instantiator_type_arguments.raw() ==
482 instantiator_type_arguments.raw())) { 404 instantiator_type_arguments.raw())) {
483 if (FLAG_trace_type_checks) { 405 OS::PrintErr(" Error in test cache %p ix: %" Pd ",", new_cache.raw(), i);
484 OS::PrintErr("%" Pd " ", i); 406 PrintTypeCheck(" duplicate cache entry", instance, type,
485 if (type_arguments_replaced) { 407 instantiator_type_arguments, result);
486 PrintTypeCheck("Duplicate cache entry (canonical.)", instance, type, 408 UNREACHABLE();
487 instantiator_type_arguments, result);
488 } else {
489 PrintTypeCheck("WARNING Duplicate cache entry", instance, type,
490 instantiator_type_arguments, result);
491 }
492 }
493 // Can occur if we have canonicalized arguments.
494 // TODO(srdjan): Investigate why this assert can fail.
495 // ASSERT(type_arguments_replaced);
496 return; 409 return;
497 } 410 }
498 } 411 }
499 if (!instantiator_type_arguments.IsInstantiatedTypeArguments()) { 412 #endif
500 new_cache.AddCheck(instance_class.id(), 413 new_cache.AddCheck(instance_class.id(),
501 instance_type_arguments, 414 instance_type_arguments,
502 instantiator_type_arguments, 415 instantiator_type_arguments,
503 result); 416 result);
504 }
505 if (FLAG_trace_type_checks) { 417 if (FLAG_trace_type_checks) {
506 AbstractType& test_type = AbstractType::Handle(type.raw()); 418 AbstractType& test_type = AbstractType::Handle(type.raw());
507 if (!test_type.IsInstantiated()) { 419 if (!test_type.IsInstantiated()) {
508 Error& bound_error = Error::Handle(); 420 Error& bound_error = Error::Handle();
509 test_type = type.InstantiateFrom(instantiator_type_arguments, 421 test_type = type.InstantiateFrom(instantiator_type_arguments,
510 &bound_error); 422 &bound_error);
511 ASSERT(bound_error.IsNull()); // Malbounded types are not optimized. 423 ASSERT(bound_error.IsNull()); // Malbounded types are not optimized.
512 } 424 }
513 OS::PrintErr(" Updated test cache %p ix: %" Pd " with " 425 OS::PrintErr(" Updated test cache %p ix: %" Pd " with "
514 "(cid: %" Pd ", type-args: %p, instantiator: %p, result: %s)\n" 426 "(cid: %" Pd ", type-args: %p, instantiator: %p, result: %s)\n"
(...skipping 28 matching lines...) Expand all
543 // Arg0: instance being checked. 455 // Arg0: instance being checked.
544 // Arg1: type. 456 // Arg1: type.
545 // Arg2: instantiator (or null). 457 // Arg2: instantiator (or null).
546 // Arg3: type arguments of the instantiator of the type. 458 // Arg3: type arguments of the instantiator of the type.
547 // Arg4: SubtypeTestCache. 459 // Arg4: SubtypeTestCache.
548 // Return value: true or false, or may throw a type error in checked mode. 460 // Return value: true or false, or may throw a type error in checked mode.
549 DEFINE_RUNTIME_ENTRY(Instanceof, 5) { 461 DEFINE_RUNTIME_ENTRY(Instanceof, 5) {
550 const Instance& instance = Instance::CheckedHandle(arguments.ArgAt(0)); 462 const Instance& instance = Instance::CheckedHandle(arguments.ArgAt(0));
551 const AbstractType& type = AbstractType::CheckedHandle(arguments.ArgAt(1)); 463 const AbstractType& type = AbstractType::CheckedHandle(arguments.ArgAt(1));
552 const Instance& instantiator = Instance::CheckedHandle(arguments.ArgAt(2)); 464 const Instance& instantiator = Instance::CheckedHandle(arguments.ArgAt(2));
553 const AbstractTypeArguments& instantiator_type_arguments = 465 const TypeArguments& instantiator_type_arguments =
554 AbstractTypeArguments::CheckedHandle(arguments.ArgAt(3)); 466 TypeArguments::CheckedHandle(arguments.ArgAt(3));
555 const SubtypeTestCache& cache = 467 const SubtypeTestCache& cache =
556 SubtypeTestCache::CheckedHandle(arguments.ArgAt(4)); 468 SubtypeTestCache::CheckedHandle(arguments.ArgAt(4));
557 ASSERT(type.IsFinalized()); 469 ASSERT(type.IsFinalized());
558 ASSERT(!type.IsDynamicType()); // No need to check assignment. 470 ASSERT(!type.IsDynamicType()); // No need to check assignment.
559 ASSERT(!type.IsMalformed()); // Already checked in code generator. 471 ASSERT(!type.IsMalformed()); // Already checked in code generator.
560 ASSERT(!type.IsMalbounded()); // Already checked in code generator. 472 ASSERT(!type.IsMalbounded()); // Already checked in code generator.
561 Error& bound_error = Error::Handle(); 473 Error& bound_error = Error::Handle();
562 const Bool& result = 474 const Bool& result =
563 Bool::Get(instance.IsInstanceOf(type, 475 Bool::Get(instance.IsInstanceOf(type,
564 instantiator_type_arguments, 476 instantiator_type_arguments,
(...skipping 26 matching lines...) Expand all
591 // Arg3: type arguments of the instantiator of the type being assigned to. 503 // Arg3: type arguments of the instantiator of the type being assigned to.
592 // Arg4: name of variable being assigned to. 504 // Arg4: name of variable being assigned to.
593 // Arg5: SubtypeTestCache. 505 // Arg5: SubtypeTestCache.
594 // Return value: instance if a subtype, otherwise throw a TypeError. 506 // Return value: instance if a subtype, otherwise throw a TypeError.
595 DEFINE_RUNTIME_ENTRY(TypeCheck, 6) { 507 DEFINE_RUNTIME_ENTRY(TypeCheck, 6) {
596 const Instance& src_instance = Instance::CheckedHandle(arguments.ArgAt(0)); 508 const Instance& src_instance = Instance::CheckedHandle(arguments.ArgAt(0));
597 const AbstractType& dst_type = 509 const AbstractType& dst_type =
598 AbstractType::CheckedHandle(arguments.ArgAt(1)); 510 AbstractType::CheckedHandle(arguments.ArgAt(1));
599 const Instance& dst_instantiator = 511 const Instance& dst_instantiator =
600 Instance::CheckedHandle(arguments.ArgAt(2)); 512 Instance::CheckedHandle(arguments.ArgAt(2));
601 const AbstractTypeArguments& instantiator_type_arguments = 513 const TypeArguments& instantiator_type_arguments =
602 AbstractTypeArguments::CheckedHandle(arguments.ArgAt(3)); 514 TypeArguments::CheckedHandle(arguments.ArgAt(3));
603 const String& dst_name = String::CheckedHandle(arguments.ArgAt(4)); 515 const String& dst_name = String::CheckedHandle(arguments.ArgAt(4));
604 const SubtypeTestCache& cache = 516 const SubtypeTestCache& cache =
605 SubtypeTestCache::CheckedHandle(arguments.ArgAt(5)); 517 SubtypeTestCache::CheckedHandle(arguments.ArgAt(5));
606 ASSERT(!dst_type.IsDynamicType()); // No need to check assignment. 518 ASSERT(!dst_type.IsDynamicType()); // No need to check assignment.
607 ASSERT(!dst_type.IsMalformed()); // Already checked in code generator. 519 ASSERT(!dst_type.IsMalformed()); // Already checked in code generator.
608 ASSERT(!dst_type.IsMalbounded()); // Already checked in code generator. 520 ASSERT(!dst_type.IsMalbounded()); // Already checked in code generator.
609 ASSERT(!src_instance.IsNull()); // Already checked in inlined code. 521 ASSERT(!src_instance.IsNull()); // Already checked in inlined code.
610 522
611 Error& bound_error = Error::Handle(); 523 Error& bound_error = Error::Handle();
612 const bool is_instance_of = src_instance.IsInstanceOf( 524 const bool is_instance_of = src_instance.IsInstanceOf(
(...skipping 1074 matching lines...) Expand 10 before | Expand all | Expand 10 after
1687 // of the given value. 1599 // of the given value.
1688 // Arg0: Field object; 1600 // Arg0: Field object;
1689 // Arg1: Value that is being stored. 1601 // Arg1: Value that is being stored.
1690 DEFINE_RUNTIME_ENTRY(UpdateFieldCid, 2) { 1602 DEFINE_RUNTIME_ENTRY(UpdateFieldCid, 2) {
1691 const Field& field = Field::CheckedHandle(arguments.ArgAt(0)); 1603 const Field& field = Field::CheckedHandle(arguments.ArgAt(0));
1692 const Object& value = Object::Handle(arguments.ArgAt(1)); 1604 const Object& value = Object::Handle(arguments.ArgAt(1));
1693 field.UpdateGuardedCidAndLength(value); 1605 field.UpdateGuardedCidAndLength(value);
1694 } 1606 }
1695 1607
1696 } // namespace dart 1608 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698