| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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/object.h" | 5 #include "vm/object.h" |
| 6 | 6 |
| 7 #include "vm/hash_table.h" | 7 #include "vm/hash_table.h" |
| 8 #include "vm/isolate_reload.h" | 8 #include "vm/isolate_reload.h" |
| 9 #include "vm/log.h" | 9 #include "vm/log.h" |
| 10 #include "vm/resolver.h" | 10 #include "vm/resolver.h" |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 ASSERT(!edge_counters_array.IsNull()); | 51 ASSERT(!edge_counters_array.IsNull()); |
| 52 // Fill edge counters array with zeros. | 52 // Fill edge counters array with zeros. |
| 53 const Smi& zero = Smi::Handle(Smi::New(0)); | 53 const Smi& zero = Smi::Handle(Smi::New(0)); |
| 54 for (intptr_t i = 0; i < edge_counters_array.Length(); i++) { | 54 for (intptr_t i = 0; i < edge_counters_array.Length(); i++) { |
| 55 edge_counters_array.SetAt(i, zero); | 55 edge_counters_array.SetAt(i, zero); |
| 56 } | 56 } |
| 57 } | 57 } |
| 58 | 58 |
| 59 | 59 |
| 60 void Code::ResetICDatas(Zone* zone) const { | 60 void Code::ResetICDatas(Zone* zone) const { |
| 61 // Iterate over the Code's object pool and reset all ICDatas. | 61 // Iterate over the Code's object pool and reset all ICDatas. |
| 62 #ifdef TARGET_ARCH_IA32 | 62 #ifdef TARGET_ARCH_IA32 |
| 63 // IA32 does not have an object pool, but, we can iterate over all | 63 // IA32 does not have an object pool, but, we can iterate over all |
| 64 // embedded objects by using the variable length data section. | 64 // embedded objects by using the variable length data section. |
| 65 if (!is_alive()) { | 65 if (!is_alive()) { |
| 66 return; | 66 return; |
| 67 } | 67 } |
| 68 const Instructions& instrs = Instructions::Handle(zone, instructions()); | 68 const Instructions& instrs = Instructions::Handle(zone, instructions()); |
| 69 ASSERT(!instrs.IsNull()); | 69 ASSERT(!instrs.IsNull()); |
| 70 uword base_address = instrs.PayloadStart(); | 70 uword base_address = instrs.PayloadStart(); |
| 71 Object& object = Object::Handle(zone); | 71 Object& object = Object::Handle(zone); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 154 const Array& my_constants = Array::Handle(constants()); | 154 const Array& my_constants = Array::Handle(constants()); |
| 155 ASSERT(my_constants.Length() == 0); | 155 ASSERT(my_constants.Length() == 0); |
| 156 } | 156 } |
| 157 #endif // defined(DEBUG). | 157 #endif // defined(DEBUG). |
| 158 // Copy old constants into new class. | 158 // Copy old constants into new class. |
| 159 const Array& old_constants = Array::Handle(old_cls.constants()); | 159 const Array& old_constants = Array::Handle(old_cls.constants()); |
| 160 if (old_constants.IsNull() || old_constants.Length() == 0) { | 160 if (old_constants.IsNull() || old_constants.Length() == 0) { |
| 161 return; | 161 return; |
| 162 } | 162 } |
| 163 TIR_Print("Copied %" Pd " canonical constants for class `%s`\n", | 163 TIR_Print("Copied %" Pd " canonical constants for class `%s`\n", |
| 164 old_constants.Length(), | 164 old_constants.Length(), ToCString()); |
| 165 ToCString()); | |
| 166 set_constants(old_constants); | 165 set_constants(old_constants); |
| 167 } | 166 } |
| 168 | 167 |
| 169 | 168 |
| 170 void Class::CopyCanonicalType(const Class& old_cls) const { | 169 void Class::CopyCanonicalType(const Class& old_cls) const { |
| 171 const Type& old_canonical_type = Type::Handle(old_cls.canonical_type()); | 170 const Type& old_canonical_type = Type::Handle(old_cls.canonical_type()); |
| 172 if (old_canonical_type.IsNull()) { | 171 if (old_canonical_type.IsNull()) { |
| 173 return; | 172 return; |
| 174 } | 173 } |
| 175 set_canonical_type(old_canonical_type); | 174 set_canonical_type(old_canonical_type); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 231 | 230 |
| 232 Array& enum_fields = Array::Handle(zone); | 231 Array& enum_fields = Array::Handle(zone); |
| 233 Field& field = Field::Handle(zone); | 232 Field& field = Field::Handle(zone); |
| 234 String& enum_ident = String::Handle(); | 233 String& enum_ident = String::Handle(); |
| 235 Instance& old_enum_value = Instance::Handle(zone); | 234 Instance& old_enum_value = Instance::Handle(zone); |
| 236 Instance& enum_value = Instance::Handle(zone); | 235 Instance& enum_value = Instance::Handle(zone); |
| 237 // The E.values array. | 236 // The E.values array. |
| 238 Instance& old_enum_values = Instance::Handle(zone); | 237 Instance& old_enum_values = Instance::Handle(zone); |
| 239 // The E.values array. | 238 // The E.values array. |
| 240 Instance& enum_values = Instance::Handle(zone); | 239 Instance& enum_values = Instance::Handle(zone); |
| 241 Array& enum_map_storage = Array::Handle(zone, | 240 Array& enum_map_storage = |
| 242 HashTables::New<UnorderedHashMap<EnumMapTraits> >(4)); | 241 Array::Handle(zone, HashTables::New<UnorderedHashMap<EnumMapTraits> >(4)); |
| 243 ASSERT(!enum_map_storage.IsNull()); | 242 ASSERT(!enum_map_storage.IsNull()); |
| 244 | 243 |
| 245 TIR_Print("Replacing enum `%s`\n", String::Handle(Name()).ToCString()); | 244 TIR_Print("Replacing enum `%s`\n", String::Handle(Name()).ToCString()); |
| 246 | 245 |
| 247 { | 246 { |
| 248 UnorderedHashMap<EnumMapTraits> enum_map(enum_map_storage.raw()); | 247 UnorderedHashMap<EnumMapTraits> enum_map(enum_map_storage.raw()); |
| 249 // Build a map of all enum name -> old enum instance. | 248 // Build a map of all enum name -> old enum instance. |
| 250 enum_fields = old_enum.fields(); | 249 enum_fields = old_enum.fields(); |
| 251 for (intptr_t i = 0; i < enum_fields.Length(); i++) { | 250 for (intptr_t i = 0; i < enum_fields.Length(); i++) { |
| 252 field = Field::RawCast(enum_fields.At(i)); | 251 field = Field::RawCast(enum_fields.At(i)); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 309 enum_map_storage = enum_map.Release().raw(); | 308 enum_map_storage = enum_map.Release().raw(); |
| 310 } | 309 } |
| 311 | 310 |
| 312 // Map the old E.values array to the new E.values array. | 311 // Map the old E.values array to the new E.values array. |
| 313 ASSERT(!old_enum_values.IsNull()); | 312 ASSERT(!old_enum_values.IsNull()); |
| 314 ASSERT(!enum_values.IsNull()); | 313 ASSERT(!enum_values.IsNull()); |
| 315 reload_context->AddEnumBecomeMapping(old_enum_values, enum_values); | 314 reload_context->AddEnumBecomeMapping(old_enum_values, enum_values); |
| 316 | 315 |
| 317 if (enums_deleted && FLAG_trace_reload_verbose) { | 316 if (enums_deleted && FLAG_trace_reload_verbose) { |
| 318 // TODO(johnmccutchan): Add this to the reload 'notices' list. | 317 // TODO(johnmccutchan): Add this to the reload 'notices' list. |
| 319 VTIR_Print("The following enum values were deleted and are forever lost in " | 318 VTIR_Print( |
| 320 "the heap:\n"); | 319 "The following enum values were deleted and are forever lost in " |
| 320 "the heap:\n"); |
| 321 UnorderedHashMap<EnumMapTraits> enum_map(enum_map_storage.raw()); | 321 UnorderedHashMap<EnumMapTraits> enum_map(enum_map_storage.raw()); |
| 322 UnorderedHashMap<EnumMapTraits>::Iterator it(&enum_map); | 322 UnorderedHashMap<EnumMapTraits>::Iterator it(&enum_map); |
| 323 while (it.MoveNext()) { | 323 while (it.MoveNext()) { |
| 324 const intptr_t entry = it.Current(); | 324 const intptr_t entry = it.Current(); |
| 325 enum_ident = String::RawCast(enum_map.GetKey(entry)); | 325 enum_ident = String::RawCast(enum_map.GetKey(entry)); |
| 326 ASSERT(!enum_ident.IsNull()); | 326 ASSERT(!enum_ident.IsNull()); |
| 327 } | 327 } |
| 328 enum_map.Release(); | 328 enum_map.Release(); |
| 329 } | 329 } |
| 330 } | 330 } |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 378 void Class::MigrateImplicitStaticClosures(IsolateReloadContext* irc, | 378 void Class::MigrateImplicitStaticClosures(IsolateReloadContext* irc, |
| 379 const Class& new_cls) const { | 379 const Class& new_cls) const { |
| 380 const Array& funcs = Array::Handle(functions()); | 380 const Array& funcs = Array::Handle(functions()); |
| 381 Function& old_func = Function::Handle(); | 381 Function& old_func = Function::Handle(); |
| 382 String& selector = String::Handle(); | 382 String& selector = String::Handle(); |
| 383 Function& new_func = Function::Handle(); | 383 Function& new_func = Function::Handle(); |
| 384 Instance& old_closure = Instance::Handle(); | 384 Instance& old_closure = Instance::Handle(); |
| 385 Instance& new_closure = Instance::Handle(); | 385 Instance& new_closure = Instance::Handle(); |
| 386 for (intptr_t i = 0; i < funcs.Length(); i++) { | 386 for (intptr_t i = 0; i < funcs.Length(); i++) { |
| 387 old_func ^= funcs.At(i); | 387 old_func ^= funcs.At(i); |
| 388 if (old_func.is_static() && | 388 if (old_func.is_static() && old_func.HasImplicitClosureFunction()) { |
| 389 old_func.HasImplicitClosureFunction()) { | |
| 390 selector = old_func.name(); | 389 selector = old_func.name(); |
| 391 new_func = new_cls.LookupFunction(selector); | 390 new_func = new_cls.LookupFunction(selector); |
| 392 if (!new_func.IsNull() && new_func.is_static()) { | 391 if (!new_func.IsNull() && new_func.is_static()) { |
| 393 old_func = old_func.ImplicitClosureFunction(); | 392 old_func = old_func.ImplicitClosureFunction(); |
| 394 old_closure = old_func.ImplicitStaticClosure(); | 393 old_closure = old_func.ImplicitStaticClosure(); |
| 395 new_func = new_func.ImplicitClosureFunction(); | 394 new_func = new_func.ImplicitClosureFunction(); |
| 396 new_closure = new_func.ImplicitStaticClosure(); | 395 new_closure = new_func.ImplicitStaticClosure(); |
| 397 if (old_closure.IsCanonical()) { | 396 if (old_closure.IsCanonical()) { |
| 398 new_closure.SetCanonical(); | 397 new_closure.SetCanonical(); |
| 399 } | 398 } |
| 400 irc->AddBecomeMapping(old_closure, new_closure); | 399 irc->AddBecomeMapping(old_closure, new_closure); |
| 401 } | 400 } |
| 402 } | 401 } |
| 403 } | 402 } |
| 404 } | 403 } |
| 405 | 404 |
| 406 | 405 |
| 407 class EnumClassConflict : public ClassReasonForCancelling { | 406 class EnumClassConflict : public ClassReasonForCancelling { |
| 408 public: | 407 public: |
| 409 EnumClassConflict(Zone* zone, const Class& from, const Class& to) | 408 EnumClassConflict(Zone* zone, const Class& from, const Class& to) |
| 410 : ClassReasonForCancelling(zone, from, to) { } | 409 : ClassReasonForCancelling(zone, from, to) {} |
| 411 | 410 |
| 412 RawString* ToString() { | 411 RawString* ToString() { |
| 413 return String::NewFormatted( | 412 return String::NewFormatted( |
| 414 from_.is_enum_class() | 413 from_.is_enum_class() |
| 415 ? "Enum class cannot be redefined to be a non-enum class: %s" | 414 ? "Enum class cannot be redefined to be a non-enum class: %s" |
| 416 : "Class cannot be redefined to be a enum class: %s", | 415 : "Class cannot be redefined to be a enum class: %s", |
| 417 from_.ToCString()); | 416 from_.ToCString()); |
| 418 } | 417 } |
| 419 }; | 418 }; |
| 420 | 419 |
| 421 | 420 |
| 422 class EnsureFinalizedError : public ClassReasonForCancelling { | 421 class EnsureFinalizedError : public ClassReasonForCancelling { |
| 423 public: | 422 public: |
| 424 EnsureFinalizedError(Zone* zone, | 423 EnsureFinalizedError(Zone* zone, |
| 425 const Class& from, | 424 const Class& from, |
| 426 const Class& to, | 425 const Class& to, |
| 427 const Error& error) | 426 const Error& error) |
| 428 : ClassReasonForCancelling(zone, from, to), error_(error) { } | 427 : ClassReasonForCancelling(zone, from, to), error_(error) {} |
| 429 | 428 |
| 430 private: | 429 private: |
| 431 const Error& error_; | 430 const Error& error_; |
| 432 | 431 |
| 433 RawError* ToError() { return error_.raw(); } | 432 RawError* ToError() { return error_.raw(); } |
| 434 | 433 |
| 435 RawString* ToString() { | 434 RawString* ToString() { return String::New(error_.ToErrorCString()); } |
| 436 return String::New(error_.ToErrorCString()); | |
| 437 } | |
| 438 }; | 435 }; |
| 439 | 436 |
| 440 | 437 |
| 441 class NativeFieldsConflict : public ClassReasonForCancelling { | 438 class NativeFieldsConflict : public ClassReasonForCancelling { |
| 442 public: | 439 public: |
| 443 NativeFieldsConflict(Zone* zone, const Class& from, const Class& to) | 440 NativeFieldsConflict(Zone* zone, const Class& from, const Class& to) |
| 444 : ClassReasonForCancelling(zone, from, to) { } | 441 : ClassReasonForCancelling(zone, from, to) {} |
| 445 | 442 |
| 446 private: | 443 private: |
| 447 RawString* ToString() { | 444 RawString* ToString() { |
| 448 return String::NewFormatted( | 445 return String::NewFormatted("Number of native fields changed in %s", |
| 449 "Number of native fields changed in %s", from_.ToCString()); | 446 from_.ToCString()); |
| 450 } | 447 } |
| 451 }; | 448 }; |
| 452 | 449 |
| 453 | 450 |
| 454 class TypeParametersChanged : public ClassReasonForCancelling { | 451 class TypeParametersChanged : public ClassReasonForCancelling { |
| 455 public: | 452 public: |
| 456 TypeParametersChanged(Zone* zone, const Class& from, const Class& to) | 453 TypeParametersChanged(Zone* zone, const Class& from, const Class& to) |
| 457 : ClassReasonForCancelling(zone, from, to) {} | 454 : ClassReasonForCancelling(zone, from, to) {} |
| 458 | 455 |
| 459 RawString* ToString() { | 456 RawString* ToString() { |
| 460 return String::NewFormatted( | 457 return String::NewFormatted( |
| 461 "Limitation: type parameters have changed for %s", from_.ToCString()); | 458 "Limitation: type parameters have changed for %s", from_.ToCString()); |
| 462 } | 459 } |
| 463 | 460 |
| 464 void AppendTo(JSONArray* array) { | 461 void AppendTo(JSONArray* array) { |
| 465 JSONObject jsobj(array); | 462 JSONObject jsobj(array); |
| 466 jsobj.AddProperty("type", "ReasonForCancellingReload"); | 463 jsobj.AddProperty("type", "ReasonForCancellingReload"); |
| 467 jsobj.AddProperty("kind", "TypeParametersChanged"); | 464 jsobj.AddProperty("kind", "TypeParametersChanged"); |
| 468 jsobj.AddProperty("class", to_); | 465 jsobj.AddProperty("class", to_); |
| 469 jsobj.AddProperty("message", | 466 jsobj.AddProperty("message", |
| 470 "Limitation: changing type parameters " | 467 "Limitation: changing type parameters " |
| 471 "does not work with hot reload."); | 468 "does not work with hot reload."); |
| 472 } | 469 } |
| 473 }; | 470 }; |
| 474 | 471 |
| 475 | 472 |
| 476 class PreFinalizedConflict : public ClassReasonForCancelling { | 473 class PreFinalizedConflict : public ClassReasonForCancelling { |
| 477 public: | 474 public: |
| 478 PreFinalizedConflict(Zone* zone, const Class& from, const Class& to) | 475 PreFinalizedConflict(Zone* zone, const Class& from, const Class& to) |
| 479 : ClassReasonForCancelling(zone, from, to) {} | 476 : ClassReasonForCancelling(zone, from, to) {} |
| 480 | 477 |
| 481 private: | 478 private: |
| 482 RawString* ToString() { | 479 RawString* ToString() { |
| 483 return String::NewFormatted( | 480 return String::NewFormatted( |
| 484 "Original class ('%s') is prefinalized and replacement class " | 481 "Original class ('%s') is prefinalized and replacement class " |
| 485 "('%s') is not ", | 482 "('%s') is not ", |
| 486 from_.ToCString(), to_.ToCString()); | 483 from_.ToCString(), to_.ToCString()); |
| 487 } | 484 } |
| 488 }; | 485 }; |
| 489 | 486 |
| 490 | 487 |
| 491 class InstanceSizeConflict : public ClassReasonForCancelling { | 488 class InstanceSizeConflict : public ClassReasonForCancelling { |
| 492 public: | 489 public: |
| 493 InstanceSizeConflict(Zone* zone, const Class& from, const Class& to) | 490 InstanceSizeConflict(Zone* zone, const Class& from, const Class& to) |
| 494 : ClassReasonForCancelling(zone, from, to) {} | 491 : ClassReasonForCancelling(zone, from, to) {} |
| 495 | 492 |
| 496 private: | 493 private: |
| 497 RawString* ToString() { | 494 RawString* ToString() { |
| 498 return String::NewFormatted( | 495 return String::NewFormatted("Instance size mismatch between '%s' (%" Pd |
| 499 "Instance size mismatch between '%s' (%" Pd ") and replacement " | 496 ") and replacement " |
| 500 "'%s' ( %" Pd ")", | 497 "'%s' ( %" Pd ")", |
| 501 from_.ToCString(), | 498 from_.ToCString(), from_.instance_size(), |
| 502 from_.instance_size(), | 499 to_.ToCString(), to_.instance_size()); |
| 503 to_.ToCString(), | |
| 504 to_.instance_size()); | |
| 505 } | 500 } |
| 506 }; | 501 }; |
| 507 | 502 |
| 508 | 503 |
| 509 class UnimplementedDeferredLibrary : public ReasonForCancelling { | 504 class UnimplementedDeferredLibrary : public ReasonForCancelling { |
| 510 public: | 505 public: |
| 511 UnimplementedDeferredLibrary(Zone* zone, | 506 UnimplementedDeferredLibrary(Zone* zone, |
| 512 const Library& from, | 507 const Library& from, |
| 513 const Library& to, | 508 const Library& to, |
| 514 const String& name) | 509 const String& name) |
| (...skipping 15 matching lines...) Expand all Loading... |
| 530 }; | 525 }; |
| 531 | 526 |
| 532 | 527 |
| 533 // This is executed before interating over the instances. | 528 // This is executed before interating over the instances. |
| 534 void Class::CheckReload(const Class& replacement, | 529 void Class::CheckReload(const Class& replacement, |
| 535 IsolateReloadContext* context) const { | 530 IsolateReloadContext* context) const { |
| 536 ASSERT(IsolateReloadContext::IsSameClass(*this, replacement)); | 531 ASSERT(IsolateReloadContext::IsSameClass(*this, replacement)); |
| 537 | 532 |
| 538 // Class cannot change enum property. | 533 // Class cannot change enum property. |
| 539 if (is_enum_class() != replacement.is_enum_class()) { | 534 if (is_enum_class() != replacement.is_enum_class()) { |
| 540 context->AddReasonForCancelling( | 535 context->AddReasonForCancelling(new (context->zone()) EnumClassConflict( |
| 541 new(context->zone()) | 536 context->zone(), *this, replacement)); |
| 542 EnumClassConflict(context->zone(), *this, replacement)); | |
| 543 return; | 537 return; |
| 544 } | 538 } |
| 545 | 539 |
| 546 if (is_finalized()) { | 540 if (is_finalized()) { |
| 547 // Ensure the replacement class is also finalized. | 541 // Ensure the replacement class is also finalized. |
| 548 const Error& error = | 542 const Error& error = |
| 549 Error::Handle(replacement.EnsureIsFinalized(Thread::Current())); | 543 Error::Handle(replacement.EnsureIsFinalized(Thread::Current())); |
| 550 if (!error.IsNull()) { | 544 if (!error.IsNull()) { |
| 551 context->AddReasonForCancelling( | 545 context->AddReasonForCancelling( |
| 552 new(context->zone()) | 546 new (context->zone()) |
| 553 EnsureFinalizedError(context->zone(), *this, replacement, error)); | 547 EnsureFinalizedError(context->zone(), *this, replacement, error)); |
| 554 return; // No reason to check other properties. | 548 return; // No reason to check other properties. |
| 555 } | 549 } |
| 556 ASSERT(replacement.is_finalized()); | 550 ASSERT(replacement.is_finalized()); |
| 557 TIR_Print("Finalized replacement class for %s\n", ToCString()); | 551 TIR_Print("Finalized replacement class for %s\n", ToCString()); |
| 558 } | 552 } |
| 559 | 553 |
| 560 // Native field count cannot change. | 554 // Native field count cannot change. |
| 561 if (num_native_fields() != replacement.num_native_fields()) { | 555 if (num_native_fields() != replacement.num_native_fields()) { |
| 562 context->AddReasonForCancelling( | 556 context->AddReasonForCancelling(new (context->zone()) NativeFieldsConflict( |
| 563 new(context->zone()) | 557 context->zone(), *this, replacement)); |
| 564 NativeFieldsConflict(context->zone(), *this, replacement)); | 558 return; |
| 565 return; | |
| 566 } | 559 } |
| 567 | 560 |
| 568 // Just checking. | 561 // Just checking. |
| 569 ASSERT(is_enum_class() == replacement.is_enum_class()); | 562 ASSERT(is_enum_class() == replacement.is_enum_class()); |
| 570 ASSERT(num_native_fields() == replacement.num_native_fields()); | 563 ASSERT(num_native_fields() == replacement.num_native_fields()); |
| 571 | 564 |
| 572 if (is_finalized()) { | 565 if (is_finalized()) { |
| 573 if (!CanReloadFinalized(replacement, context)) return; | 566 if (!CanReloadFinalized(replacement, context)) return; |
| 574 } | 567 } |
| 575 if (is_prefinalized()) { | 568 if (is_prefinalized()) { |
| 576 if (!CanReloadPreFinalized(replacement, context)) return; | 569 if (!CanReloadPreFinalized(replacement, context)) return; |
| 577 } | 570 } |
| 578 ASSERT(is_finalized() == replacement.is_finalized()); | 571 ASSERT(is_finalized() == replacement.is_finalized()); |
| 579 TIR_Print("Class `%s` can be reloaded (%" Pd " and %" Pd ")\n", | 572 TIR_Print("Class `%s` can be reloaded (%" Pd " and %" Pd ")\n", ToCString(), |
| 580 ToCString(), id(), replacement.id()); | 573 id(), replacement.id()); |
| 581 } | 574 } |
| 582 | 575 |
| 583 | 576 |
| 584 | |
| 585 bool Class::RequiresInstanceMorphing(const Class& replacement) const { | 577 bool Class::RequiresInstanceMorphing(const Class& replacement) const { |
| 586 // Get the field maps for both classes. These field maps walk the class | 578 // Get the field maps for both classes. These field maps walk the class |
| 587 // hierarchy. | 579 // hierarchy. |
| 588 const Array& fields = Array::Handle(OffsetToFieldMap()); | 580 const Array& fields = Array::Handle(OffsetToFieldMap()); |
| 589 const Array& replacement_fields | 581 const Array& replacement_fields = |
| 590 = Array::Handle(replacement.OffsetToFieldMap()); | 582 Array::Handle(replacement.OffsetToFieldMap()); |
| 591 | 583 |
| 592 // Check that the size of the instance is the same. | 584 // Check that the size of the instance is the same. |
| 593 if (fields.Length() != replacement_fields.Length()) return true; | 585 if (fields.Length() != replacement_fields.Length()) return true; |
| 594 | 586 |
| 595 // Check that we have the same next field offset. This check is not | 587 // Check that we have the same next field offset. This check is not |
| 596 // redundant with the one above because the instance OffsetToFieldMap | 588 // redundant with the one above because the instance OffsetToFieldMap |
| 597 // array length is based on the instance size (which may be aligned up). | 589 // array length is based on the instance size (which may be aligned up). |
| 598 if (next_field_offset() != replacement.next_field_offset()) return true; | 590 if (next_field_offset() != replacement.next_field_offset()) return true; |
| 599 | 591 |
| 600 // Verify that field names / offsets match across the entire hierarchy. | 592 // Verify that field names / offsets match across the entire hierarchy. |
| (...skipping 19 matching lines...) Expand all Loading... |
| 620 | 612 |
| 621 bool Class::CanReloadFinalized(const Class& replacement, | 613 bool Class::CanReloadFinalized(const Class& replacement, |
| 622 IsolateReloadContext* context) const { | 614 IsolateReloadContext* context) const { |
| 623 // Make sure the declaration types matches for the two classes. | 615 // Make sure the declaration types matches for the two classes. |
| 624 // ex. class A<int,B> {} cannot be replace with class A<B> {}. | 616 // ex. class A<int,B> {} cannot be replace with class A<B> {}. |
| 625 | 617 |
| 626 const AbstractType& dt = AbstractType::Handle(DeclarationType()); | 618 const AbstractType& dt = AbstractType::Handle(DeclarationType()); |
| 627 const AbstractType& replacement_dt = | 619 const AbstractType& replacement_dt = |
| 628 AbstractType::Handle(replacement.DeclarationType()); | 620 AbstractType::Handle(replacement.DeclarationType()); |
| 629 if (!dt.Equals(replacement_dt)) { | 621 if (!dt.Equals(replacement_dt)) { |
| 630 context->AddReasonForCancelling( | 622 context->AddReasonForCancelling(new (context->zone()) TypeParametersChanged( |
| 631 new(context->zone()) | 623 context->zone(), *this, replacement)); |
| 632 TypeParametersChanged(context->zone(), *this, replacement)); | |
| 633 return false; | 624 return false; |
| 634 } | 625 } |
| 635 if (RequiresInstanceMorphing(replacement)) { | 626 if (RequiresInstanceMorphing(replacement)) { |
| 636 context->AddInstanceMorpher( | 627 context->AddInstanceMorpher(new (context->zone()) InstanceMorpher( |
| 637 new(context->zone()) | 628 context->zone(), *this, replacement)); |
| 638 InstanceMorpher(context->zone(), *this, replacement)); | |
| 639 } | 629 } |
| 640 return true; | 630 return true; |
| 641 } | 631 } |
| 642 | 632 |
| 643 | 633 |
| 644 bool Class::CanReloadPreFinalized(const Class& replacement, | 634 bool Class::CanReloadPreFinalized(const Class& replacement, |
| 645 IsolateReloadContext* context) const { | 635 IsolateReloadContext* context) const { |
| 646 // The replacement class must also prefinalized. | 636 // The replacement class must also prefinalized. |
| 647 if (!replacement.is_prefinalized()) { | 637 if (!replacement.is_prefinalized()) { |
| 648 context->AddReasonForCancelling( | 638 context->AddReasonForCancelling(new (context->zone()) PreFinalizedConflict( |
| 649 new(context->zone()) | 639 context->zone(), *this, replacement)); |
| 650 PreFinalizedConflict(context->zone(), *this, replacement)); | 640 return false; |
| 651 return false; | |
| 652 } | 641 } |
| 653 // Check the instance sizes are equal. | 642 // Check the instance sizes are equal. |
| 654 if (instance_size() != replacement.instance_size()) { | 643 if (instance_size() != replacement.instance_size()) { |
| 655 context->AddReasonForCancelling( | 644 context->AddReasonForCancelling(new (context->zone()) InstanceSizeConflict( |
| 656 new(context->zone()) | 645 context->zone(), *this, replacement)); |
| 657 InstanceSizeConflict(context->zone(), *this, replacement)); | 646 return false; |
| 658 return false; | |
| 659 } | 647 } |
| 660 return true; | 648 return true; |
| 661 } | 649 } |
| 662 | 650 |
| 663 | 651 |
| 664 void Library::CheckReload(const Library& replacement, | 652 void Library::CheckReload(const Library& replacement, |
| 665 IsolateReloadContext* context) const { | 653 IsolateReloadContext* context) const { |
| 666 // TODO(26878): If the replacement library uses deferred loading, | 654 // TODO(26878): If the replacement library uses deferred loading, |
| 667 // reject it. We do not yet support reloading deferred libraries. | 655 // reject it. We do not yet support reloading deferred libraries. |
| 668 LibraryPrefix& prefix = LibraryPrefix::Handle(); | 656 LibraryPrefix& prefix = LibraryPrefix::Handle(); |
| 669 LibraryPrefixIterator it(replacement); | 657 LibraryPrefixIterator it(replacement); |
| 670 while (it.HasNext()) { | 658 while (it.HasNext()) { |
| 671 prefix = it.GetNext(); | 659 prefix = it.GetNext(); |
| 672 if (prefix.is_deferred_load()) { | 660 if (prefix.is_deferred_load()) { |
| 673 const String& prefix_name = String::Handle(prefix.name()); | 661 const String& prefix_name = String::Handle(prefix.name()); |
| 674 context->AddReasonForCancelling( | 662 context->AddReasonForCancelling( |
| 675 new(context->zone()) | 663 new (context->zone()) UnimplementedDeferredLibrary( |
| 676 UnimplementedDeferredLibrary(context->zone(), | 664 context->zone(), *this, replacement, prefix_name)); |
| 677 *this, replacement, prefix_name)); | |
| 678 return; | 665 return; |
| 679 } | 666 } |
| 680 } | 667 } |
| 681 } | 668 } |
| 682 | 669 |
| 683 | 670 |
| 684 static const Function* static_call_target = NULL; | 671 static const Function* static_call_target = NULL; |
| 685 | 672 |
| 686 | 673 |
| 687 void ICData::Reset(Zone* zone) const { | 674 void ICData::Reset(Zone* zone) const { |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 734 cls = cls.SuperClass(); | 721 cls = cls.SuperClass(); |
| 735 } | 722 } |
| 736 } else { | 723 } else { |
| 737 // This can be incorrect if the call site was an unqualified invocation. | 724 // This can be incorrect if the call site was an unqualified invocation. |
| 738 const Class& cls = Class::Handle(zone, old_target.Owner()); | 725 const Class& cls = Class::Handle(zone, old_target.Owner()); |
| 739 new_target = cls.LookupStaticFunction(selector); | 726 new_target = cls.LookupStaticFunction(selector); |
| 740 } | 727 } |
| 741 | 728 |
| 742 const Array& args_desc_array = Array::Handle(zone, arguments_descriptor()); | 729 const Array& args_desc_array = Array::Handle(zone, arguments_descriptor()); |
| 743 ArgumentsDescriptor args_desc(args_desc_array); | 730 ArgumentsDescriptor args_desc(args_desc_array); |
| 744 if (new_target.IsNull() || | 731 if (new_target.IsNull() || !new_target.AreValidArguments(args_desc, NULL)) { |
| 745 !new_target.AreValidArguments(args_desc, NULL)) { | |
| 746 // TODO(rmacnak): Patch to a NSME stub. | 732 // TODO(rmacnak): Patch to a NSME stub. |
| 747 VTIR_Print("Cannot rebind static call to %s from %s\n", | 733 VTIR_Print("Cannot rebind static call to %s from %s\n", |
| 748 old_target.ToCString(), | 734 old_target.ToCString(), |
| 749 Object::Handle(zone, Owner()).ToCString()); | 735 Object::Handle(zone, Owner()).ToCString()); |
| 750 return; | 736 return; |
| 751 } | 737 } |
| 752 ClearAndSetStaticTarget(new_target); | 738 ClearAndSetStaticTarget(new_target); |
| 753 } else { | 739 } else { |
| 754 intptr_t num_args = NumArgsTested(); | 740 intptr_t num_args = NumArgsTested(); |
| 755 if (num_args == 2) { | 741 if (num_args == 2) { |
| 756 ClearWithSentinel(); | 742 ClearWithSentinel(); |
| 757 } else { | 743 } else { |
| 758 const Array& data_array = | 744 const Array& data_array = |
| 759 Array::Handle(zone, CachedEmptyICDataArray(num_args)); | 745 Array::Handle(zone, CachedEmptyICDataArray(num_args)); |
| 760 set_ic_data_array(data_array); | 746 set_ic_data_array(data_array); |
| 761 } | 747 } |
| 762 } | 748 } |
| 763 } | 749 } |
| 764 | 750 |
| 765 #endif // !PRODUCT | 751 #endif // !PRODUCT |
| 766 | 752 |
| 767 } // namespace dart. | 753 } // namespace dart. |
| OLD | NEW |