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/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/code_patcher.h" | 9 #include "vm/code_patcher.h" |
10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
227 ASSERT(type_arguments.IsNull() || | 227 ASSERT(type_arguments.IsNull() || |
228 (type_arguments.IsInstantiated() && | 228 (type_arguments.IsInstantiated() && |
229 (type_arguments.Length() >= cls.NumTypeArguments()))); | 229 (type_arguments.Length() >= cls.NumTypeArguments()))); |
230 instance.SetTypeArguments(type_arguments); | 230 instance.SetTypeArguments(type_arguments); |
231 } | 231 } |
232 | 232 |
233 | 233 |
234 // Instantiate type. | 234 // Instantiate type. |
235 // Arg0: uninstantiated type. | 235 // Arg0: uninstantiated type. |
236 // Arg1: instantiator type arguments. | 236 // Arg1: instantiator type arguments. |
| 237 // Arg2: function type arguments. |
237 // Return value: instantiated type. | 238 // Return value: instantiated type. |
238 DEFINE_RUNTIME_ENTRY(InstantiateType, 2) { | 239 DEFINE_RUNTIME_ENTRY(InstantiateType, 3) { |
239 AbstractType& type = AbstractType::CheckedHandle(zone, arguments.ArgAt(0)); | 240 AbstractType& type = AbstractType::CheckedHandle(zone, arguments.ArgAt(0)); |
240 const TypeArguments& instantiator = | 241 const TypeArguments& instantiator_type_arguments = |
241 TypeArguments::CheckedHandle(zone, arguments.ArgAt(1)); | 242 TypeArguments::CheckedHandle(zone, arguments.ArgAt(1)); |
| 243 const TypeArguments& function_type_arguments = |
| 244 TypeArguments::CheckedHandle(zone, arguments.ArgAt(2)); |
242 ASSERT(!type.IsNull() && !type.IsInstantiated()); | 245 ASSERT(!type.IsNull() && !type.IsInstantiated()); |
243 ASSERT(instantiator.IsNull() || instantiator.IsInstantiated()); | 246 ASSERT(instantiator_type_arguments.IsNull() || |
| 247 instantiator_type_arguments.IsInstantiated()); |
| 248 ASSERT(function_type_arguments.IsNull() || |
| 249 function_type_arguments.IsInstantiated()); |
244 Error& bound_error = Error::Handle(zone); | 250 Error& bound_error = Error::Handle(zone); |
245 type = | 251 type = |
246 type.InstantiateFrom(instantiator, &bound_error, NULL, NULL, Heap::kOld); | 252 type.InstantiateFrom(instantiator_type_arguments, function_type_arguments, |
| 253 &bound_error, NULL, NULL, Heap::kOld); |
247 if (!bound_error.IsNull()) { | 254 if (!bound_error.IsNull()) { |
248 // Throw a dynamic type error. | 255 // Throw a dynamic type error. |
249 const TokenPosition location = GetCallerLocation(); | 256 const TokenPosition location = GetCallerLocation(); |
250 String& bound_error_message = | 257 String& bound_error_message = |
251 String::Handle(zone, String::New(bound_error.ToErrorCString())); | 258 String::Handle(zone, String::New(bound_error.ToErrorCString())); |
252 Exceptions::CreateAndThrowTypeError(location, AbstractType::Handle(zone), | 259 Exceptions::CreateAndThrowTypeError(location, AbstractType::Handle(zone), |
253 AbstractType::Handle(zone), | 260 AbstractType::Handle(zone), |
254 Symbols::Empty(), bound_error_message); | 261 Symbols::Empty(), bound_error_message); |
255 UNREACHABLE(); | 262 UNREACHABLE(); |
256 } | 263 } |
257 if (type.IsTypeRef()) { | 264 if (type.IsTypeRef()) { |
258 type = TypeRef::Cast(type).type(); | 265 type = TypeRef::Cast(type).type(); |
259 ASSERT(!type.IsTypeRef()); | 266 ASSERT(!type.IsTypeRef()); |
260 ASSERT(type.IsCanonical()); | 267 ASSERT(type.IsCanonical()); |
261 } | 268 } |
262 ASSERT(!type.IsNull() && type.IsInstantiated()); | 269 ASSERT(!type.IsNull() && type.IsInstantiated()); |
263 arguments.SetReturn(type); | 270 arguments.SetReturn(type); |
264 } | 271 } |
265 | 272 |
266 | 273 |
267 // Instantiate type arguments. | 274 // Instantiate type arguments. |
268 // Arg0: uninstantiated type arguments. | 275 // Arg0: uninstantiated type arguments. |
269 // Arg1: instantiator type arguments. | 276 // Arg1: instantiator type arguments. |
| 277 // Arg2: function type arguments. |
270 // Return value: instantiated type arguments. | 278 // Return value: instantiated type arguments. |
271 DEFINE_RUNTIME_ENTRY(InstantiateTypeArguments, 2) { | 279 DEFINE_RUNTIME_ENTRY(InstantiateTypeArguments, 3) { |
272 TypeArguments& type_arguments = | 280 TypeArguments& type_arguments = |
273 TypeArguments::CheckedHandle(zone, arguments.ArgAt(0)); | 281 TypeArguments::CheckedHandle(zone, arguments.ArgAt(0)); |
274 const TypeArguments& instantiator = | 282 const TypeArguments& instantiator_type_arguments = |
275 TypeArguments::CheckedHandle(zone, arguments.ArgAt(1)); | 283 TypeArguments::CheckedHandle(zone, arguments.ArgAt(1)); |
| 284 const TypeArguments& function_type_arguments = |
| 285 TypeArguments::CheckedHandle(zone, arguments.ArgAt(2)); |
276 ASSERT(!type_arguments.IsNull() && !type_arguments.IsInstantiated()); | 286 ASSERT(!type_arguments.IsNull() && !type_arguments.IsInstantiated()); |
277 ASSERT(instantiator.IsNull() || instantiator.IsInstantiated()); | 287 ASSERT(instantiator_type_arguments.IsNull() || |
| 288 instantiator_type_arguments.IsInstantiated()); |
| 289 ASSERT(function_type_arguments.IsNull() || |
| 290 function_type_arguments.IsInstantiated()); |
278 // Code inlined in the caller should have optimized the case where the | 291 // Code inlined in the caller should have optimized the case where the |
279 // instantiator can be reused as type argument vector. | 292 // instantiator can be reused as type argument vector. |
280 ASSERT(!type_arguments.IsUninstantiatedIdentity()); | 293 ASSERT(!type_arguments.IsUninstantiatedIdentity()); |
281 if (isolate->type_checks()) { | 294 if (isolate->type_checks()) { |
282 Error& bound_error = Error::Handle(zone); | 295 Error& bound_error = Error::Handle(zone); |
283 type_arguments = type_arguments.InstantiateAndCanonicalizeFrom( | 296 type_arguments = type_arguments.InstantiateAndCanonicalizeFrom( |
284 instantiator, &bound_error); | 297 instantiator_type_arguments, function_type_arguments, &bound_error); |
285 if (!bound_error.IsNull()) { | 298 if (!bound_error.IsNull()) { |
286 // Throw a dynamic type error. | 299 // Throw a dynamic type error. |
287 const TokenPosition location = GetCallerLocation(); | 300 const TokenPosition location = GetCallerLocation(); |
288 String& bound_error_message = | 301 String& bound_error_message = |
289 String::Handle(zone, String::New(bound_error.ToErrorCString())); | 302 String::Handle(zone, String::New(bound_error.ToErrorCString())); |
290 Exceptions::CreateAndThrowTypeError( | 303 Exceptions::CreateAndThrowTypeError( |
291 location, AbstractType::Handle(zone), AbstractType::Handle(zone), | 304 location, AbstractType::Handle(zone), AbstractType::Handle(zone), |
292 Symbols::Empty(), bound_error_message); | 305 Symbols::Empty(), bound_error_message); |
293 UNREACHABLE(); | 306 UNREACHABLE(); |
294 } | 307 } |
295 } else { | 308 } else { |
296 type_arguments = | 309 type_arguments = type_arguments.InstantiateAndCanonicalizeFrom( |
297 type_arguments.InstantiateAndCanonicalizeFrom(instantiator, NULL); | 310 instantiator_type_arguments, function_type_arguments, NULL); |
298 } | 311 } |
299 ASSERT(type_arguments.IsNull() || type_arguments.IsInstantiated()); | 312 ASSERT(type_arguments.IsNull() || type_arguments.IsInstantiated()); |
300 arguments.SetReturn(type_arguments); | 313 arguments.SetReturn(type_arguments); |
301 } | 314 } |
302 | 315 |
303 | 316 |
304 // Allocate a new context large enough to hold the given number of variables. | 317 // Allocate a new context large enough to hold the given number of variables. |
305 // Arg0: number of variables. | 318 // Arg0: number of variables. |
306 // Return value: newly allocated context. | 319 // Return value: newly allocated context. |
307 DEFINE_RUNTIME_ENTRY(AllocateContext, 1) { | 320 DEFINE_RUNTIME_ENTRY(AllocateContext, 1) { |
(...skipping 18 matching lines...) Expand all Loading... |
326 } | 339 } |
327 arguments.SetReturn(cloned_ctx); | 340 arguments.SetReturn(cloned_ctx); |
328 } | 341 } |
329 | 342 |
330 | 343 |
331 // Helper routine for tracing a type check. | 344 // Helper routine for tracing a type check. |
332 static void PrintTypeCheck(const char* message, | 345 static void PrintTypeCheck(const char* message, |
333 const Instance& instance, | 346 const Instance& instance, |
334 const AbstractType& type, | 347 const AbstractType& type, |
335 const TypeArguments& instantiator_type_arguments, | 348 const TypeArguments& instantiator_type_arguments, |
| 349 const TypeArguments& function_type_arguments, |
336 const Bool& result) { | 350 const Bool& result) { |
337 DartFrameIterator iterator; | 351 DartFrameIterator iterator; |
338 StackFrame* caller_frame = iterator.NextFrame(); | 352 StackFrame* caller_frame = iterator.NextFrame(); |
339 ASSERT(caller_frame != NULL); | 353 ASSERT(caller_frame != NULL); |
340 | 354 |
341 const AbstractType& instance_type = | 355 const AbstractType& instance_type = |
342 AbstractType::Handle(instance.GetType(Heap::kNew)); | 356 AbstractType::Handle(instance.GetType(Heap::kNew)); |
343 ASSERT(instance_type.IsInstantiated()); | 357 ASSERT(instance_type.IsInstantiated()); |
344 if (type.IsInstantiated()) { | 358 if (type.IsInstantiated()) { |
345 OS::PrintErr("%s: '%s' %" Pd " %s '%s' %" Pd " (pc: %#" Px ").\n", message, | 359 OS::PrintErr("%s: '%s' %" Pd " %s '%s' %" Pd " (pc: %#" Px ").\n", message, |
346 String::Handle(instance_type.Name()).ToCString(), | 360 String::Handle(instance_type.Name()).ToCString(), |
347 Class::Handle(instance_type.type_class()).id(), | 361 Class::Handle(instance_type.type_class()).id(), |
348 (result.raw() == Bool::True().raw()) ? "is" : "is !", | 362 (result.raw() == Bool::True().raw()) ? "is" : "is !", |
349 String::Handle(type.Name()).ToCString(), | 363 String::Handle(type.Name()).ToCString(), |
350 Class::Handle(type.type_class()).id(), caller_frame->pc()); | 364 Class::Handle(type.type_class()).id(), caller_frame->pc()); |
351 } else { | 365 } else { |
352 // Instantiate type before printing. | 366 // Instantiate type before printing. |
353 Error& bound_error = Error::Handle(); | 367 Error& bound_error = Error::Handle(); |
354 const AbstractType& instantiated_type = | 368 const AbstractType& instantiated_type = |
355 AbstractType::Handle(type.InstantiateFrom( | 369 AbstractType::Handle(type.InstantiateFrom( |
356 instantiator_type_arguments, &bound_error, NULL, NULL, Heap::kOld)); | 370 instantiator_type_arguments, function_type_arguments, &bound_error, |
| 371 NULL, NULL, Heap::kOld)); |
357 OS::PrintErr("%s: '%s' %s '%s' instantiated from '%s' (pc: %#" Px ").\n", | 372 OS::PrintErr("%s: '%s' %s '%s' instantiated from '%s' (pc: %#" Px ").\n", |
358 message, String::Handle(instance_type.Name()).ToCString(), | 373 message, String::Handle(instance_type.Name()).ToCString(), |
359 (result.raw() == Bool::True().raw()) ? "is" : "is !", | 374 (result.raw() == Bool::True().raw()) ? "is" : "is !", |
360 String::Handle(instantiated_type.Name()).ToCString(), | 375 String::Handle(instantiated_type.Name()).ToCString(), |
361 String::Handle(type.Name()).ToCString(), caller_frame->pc()); | 376 String::Handle(type.Name()).ToCString(), caller_frame->pc()); |
362 if (!bound_error.IsNull()) { | 377 if (!bound_error.IsNull()) { |
363 OS::Print(" bound error: %s\n", bound_error.ToErrorCString()); | 378 OS::Print(" bound error: %s\n", bound_error.ToErrorCString()); |
364 } | 379 } |
365 } | 380 } |
366 const Function& function = | 381 const Function& function = |
367 Function::Handle(caller_frame->LookupDartFunction()); | 382 Function::Handle(caller_frame->LookupDartFunction()); |
368 OS::PrintErr(" -> Function %s\n", function.ToFullyQualifiedCString()); | 383 OS::PrintErr(" -> Function %s\n", function.ToFullyQualifiedCString()); |
369 } | 384 } |
370 | 385 |
371 | 386 |
372 // This updates the type test cache, an array containing 4-value elements | 387 // This updates the type test cache, an array containing 5-value elements |
373 // (instance class (or function if the instance is a closure), instance type | 388 // (instance class (or function if the instance is a closure), instance type |
374 // arguments, instantiator type arguments and test_result). It can be applied to | 389 // arguments, instantiator type arguments, function type arguments, |
375 // classes with type arguments in which case it contains just the result of the | 390 // and test_result). It can be applied to classes with type arguments in which |
376 // class subtype test, not including the evaluation of type arguments. | 391 // case it contains just the result of the class subtype test, not including the |
| 392 // evaluation of type arguments. |
377 // This operation is currently very slow (lookup of code is not efficient yet). | 393 // This operation is currently very slow (lookup of code is not efficient yet). |
378 static void UpdateTypeTestCache( | 394 static void UpdateTypeTestCache( |
379 const Instance& instance, | 395 const Instance& instance, |
380 const AbstractType& type, | 396 const AbstractType& type, |
381 const TypeArguments& instantiator_type_arguments, | 397 const TypeArguments& instantiator_type_arguments, |
| 398 const TypeArguments& function_type_arguments, |
382 const Bool& result, | 399 const Bool& result, |
383 const SubtypeTestCache& new_cache) { | 400 const SubtypeTestCache& new_cache) { |
384 // Since the test is expensive, don't do it unless necessary. | 401 // Since the test is expensive, don't do it unless necessary. |
385 // The list of disallowed cases will decrease as they are implemented in | 402 // The list of disallowed cases will decrease as they are implemented in |
386 // inlined assembly. | 403 // inlined assembly. |
387 if (new_cache.IsNull()) { | 404 if (new_cache.IsNull()) { |
388 if (FLAG_trace_type_checks) { | 405 if (FLAG_trace_type_checks) { |
389 OS::Print("UpdateTypeTestCache: cache is null\n"); | 406 OS::Print("UpdateTypeTestCache: cache is null\n"); |
390 } | 407 } |
391 return; | 408 return; |
392 } | 409 } |
393 if (instance.IsSmi()) { | 410 if (instance.IsSmi()) { |
394 if (FLAG_trace_type_checks) { | 411 if (FLAG_trace_type_checks) { |
395 OS::Print("UpdateTypeTestCache: instance is Smi\n"); | 412 OS::Print("UpdateTypeTestCache: instance is Smi\n"); |
396 } | 413 } |
397 return; | 414 return; |
398 } | 415 } |
| 416 // If the type is uninstantiated and refers to parent function type |
| 417 // parameters, the context is required in the type test and the cache |
| 418 // therefore cannot be used. |
| 419 if (!type.IsInstantiated(kParentFunctions)) { |
| 420 if (FLAG_trace_type_checks) { |
| 421 OS::Print( |
| 422 "UpdateTypeTestCache: type refers to parent function's type " |
| 423 "parameters\n"); |
| 424 } |
| 425 return; |
| 426 } |
399 const Class& instance_class = Class::Handle(instance.clazz()); | 427 const Class& instance_class = Class::Handle(instance.clazz()); |
400 Object& instance_class_id_or_function = Object::Handle(); | 428 Object& instance_class_id_or_function = Object::Handle(); |
401 TypeArguments& instance_type_arguments = TypeArguments::Handle(); | 429 TypeArguments& instance_type_arguments = TypeArguments::Handle(); |
402 if (instance_class.IsClosureClass()) { | 430 if (instance_class.IsClosureClass()) { |
403 instance_class_id_or_function = Closure::Cast(instance).function(); | 431 instance_class_id_or_function = Closure::Cast(instance).function(); |
404 instance_type_arguments = Closure::Cast(instance).instantiator(); | 432 instance_type_arguments = Closure::Cast(instance).instantiator(); |
405 } else { | 433 } else { |
406 instance_class_id_or_function = Smi::New(instance_class.id()); | 434 instance_class_id_or_function = Smi::New(instance_class.id()); |
407 if (instance_class.NumTypeArguments() > 0) { | 435 if (instance_class.NumTypeArguments() > 0) { |
408 instance_type_arguments = instance.GetTypeArguments(); | 436 instance_type_arguments = instance.GetTypeArguments(); |
409 } | 437 } |
410 } | 438 } |
411 const intptr_t len = new_cache.NumberOfChecks(); | 439 const intptr_t len = new_cache.NumberOfChecks(); |
412 if (len >= FLAG_max_subtype_cache_entries) { | 440 if (len >= FLAG_max_subtype_cache_entries) { |
413 return; | 441 return; |
414 } | 442 } |
415 #if defined(DEBUG) | 443 #if defined(DEBUG) |
416 ASSERT(instance_type_arguments.IsNull() || | 444 ASSERT(instance_type_arguments.IsNull() || |
417 instance_type_arguments.IsCanonical()); | 445 instance_type_arguments.IsCanonical()); |
418 ASSERT(instantiator_type_arguments.IsNull() || | 446 ASSERT(instantiator_type_arguments.IsNull() || |
419 instantiator_type_arguments.IsCanonical()); | 447 instantiator_type_arguments.IsCanonical()); |
| 448 ASSERT(function_type_arguments.IsNull() || |
| 449 function_type_arguments.IsCanonical()); |
420 Object& last_instance_class_id_or_function = Object::Handle(); | 450 Object& last_instance_class_id_or_function = Object::Handle(); |
421 TypeArguments& last_instance_type_arguments = TypeArguments::Handle(); | 451 TypeArguments& last_instance_type_arguments = TypeArguments::Handle(); |
422 TypeArguments& last_instantiator_type_arguments = TypeArguments::Handle(); | 452 TypeArguments& last_instantiator_type_arguments = TypeArguments::Handle(); |
| 453 TypeArguments& last_function_type_arguments = TypeArguments::Handle(); |
423 Bool& last_result = Bool::Handle(); | 454 Bool& last_result = Bool::Handle(); |
424 for (intptr_t i = 0; i < len; ++i) { | 455 for (intptr_t i = 0; i < len; ++i) { |
425 new_cache.GetCheck(i, &last_instance_class_id_or_function, | 456 new_cache.GetCheck(i, &last_instance_class_id_or_function, |
426 &last_instance_type_arguments, | 457 &last_instance_type_arguments, |
427 &last_instantiator_type_arguments, &last_result); | 458 &last_instantiator_type_arguments, |
| 459 &last_function_type_arguments, &last_result); |
428 if ((last_instance_class_id_or_function.raw() == | 460 if ((last_instance_class_id_or_function.raw() == |
429 instance_class_id_or_function.raw()) && | 461 instance_class_id_or_function.raw()) && |
430 (last_instance_type_arguments.raw() == instance_type_arguments.raw()) && | 462 (last_instance_type_arguments.raw() == instance_type_arguments.raw()) && |
431 (last_instantiator_type_arguments.raw() == | 463 (last_instantiator_type_arguments.raw() == |
432 instantiator_type_arguments.raw())) { | 464 instantiator_type_arguments.raw()) && |
| 465 (last_function_type_arguments.raw() == |
| 466 last_function_type_arguments.raw())) { |
433 OS::PrintErr(" Error in test cache %p ix: %" Pd ",", new_cache.raw(), i); | 467 OS::PrintErr(" Error in test cache %p ix: %" Pd ",", new_cache.raw(), i); |
434 PrintTypeCheck(" duplicate cache entry", instance, type, | 468 PrintTypeCheck(" duplicate cache entry", instance, type, |
435 instantiator_type_arguments, result); | 469 instantiator_type_arguments, function_type_arguments, |
| 470 result); |
436 UNREACHABLE(); | 471 UNREACHABLE(); |
437 return; | 472 return; |
438 } | 473 } |
439 } | 474 } |
440 #endif | 475 #endif |
441 new_cache.AddCheck(instance_class_id_or_function, instance_type_arguments, | 476 new_cache.AddCheck(instance_class_id_or_function, instance_type_arguments, |
442 instantiator_type_arguments, result); | 477 instantiator_type_arguments, function_type_arguments, |
| 478 result); |
443 if (FLAG_trace_type_checks) { | 479 if (FLAG_trace_type_checks) { |
444 AbstractType& test_type = AbstractType::Handle(type.raw()); | 480 AbstractType& test_type = AbstractType::Handle(type.raw()); |
445 if (!test_type.IsInstantiated()) { | 481 if (!test_type.IsInstantiated()) { |
446 Error& bound_error = Error::Handle(); | 482 Error& bound_error = Error::Handle(); |
447 test_type = type.InstantiateFrom(instantiator_type_arguments, | 483 test_type = type.InstantiateFrom(instantiator_type_arguments, |
448 &bound_error, NULL, NULL, Heap::kNew); | 484 function_type_arguments, &bound_error, |
| 485 NULL, NULL, Heap::kNew); |
449 ASSERT(bound_error.IsNull()); // Malbounded types are not optimized. | 486 ASSERT(bound_error.IsNull()); // Malbounded types are not optimized. |
450 } | 487 } |
451 OS::PrintErr( | 488 OS::PrintErr( |
452 " Updated test cache %p ix: %" Pd | 489 " Updated test cache %p ix: %" Pd |
453 " with " | 490 " with " |
454 "(cid-or-fun: %p, type-args: %p, instantiator: %p, result: %s)\n" | 491 "(cid-or-fun: %p, type-args: %p, i-type-args: %p, f-type-args: %p, " |
| 492 "result: %s)\n" |
455 " instance [class: (%p '%s' cid: %" Pd | 493 " instance [class: (%p '%s' cid: %" Pd |
456 "), type-args: %p %s]\n" | 494 "), type-args: %p %s]\n" |
457 " test-type [class: (%p '%s' cid: %" Pd "), in-type-args: %p %s]\n", | 495 " test-type [class: (%p '%s' cid: %" Pd |
| 496 "), i-type-args: %p %s, " |
| 497 ", f-type-args: %p %s]\n", |
458 new_cache.raw(), len, | 498 new_cache.raw(), len, |
459 | 499 |
460 instance_class_id_or_function.raw(), instance_type_arguments.raw(), | 500 instance_class_id_or_function.raw(), instance_type_arguments.raw(), |
461 instantiator_type_arguments.raw(), result.ToCString(), | 501 instantiator_type_arguments.raw(), instantiator_type_arguments.raw(), |
| 502 result.ToCString(), |
462 | 503 |
463 instance_class.raw(), String::Handle(instance_class.Name()).ToCString(), | 504 instance_class.raw(), String::Handle(instance_class.Name()).ToCString(), |
464 instance_class.id(), instance_type_arguments.raw(), | 505 instance_class.id(), instance_type_arguments.raw(), |
465 instance_type_arguments.ToCString(), | 506 instance_type_arguments.ToCString(), |
466 | 507 |
467 test_type.type_class(), | 508 test_type.type_class(), |
468 String::Handle(Class::Handle(test_type.type_class()).Name()) | 509 String::Handle(Class::Handle(test_type.type_class()).Name()) |
469 .ToCString(), | 510 .ToCString(), |
470 Class::Handle(test_type.type_class()).id(), | 511 Class::Handle(test_type.type_class()).id(), |
471 instantiator_type_arguments.raw(), | 512 instantiator_type_arguments.raw(), |
| 513 instantiator_type_arguments.ToCString(), |
| 514 instantiator_type_arguments.raw(), |
472 instantiator_type_arguments.ToCString()); | 515 instantiator_type_arguments.ToCString()); |
473 } | 516 } |
474 } | 517 } |
475 | 518 |
476 | 519 |
477 // Check that the given instance is an instance of the given type. | 520 // Check that the given instance is an instance of the given type. |
478 // Tested instance may not be null, because the null test is inlined. | 521 // Tested instance may not be null, because the null test is inlined. |
479 // Arg0: instance being checked. | 522 // Arg0: instance being checked. |
480 // Arg1: type. | 523 // Arg1: type. |
481 // Arg2: type arguments of the instantiator of the type. | 524 // Arg2: type arguments of the instantiator of the type. |
482 // Arg3: SubtypeTestCache. | 525 // Arg3: type arguments of the function of the type. |
| 526 // Arg4: SubtypeTestCache. |
483 // Return value: true or false, or may throw a type error in checked mode. | 527 // Return value: true or false, or may throw a type error in checked mode. |
484 DEFINE_RUNTIME_ENTRY(Instanceof, 4) { | 528 DEFINE_RUNTIME_ENTRY(Instanceof, 5) { |
485 const Instance& instance = Instance::CheckedHandle(zone, arguments.ArgAt(0)); | 529 const Instance& instance = Instance::CheckedHandle(zone, arguments.ArgAt(0)); |
486 const AbstractType& type = | 530 const AbstractType& type = |
487 AbstractType::CheckedHandle(zone, arguments.ArgAt(1)); | 531 AbstractType::CheckedHandle(zone, arguments.ArgAt(1)); |
488 const TypeArguments& instantiator_type_arguments = | 532 const TypeArguments& instantiator_type_arguments = |
489 TypeArguments::CheckedHandle(zone, arguments.ArgAt(2)); | 533 TypeArguments::CheckedHandle(zone, arguments.ArgAt(2)); |
| 534 const TypeArguments& function_type_arguments = |
| 535 TypeArguments::CheckedHandle(zone, arguments.ArgAt(3)); |
490 const SubtypeTestCache& cache = | 536 const SubtypeTestCache& cache = |
491 SubtypeTestCache::CheckedHandle(zone, arguments.ArgAt(3)); | 537 SubtypeTestCache::CheckedHandle(zone, arguments.ArgAt(4)); |
492 ASSERT(type.IsFinalized()); | 538 ASSERT(type.IsFinalized()); |
493 ASSERT(!type.IsMalformed()); // Already checked in code generator. | 539 ASSERT(!type.IsMalformed()); // Already checked in code generator. |
494 ASSERT(!type.IsMalbounded()); // Already checked in code generator. | 540 ASSERT(!type.IsMalbounded()); // Already checked in code generator. |
495 ASSERT(!type.IsDynamicType()); // No need to check assignment. | 541 ASSERT(!type.IsDynamicType()); // No need to check assignment. |
496 Error& bound_error = Error::Handle(zone); | 542 Error& bound_error = Error::Handle(zone); |
497 const Bool& result = Bool::Get( | 543 const Bool& result = |
498 instance.IsInstanceOf(type, instantiator_type_arguments, &bound_error)); | 544 Bool::Get(instance.IsInstanceOf(type, instantiator_type_arguments, |
| 545 function_type_arguments, &bound_error)); |
499 if (FLAG_trace_type_checks) { | 546 if (FLAG_trace_type_checks) { |
500 PrintTypeCheck("InstanceOf", instance, type, instantiator_type_arguments, | 547 PrintTypeCheck("InstanceOf", instance, type, instantiator_type_arguments, |
501 result); | 548 function_type_arguments, result); |
502 } | 549 } |
503 if (!result.value() && !bound_error.IsNull()) { | 550 if (!result.value() && !bound_error.IsNull()) { |
504 // Throw a dynamic type error only if the instanceof test fails. | 551 // Throw a dynamic type error only if the instanceof test fails. |
505 const TokenPosition location = GetCallerLocation(); | 552 const TokenPosition location = GetCallerLocation(); |
506 String& bound_error_message = | 553 String& bound_error_message = |
507 String::Handle(zone, String::New(bound_error.ToErrorCString())); | 554 String::Handle(zone, String::New(bound_error.ToErrorCString())); |
508 Exceptions::CreateAndThrowTypeError(location, AbstractType::Handle(zone), | 555 Exceptions::CreateAndThrowTypeError(location, AbstractType::Handle(zone), |
509 AbstractType::Handle(zone), | 556 AbstractType::Handle(zone), |
510 Symbols::Empty(), bound_error_message); | 557 Symbols::Empty(), bound_error_message); |
511 UNREACHABLE(); | 558 UNREACHABLE(); |
512 } | 559 } |
513 UpdateTypeTestCache(instance, type, instantiator_type_arguments, result, | 560 UpdateTypeTestCache(instance, type, instantiator_type_arguments, |
514 cache); | 561 function_type_arguments, result, cache); |
515 arguments.SetReturn(result); | 562 arguments.SetReturn(result); |
516 } | 563 } |
517 | 564 |
518 | 565 |
519 // Check that the type of the given instance is a subtype of the given type and | 566 // Check that the type of the given instance is a subtype of the given type and |
520 // can therefore be assigned. | 567 // can therefore be assigned. |
521 // Arg0: instance being assigned. | 568 // Arg0: instance being assigned. |
522 // Arg1: type being assigned to. | 569 // Arg1: type being assigned to. |
523 // Arg2: type arguments of the instantiator of the type being assigned to. | 570 // Arg2: type arguments of the instantiator of the type being assigned to. |
524 // Arg3: name of variable being assigned to. | 571 // Arg3: type arguments of the function of the type being assigned to. |
525 // Arg4: SubtypeTestCache. | 572 // Arg4: name of variable being assigned to. |
| 573 // Arg5: SubtypeTestCache. |
526 // Return value: instance if a subtype, otherwise throw a TypeError. | 574 // Return value: instance if a subtype, otherwise throw a TypeError. |
527 DEFINE_RUNTIME_ENTRY(TypeCheck, 5) { | 575 DEFINE_RUNTIME_ENTRY(TypeCheck, 6) { |
528 const Instance& src_instance = | 576 const Instance& src_instance = |
529 Instance::CheckedHandle(zone, arguments.ArgAt(0)); | 577 Instance::CheckedHandle(zone, arguments.ArgAt(0)); |
530 AbstractType& dst_type = | 578 AbstractType& dst_type = |
531 AbstractType::CheckedHandle(zone, arguments.ArgAt(1)); | 579 AbstractType::CheckedHandle(zone, arguments.ArgAt(1)); |
532 const TypeArguments& instantiator_type_arguments = | 580 const TypeArguments& instantiator_type_arguments = |
533 TypeArguments::CheckedHandle(zone, arguments.ArgAt(2)); | 581 TypeArguments::CheckedHandle(zone, arguments.ArgAt(2)); |
534 const String& dst_name = String::CheckedHandle(zone, arguments.ArgAt(3)); | 582 const TypeArguments& function_type_arguments = |
| 583 TypeArguments::CheckedHandle(zone, arguments.ArgAt(3)); |
| 584 const String& dst_name = String::CheckedHandle(zone, arguments.ArgAt(4)); |
535 const SubtypeTestCache& cache = | 585 const SubtypeTestCache& cache = |
536 SubtypeTestCache::CheckedHandle(zone, arguments.ArgAt(4)); | 586 SubtypeTestCache::CheckedHandle(zone, arguments.ArgAt(5)); |
537 ASSERT(!dst_type.IsMalformed()); // Already checked in code generator. | 587 ASSERT(!dst_type.IsMalformed()); // Already checked in code generator. |
538 ASSERT(!dst_type.IsMalbounded()); // Already checked in code generator. | 588 ASSERT(!dst_type.IsMalbounded()); // Already checked in code generator. |
539 ASSERT(!dst_type.IsDynamicType()); // No need to check assignment. | 589 ASSERT(!dst_type.IsDynamicType()); // No need to check assignment. |
540 ASSERT(!src_instance.IsNull()); // Already checked in inlined code. | 590 ASSERT(!src_instance.IsNull()); // Already checked in inlined code. |
541 | 591 |
542 Error& bound_error = Error::Handle(zone); | 592 Error& bound_error = Error::Handle(zone); |
543 const bool is_instance_of = src_instance.IsInstanceOf( | 593 const bool is_instance_of = |
544 dst_type, instantiator_type_arguments, &bound_error); | 594 src_instance.IsInstanceOf(dst_type, instantiator_type_arguments, |
| 595 function_type_arguments, &bound_error); |
545 | 596 |
546 if (FLAG_trace_type_checks) { | 597 if (FLAG_trace_type_checks) { |
547 PrintTypeCheck("TypeCheck", src_instance, dst_type, | 598 PrintTypeCheck("TypeCheck", src_instance, dst_type, |
548 instantiator_type_arguments, Bool::Get(is_instance_of)); | 599 instantiator_type_arguments, function_type_arguments, |
| 600 Bool::Get(is_instance_of)); |
549 } | 601 } |
550 if (!is_instance_of) { | 602 if (!is_instance_of) { |
551 // Throw a dynamic type error. | 603 // Throw a dynamic type error. |
552 const TokenPosition location = GetCallerLocation(); | 604 const TokenPosition location = GetCallerLocation(); |
553 const AbstractType& src_type = | 605 const AbstractType& src_type = |
554 AbstractType::Handle(zone, src_instance.GetType(Heap::kNew)); | 606 AbstractType::Handle(zone, src_instance.GetType(Heap::kNew)); |
555 if (!dst_type.IsInstantiated()) { | 607 if (!dst_type.IsInstantiated()) { |
556 // Instantiate dst_type before reporting the error. | 608 // Instantiate dst_type before reporting the error. |
557 dst_type = dst_type.InstantiateFrom(instantiator_type_arguments, NULL, | 609 dst_type = dst_type.InstantiateFrom(instantiator_type_arguments, |
558 NULL, NULL, Heap::kNew); | 610 function_type_arguments, NULL, NULL, |
| 611 NULL, Heap::kNew); |
559 // Note that instantiated dst_type may be malbounded. | 612 // Note that instantiated dst_type may be malbounded. |
560 } | 613 } |
561 String& bound_error_message = String::Handle(zone); | 614 String& bound_error_message = String::Handle(zone); |
562 if (!bound_error.IsNull()) { | 615 if (!bound_error.IsNull()) { |
563 ASSERT(isolate->type_checks()); | 616 ASSERT(isolate->type_checks()); |
564 bound_error_message = String::New(bound_error.ToErrorCString()); | 617 bound_error_message = String::New(bound_error.ToErrorCString()); |
565 } | 618 } |
566 Exceptions::CreateAndThrowTypeError(location, src_type, dst_type, dst_name, | 619 Exceptions::CreateAndThrowTypeError(location, src_type, dst_type, dst_name, |
567 bound_error_message); | 620 bound_error_message); |
568 UNREACHABLE(); | 621 UNREACHABLE(); |
569 } | 622 } |
570 UpdateTypeTestCache(src_instance, dst_type, instantiator_type_arguments, | 623 UpdateTypeTestCache(src_instance, dst_type, instantiator_type_arguments, |
571 Bool::True(), cache); | 624 function_type_arguments, Bool::True(), cache); |
572 arguments.SetReturn(src_instance); | 625 arguments.SetReturn(src_instance); |
573 } | 626 } |
574 | 627 |
575 | 628 |
576 // Report that the type of the given object is not bool in conditional context. | 629 // Report that the type of the given object is not bool in conditional context. |
577 // Throw assertion error if the object is null. (cf. Boolean Conversion | 630 // Throw assertion error if the object is null. (cf. Boolean Conversion |
578 // in language Spec.) | 631 // in language Spec.) |
579 // Arg0: bad object. | 632 // Arg0: bad object. |
580 // Return value: none, throws TypeError or AssertionError. | 633 // Return value: none, throws TypeError or AssertionError. |
581 DEFINE_RUNTIME_ENTRY(NonBoolTypeError, 1) { | 634 DEFINE_RUNTIME_ENTRY(NonBoolTypeError, 1) { |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
799 ASSERT(!result.IsNull() || !FLAG_lazy_dispatchers); | 852 ASSERT(!result.IsNull() || !FLAG_lazy_dispatchers); |
800 return result.raw(); | 853 return result.raw(); |
801 } | 854 } |
802 | 855 |
803 | 856 |
804 // Perform the subtype and return constant function based on the result. | 857 // Perform the subtype and return constant function based on the result. |
805 static RawFunction* ComputeTypeCheckTarget(const Instance& receiver, | 858 static RawFunction* ComputeTypeCheckTarget(const Instance& receiver, |
806 const AbstractType& type, | 859 const AbstractType& type, |
807 const ArgumentsDescriptor& desc) { | 860 const ArgumentsDescriptor& desc) { |
808 Error& error = Error::Handle(); | 861 Error& error = Error::Handle(); |
809 bool result = | 862 bool result = receiver.IsInstanceOf(type, Object::null_type_arguments(), |
810 receiver.IsInstanceOf(type, Object::null_type_arguments(), &error); | 863 Object::null_type_arguments(), &error); |
811 ASSERT(error.IsNull()); | 864 ASSERT(error.IsNull()); |
812 ObjectStore* store = Isolate::Current()->object_store(); | 865 ObjectStore* store = Isolate::Current()->object_store(); |
813 const Function& target = | 866 const Function& target = |
814 Function::Handle(result ? store->simple_instance_of_true_function() | 867 Function::Handle(result ? store->simple_instance_of_true_function() |
815 : store->simple_instance_of_false_function()); | 868 : store->simple_instance_of_false_function()); |
816 ASSERT(!target.IsNull()); | 869 ASSERT(!target.IsNull()); |
817 return target.raw(); | 870 return target.raw(); |
818 } | 871 } |
819 | 872 |
820 | 873 |
(...skipping 1398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2219 const intptr_t elm_size = old_data.ElementSizeInBytes(); | 2272 const intptr_t elm_size = old_data.ElementSizeInBytes(); |
2220 const TypedData& new_data = | 2273 const TypedData& new_data = |
2221 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); | 2274 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); |
2222 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); | 2275 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); |
2223 typed_data_cell.SetAt(0, new_data); | 2276 typed_data_cell.SetAt(0, new_data); |
2224 arguments.SetReturn(new_data); | 2277 arguments.SetReturn(new_data); |
2225 } | 2278 } |
2226 | 2279 |
2227 | 2280 |
2228 } // namespace dart | 2281 } // namespace dart |
OLD | NEW |