| 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 |