| 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 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 183 (type_arguments.Length() >= cls.NumTypeArguments()))); | 183 (type_arguments.Length() >= cls.NumTypeArguments()))); |
| 184 instance.SetTypeArguments(type_arguments); | 184 instance.SetTypeArguments(type_arguments); |
| 185 } | 185 } |
| 186 | 186 |
| 187 | 187 |
| 188 // Instantiate type. | 188 // Instantiate type. |
| 189 // Arg0: uninstantiated type. | 189 // Arg0: uninstantiated type. |
| 190 // Arg1: instantiator type arguments. | 190 // Arg1: instantiator type arguments. |
| 191 // Return value: instantiated type. | 191 // Return value: instantiated type. |
| 192 DEFINE_RUNTIME_ENTRY(InstantiateType, 2) { | 192 DEFINE_RUNTIME_ENTRY(InstantiateType, 2) { |
| 193 AbstractType& type = AbstractType::CheckedHandle(arguments.ArgAt(0)); | 193 AbstractType& type = AbstractType::CheckedHandle(zone, arguments.ArgAt(0)); |
| 194 const TypeArguments& instantiator = | 194 const TypeArguments& instantiator = |
| 195 TypeArguments::CheckedHandle(arguments.ArgAt(1)); | 195 TypeArguments::CheckedHandle(zone, arguments.ArgAt(1)); |
| 196 ASSERT(!type.IsNull() && !type.IsInstantiated()); | 196 ASSERT(!type.IsNull() && !type.IsInstantiated()); |
| 197 ASSERT(instantiator.IsNull() || instantiator.IsInstantiated()); | 197 ASSERT(instantiator.IsNull() || instantiator.IsInstantiated()); |
| 198 Error& bound_error = Error::Handle(); | 198 Error& bound_error = Error::Handle(zone); |
| 199 type = | 199 type = |
| 200 type.InstantiateFrom(instantiator, &bound_error, NULL, NULL, Heap::kOld); | 200 type.InstantiateFrom(instantiator, &bound_error, NULL, NULL, Heap::kOld); |
| 201 if (!bound_error.IsNull()) { | 201 if (!bound_error.IsNull()) { |
| 202 // Throw a dynamic type error. | 202 // Throw a dynamic type error. |
| 203 const TokenPosition location = GetCallerLocation(); | 203 const TokenPosition location = GetCallerLocation(); |
| 204 String& bound_error_message = String::Handle( | 204 String& bound_error_message = String::Handle( |
| 205 String::New(bound_error.ToErrorCString())); | 205 zone, String::New(bound_error.ToErrorCString())); |
| 206 Exceptions::CreateAndThrowTypeError( | 206 Exceptions::CreateAndThrowTypeError( |
| 207 location, Symbols::Empty(), Symbols::Empty(), | 207 location, AbstractType::Handle(zone), AbstractType::Handle(zone), |
| 208 Symbols::Empty(), bound_error_message); | 208 Symbols::Empty(), bound_error_message); |
| 209 UNREACHABLE(); | 209 UNREACHABLE(); |
| 210 } | 210 } |
| 211 if (type.IsTypeRef()) { | 211 if (type.IsTypeRef()) { |
| 212 type = TypeRef::Cast(type).type(); | 212 type = TypeRef::Cast(type).type(); |
| 213 ASSERT(!type.IsTypeRef()); | 213 ASSERT(!type.IsTypeRef()); |
| 214 ASSERT(type.IsCanonical()); | 214 ASSERT(type.IsCanonical()); |
| 215 } | 215 } |
| 216 ASSERT(!type.IsNull() && type.IsInstantiated()); | 216 ASSERT(!type.IsNull() && type.IsInstantiated()); |
| 217 arguments.SetReturn(type); | 217 arguments.SetReturn(type); |
| 218 } | 218 } |
| 219 | 219 |
| 220 | 220 |
| 221 // Instantiate type arguments. | 221 // Instantiate type arguments. |
| 222 // Arg0: uninstantiated type arguments. | 222 // Arg0: uninstantiated type arguments. |
| 223 // Arg1: instantiator type arguments. | 223 // Arg1: instantiator type arguments. |
| 224 // Return value: instantiated type arguments. | 224 // Return value: instantiated type arguments. |
| 225 DEFINE_RUNTIME_ENTRY(InstantiateTypeArguments, 2) { | 225 DEFINE_RUNTIME_ENTRY(InstantiateTypeArguments, 2) { |
| 226 TypeArguments& type_arguments = | 226 TypeArguments& type_arguments = |
| 227 TypeArguments::CheckedHandle(arguments.ArgAt(0)); | 227 TypeArguments::CheckedHandle(zone, arguments.ArgAt(0)); |
| 228 const TypeArguments& instantiator = | 228 const TypeArguments& instantiator = |
| 229 TypeArguments::CheckedHandle(arguments.ArgAt(1)); | 229 TypeArguments::CheckedHandle(zone, arguments.ArgAt(1)); |
| 230 ASSERT(!type_arguments.IsNull() && !type_arguments.IsInstantiated()); | 230 ASSERT(!type_arguments.IsNull() && !type_arguments.IsInstantiated()); |
| 231 ASSERT(instantiator.IsNull() || instantiator.IsInstantiated()); | 231 ASSERT(instantiator.IsNull() || instantiator.IsInstantiated()); |
| 232 // Code inlined in the caller should have optimized the case where the | 232 // Code inlined in the caller should have optimized the case where the |
| 233 // instantiator can be reused as type argument vector. | 233 // instantiator can be reused as type argument vector. |
| 234 ASSERT(instantiator.IsNull() || !type_arguments.IsUninstantiatedIdentity()); | 234 ASSERT(instantiator.IsNull() || !type_arguments.IsUninstantiatedIdentity()); |
| 235 if (isolate->type_checks()) { | 235 if (isolate->type_checks()) { |
| 236 Error& bound_error = Error::Handle(); | 236 Error& bound_error = Error::Handle(zone); |
| 237 type_arguments = | 237 type_arguments = |
| 238 type_arguments.InstantiateAndCanonicalizeFrom(instantiator, | 238 type_arguments.InstantiateAndCanonicalizeFrom(instantiator, |
| 239 &bound_error); | 239 &bound_error); |
| 240 if (!bound_error.IsNull()) { | 240 if (!bound_error.IsNull()) { |
| 241 // Throw a dynamic type error. | 241 // Throw a dynamic type error. |
| 242 const TokenPosition location = GetCallerLocation(); | 242 const TokenPosition location = GetCallerLocation(); |
| 243 String& bound_error_message = String::Handle( | 243 String& bound_error_message = String::Handle( |
| 244 String::New(bound_error.ToErrorCString())); | 244 zone, String::New(bound_error.ToErrorCString())); |
| 245 Exceptions::CreateAndThrowTypeError( | 245 Exceptions::CreateAndThrowTypeError( |
| 246 location, Symbols::Empty(), Symbols::Empty(), | 246 location, AbstractType::Handle(zone), AbstractType::Handle(zone), |
| 247 Symbols::Empty(), bound_error_message); | 247 Symbols::Empty(), bound_error_message); |
| 248 UNREACHABLE(); | 248 UNREACHABLE(); |
| 249 } | 249 } |
| 250 } else { | 250 } else { |
| 251 type_arguments = | 251 type_arguments = |
| 252 type_arguments.InstantiateAndCanonicalizeFrom(instantiator, NULL); | 252 type_arguments.InstantiateAndCanonicalizeFrom(instantiator, NULL); |
| 253 } | 253 } |
| 254 ASSERT(type_arguments.IsNull() || type_arguments.IsInstantiated()); | 254 ASSERT(type_arguments.IsNull() || type_arguments.IsInstantiated()); |
| 255 arguments.SetReturn(type_arguments); | 255 arguments.SetReturn(type_arguments); |
| 256 } | 256 } |
| 257 | 257 |
| 258 | 258 |
| 259 // Allocate a new context large enough to hold the given number of variables. | 259 // Allocate a new context large enough to hold the given number of variables. |
| 260 // Arg0: number of variables. | 260 // Arg0: number of variables. |
| 261 // Return value: newly allocated context. | 261 // Return value: newly allocated context. |
| 262 DEFINE_RUNTIME_ENTRY(AllocateContext, 1) { | 262 DEFINE_RUNTIME_ENTRY(AllocateContext, 1) { |
| 263 const Smi& num_variables = Smi::CheckedHandle(arguments.ArgAt(0)); | 263 const Smi& num_variables = Smi::CheckedHandle(zone, arguments.ArgAt(0)); |
| 264 arguments.SetReturn(Context::Handle(Context::New(num_variables.Value()))); | 264 arguments.SetReturn(Context::Handle(Context::New(num_variables.Value()))); |
| 265 } | 265 } |
| 266 | 266 |
| 267 | 267 |
| 268 // Make a copy of the given context, including the values of the captured | 268 // Make a copy of the given context, including the values of the captured |
| 269 // variables. | 269 // variables. |
| 270 // Arg0: the context to be cloned. | 270 // Arg0: the context to be cloned. |
| 271 // Return value: newly allocated context. | 271 // Return value: newly allocated context. |
| 272 DEFINE_RUNTIME_ENTRY(CloneContext, 1) { | 272 DEFINE_RUNTIME_ENTRY(CloneContext, 1) { |
| 273 const Context& ctx = Context::CheckedHandle(arguments.ArgAt(0)); | 273 const Context& ctx = Context::CheckedHandle(zone, arguments.ArgAt(0)); |
| 274 Context& cloned_ctx = Context::Handle(Context::New(ctx.num_variables())); | 274 Context& cloned_ctx = |
| 275 Context::Handle(zone, Context::New(ctx.num_variables())); |
| 275 cloned_ctx.set_parent(Context::Handle(ctx.parent())); | 276 cloned_ctx.set_parent(Context::Handle(ctx.parent())); |
| 276 Object& inst = Object::Handle(zone); | 277 Object& inst = Object::Handle(zone); |
| 277 for (int i = 0; i < ctx.num_variables(); i++) { | 278 for (int i = 0; i < ctx.num_variables(); i++) { |
| 278 inst = ctx.At(i); | 279 inst = ctx.At(i); |
| 279 cloned_ctx.SetAt(i, inst); | 280 cloned_ctx.SetAt(i, inst); |
| 280 } | 281 } |
| 281 arguments.SetReturn(cloned_ctx); | 282 arguments.SetReturn(cloned_ctx); |
| 282 } | 283 } |
| 283 | 284 |
| 284 | 285 |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 442 | 443 |
| 443 | 444 |
| 444 // Check that the given instance is an instance of the given type. | 445 // Check that the given instance is an instance of the given type. |
| 445 // Tested instance may not be null, because the null test is inlined. | 446 // Tested instance may not be null, because the null test is inlined. |
| 446 // Arg0: instance being checked. | 447 // Arg0: instance being checked. |
| 447 // Arg1: type. | 448 // Arg1: type. |
| 448 // Arg2: type arguments of the instantiator of the type. | 449 // Arg2: type arguments of the instantiator of the type. |
| 449 // Arg3: SubtypeTestCache. | 450 // Arg3: SubtypeTestCache. |
| 450 // Return value: true or false, or may throw a type error in checked mode. | 451 // Return value: true or false, or may throw a type error in checked mode. |
| 451 DEFINE_RUNTIME_ENTRY(Instanceof, 4) { | 452 DEFINE_RUNTIME_ENTRY(Instanceof, 4) { |
| 452 const Instance& instance = Instance::CheckedHandle(arguments.ArgAt(0)); | 453 const Instance& instance = Instance::CheckedHandle(zone, arguments.ArgAt(0)); |
| 453 const AbstractType& type = AbstractType::CheckedHandle(arguments.ArgAt(1)); | 454 const AbstractType& type = |
| 455 AbstractType::CheckedHandle(zone, arguments.ArgAt(1)); |
| 454 const TypeArguments& instantiator_type_arguments = | 456 const TypeArguments& instantiator_type_arguments = |
| 455 TypeArguments::CheckedHandle(arguments.ArgAt(2)); | 457 TypeArguments::CheckedHandle(zone, arguments.ArgAt(2)); |
| 456 const SubtypeTestCache& cache = | 458 const SubtypeTestCache& cache = |
| 457 SubtypeTestCache::CheckedHandle(arguments.ArgAt(3)); | 459 SubtypeTestCache::CheckedHandle(zone, arguments.ArgAt(3)); |
| 458 ASSERT(type.IsFinalized()); | 460 ASSERT(type.IsFinalized()); |
| 459 ASSERT(!type.IsDynamicType()); // No need to check assignment. | 461 ASSERT(!type.IsDynamicType()); // No need to check assignment. |
| 460 ASSERT(!type.IsMalformed()); // Already checked in code generator. | 462 ASSERT(!type.IsMalformed()); // Already checked in code generator. |
| 461 ASSERT(!type.IsMalbounded()); // Already checked in code generator. | 463 ASSERT(!type.IsMalbounded()); // Already checked in code generator. |
| 462 Error& bound_error = Error::Handle(); | 464 Error& bound_error = Error::Handle(zone); |
| 463 const Bool& result = | 465 const Bool& result = |
| 464 Bool::Get(instance.IsInstanceOf(type, | 466 Bool::Get(instance.IsInstanceOf(type, |
| 465 instantiator_type_arguments, | 467 instantiator_type_arguments, |
| 466 &bound_error)); | 468 &bound_error)); |
| 467 if (FLAG_trace_type_checks) { | 469 if (FLAG_trace_type_checks) { |
| 468 PrintTypeCheck("InstanceOf", | 470 PrintTypeCheck("InstanceOf", |
| 469 instance, type, instantiator_type_arguments, result); | 471 instance, type, instantiator_type_arguments, result); |
| 470 } | 472 } |
| 471 if (!result.value() && !bound_error.IsNull()) { | 473 if (!result.value() && !bound_error.IsNull()) { |
| 472 // Throw a dynamic type error only if the instanceof test fails. | 474 // Throw a dynamic type error only if the instanceof test fails. |
| 473 const TokenPosition location = GetCallerLocation(); | 475 const TokenPosition location = GetCallerLocation(); |
| 474 String& bound_error_message = String::Handle( | 476 String& bound_error_message = String::Handle( |
| 475 String::New(bound_error.ToErrorCString())); | 477 zone, String::New(bound_error.ToErrorCString())); |
| 476 Exceptions::CreateAndThrowTypeError( | 478 Exceptions::CreateAndThrowTypeError( |
| 477 location, Symbols::Empty(), Symbols::Empty(), | 479 location, AbstractType::Handle(zone), AbstractType::Handle(zone), |
| 478 Symbols::Empty(), bound_error_message); | 480 Symbols::Empty(), bound_error_message); |
| 479 UNREACHABLE(); | 481 UNREACHABLE(); |
| 480 } | 482 } |
| 481 UpdateTypeTestCache( | 483 UpdateTypeTestCache( |
| 482 instance, type, instantiator_type_arguments, result, cache); | 484 instance, type, instantiator_type_arguments, result, cache); |
| 483 arguments.SetReturn(result); | 485 arguments.SetReturn(result); |
| 484 } | 486 } |
| 485 | 487 |
| 486 | 488 |
| 487 // Check that the type of the given instance is a subtype of the given type and | 489 // Check that the type of the given instance is a subtype of the given type and |
| 488 // can therefore be assigned. | 490 // can therefore be assigned. |
| 489 // Arg0: instance being assigned. | 491 // Arg0: instance being assigned. |
| 490 // Arg1: type being assigned to. | 492 // Arg1: type being assigned to. |
| 491 // Arg2: type arguments of the instantiator of the type being assigned to. | 493 // Arg2: type arguments of the instantiator of the type being assigned to. |
| 492 // Arg3: name of variable being assigned to. | 494 // Arg3: name of variable being assigned to. |
| 493 // Arg4: SubtypeTestCache. | 495 // Arg4: SubtypeTestCache. |
| 494 // Return value: instance if a subtype, otherwise throw a TypeError. | 496 // Return value: instance if a subtype, otherwise throw a TypeError. |
| 495 DEFINE_RUNTIME_ENTRY(TypeCheck, 5) { | 497 DEFINE_RUNTIME_ENTRY(TypeCheck, 5) { |
| 496 const Instance& src_instance = Instance::CheckedHandle(arguments.ArgAt(0)); | 498 const Instance& src_instance = |
| 497 AbstractType& dst_type = AbstractType::CheckedHandle(arguments.ArgAt(1)); | 499 Instance::CheckedHandle(zone, arguments.ArgAt(0)); |
| 500 AbstractType& dst_type = |
| 501 AbstractType::CheckedHandle(zone, arguments.ArgAt(1)); |
| 498 const TypeArguments& instantiator_type_arguments = | 502 const TypeArguments& instantiator_type_arguments = |
| 499 TypeArguments::CheckedHandle(arguments.ArgAt(2)); | 503 TypeArguments::CheckedHandle(zone, arguments.ArgAt(2)); |
| 500 const String& dst_name = String::CheckedHandle(arguments.ArgAt(3)); | 504 const String& dst_name = String::CheckedHandle(zone, arguments.ArgAt(3)); |
| 501 const SubtypeTestCache& cache = | 505 const SubtypeTestCache& cache = |
| 502 SubtypeTestCache::CheckedHandle(arguments.ArgAt(4)); | 506 SubtypeTestCache::CheckedHandle(zone, arguments.ArgAt(4)); |
| 503 ASSERT(!dst_type.IsDynamicType()); // No need to check assignment. | 507 ASSERT(!dst_type.IsDynamicType()); // No need to check assignment. |
| 504 ASSERT(!dst_type.IsMalformed()); // Already checked in code generator. | 508 ASSERT(!dst_type.IsMalformed()); // Already checked in code generator. |
| 505 ASSERT(!dst_type.IsMalbounded()); // Already checked in code generator. | 509 ASSERT(!dst_type.IsMalbounded()); // Already checked in code generator. |
| 506 ASSERT(!src_instance.IsNull()); // Already checked in inlined code. | 510 ASSERT(!src_instance.IsNull()); // Already checked in inlined code. |
| 507 | 511 |
| 508 Error& bound_error = Error::Handle(); | 512 Error& bound_error = Error::Handle(zone); |
| 509 const bool is_instance_of = src_instance.IsInstanceOf( | 513 const bool is_instance_of = src_instance.IsInstanceOf( |
| 510 dst_type, instantiator_type_arguments, &bound_error); | 514 dst_type, instantiator_type_arguments, &bound_error); |
| 511 | 515 |
| 512 if (FLAG_trace_type_checks) { | 516 if (FLAG_trace_type_checks) { |
| 513 PrintTypeCheck("TypeCheck", | 517 PrintTypeCheck("TypeCheck", |
| 514 src_instance, dst_type, instantiator_type_arguments, | 518 src_instance, dst_type, instantiator_type_arguments, |
| 515 Bool::Get(is_instance_of)); | 519 Bool::Get(is_instance_of)); |
| 516 } | 520 } |
| 517 if (!is_instance_of) { | 521 if (!is_instance_of) { |
| 518 // Throw a dynamic type error. | 522 // Throw a dynamic type error. |
| 519 const TokenPosition location = GetCallerLocation(); | 523 const TokenPosition location = GetCallerLocation(); |
| 520 const AbstractType& src_type = AbstractType::Handle(src_instance.GetType()); | 524 const AbstractType& src_type = |
| 521 String& src_type_name = String::Handle(src_type.UserVisibleName()); | 525 AbstractType::Handle(zone, src_instance.GetType()); |
| 522 if (!dst_type.IsInstantiated()) { | 526 if (!dst_type.IsInstantiated()) { |
| 523 // Instantiate dst_type before reporting the error. | 527 // Instantiate dst_type before reporting the error. |
| 524 dst_type = dst_type.InstantiateFrom(instantiator_type_arguments, NULL, | 528 dst_type = dst_type.InstantiateFrom(instantiator_type_arguments, NULL, |
| 525 NULL, NULL, Heap::kNew); | 529 NULL, NULL, Heap::kNew); |
| 526 // Note that instantiated dst_type may be malbounded. | 530 // Note that instantiated dst_type may be malbounded. |
| 527 } | 531 } |
| 528 String& dst_type_name = String::Handle(dst_type.UserVisibleName()); | 532 String& bound_error_message = String::Handle(zone); |
| 529 String& bound_error_message = String::Handle(); | |
| 530 if (!bound_error.IsNull()) { | 533 if (!bound_error.IsNull()) { |
| 531 ASSERT(isolate->type_checks()); | 534 ASSERT(isolate->type_checks()); |
| 532 bound_error_message = String::New(bound_error.ToErrorCString()); | 535 bound_error_message = String::New(bound_error.ToErrorCString()); |
| 533 } | 536 } |
| 534 if (src_type_name.Equals(dst_type_name)) { | 537 Exceptions::CreateAndThrowTypeError(location, src_type, dst_type, |
| 535 src_type_name = src_type.UserVisibleNameWithURI(); | |
| 536 dst_type_name = dst_type.UserVisibleNameWithURI(); | |
| 537 } | |
| 538 Exceptions::CreateAndThrowTypeError(location, src_type_name, dst_type_name, | |
| 539 dst_name, bound_error_message); | 538 dst_name, bound_error_message); |
| 540 UNREACHABLE(); | 539 UNREACHABLE(); |
| 541 } | 540 } |
| 542 UpdateTypeTestCache( | 541 UpdateTypeTestCache( |
| 543 src_instance, dst_type, instantiator_type_arguments, Bool::True(), cache); | 542 src_instance, dst_type, instantiator_type_arguments, Bool::True(), cache); |
| 544 arguments.SetReturn(src_instance); | 543 arguments.SetReturn(src_instance); |
| 545 } | 544 } |
| 546 | 545 |
| 547 | 546 |
| 548 // Report that the type of the given object is not bool in conditional context. | 547 // Report that the type of the given object is not bool in conditional context. |
| 549 // Throw assertion error if the object is null. (cf. Boolean Conversion | 548 // Throw assertion error if the object is null. (cf. Boolean Conversion |
| 550 // in language Spec.) | 549 // in language Spec.) |
| 551 // Arg0: bad object. | 550 // Arg0: bad object. |
| 552 // Return value: none, throws TypeError or AssertionError. | 551 // Return value: none, throws TypeError or AssertionError. |
| 553 DEFINE_RUNTIME_ENTRY(NonBoolTypeError, 1) { | 552 DEFINE_RUNTIME_ENTRY(NonBoolTypeError, 1) { |
| 554 const TokenPosition location = GetCallerLocation(); | 553 const TokenPosition location = GetCallerLocation(); |
| 555 const Instance& src_instance = Instance::CheckedHandle(arguments.ArgAt(0)); | 554 const Instance& src_instance = |
| 555 Instance::CheckedHandle(zone, arguments.ArgAt(0)); |
| 556 | 556 |
| 557 if (src_instance.IsNull()) { | 557 if (src_instance.IsNull()) { |
| 558 const Array& args = Array::Handle(Array::New(4)); | 558 const Array& args = Array::Handle(zone, Array::New(4)); |
| 559 args.SetAt(0, String::Handle( | 559 args.SetAt(0, String::Handle(zone, |
| 560 String::New("Failed assertion: boolean expression must not be null"))); | 560 String::New("Failed assertion: boolean expression must not be null"))); |
| 561 | 561 |
| 562 // No source code for this assertion, set url to null. | 562 // No source code for this assertion, set url to null. |
| 563 args.SetAt(1, String::Handle(String::null())); | 563 args.SetAt(1, String::Handle(zone, String::null())); |
| 564 args.SetAt(2, Smi::Handle(Smi::New(0))); | 564 args.SetAt(2, Smi::Handle(zone, Smi::New(0))); |
| 565 args.SetAt(3, Smi::Handle(Smi::New(0))); | 565 args.SetAt(3, Smi::Handle(zone, Smi::New(0))); |
| 566 | 566 |
| 567 Exceptions::ThrowByType(Exceptions::kAssertion, args); | 567 Exceptions::ThrowByType(Exceptions::kAssertion, args); |
| 568 UNREACHABLE(); | 568 UNREACHABLE(); |
| 569 } | 569 } |
| 570 | 570 |
| 571 ASSERT(!src_instance.IsBool()); | 571 ASSERT(!src_instance.IsBool()); |
| 572 const Type& bool_interface = Type::Handle(Type::BoolType()); | 572 const Type& bool_interface = Type::Handle(Type::BoolType()); |
| 573 const AbstractType& src_type = AbstractType::Handle(src_instance.GetType()); | 573 const AbstractType& src_type = |
| 574 const String& src_type_name = String::Handle(src_type.UserVisibleName()); | 574 AbstractType::Handle(zone, src_instance.GetType()); |
| 575 const String& bool_type_name = | 575 const String& no_bound_error = String::Handle(zone); |
| 576 String::Handle(bool_interface.UserVisibleName()); | 576 Exceptions::CreateAndThrowTypeError(location, src_type, bool_interface, |
| 577 const String& no_bound_error = String::Handle(); | |
| 578 Exceptions::CreateAndThrowTypeError(location, src_type_name, bool_type_name, | |
| 579 Symbols::BooleanExpression(), | 577 Symbols::BooleanExpression(), |
| 580 no_bound_error); | 578 no_bound_error); |
| 581 UNREACHABLE(); | 579 UNREACHABLE(); |
| 582 } | 580 } |
| 583 | 581 |
| 584 | 582 |
| 585 // Report that the type of the type check is malformed or malbounded. | 583 // Report that the type of the type check is malformed or malbounded. |
| 586 // Arg0: src value. | 584 // Arg0: src value. |
| 587 // Arg1: name of destination being assigned to. | 585 // Arg1: name of destination being assigned to. |
| 588 // Arg2: type of destination being assigned to. | 586 // Arg2: type of destination being assigned to. |
| 589 // Return value: none, throws an exception. | 587 // Return value: none, throws an exception. |
| 590 DEFINE_RUNTIME_ENTRY(BadTypeError, 3) { | 588 DEFINE_RUNTIME_ENTRY(BadTypeError, 3) { |
| 591 const TokenPosition location = GetCallerLocation(); | 589 const TokenPosition location = GetCallerLocation(); |
| 592 const Instance& src_value = Instance::CheckedHandle(arguments.ArgAt(0)); | 590 const Instance& src_value = Instance::CheckedHandle(zone, arguments.ArgAt(0)); |
| 593 const String& dst_name = String::CheckedHandle(arguments.ArgAt(1)); | 591 const String& dst_name = String::CheckedHandle(zone, arguments.ArgAt(1)); |
| 594 const AbstractType& dst_type = | 592 const AbstractType& dst_type = |
| 595 AbstractType::CheckedHandle(arguments.ArgAt(2)); | 593 AbstractType::CheckedHandle(zone, arguments.ArgAt(2)); |
| 596 const AbstractType& src_type = AbstractType::Handle(src_value.GetType()); | 594 const AbstractType& src_type = |
| 597 const String& src_type_name = String::Handle(src_type.UserVisibleName()); | 595 AbstractType::Handle(zone, src_value.GetType()); |
| 598 | |
| 599 String& dst_type_name = String::Handle(); | |
| 600 LanguageError& error = LanguageError::Handle(dst_type.error()); | |
| 601 ASSERT(!error.IsNull()); | |
| 602 if (error.kind() == Report::kMalformedType) { | |
| 603 dst_type_name = Symbols::Malformed().raw(); | |
| 604 } else { | |
| 605 ASSERT(error.kind() == Report::kMalboundedType); | |
| 606 dst_type_name = Symbols::Malbounded().raw(); | |
| 607 } | |
| 608 const String& error_message = String::ZoneHandle( | |
| 609 Symbols::New(error.ToErrorCString())); | |
| 610 Exceptions::CreateAndThrowTypeError( | 596 Exceptions::CreateAndThrowTypeError( |
| 611 location, src_type_name, dst_type_name, dst_name, error_message); | 597 location, src_type, dst_type, dst_name, String::Handle(zone)); |
| 612 UNREACHABLE(); | 598 UNREACHABLE(); |
| 613 } | 599 } |
| 614 | 600 |
| 615 | 601 |
| 616 DEFINE_RUNTIME_ENTRY(Throw, 1) { | 602 DEFINE_RUNTIME_ENTRY(Throw, 1) { |
| 617 const Instance& exception = | 603 const Instance& exception = |
| 618 Instance::CheckedHandle(zone, arguments.ArgAt(0)); | 604 Instance::CheckedHandle(zone, arguments.ArgAt(0)); |
| 619 Exceptions::Throw(thread, exception); | 605 Exceptions::Throw(thread, exception); |
| 620 } | 606 } |
| 621 | 607 |
| 622 | 608 |
| 623 DEFINE_RUNTIME_ENTRY(ReThrow, 2) { | 609 DEFINE_RUNTIME_ENTRY(ReThrow, 2) { |
| 624 const Instance& exception = | 610 const Instance& exception = |
| 625 Instance::CheckedHandle(zone, arguments.ArgAt(0)); | 611 Instance::CheckedHandle(zone, arguments.ArgAt(0)); |
| 626 const Instance& stacktrace = | 612 const Instance& stacktrace = |
| 627 Instance::CheckedHandle(zone, arguments.ArgAt(1)); | 613 Instance::CheckedHandle(zone, arguments.ArgAt(1)); |
| 628 Exceptions::ReThrow(thread, exception, stacktrace); | 614 Exceptions::ReThrow(thread, exception, stacktrace); |
| 629 } | 615 } |
| 630 | 616 |
| 631 | 617 |
| 632 // Patches static call in optimized code with the target's entry point. | 618 // Patches static call in optimized code with the target's entry point. |
| 633 // Compiles target if necessary. | 619 // Compiles target if necessary. |
| 634 DEFINE_RUNTIME_ENTRY(PatchStaticCall, 0) { | 620 DEFINE_RUNTIME_ENTRY(PatchStaticCall, 0) { |
| 635 DartFrameIterator iterator; | 621 DartFrameIterator iterator; |
| 636 StackFrame* caller_frame = iterator.NextFrame(); | 622 StackFrame* caller_frame = iterator.NextFrame(); |
| 637 ASSERT(caller_frame != NULL); | 623 ASSERT(caller_frame != NULL); |
| 638 const Code& caller_code = Code::Handle(caller_frame->LookupDartCode()); | 624 const Code& caller_code = Code::Handle(zone, caller_frame->LookupDartCode()); |
| 639 ASSERT(!caller_code.IsNull()); | 625 ASSERT(!caller_code.IsNull()); |
| 640 ASSERT(caller_code.is_optimized()); | 626 ASSERT(caller_code.is_optimized()); |
| 641 const Function& target_function = Function::Handle( | 627 const Function& target_function = Function::Handle( |
| 642 caller_code.GetStaticCallTargetFunctionAt(caller_frame->pc())); | 628 zone, caller_code.GetStaticCallTargetFunctionAt(caller_frame->pc())); |
| 643 if (!target_function.HasCode()) { | 629 if (!target_function.HasCode()) { |
| 644 const Error& error = | 630 const Error& error = |
| 645 Error::Handle(Compiler::CompileFunction(thread, target_function)); | 631 Error::Handle(zone, Compiler::CompileFunction(thread, target_function)); |
| 646 if (!error.IsNull()) { | 632 if (!error.IsNull()) { |
| 647 Exceptions::PropagateError(error); | 633 Exceptions::PropagateError(error); |
| 648 } | 634 } |
| 649 } | 635 } |
| 650 const Code& target_code = Code::Handle(target_function.CurrentCode()); | 636 const Code& target_code = Code::Handle(zone, target_function.CurrentCode()); |
| 651 // Before patching verify that we are not repeatedly patching to the same | 637 // Before patching verify that we are not repeatedly patching to the same |
| 652 // target. | 638 // target. |
| 653 ASSERT(target_code.raw() != | 639 ASSERT(target_code.raw() != |
| 654 CodePatcher::GetStaticCallTargetAt(caller_frame->pc(), caller_code)); | 640 CodePatcher::GetStaticCallTargetAt(caller_frame->pc(), caller_code)); |
| 655 CodePatcher::PatchStaticCallAt(caller_frame->pc(), | 641 CodePatcher::PatchStaticCallAt(caller_frame->pc(), |
| 656 caller_code, | 642 caller_code, |
| 657 target_code); | 643 target_code); |
| 658 caller_code.SetStaticCallTargetCodeAt(caller_frame->pc(), target_code); | 644 caller_code.SetStaticCallTargetCodeAt(caller_frame->pc(), target_code); |
| 659 if (FLAG_trace_patching) { | 645 if (FLAG_trace_patching) { |
| 660 THR_Print("PatchStaticCall: patching caller pc %#" Px "" | 646 THR_Print("PatchStaticCall: patching caller pc %#" Px "" |
| (...skipping 20 matching lines...) Expand all Loading... |
| 681 // set on a runtime stub call. | 667 // set on a runtime stub call. |
| 682 DEFINE_RUNTIME_ENTRY(BreakpointRuntimeHandler, 0) { | 668 DEFINE_RUNTIME_ENTRY(BreakpointRuntimeHandler, 0) { |
| 683 if (!FLAG_support_debugger) { | 669 if (!FLAG_support_debugger) { |
| 684 UNREACHABLE(); | 670 UNREACHABLE(); |
| 685 return; | 671 return; |
| 686 } | 672 } |
| 687 DartFrameIterator iterator; | 673 DartFrameIterator iterator; |
| 688 StackFrame* caller_frame = iterator.NextFrame(); | 674 StackFrame* caller_frame = iterator.NextFrame(); |
| 689 ASSERT(caller_frame != NULL); | 675 ASSERT(caller_frame != NULL); |
| 690 const Code& orig_stub = Code::Handle( | 676 const Code& orig_stub = Code::Handle( |
| 691 isolate->debugger()->GetPatchedStubAddress(caller_frame->pc())); | 677 zone, isolate->debugger()->GetPatchedStubAddress(caller_frame->pc())); |
| 692 const Error& error = Error::Handle(isolate->debugger()->SignalBpReached()); | 678 const Error& error = |
| 679 Error::Handle(zone, isolate->debugger()->SignalBpReached()); |
| 693 if (!error.IsNull()) { | 680 if (!error.IsNull()) { |
| 694 Exceptions::PropagateError(error); | 681 Exceptions::PropagateError(error); |
| 695 UNREACHABLE(); | 682 UNREACHABLE(); |
| 696 } | 683 } |
| 697 arguments.SetReturn(orig_stub); | 684 arguments.SetReturn(orig_stub); |
| 698 } | 685 } |
| 699 | 686 |
| 700 | 687 |
| 701 DEFINE_RUNTIME_ENTRY(SingleStepHandler, 0) { | 688 DEFINE_RUNTIME_ENTRY(SingleStepHandler, 0) { |
| 702 if (!FLAG_support_debugger) { | 689 if (!FLAG_support_debugger) { |
| 703 UNREACHABLE(); | 690 UNREACHABLE(); |
| 704 return; | 691 return; |
| 705 } | 692 } |
| 706 const Error& error = | 693 const Error& error = |
| 707 Error::Handle(isolate->debugger()->DebuggerStepCallback()); | 694 Error::Handle(zone, isolate->debugger()->DebuggerStepCallback()); |
| 708 if (!error.IsNull()) { | 695 if (!error.IsNull()) { |
| 709 Exceptions::PropagateError(error); | 696 Exceptions::PropagateError(error); |
| 710 UNREACHABLE(); | 697 UNREACHABLE(); |
| 711 } | 698 } |
| 712 } | 699 } |
| 713 | 700 |
| 714 | 701 |
| 715 // An instance call of the form o.f(...) could not be resolved. Check if | 702 // An instance call of the form o.f(...) could not be resolved. Check if |
| 716 // there is a getter with the same name. If so, invoke it. If the value is | 703 // there is a getter with the same name. If so, invoke it. If the value is |
| 717 // a closure, invoke it with the given arguments. If the value is a | 704 // a closure, invoke it with the given arguments. If the value is a |
| (...skipping 1174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1892 const intptr_t elm_size = old_data.ElementSizeInBytes(); | 1879 const intptr_t elm_size = old_data.ElementSizeInBytes(); |
| 1893 const TypedData& new_data = | 1880 const TypedData& new_data = |
| 1894 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); | 1881 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); |
| 1895 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); | 1882 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); |
| 1896 typed_data_cell.SetAt(0, new_data); | 1883 typed_data_cell.SetAt(0, new_data); |
| 1897 arguments.SetReturn(new_data); | 1884 arguments.SetReturn(new_data); |
| 1898 } | 1885 } |
| 1899 | 1886 |
| 1900 | 1887 |
| 1901 } // namespace dart | 1888 } // namespace dart |
| OLD | NEW |