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 |