| 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" |
| 11 #include "vm/symbols.h" | 11 #include "vm/symbols.h" |
| 12 | 12 |
| 13 namespace dart { | 13 namespace dart { |
| 14 | 14 |
| 15 #ifndef PRODUCT | 15 #ifndef PRODUCT |
| 16 | 16 |
| 17 DECLARE_FLAG(bool, trace_reload); | 17 DECLARE_FLAG(bool, trace_reload); |
| 18 DECLARE_FLAG(bool, trace_reload_verbose); | 18 DECLARE_FLAG(bool, trace_reload_verbose); |
| 19 DECLARE_FLAG(bool, two_args_smi_icd); | 19 DECLARE_FLAG(bool, two_args_smi_icd); |
| 20 | 20 |
| 21 | |
| 22 class ObjectReloadUtils : public AllStatic { | 21 class ObjectReloadUtils : public AllStatic { |
| 23 static void DumpLibraryDictionary(const Library& lib) { | 22 static void DumpLibraryDictionary(const Library& lib) { |
| 24 DictionaryIterator it(lib); | 23 DictionaryIterator it(lib); |
| 25 Object& entry = Object::Handle(); | 24 Object& entry = Object::Handle(); |
| 26 String& name = String::Handle(); | 25 String& name = String::Handle(); |
| 27 TIR_Print("Dumping dictionary for %s\n", lib.ToCString()); | 26 TIR_Print("Dumping dictionary for %s\n", lib.ToCString()); |
| 28 while (it.HasNext()) { | 27 while (it.HasNext()) { |
| 29 entry = it.GetNext(); | 28 entry = it.GetNext(); |
| 30 name = entry.DictionaryName(); | 29 name = entry.DictionaryName(); |
| 31 TIR_Print("%s -> %s\n", name.ToCString(), entry.ToCString()); | 30 TIR_Print("%s -> %s\n", name.ToCString(), entry.ToCString()); |
| 32 } | 31 } |
| 33 } | 32 } |
| 34 }; | 33 }; |
| 35 | 34 |
| 36 | |
| 37 void Function::Reparent(const Class& new_cls) const { | 35 void Function::Reparent(const Class& new_cls) const { |
| 38 set_owner(new_cls); | 36 set_owner(new_cls); |
| 39 } | 37 } |
| 40 | 38 |
| 41 | |
| 42 void Function::ZeroEdgeCounters() const { | 39 void Function::ZeroEdgeCounters() const { |
| 43 const Array& saved_ic_data = Array::Handle(ic_data_array()); | 40 const Array& saved_ic_data = Array::Handle(ic_data_array()); |
| 44 if (saved_ic_data.IsNull()) { | 41 if (saved_ic_data.IsNull()) { |
| 45 return; | 42 return; |
| 46 } | 43 } |
| 47 const intptr_t saved_ic_datalength = saved_ic_data.Length(); | 44 const intptr_t saved_ic_datalength = saved_ic_data.Length(); |
| 48 ASSERT(saved_ic_datalength > 0); | 45 ASSERT(saved_ic_datalength > 0); |
| 49 const Array& edge_counters_array = | 46 const Array& edge_counters_array = |
| 50 Array::Handle(Array::RawCast(saved_ic_data.At(0))); | 47 Array::Handle(Array::RawCast(saved_ic_data.At(0))); |
| 51 ASSERT(!edge_counters_array.IsNull()); | 48 ASSERT(!edge_counters_array.IsNull()); |
| 52 // Fill edge counters array with zeros. | 49 // Fill edge counters array with zeros. |
| 53 const Smi& zero = Smi::Handle(Smi::New(0)); | 50 const Smi& zero = Smi::Handle(Smi::New(0)); |
| 54 for (intptr_t i = 0; i < edge_counters_array.Length(); i++) { | 51 for (intptr_t i = 0; i < edge_counters_array.Length(); i++) { |
| 55 edge_counters_array.SetAt(i, zero); | 52 edge_counters_array.SetAt(i, zero); |
| 56 } | 53 } |
| 57 } | 54 } |
| 58 | 55 |
| 59 | |
| 60 void Code::ResetICDatas(Zone* zone) const { | 56 void Code::ResetICDatas(Zone* zone) const { |
| 61 // Iterate over the Code's object pool and reset all ICDatas. | 57 // Iterate over the Code's object pool and reset all ICDatas. |
| 62 #ifdef TARGET_ARCH_IA32 | 58 #ifdef TARGET_ARCH_IA32 |
| 63 // IA32 does not have an object pool, but, we can iterate over all | 59 // IA32 does not have an object pool, but, we can iterate over all |
| 64 // embedded objects by using the variable length data section. | 60 // embedded objects by using the variable length data section. |
| 65 if (!is_alive()) { | 61 if (!is_alive()) { |
| 66 return; | 62 return; |
| 67 } | 63 } |
| 68 const Instructions& instrs = Instructions::Handle(zone, instructions()); | 64 const Instructions& instrs = Instructions::Handle(zone, instructions()); |
| 69 ASSERT(!instrs.IsNull()); | 65 ASSERT(!instrs.IsNull()); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 94 continue; | 90 continue; |
| 95 } | 91 } |
| 96 object = pool.ObjectAt(i); | 92 object = pool.ObjectAt(i); |
| 97 if (object.IsICData()) { | 93 if (object.IsICData()) { |
| 98 ICData::Cast(object).Reset(zone); | 94 ICData::Cast(object).Reset(zone); |
| 99 } | 95 } |
| 100 } | 96 } |
| 101 #endif | 97 #endif |
| 102 } | 98 } |
| 103 | 99 |
| 104 | |
| 105 void Class::CopyStaticFieldValues(const Class& old_cls) const { | 100 void Class::CopyStaticFieldValues(const Class& old_cls) const { |
| 106 // We only update values for non-enum classes. | 101 // We only update values for non-enum classes. |
| 107 const bool update_values = !is_enum_class(); | 102 const bool update_values = !is_enum_class(); |
| 108 | 103 |
| 109 IsolateReloadContext* reload_context = Isolate::Current()->reload_context(); | 104 IsolateReloadContext* reload_context = Isolate::Current()->reload_context(); |
| 110 ASSERT(reload_context != NULL); | 105 ASSERT(reload_context != NULL); |
| 111 | 106 |
| 112 const Array& old_field_list = Array::Handle(old_cls.fields()); | 107 const Array& old_field_list = Array::Handle(old_cls.fields()); |
| 113 Field& old_field = Field::Handle(); | 108 Field& old_field = Field::Handle(); |
| 114 String& old_name = String::Handle(); | 109 String& old_name = String::Handle(); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 134 value = old_field.StaticValue(); | 129 value = old_field.StaticValue(); |
| 135 field.SetStaticValue(value); | 130 field.SetStaticValue(value); |
| 136 } | 131 } |
| 137 reload_context->AddStaticFieldMapping(old_field, field); | 132 reload_context->AddStaticFieldMapping(old_field, field); |
| 138 } | 133 } |
| 139 } | 134 } |
| 140 } | 135 } |
| 141 } | 136 } |
| 142 } | 137 } |
| 143 | 138 |
| 144 | |
| 145 void Class::CopyCanonicalConstants(const Class& old_cls) const { | 139 void Class::CopyCanonicalConstants(const Class& old_cls) const { |
| 146 if (is_enum_class()) { | 140 if (is_enum_class()) { |
| 147 // We do not copy enum classes's canonical constants because we explicitly | 141 // We do not copy enum classes's canonical constants because we explicitly |
| 148 // become the old enum values to the new enum values. | 142 // become the old enum values to the new enum values. |
| 149 return; | 143 return; |
| 150 } | 144 } |
| 151 #if defined(DEBUG) | 145 #if defined(DEBUG) |
| 152 { | 146 { |
| 153 // Class has no canonical constants allocated. | 147 // Class has no canonical constants allocated. |
| 154 const Array& my_constants = Array::Handle(constants()); | 148 const Array& my_constants = Array::Handle(constants()); |
| 155 ASSERT(my_constants.Length() == 0); | 149 ASSERT(my_constants.Length() == 0); |
| 156 } | 150 } |
| 157 #endif // defined(DEBUG). | 151 #endif // defined(DEBUG). |
| 158 // Copy old constants into new class. | 152 // Copy old constants into new class. |
| 159 const Array& old_constants = Array::Handle(old_cls.constants()); | 153 const Array& old_constants = Array::Handle(old_cls.constants()); |
| 160 if (old_constants.IsNull() || old_constants.Length() == 0) { | 154 if (old_constants.IsNull() || old_constants.Length() == 0) { |
| 161 return; | 155 return; |
| 162 } | 156 } |
| 163 TIR_Print("Copied %" Pd " canonical constants for class `%s`\n", | 157 TIR_Print("Copied %" Pd " canonical constants for class `%s`\n", |
| 164 old_constants.Length(), ToCString()); | 158 old_constants.Length(), ToCString()); |
| 165 set_constants(old_constants); | 159 set_constants(old_constants); |
| 166 } | 160 } |
| 167 | 161 |
| 168 | |
| 169 void Class::CopyCanonicalType(const Class& old_cls) const { | 162 void Class::CopyCanonicalType(const Class& old_cls) const { |
| 170 const Type& old_canonical_type = Type::Handle(old_cls.canonical_type()); | 163 const Type& old_canonical_type = Type::Handle(old_cls.canonical_type()); |
| 171 if (old_canonical_type.IsNull()) { | 164 if (old_canonical_type.IsNull()) { |
| 172 return; | 165 return; |
| 173 } | 166 } |
| 174 set_canonical_type(old_canonical_type); | 167 set_canonical_type(old_canonical_type); |
| 175 } | 168 } |
| 176 | 169 |
| 177 | |
| 178 class EnumMapTraits { | 170 class EnumMapTraits { |
| 179 public: | 171 public: |
| 180 static bool ReportStats() { return false; } | 172 static bool ReportStats() { return false; } |
| 181 static const char* Name() { return "EnumMapTraits"; } | 173 static const char* Name() { return "EnumMapTraits"; } |
| 182 | 174 |
| 183 static bool IsMatch(const Object& a, const Object& b) { | 175 static bool IsMatch(const Object& a, const Object& b) { |
| 184 return a.raw() == b.raw(); | 176 return a.raw() == b.raw(); |
| 185 } | 177 } |
| 186 | 178 |
| 187 static uword Hash(const Object& obj) { | 179 static uword Hash(const Object& obj) { |
| 188 ASSERT(obj.IsString()); | 180 ASSERT(obj.IsString()); |
| 189 return String::Cast(obj).Hash(); | 181 return String::Cast(obj).Hash(); |
| 190 } | 182 } |
| 191 }; | 183 }; |
| 192 | 184 |
| 193 | |
| 194 // Given an old enum class, add become mappings from old values to new values. | 185 // Given an old enum class, add become mappings from old values to new values. |
| 195 // Some notes about how we reload enums below: | 186 // Some notes about how we reload enums below: |
| 196 // | 187 // |
| 197 // When an enum is reloaded the following three things can happen, possibly | 188 // When an enum is reloaded the following three things can happen, possibly |
| 198 // simultaneously. | 189 // simultaneously. |
| 199 // | 190 // |
| 200 // 1) A new enum value is added. | 191 // 1) A new enum value is added. |
| 201 // This case is handled automatically. | 192 // This case is handled automatically. |
| 202 // 2) Enum values are reordered. | 193 // 2) Enum values are reordered. |
| 203 // We pair old and new enums and the old enums 'become' the new ones so | 194 // We pair old and new enums and the old enums 'become' the new ones so |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 340 ASSERT(!enum_ident.IsNull()); | 331 ASSERT(!enum_ident.IsNull()); |
| 341 old_enum_value ^= enum_map.GetOrNull(enum_ident); | 332 old_enum_value ^= enum_map.GetOrNull(enum_ident); |
| 342 VTIR_Print("Element `%s` was deleted\n", enum_ident.ToCString()); | 333 VTIR_Print("Element `%s` was deleted\n", enum_ident.ToCString()); |
| 343 reload_context->AddEnumBecomeMapping(old_enum_value, | 334 reload_context->AddEnumBecomeMapping(old_enum_value, |
| 344 deleted_enum_sentinel); | 335 deleted_enum_sentinel); |
| 345 } | 336 } |
| 346 enum_map.Release(); | 337 enum_map.Release(); |
| 347 } | 338 } |
| 348 } | 339 } |
| 349 | 340 |
| 350 | |
| 351 void Class::PatchFieldsAndFunctions() const { | 341 void Class::PatchFieldsAndFunctions() const { |
| 352 // Move all old functions and fields to a patch class so that they | 342 // Move all old functions and fields to a patch class so that they |
| 353 // still refer to their original script. | 343 // still refer to their original script. |
| 354 const PatchClass& patch = | 344 const PatchClass& patch = |
| 355 PatchClass::Handle(PatchClass::New(*this, Script::Handle(script()))); | 345 PatchClass::Handle(PatchClass::New(*this, Script::Handle(script()))); |
| 356 ASSERT(!patch.IsNull()); | 346 ASSERT(!patch.IsNull()); |
| 357 | 347 |
| 358 const Array& funcs = Array::Handle(functions()); | 348 const Array& funcs = Array::Handle(functions()); |
| 359 Function& func = Function::Handle(); | 349 Function& func = Function::Handle(); |
| 360 Object& owner = Object::Handle(); | 350 Object& owner = Object::Handle(); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 385 owner = field.RawOwner(); | 375 owner = field.RawOwner(); |
| 386 ASSERT(!owner.IsNull()); | 376 ASSERT(!owner.IsNull()); |
| 387 if (!owner.IsPatchClass()) { | 377 if (!owner.IsPatchClass()) { |
| 388 ASSERT(owner.raw() == this->raw()); | 378 ASSERT(owner.raw() == this->raw()); |
| 389 field.set_owner(patch); | 379 field.set_owner(patch); |
| 390 } | 380 } |
| 391 field.ForceDynamicGuardedCidAndLength(); | 381 field.ForceDynamicGuardedCidAndLength(); |
| 392 } | 382 } |
| 393 } | 383 } |
| 394 | 384 |
| 395 | |
| 396 void Class::MigrateImplicitStaticClosures(IsolateReloadContext* irc, | 385 void Class::MigrateImplicitStaticClosures(IsolateReloadContext* irc, |
| 397 const Class& new_cls) const { | 386 const Class& new_cls) const { |
| 398 const Array& funcs = Array::Handle(functions()); | 387 const Array& funcs = Array::Handle(functions()); |
| 399 Function& old_func = Function::Handle(); | 388 Function& old_func = Function::Handle(); |
| 400 String& selector = String::Handle(); | 389 String& selector = String::Handle(); |
| 401 Function& new_func = Function::Handle(); | 390 Function& new_func = Function::Handle(); |
| 402 Instance& old_closure = Instance::Handle(); | 391 Instance& old_closure = Instance::Handle(); |
| 403 Instance& new_closure = Instance::Handle(); | 392 Instance& new_closure = Instance::Handle(); |
| 404 for (intptr_t i = 0; i < funcs.Length(); i++) { | 393 for (intptr_t i = 0; i < funcs.Length(); i++) { |
| 405 old_func ^= funcs.At(i); | 394 old_func ^= funcs.At(i); |
| 406 if (old_func.is_static() && old_func.HasImplicitClosureFunction()) { | 395 if (old_func.is_static() && old_func.HasImplicitClosureFunction()) { |
| 407 selector = old_func.name(); | 396 selector = old_func.name(); |
| 408 new_func = new_cls.LookupFunction(selector); | 397 new_func = new_cls.LookupFunction(selector); |
| 409 if (!new_func.IsNull() && new_func.is_static()) { | 398 if (!new_func.IsNull() && new_func.is_static()) { |
| 410 old_func = old_func.ImplicitClosureFunction(); | 399 old_func = old_func.ImplicitClosureFunction(); |
| 411 old_closure = old_func.ImplicitStaticClosure(); | 400 old_closure = old_func.ImplicitStaticClosure(); |
| 412 new_func = new_func.ImplicitClosureFunction(); | 401 new_func = new_func.ImplicitClosureFunction(); |
| 413 new_closure = new_func.ImplicitStaticClosure(); | 402 new_closure = new_func.ImplicitStaticClosure(); |
| 414 if (old_closure.IsCanonical()) { | 403 if (old_closure.IsCanonical()) { |
| 415 new_closure.SetCanonical(); | 404 new_closure.SetCanonical(); |
| 416 } | 405 } |
| 417 irc->AddBecomeMapping(old_closure, new_closure); | 406 irc->AddBecomeMapping(old_closure, new_closure); |
| 418 } | 407 } |
| 419 } | 408 } |
| 420 } | 409 } |
| 421 } | 410 } |
| 422 | 411 |
| 423 | |
| 424 class EnumClassConflict : public ClassReasonForCancelling { | 412 class EnumClassConflict : public ClassReasonForCancelling { |
| 425 public: | 413 public: |
| 426 EnumClassConflict(Zone* zone, const Class& from, const Class& to) | 414 EnumClassConflict(Zone* zone, const Class& from, const Class& to) |
| 427 : ClassReasonForCancelling(zone, from, to) {} | 415 : ClassReasonForCancelling(zone, from, to) {} |
| 428 | 416 |
| 429 RawString* ToString() { | 417 RawString* ToString() { |
| 430 return String::NewFormatted( | 418 return String::NewFormatted( |
| 431 from_.is_enum_class() | 419 from_.is_enum_class() |
| 432 ? "Enum class cannot be redefined to be a non-enum class: %s" | 420 ? "Enum class cannot be redefined to be a non-enum class: %s" |
| 433 : "Class cannot be redefined to be a enum class: %s", | 421 : "Class cannot be redefined to be a enum class: %s", |
| 434 from_.ToCString()); | 422 from_.ToCString()); |
| 435 } | 423 } |
| 436 }; | 424 }; |
| 437 | 425 |
| 438 | |
| 439 class TypedefClassConflict : public ClassReasonForCancelling { | 426 class TypedefClassConflict : public ClassReasonForCancelling { |
| 440 public: | 427 public: |
| 441 TypedefClassConflict(Zone* zone, const Class& from, const Class& to) | 428 TypedefClassConflict(Zone* zone, const Class& from, const Class& to) |
| 442 : ClassReasonForCancelling(zone, from, to) {} | 429 : ClassReasonForCancelling(zone, from, to) {} |
| 443 | 430 |
| 444 RawString* ToString() { | 431 RawString* ToString() { |
| 445 return String::NewFormatted( | 432 return String::NewFormatted( |
| 446 from_.IsTypedefClass() | 433 from_.IsTypedefClass() |
| 447 ? "Typedef class cannot be redefined to be a non-typedef class: %s" | 434 ? "Typedef class cannot be redefined to be a non-typedef class: %s" |
| 448 : "Class cannot be redefined to be a typedef class: %s", | 435 : "Class cannot be redefined to be a typedef class: %s", |
| 449 from_.ToCString()); | 436 from_.ToCString()); |
| 450 } | 437 } |
| 451 }; | 438 }; |
| 452 | 439 |
| 453 | |
| 454 class EnsureFinalizedError : public ClassReasonForCancelling { | 440 class EnsureFinalizedError : public ClassReasonForCancelling { |
| 455 public: | 441 public: |
| 456 EnsureFinalizedError(Zone* zone, | 442 EnsureFinalizedError(Zone* zone, |
| 457 const Class& from, | 443 const Class& from, |
| 458 const Class& to, | 444 const Class& to, |
| 459 const Error& error) | 445 const Error& error) |
| 460 : ClassReasonForCancelling(zone, from, to), error_(error) {} | 446 : ClassReasonForCancelling(zone, from, to), error_(error) {} |
| 461 | 447 |
| 462 private: | 448 private: |
| 463 const Error& error_; | 449 const Error& error_; |
| 464 | 450 |
| 465 RawError* ToError() { return error_.raw(); } | 451 RawError* ToError() { return error_.raw(); } |
| 466 | 452 |
| 467 RawString* ToString() { return String::New(error_.ToErrorCString()); } | 453 RawString* ToString() { return String::New(error_.ToErrorCString()); } |
| 468 }; | 454 }; |
| 469 | 455 |
| 470 | |
| 471 class NativeFieldsConflict : public ClassReasonForCancelling { | 456 class NativeFieldsConflict : public ClassReasonForCancelling { |
| 472 public: | 457 public: |
| 473 NativeFieldsConflict(Zone* zone, const Class& from, const Class& to) | 458 NativeFieldsConflict(Zone* zone, const Class& from, const Class& to) |
| 474 : ClassReasonForCancelling(zone, from, to) {} | 459 : ClassReasonForCancelling(zone, from, to) {} |
| 475 | 460 |
| 476 private: | 461 private: |
| 477 RawString* ToString() { | 462 RawString* ToString() { |
| 478 return String::NewFormatted("Number of native fields changed in %s", | 463 return String::NewFormatted("Number of native fields changed in %s", |
| 479 from_.ToCString()); | 464 from_.ToCString()); |
| 480 } | 465 } |
| 481 }; | 466 }; |
| 482 | 467 |
| 483 | |
| 484 class TypeParametersChanged : public ClassReasonForCancelling { | 468 class TypeParametersChanged : public ClassReasonForCancelling { |
| 485 public: | 469 public: |
| 486 TypeParametersChanged(Zone* zone, const Class& from, const Class& to) | 470 TypeParametersChanged(Zone* zone, const Class& from, const Class& to) |
| 487 : ClassReasonForCancelling(zone, from, to) {} | 471 : ClassReasonForCancelling(zone, from, to) {} |
| 488 | 472 |
| 489 RawString* ToString() { | 473 RawString* ToString() { |
| 490 return String::NewFormatted( | 474 return String::NewFormatted( |
| 491 "Limitation: type parameters have changed for %s", from_.ToCString()); | 475 "Limitation: type parameters have changed for %s", from_.ToCString()); |
| 492 } | 476 } |
| 493 | 477 |
| 494 void AppendTo(JSONArray* array) { | 478 void AppendTo(JSONArray* array) { |
| 495 JSONObject jsobj(array); | 479 JSONObject jsobj(array); |
| 496 jsobj.AddProperty("type", "ReasonForCancellingReload"); | 480 jsobj.AddProperty("type", "ReasonForCancellingReload"); |
| 497 jsobj.AddProperty("kind", "TypeParametersChanged"); | 481 jsobj.AddProperty("kind", "TypeParametersChanged"); |
| 498 jsobj.AddProperty("class", to_); | 482 jsobj.AddProperty("class", to_); |
| 499 jsobj.AddProperty("message", | 483 jsobj.AddProperty("message", |
| 500 "Limitation: changing type parameters " | 484 "Limitation: changing type parameters " |
| 501 "does not work with hot reload."); | 485 "does not work with hot reload."); |
| 502 } | 486 } |
| 503 }; | 487 }; |
| 504 | 488 |
| 505 | |
| 506 class PreFinalizedConflict : public ClassReasonForCancelling { | 489 class PreFinalizedConflict : public ClassReasonForCancelling { |
| 507 public: | 490 public: |
| 508 PreFinalizedConflict(Zone* zone, const Class& from, const Class& to) | 491 PreFinalizedConflict(Zone* zone, const Class& from, const Class& to) |
| 509 : ClassReasonForCancelling(zone, from, to) {} | 492 : ClassReasonForCancelling(zone, from, to) {} |
| 510 | 493 |
| 511 private: | 494 private: |
| 512 RawString* ToString() { | 495 RawString* ToString() { |
| 513 return String::NewFormatted( | 496 return String::NewFormatted( |
| 514 "Original class ('%s') is prefinalized and replacement class " | 497 "Original class ('%s') is prefinalized and replacement class " |
| 515 "('%s') is not ", | 498 "('%s') is not ", |
| 516 from_.ToCString(), to_.ToCString()); | 499 from_.ToCString(), to_.ToCString()); |
| 517 } | 500 } |
| 518 }; | 501 }; |
| 519 | 502 |
| 520 | |
| 521 class InstanceSizeConflict : public ClassReasonForCancelling { | 503 class InstanceSizeConflict : public ClassReasonForCancelling { |
| 522 public: | 504 public: |
| 523 InstanceSizeConflict(Zone* zone, const Class& from, const Class& to) | 505 InstanceSizeConflict(Zone* zone, const Class& from, const Class& to) |
| 524 : ClassReasonForCancelling(zone, from, to) {} | 506 : ClassReasonForCancelling(zone, from, to) {} |
| 525 | 507 |
| 526 private: | 508 private: |
| 527 RawString* ToString() { | 509 RawString* ToString() { |
| 528 return String::NewFormatted("Instance size mismatch between '%s' (%" Pd | 510 return String::NewFormatted("Instance size mismatch between '%s' (%" Pd |
| 529 ") and replacement " | 511 ") and replacement " |
| 530 "'%s' ( %" Pd ")", | 512 "'%s' ( %" Pd ")", |
| 531 from_.ToCString(), from_.instance_size(), | 513 from_.ToCString(), from_.instance_size(), |
| 532 to_.ToCString(), to_.instance_size()); | 514 to_.ToCString(), to_.instance_size()); |
| 533 } | 515 } |
| 534 }; | 516 }; |
| 535 | 517 |
| 536 | |
| 537 class UnimplementedDeferredLibrary : public ReasonForCancelling { | 518 class UnimplementedDeferredLibrary : public ReasonForCancelling { |
| 538 public: | 519 public: |
| 539 UnimplementedDeferredLibrary(Zone* zone, | 520 UnimplementedDeferredLibrary(Zone* zone, |
| 540 const Library& from, | 521 const Library& from, |
| 541 const Library& to, | 522 const Library& to, |
| 542 const String& name) | 523 const String& name) |
| 543 : ReasonForCancelling(zone), from_(from), to_(to), name_(name) {} | 524 : ReasonForCancelling(zone), from_(from), to_(to), name_(name) {} |
| 544 | 525 |
| 545 private: | 526 private: |
| 546 const Library& from_; | 527 const Library& from_; |
| 547 const Library& to_; | 528 const Library& to_; |
| 548 const String& name_; | 529 const String& name_; |
| 549 | 530 |
| 550 RawString* ToString() { | 531 RawString* ToString() { |
| 551 const String& lib_url = String::Handle(to_.url()); | 532 const String& lib_url = String::Handle(to_.url()); |
| 552 from_.ToCString(); | 533 from_.ToCString(); |
| 553 return String::NewFormatted( | 534 return String::NewFormatted( |
| 554 "Reloading support for deferred loading has not yet been implemented:" | 535 "Reloading support for deferred loading has not yet been implemented:" |
| 555 " library '%s' has deferred import '%s'", | 536 " library '%s' has deferred import '%s'", |
| 556 lib_url.ToCString(), name_.ToCString()); | 537 lib_url.ToCString(), name_.ToCString()); |
| 557 } | 538 } |
| 558 }; | 539 }; |
| 559 | 540 |
| 560 | |
| 561 // This is executed before iterating over the instances. | 541 // This is executed before iterating over the instances. |
| 562 void Class::CheckReload(const Class& replacement, | 542 void Class::CheckReload(const Class& replacement, |
| 563 IsolateReloadContext* context) const { | 543 IsolateReloadContext* context) const { |
| 564 ASSERT(IsolateReloadContext::IsSameClass(*this, replacement)); | 544 ASSERT(IsolateReloadContext::IsSameClass(*this, replacement)); |
| 565 | 545 |
| 566 // Class cannot change enum property. | 546 // Class cannot change enum property. |
| 567 if (is_enum_class() != replacement.is_enum_class()) { | 547 if (is_enum_class() != replacement.is_enum_class()) { |
| 568 context->AddReasonForCancelling(new (context->zone()) EnumClassConflict( | 548 context->AddReasonForCancelling(new (context->zone()) EnumClassConflict( |
| 569 context->zone(), *this, replacement)); | 549 context->zone(), *this, replacement)); |
| 570 return; | 550 return; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 606 if (!CanReloadFinalized(replacement, context)) return; | 586 if (!CanReloadFinalized(replacement, context)) return; |
| 607 } | 587 } |
| 608 if (is_prefinalized()) { | 588 if (is_prefinalized()) { |
| 609 if (!CanReloadPreFinalized(replacement, context)) return; | 589 if (!CanReloadPreFinalized(replacement, context)) return; |
| 610 } | 590 } |
| 611 ASSERT(is_finalized() == replacement.is_finalized()); | 591 ASSERT(is_finalized() == replacement.is_finalized()); |
| 612 TIR_Print("Class `%s` can be reloaded (%" Pd " and %" Pd ")\n", ToCString(), | 592 TIR_Print("Class `%s` can be reloaded (%" Pd " and %" Pd ")\n", ToCString(), |
| 613 id(), replacement.id()); | 593 id(), replacement.id()); |
| 614 } | 594 } |
| 615 | 595 |
| 616 | |
| 617 bool Class::RequiresInstanceMorphing(const Class& replacement) const { | 596 bool Class::RequiresInstanceMorphing(const Class& replacement) const { |
| 618 // Get the field maps for both classes. These field maps walk the class | 597 // Get the field maps for both classes. These field maps walk the class |
| 619 // hierarchy. | 598 // hierarchy. |
| 620 const Array& fields = | 599 const Array& fields = |
| 621 Array::Handle(OffsetToFieldMap(true /* original classes */)); | 600 Array::Handle(OffsetToFieldMap(true /* original classes */)); |
| 622 const Array& replacement_fields = | 601 const Array& replacement_fields = |
| 623 Array::Handle(replacement.OffsetToFieldMap()); | 602 Array::Handle(replacement.OffsetToFieldMap()); |
| 624 | 603 |
| 625 // Check that the size of the instance is the same. | 604 // Check that the size of the instance is the same. |
| 626 if (fields.Length() != replacement_fields.Length()) return true; | 605 if (fields.Length() != replacement_fields.Length()) return true; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 643 } | 622 } |
| 644 field = Field::RawCast(fields.At(i)); | 623 field = Field::RawCast(fields.At(i)); |
| 645 replacement_field = Field::RawCast(replacement_fields.At(i)); | 624 replacement_field = Field::RawCast(replacement_fields.At(i)); |
| 646 field_name = field.name(); | 625 field_name = field.name(); |
| 647 replacement_field_name = replacement_field.name(); | 626 replacement_field_name = replacement_field.name(); |
| 648 if (!field_name.Equals(replacement_field_name)) return true; | 627 if (!field_name.Equals(replacement_field_name)) return true; |
| 649 } | 628 } |
| 650 return false; | 629 return false; |
| 651 } | 630 } |
| 652 | 631 |
| 653 | |
| 654 bool Class::CanReloadFinalized(const Class& replacement, | 632 bool Class::CanReloadFinalized(const Class& replacement, |
| 655 IsolateReloadContext* context) const { | 633 IsolateReloadContext* context) const { |
| 656 // Make sure the declaration types matches for the two classes. | 634 // Make sure the declaration types matches for the two classes. |
| 657 // ex. class A<int,B> {} cannot be replace with class A<B> {}. | 635 // ex. class A<int,B> {} cannot be replace with class A<B> {}. |
| 658 | 636 |
| 659 const AbstractType& dt = AbstractType::Handle(DeclarationType()); | 637 const AbstractType& dt = AbstractType::Handle(DeclarationType()); |
| 660 const AbstractType& replacement_dt = | 638 const AbstractType& replacement_dt = |
| 661 AbstractType::Handle(replacement.DeclarationType()); | 639 AbstractType::Handle(replacement.DeclarationType()); |
| 662 if (!dt.Equals(replacement_dt)) { | 640 if (!dt.Equals(replacement_dt)) { |
| 663 context->AddReasonForCancelling(new (context->zone()) TypeParametersChanged( | 641 context->AddReasonForCancelling(new (context->zone()) TypeParametersChanged( |
| 664 context->zone(), *this, replacement)); | 642 context->zone(), *this, replacement)); |
| 665 return false; | 643 return false; |
| 666 } | 644 } |
| 667 if (RequiresInstanceMorphing(replacement)) { | 645 if (RequiresInstanceMorphing(replacement)) { |
| 668 context->AddInstanceMorpher(new (context->zone()) InstanceMorpher( | 646 context->AddInstanceMorpher(new (context->zone()) InstanceMorpher( |
| 669 context->zone(), *this, replacement)); | 647 context->zone(), *this, replacement)); |
| 670 } | 648 } |
| 671 return true; | 649 return true; |
| 672 } | 650 } |
| 673 | 651 |
| 674 | |
| 675 bool Class::CanReloadPreFinalized(const Class& replacement, | 652 bool Class::CanReloadPreFinalized(const Class& replacement, |
| 676 IsolateReloadContext* context) const { | 653 IsolateReloadContext* context) const { |
| 677 // The replacement class must also prefinalized. | 654 // The replacement class must also prefinalized. |
| 678 if (!replacement.is_prefinalized()) { | 655 if (!replacement.is_prefinalized()) { |
| 679 context->AddReasonForCancelling(new (context->zone()) PreFinalizedConflict( | 656 context->AddReasonForCancelling(new (context->zone()) PreFinalizedConflict( |
| 680 context->zone(), *this, replacement)); | 657 context->zone(), *this, replacement)); |
| 681 return false; | 658 return false; |
| 682 } | 659 } |
| 683 // Check the instance sizes are equal. | 660 // Check the instance sizes are equal. |
| 684 if (instance_size() != replacement.instance_size()) { | 661 if (instance_size() != replacement.instance_size()) { |
| 685 context->AddReasonForCancelling(new (context->zone()) InstanceSizeConflict( | 662 context->AddReasonForCancelling(new (context->zone()) InstanceSizeConflict( |
| 686 context->zone(), *this, replacement)); | 663 context->zone(), *this, replacement)); |
| 687 return false; | 664 return false; |
| 688 } | 665 } |
| 689 return true; | 666 return true; |
| 690 } | 667 } |
| 691 | 668 |
| 692 | |
| 693 void Library::CheckReload(const Library& replacement, | 669 void Library::CheckReload(const Library& replacement, |
| 694 IsolateReloadContext* context) const { | 670 IsolateReloadContext* context) const { |
| 695 // TODO(26878): If the replacement library uses deferred loading, | 671 // TODO(26878): If the replacement library uses deferred loading, |
| 696 // reject it. We do not yet support reloading deferred libraries. | 672 // reject it. We do not yet support reloading deferred libraries. |
| 697 LibraryPrefix& prefix = LibraryPrefix::Handle(); | 673 LibraryPrefix& prefix = LibraryPrefix::Handle(); |
| 698 LibraryPrefixIterator it(replacement); | 674 LibraryPrefixIterator it(replacement); |
| 699 while (it.HasNext()) { | 675 while (it.HasNext()) { |
| 700 prefix = it.GetNext(); | 676 prefix = it.GetNext(); |
| 701 if (prefix.is_deferred_load()) { | 677 if (prefix.is_deferred_load()) { |
| 702 const String& prefix_name = String::Handle(prefix.name()); | 678 const String& prefix_name = String::Handle(prefix.name()); |
| 703 context->AddReasonForCancelling( | 679 context->AddReasonForCancelling( |
| 704 new (context->zone()) UnimplementedDeferredLibrary( | 680 new (context->zone()) UnimplementedDeferredLibrary( |
| 705 context->zone(), *this, replacement, prefix_name)); | 681 context->zone(), *this, replacement, prefix_name)); |
| 706 return; | 682 return; |
| 707 } | 683 } |
| 708 } | 684 } |
| 709 } | 685 } |
| 710 | 686 |
| 711 | |
| 712 static const Function* static_call_target = NULL; | 687 static const Function* static_call_target = NULL; |
| 713 | 688 |
| 714 | |
| 715 void ICData::Reset(Zone* zone) const { | 689 void ICData::Reset(Zone* zone) const { |
| 716 if (is_static_call()) { | 690 if (is_static_call()) { |
| 717 const Function& old_target = Function::Handle(zone, GetTargetAt(0)); | 691 const Function& old_target = Function::Handle(zone, GetTargetAt(0)); |
| 718 if (old_target.IsNull()) { | 692 if (old_target.IsNull()) { |
| 719 FATAL("old_target is NULL.\n"); | 693 FATAL("old_target is NULL.\n"); |
| 720 } | 694 } |
| 721 static_call_target = &old_target; | 695 static_call_target = &old_target; |
| 722 | 696 |
| 723 const String& selector = String::Handle(zone, old_target.name()); | 697 const String& selector = String::Handle(zone, old_target.name()); |
| 724 Function& new_target = Function::Handle(zone); | 698 Function& new_target = Function::Handle(zone); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 785 const Array& data_array = | 759 const Array& data_array = |
| 786 Array::Handle(zone, CachedEmptyICDataArray(num_args)); | 760 Array::Handle(zone, CachedEmptyICDataArray(num_args)); |
| 787 set_ic_data_array(data_array); | 761 set_ic_data_array(data_array); |
| 788 } | 762 } |
| 789 } | 763 } |
| 790 } | 764 } |
| 791 | 765 |
| 792 #endif // !PRODUCT | 766 #endif // !PRODUCT |
| 793 | 767 |
| 794 } // namespace dart. | 768 } // namespace dart. |
| OLD | NEW |