| 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/isolate_reload.h" | 5 #include "vm/isolate_reload.h" |
| 6 | 6 |
| 7 #include "vm/become.h" | 7 #include "vm/become.h" |
| 8 #include "vm/bit_vector.h" | 8 #include "vm/bit_vector.h" |
| 9 #include "vm/runtime_entry.h" | |
| 10 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
| 11 #include "vm/dart_api_impl.h" | 10 #include "vm/dart_api_impl.h" |
| 12 #include "vm/hash_table.h" | 11 #include "vm/hash_table.h" |
| 13 #include "vm/isolate.h" | 12 #include "vm/isolate.h" |
| 14 #include "vm/log.h" | 13 #include "vm/log.h" |
| 15 #include "vm/object.h" | 14 #include "vm/object.h" |
| 16 #include "vm/object_store.h" | 15 #include "vm/object_store.h" |
| 17 #include "vm/parser.h" | 16 #include "vm/parser.h" |
| 17 #include "vm/runtime_entry.h" |
| 18 #include "vm/safepoint.h" | 18 #include "vm/safepoint.h" |
| 19 #include "vm/service_event.h" | 19 #include "vm/service_event.h" |
| 20 #include "vm/stack_frame.h" | 20 #include "vm/stack_frame.h" |
| 21 #include "vm/thread.h" | 21 #include "vm/thread.h" |
| 22 #include "vm/timeline.h" | 22 #include "vm/timeline.h" |
| 23 #include "vm/visitor.h" | 23 #include "vm/visitor.h" |
| 24 | 24 |
| 25 namespace dart { | 25 namespace dart { |
| 26 | 26 |
| 27 DEFINE_FLAG(bool, trace_reload, false, "Trace isolate reloading"); | 27 DEFINE_FLAG(bool, trace_reload, false, "Trace isolate reloading"); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 46 "Assert that an isolate has reloaded at least once.") | 46 "Assert that an isolate has reloaded at least once.") |
| 47 #ifndef PRODUCT | 47 #ifndef PRODUCT |
| 48 | 48 |
| 49 #define I (isolate()) | 49 #define I (isolate()) |
| 50 #define Z (thread->zone()) | 50 #define Z (thread->zone()) |
| 51 | 51 |
| 52 #define TIMELINE_SCOPE(name) \ | 52 #define TIMELINE_SCOPE(name) \ |
| 53 TimelineDurationScope tds##name(Thread::Current(), \ | 53 TimelineDurationScope tds##name(Thread::Current(), \ |
| 54 Timeline::GetIsolateStream(), #name) | 54 Timeline::GetIsolateStream(), #name) |
| 55 | 55 |
| 56 | |
| 57 InstanceMorpher::InstanceMorpher(Zone* zone, const Class& from, const Class& to) | 56 InstanceMorpher::InstanceMorpher(Zone* zone, const Class& from, const Class& to) |
| 58 : from_(Class::Handle(zone, from.raw())), | 57 : from_(Class::Handle(zone, from.raw())), |
| 59 to_(Class::Handle(zone, to.raw())), | 58 to_(Class::Handle(zone, to.raw())), |
| 60 mapping_(zone, 0) { | 59 mapping_(zone, 0) { |
| 61 before_ = new (zone) ZoneGrowableArray<const Instance*>(zone, 0); | 60 before_ = new (zone) ZoneGrowableArray<const Instance*>(zone, 0); |
| 62 after_ = new (zone) ZoneGrowableArray<const Instance*>(zone, 0); | 61 after_ = new (zone) ZoneGrowableArray<const Instance*>(zone, 0); |
| 63 new_fields_ = new (zone) ZoneGrowableArray<const Field*>(zone, 0); | 62 new_fields_ = new (zone) ZoneGrowableArray<const Field*>(zone, 0); |
| 64 ASSERT(from_.id() == to_.id()); | 63 ASSERT(from_.id() == to_.id()); |
| 65 cid_ = from_.id(); | 64 cid_ = from_.id(); |
| 66 ComputeMapping(); | 65 ComputeMapping(); |
| 67 } | 66 } |
| 68 | 67 |
| 69 | |
| 70 void InstanceMorpher::AddObject(RawObject* object) const { | 68 void InstanceMorpher::AddObject(RawObject* object) const { |
| 71 ASSERT(object->GetClassId() == cid()); | 69 ASSERT(object->GetClassId() == cid()); |
| 72 const Instance& instance = Instance::Cast(Object::Handle(object)); | 70 const Instance& instance = Instance::Cast(Object::Handle(object)); |
| 73 before_->Add(&instance); | 71 before_->Add(&instance); |
| 74 } | 72 } |
| 75 | 73 |
| 76 | |
| 77 void InstanceMorpher::ComputeMapping() { | 74 void InstanceMorpher::ComputeMapping() { |
| 78 if (from_.NumTypeArguments()) { | 75 if (from_.NumTypeArguments()) { |
| 79 // Add copying of the optional type argument field. | 76 // Add copying of the optional type argument field. |
| 80 intptr_t from_offset = from_.type_arguments_field_offset(); | 77 intptr_t from_offset = from_.type_arguments_field_offset(); |
| 81 ASSERT(from_offset != Class::kNoTypeArguments); | 78 ASSERT(from_offset != Class::kNoTypeArguments); |
| 82 intptr_t to_offset = to_.type_arguments_field_offset(); | 79 intptr_t to_offset = to_.type_arguments_field_offset(); |
| 83 ASSERT(to_offset != Class::kNoTypeArguments); | 80 ASSERT(to_offset != Class::kNoTypeArguments); |
| 84 mapping_.Add(from_offset); | 81 mapping_.Add(from_offset); |
| 85 mapping_.Add(to_offset); | 82 mapping_.Add(to_offset); |
| 86 } | 83 } |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 129 if (new_field) { | 126 if (new_field) { |
| 130 if (to_field.has_initializer()) { | 127 if (to_field.has_initializer()) { |
| 131 // This is a new field with an initializer. | 128 // This is a new field with an initializer. |
| 132 const Field& field = Field::Handle(to_field.raw()); | 129 const Field& field = Field::Handle(to_field.raw()); |
| 133 new_fields_->Add(&field); | 130 new_fields_->Add(&field); |
| 134 } | 131 } |
| 135 } | 132 } |
| 136 } | 133 } |
| 137 } | 134 } |
| 138 | 135 |
| 139 | |
| 140 RawInstance* InstanceMorpher::Morph(const Instance& instance) const { | 136 RawInstance* InstanceMorpher::Morph(const Instance& instance) const { |
| 141 const Instance& result = Instance::Handle(Instance::New(to_)); | 137 const Instance& result = Instance::Handle(Instance::New(to_)); |
| 142 // Morph the context from instance to result using mapping_. | 138 // Morph the context from instance to result using mapping_. |
| 143 for (intptr_t i = 0; i < mapping_.length(); i += 2) { | 139 for (intptr_t i = 0; i < mapping_.length(); i += 2) { |
| 144 intptr_t from_offset = mapping_.At(i); | 140 intptr_t from_offset = mapping_.At(i); |
| 145 intptr_t to_offset = mapping_.At(i + 1); | 141 intptr_t to_offset = mapping_.At(i + 1); |
| 146 const Object& value = | 142 const Object& value = |
| 147 Object::Handle(instance.RawGetFieldAtOffset(from_offset)); | 143 Object::Handle(instance.RawGetFieldAtOffset(from_offset)); |
| 148 result.RawSetFieldAtOffset(to_offset, value); | 144 result.RawSetFieldAtOffset(to_offset, value); |
| 149 } | 145 } |
| 150 // Convert the instance into a filler object. | 146 // Convert the instance into a filler object. |
| 151 Become::MakeDummyObject(instance); | 147 Become::MakeDummyObject(instance); |
| 152 return result.raw(); | 148 return result.raw(); |
| 153 } | 149 } |
| 154 | 150 |
| 155 | |
| 156 void InstanceMorpher::RunNewFieldInitializers() const { | 151 void InstanceMorpher::RunNewFieldInitializers() const { |
| 157 if ((new_fields_->length() == 0) || (after_->length() == 0)) { | 152 if ((new_fields_->length() == 0) || (after_->length() == 0)) { |
| 158 return; | 153 return; |
| 159 } | 154 } |
| 160 | 155 |
| 161 TIR_Print("Running new field initializers for class: %s\n", to_.ToCString()); | 156 TIR_Print("Running new field initializers for class: %s\n", to_.ToCString()); |
| 162 String& initializing_expression = String::Handle(); | 157 String& initializing_expression = String::Handle(); |
| 163 Function& eval_func = Function::Handle(); | 158 Function& eval_func = Function::Handle(); |
| 164 Object& result = Object::Handle(); | 159 Object& result = Object::Handle(); |
| 165 Class& owning_class = Class::Handle(); | 160 Class& owning_class = Class::Handle(); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 187 "RELOAD: Running initializer for new field `%s` resulted in " | 182 "RELOAD: Running initializer for new field `%s` resulted in " |
| 188 "an error: %s\n", | 183 "an error: %s\n", |
| 189 field->ToCString(), Error::Cast(result).ToErrorCString()); | 184 field->ToCString(), Error::Cast(result).ToErrorCString()); |
| 190 continue; | 185 continue; |
| 191 } | 186 } |
| 192 instance->RawSetFieldAtOffset(field->Offset(), result); | 187 instance->RawSetFieldAtOffset(field->Offset(), result); |
| 193 } | 188 } |
| 194 } | 189 } |
| 195 } | 190 } |
| 196 | 191 |
| 197 | |
| 198 void InstanceMorpher::CreateMorphedCopies() const { | 192 void InstanceMorpher::CreateMorphedCopies() const { |
| 199 for (intptr_t i = 0; i < before()->length(); i++) { | 193 for (intptr_t i = 0; i < before()->length(); i++) { |
| 200 const Instance& copy = Instance::Handle(Morph(*before()->At(i))); | 194 const Instance& copy = Instance::Handle(Morph(*before()->At(i))); |
| 201 after()->Add(©); | 195 after()->Add(©); |
| 202 } | 196 } |
| 203 } | 197 } |
| 204 | 198 |
| 205 | |
| 206 void InstanceMorpher::DumpFormatFor(const Class& cls) const { | 199 void InstanceMorpher::DumpFormatFor(const Class& cls) const { |
| 207 THR_Print("%s\n", cls.ToCString()); | 200 THR_Print("%s\n", cls.ToCString()); |
| 208 if (cls.NumTypeArguments()) { | 201 if (cls.NumTypeArguments()) { |
| 209 intptr_t field_offset = cls.type_arguments_field_offset(); | 202 intptr_t field_offset = cls.type_arguments_field_offset(); |
| 210 ASSERT(field_offset != Class::kNoTypeArguments); | 203 ASSERT(field_offset != Class::kNoTypeArguments); |
| 211 THR_Print(" - @%" Pd " <type arguments>\n", field_offset); | 204 THR_Print(" - @%" Pd " <type arguments>\n", field_offset); |
| 212 } | 205 } |
| 213 const Array& fields = Array::Handle(cls.OffsetToFieldMap()); | 206 const Array& fields = Array::Handle(cls.OffsetToFieldMap()); |
| 214 Field& field = Field::Handle(); | 207 Field& field = Field::Handle(); |
| 215 String& name = String::Handle(); | 208 String& name = String::Handle(); |
| 216 for (intptr_t i = 0; i < fields.Length(); i++) { | 209 for (intptr_t i = 0; i < fields.Length(); i++) { |
| 217 if (fields.At(i) != Field::null()) { | 210 if (fields.At(i) != Field::null()) { |
| 218 field = Field::RawCast(fields.At(i)); | 211 field = Field::RawCast(fields.At(i)); |
| 219 ASSERT(field.is_instance()); | 212 ASSERT(field.is_instance()); |
| 220 name = field.name(); | 213 name = field.name(); |
| 221 THR_Print(" - @%" Pd " %s\n", field.Offset(), name.ToCString()); | 214 THR_Print(" - @%" Pd " %s\n", field.Offset(), name.ToCString()); |
| 222 } | 215 } |
| 223 } | 216 } |
| 224 | 217 |
| 225 THR_Print("Mapping: "); | 218 THR_Print("Mapping: "); |
| 226 for (int i = 0; i < mapping_.length(); i += 2) { | 219 for (int i = 0; i < mapping_.length(); i += 2) { |
| 227 THR_Print(" %" Pd "->%" Pd, mapping_.At(i), mapping_.At(i + 1)); | 220 THR_Print(" %" Pd "->%" Pd, mapping_.At(i), mapping_.At(i + 1)); |
| 228 } | 221 } |
| 229 THR_Print("\n"); | 222 THR_Print("\n"); |
| 230 } | 223 } |
| 231 | 224 |
| 232 | |
| 233 void InstanceMorpher::Dump() const { | 225 void InstanceMorpher::Dump() const { |
| 234 LogBlock blocker; | 226 LogBlock blocker; |
| 235 THR_Print("Morphing from "); | 227 THR_Print("Morphing from "); |
| 236 DumpFormatFor(from_); | 228 DumpFormatFor(from_); |
| 237 THR_Print("To "); | 229 THR_Print("To "); |
| 238 DumpFormatFor(to_); | 230 DumpFormatFor(to_); |
| 239 THR_Print("\n"); | 231 THR_Print("\n"); |
| 240 } | 232 } |
| 241 | 233 |
| 242 | |
| 243 void InstanceMorpher::AppendTo(JSONArray* array) { | 234 void InstanceMorpher::AppendTo(JSONArray* array) { |
| 244 JSONObject jsobj(array); | 235 JSONObject jsobj(array); |
| 245 jsobj.AddProperty("type", "ShapeChangeMapping"); | 236 jsobj.AddProperty("type", "ShapeChangeMapping"); |
| 246 jsobj.AddProperty("class", to_); | 237 jsobj.AddProperty("class", to_); |
| 247 jsobj.AddProperty("instanceCount", before()->length()); | 238 jsobj.AddProperty("instanceCount", before()->length()); |
| 248 JSONArray map(&jsobj, "fieldOffsetMappings"); | 239 JSONArray map(&jsobj, "fieldOffsetMappings"); |
| 249 for (int i = 0; i < mapping_.length(); i += 2) { | 240 for (int i = 0; i < mapping_.length(); i += 2) { |
| 250 JSONArray pair(&map); | 241 JSONArray pair(&map); |
| 251 pair.AddValue(mapping_.At(i)); | 242 pair.AddValue(mapping_.At(i)); |
| 252 pair.AddValue(mapping_.At(i + 1)); | 243 pair.AddValue(mapping_.At(i + 1)); |
| 253 } | 244 } |
| 254 } | 245 } |
| 255 | 246 |
| 256 | |
| 257 void ReasonForCancelling::Report(IsolateReloadContext* context) { | 247 void ReasonForCancelling::Report(IsolateReloadContext* context) { |
| 258 const Error& error = Error::Handle(ToError()); | 248 const Error& error = Error::Handle(ToError()); |
| 259 context->ReportError(error); | 249 context->ReportError(error); |
| 260 } | 250 } |
| 261 | 251 |
| 262 | |
| 263 RawError* ReasonForCancelling::ToError() { | 252 RawError* ReasonForCancelling::ToError() { |
| 264 // By default create the error returned from ToString. | 253 // By default create the error returned from ToString. |
| 265 const String& message = String::Handle(ToString()); | 254 const String& message = String::Handle(ToString()); |
| 266 return LanguageError::New(message); | 255 return LanguageError::New(message); |
| 267 } | 256 } |
| 268 | 257 |
| 269 | |
| 270 RawString* ReasonForCancelling::ToString() { | 258 RawString* ReasonForCancelling::ToString() { |
| 271 UNREACHABLE(); | 259 UNREACHABLE(); |
| 272 return NULL; | 260 return NULL; |
| 273 } | 261 } |
| 274 | 262 |
| 275 | |
| 276 void ReasonForCancelling::AppendTo(JSONArray* array) { | 263 void ReasonForCancelling::AppendTo(JSONArray* array) { |
| 277 JSONObject jsobj(array); | 264 JSONObject jsobj(array); |
| 278 jsobj.AddProperty("type", "ReasonForCancelling"); | 265 jsobj.AddProperty("type", "ReasonForCancelling"); |
| 279 const String& message = String::Handle(ToString()); | 266 const String& message = String::Handle(ToString()); |
| 280 jsobj.AddProperty("message", message.ToCString()); | 267 jsobj.AddProperty("message", message.ToCString()); |
| 281 } | 268 } |
| 282 | 269 |
| 283 | |
| 284 ClassReasonForCancelling::ClassReasonForCancelling(Zone* zone, | 270 ClassReasonForCancelling::ClassReasonForCancelling(Zone* zone, |
| 285 const Class& from, | 271 const Class& from, |
| 286 const Class& to) | 272 const Class& to) |
| 287 : ReasonForCancelling(zone), | 273 : ReasonForCancelling(zone), |
| 288 from_(Class::ZoneHandle(zone, from.raw())), | 274 from_(Class::ZoneHandle(zone, from.raw())), |
| 289 to_(Class::ZoneHandle(zone, to.raw())) {} | 275 to_(Class::ZoneHandle(zone, to.raw())) {} |
| 290 | 276 |
| 291 | |
| 292 void ClassReasonForCancelling::AppendTo(JSONArray* array) { | 277 void ClassReasonForCancelling::AppendTo(JSONArray* array) { |
| 293 JSONObject jsobj(array); | 278 JSONObject jsobj(array); |
| 294 jsobj.AddProperty("type", "ReasonForCancelling"); | 279 jsobj.AddProperty("type", "ReasonForCancelling"); |
| 295 jsobj.AddProperty("class", from_); | 280 jsobj.AddProperty("class", from_); |
| 296 const String& message = String::Handle(ToString()); | 281 const String& message = String::Handle(ToString()); |
| 297 jsobj.AddProperty("message", message.ToCString()); | 282 jsobj.AddProperty("message", message.ToCString()); |
| 298 } | 283 } |
| 299 | 284 |
| 300 | |
| 301 RawError* IsolateReloadContext::error() const { | 285 RawError* IsolateReloadContext::error() const { |
| 302 ASSERT(reload_aborted()); | 286 ASSERT(reload_aborted()); |
| 303 // Report the first error to the surroundings. | 287 // Report the first error to the surroundings. |
| 304 return reasons_to_cancel_reload_.At(0)->ToError(); | 288 return reasons_to_cancel_reload_.At(0)->ToError(); |
| 305 } | 289 } |
| 306 | 290 |
| 307 | |
| 308 class ScriptUrlSetTraits { | 291 class ScriptUrlSetTraits { |
| 309 public: | 292 public: |
| 310 static bool ReportStats() { return false; } | 293 static bool ReportStats() { return false; } |
| 311 static const char* Name() { return "ScriptUrlSetTraits"; } | 294 static const char* Name() { return "ScriptUrlSetTraits"; } |
| 312 | 295 |
| 313 static bool IsMatch(const Object& a, const Object& b) { | 296 static bool IsMatch(const Object& a, const Object& b) { |
| 314 if (!a.IsString() || !b.IsString()) { | 297 if (!a.IsString() || !b.IsString()) { |
| 315 return false; | 298 return false; |
| 316 } | 299 } |
| 317 | 300 |
| 318 return String::Cast(a).Equals(String::Cast(b)); | 301 return String::Cast(a).Equals(String::Cast(b)); |
| 319 } | 302 } |
| 320 | 303 |
| 321 static uword Hash(const Object& obj) { return String::Cast(obj).Hash(); } | 304 static uword Hash(const Object& obj) { return String::Cast(obj).Hash(); } |
| 322 }; | 305 }; |
| 323 | 306 |
| 324 | |
| 325 class ClassMapTraits { | 307 class ClassMapTraits { |
| 326 public: | 308 public: |
| 327 static bool ReportStats() { return false; } | 309 static bool ReportStats() { return false; } |
| 328 static const char* Name() { return "ClassMapTraits"; } | 310 static const char* Name() { return "ClassMapTraits"; } |
| 329 | 311 |
| 330 static bool IsMatch(const Object& a, const Object& b) { | 312 static bool IsMatch(const Object& a, const Object& b) { |
| 331 if (!a.IsClass() || !b.IsClass()) { | 313 if (!a.IsClass() || !b.IsClass()) { |
| 332 return false; | 314 return false; |
| 333 } | 315 } |
| 334 return IsolateReloadContext::IsSameClass(Class::Cast(a), Class::Cast(b)); | 316 return IsolateReloadContext::IsSameClass(Class::Cast(a), Class::Cast(b)); |
| 335 } | 317 } |
| 336 | 318 |
| 337 static uword Hash(const Object& obj) { | 319 static uword Hash(const Object& obj) { |
| 338 return String::HashRawSymbol(Class::Cast(obj).Name()); | 320 return String::HashRawSymbol(Class::Cast(obj).Name()); |
| 339 } | 321 } |
| 340 }; | 322 }; |
| 341 | 323 |
| 342 | |
| 343 class LibraryMapTraits { | 324 class LibraryMapTraits { |
| 344 public: | 325 public: |
| 345 static bool ReportStats() { return false; } | 326 static bool ReportStats() { return false; } |
| 346 static const char* Name() { return "LibraryMapTraits"; } | 327 static const char* Name() { return "LibraryMapTraits"; } |
| 347 | 328 |
| 348 static bool IsMatch(const Object& a, const Object& b) { | 329 static bool IsMatch(const Object& a, const Object& b) { |
| 349 if (!a.IsLibrary() || !b.IsLibrary()) { | 330 if (!a.IsLibrary() || !b.IsLibrary()) { |
| 350 return false; | 331 return false; |
| 351 } | 332 } |
| 352 return IsolateReloadContext::IsSameLibrary(Library::Cast(a), | 333 return IsolateReloadContext::IsSameLibrary(Library::Cast(a), |
| 353 Library::Cast(b)); | 334 Library::Cast(b)); |
| 354 } | 335 } |
| 355 | 336 |
| 356 static uword Hash(const Object& obj) { return Library::Cast(obj).UrlHash(); } | 337 static uword Hash(const Object& obj) { return Library::Cast(obj).UrlHash(); } |
| 357 }; | 338 }; |
| 358 | 339 |
| 359 | |
| 360 class BecomeMapTraits { | 340 class BecomeMapTraits { |
| 361 public: | 341 public: |
| 362 static bool ReportStats() { return false; } | 342 static bool ReportStats() { return false; } |
| 363 static const char* Name() { return "BecomeMapTraits"; } | 343 static const char* Name() { return "BecomeMapTraits"; } |
| 364 | 344 |
| 365 static bool IsMatch(const Object& a, const Object& b) { | 345 static bool IsMatch(const Object& a, const Object& b) { |
| 366 return a.raw() == b.raw(); | 346 return a.raw() == b.raw(); |
| 367 } | 347 } |
| 368 | 348 |
| 369 static uword Hash(const Object& obj) { | 349 static uword Hash(const Object& obj) { |
| 370 if (obj.IsLibrary()) { | 350 if (obj.IsLibrary()) { |
| 371 return Library::Cast(obj).UrlHash(); | 351 return Library::Cast(obj).UrlHash(); |
| 372 } else if (obj.IsClass()) { | 352 } else if (obj.IsClass()) { |
| 373 if (Class::Cast(obj).id() == kFreeListElement) { | 353 if (Class::Cast(obj).id() == kFreeListElement) { |
| 374 return 0; | 354 return 0; |
| 375 } | 355 } |
| 376 return String::HashRawSymbol(Class::Cast(obj).Name()); | 356 return String::HashRawSymbol(Class::Cast(obj).Name()); |
| 377 } else if (obj.IsField()) { | 357 } else if (obj.IsField()) { |
| 378 return String::HashRawSymbol(Field::Cast(obj).name()); | 358 return String::HashRawSymbol(Field::Cast(obj).name()); |
| 379 } else if (obj.IsInstance()) { | 359 } else if (obj.IsInstance()) { |
| 380 return Smi::Handle(Smi::RawCast(Instance::Cast(obj).HashCode())).Value(); | 360 return Smi::Handle(Smi::RawCast(Instance::Cast(obj).HashCode())).Value(); |
| 381 } | 361 } |
| 382 return 0; | 362 return 0; |
| 383 } | 363 } |
| 384 }; | 364 }; |
| 385 | 365 |
| 386 | |
| 387 bool IsolateReloadContext::IsSameField(const Field& a, const Field& b) { | 366 bool IsolateReloadContext::IsSameField(const Field& a, const Field& b) { |
| 388 if (a.is_static() != b.is_static()) { | 367 if (a.is_static() != b.is_static()) { |
| 389 return false; | 368 return false; |
| 390 } | 369 } |
| 391 const Class& a_cls = Class::Handle(a.Owner()); | 370 const Class& a_cls = Class::Handle(a.Owner()); |
| 392 const Class& b_cls = Class::Handle(b.Owner()); | 371 const Class& b_cls = Class::Handle(b.Owner()); |
| 393 | 372 |
| 394 if (!IsSameClass(a_cls, b_cls)) { | 373 if (!IsSameClass(a_cls, b_cls)) { |
| 395 return false; | 374 return false; |
| 396 } | 375 } |
| 397 | 376 |
| 398 const String& a_name = String::Handle(a.name()); | 377 const String& a_name = String::Handle(a.name()); |
| 399 const String& b_name = String::Handle(b.name()); | 378 const String& b_name = String::Handle(b.name()); |
| 400 | 379 |
| 401 return a_name.Equals(b_name); | 380 return a_name.Equals(b_name); |
| 402 } | 381 } |
| 403 | 382 |
| 404 | |
| 405 bool IsolateReloadContext::IsSameClass(const Class& a, const Class& b) { | 383 bool IsolateReloadContext::IsSameClass(const Class& a, const Class& b) { |
| 406 if (a.is_patch() != b.is_patch()) { | 384 if (a.is_patch() != b.is_patch()) { |
| 407 // TODO(johnmccutchan): Should we just check the class kind bits? | 385 // TODO(johnmccutchan): Should we just check the class kind bits? |
| 408 return false; | 386 return false; |
| 409 } | 387 } |
| 410 | 388 |
| 411 // TODO(turnidge): We need to look at generic type arguments for | 389 // TODO(turnidge): We need to look at generic type arguments for |
| 412 // synthetic mixin classes. Their names are not necessarily unique | 390 // synthetic mixin classes. Their names are not necessarily unique |
| 413 // currently. | 391 // currently. |
| 414 const String& a_name = String::Handle(a.Name()); | 392 const String& a_name = String::Handle(a.Name()); |
| 415 const String& b_name = String::Handle(b.Name()); | 393 const String& b_name = String::Handle(b.Name()); |
| 416 | 394 |
| 417 if (!a_name.Equals(b_name)) { | 395 if (!a_name.Equals(b_name)) { |
| 418 return false; | 396 return false; |
| 419 } | 397 } |
| 420 | 398 |
| 421 const Library& a_lib = Library::Handle(a.library()); | 399 const Library& a_lib = Library::Handle(a.library()); |
| 422 const Library& b_lib = Library::Handle(b.library()); | 400 const Library& b_lib = Library::Handle(b.library()); |
| 423 | 401 |
| 424 if (a_lib.IsNull() || b_lib.IsNull()) { | 402 if (a_lib.IsNull() || b_lib.IsNull()) { |
| 425 return a_lib.raw() == b_lib.raw(); | 403 return a_lib.raw() == b_lib.raw(); |
| 426 } | 404 } |
| 427 return (a_lib.private_key() == b_lib.private_key()); | 405 return (a_lib.private_key() == b_lib.private_key()); |
| 428 } | 406 } |
| 429 | 407 |
| 430 | |
| 431 bool IsolateReloadContext::IsSameLibrary(const Library& a_lib, | 408 bool IsolateReloadContext::IsSameLibrary(const Library& a_lib, |
| 432 const Library& b_lib) { | 409 const Library& b_lib) { |
| 433 const String& a_lib_url = | 410 const String& a_lib_url = |
| 434 String::Handle(a_lib.IsNull() ? String::null() : a_lib.url()); | 411 String::Handle(a_lib.IsNull() ? String::null() : a_lib.url()); |
| 435 const String& b_lib_url = | 412 const String& b_lib_url = |
| 436 String::Handle(b_lib.IsNull() ? String::null() : b_lib.url()); | 413 String::Handle(b_lib.IsNull() ? String::null() : b_lib.url()); |
| 437 return a_lib_url.Equals(b_lib_url); | 414 return a_lib_url.Equals(b_lib_url); |
| 438 } | 415 } |
| 439 | 416 |
| 440 | |
| 441 IsolateReloadContext::IsolateReloadContext(Isolate* isolate, JSONStream* js) | 417 IsolateReloadContext::IsolateReloadContext(Isolate* isolate, JSONStream* js) |
| 442 : zone_(Thread::Current()->zone()), | 418 : zone_(Thread::Current()->zone()), |
| 443 start_time_micros_(OS::GetCurrentMonotonicMicros()), | 419 start_time_micros_(OS::GetCurrentMonotonicMicros()), |
| 444 reload_timestamp_(OS::GetCurrentTimeMillis()), | 420 reload_timestamp_(OS::GetCurrentTimeMillis()), |
| 445 isolate_(isolate), | 421 isolate_(isolate), |
| 446 reload_skipped_(false), | 422 reload_skipped_(false), |
| 447 reload_aborted_(false), | 423 reload_aborted_(false), |
| 448 reload_finalized_(false), | 424 reload_finalized_(false), |
| 449 js_(js), | 425 js_(js), |
| 450 saved_num_cids_(-1), | 426 saved_num_cids_(-1), |
| (...skipping 14 matching lines...) Expand all Loading... |
| 465 saved_root_library_(Library::null()), | 441 saved_root_library_(Library::null()), |
| 466 saved_libraries_(GrowableObjectArray::null()), | 442 saved_libraries_(GrowableObjectArray::null()), |
| 467 root_url_prefix_(String::null()), | 443 root_url_prefix_(String::null()), |
| 468 old_root_url_prefix_(String::null()) { | 444 old_root_url_prefix_(String::null()) { |
| 469 // NOTE: DO NOT ALLOCATE ANY RAW OBJECTS HERE. The IsolateReloadContext is not | 445 // NOTE: DO NOT ALLOCATE ANY RAW OBJECTS HERE. The IsolateReloadContext is not |
| 470 // associated with the isolate yet and if a GC is triggered here the raw | 446 // associated with the isolate yet and if a GC is triggered here the raw |
| 471 // objects will not be properly accounted for. | 447 // objects will not be properly accounted for. |
| 472 ASSERT(zone_ != NULL); | 448 ASSERT(zone_ != NULL); |
| 473 } | 449 } |
| 474 | 450 |
| 475 | |
| 476 IsolateReloadContext::~IsolateReloadContext() { | 451 IsolateReloadContext::~IsolateReloadContext() { |
| 477 ASSERT(saved_class_table_ == NULL); | 452 ASSERT(saved_class_table_ == NULL); |
| 478 } | 453 } |
| 479 | 454 |
| 480 | |
| 481 void IsolateReloadContext::ReportError(const Error& error) { | 455 void IsolateReloadContext::ReportError(const Error& error) { |
| 482 if (FLAG_trace_reload) { | 456 if (FLAG_trace_reload) { |
| 483 THR_Print("ISO-RELOAD: Error: %s\n", error.ToErrorCString()); | 457 THR_Print("ISO-RELOAD: Error: %s\n", error.ToErrorCString()); |
| 484 } | 458 } |
| 485 ServiceEvent service_event(I, ServiceEvent::kIsolateReload); | 459 ServiceEvent service_event(I, ServiceEvent::kIsolateReload); |
| 486 service_event.set_reload_error(&error); | 460 service_event.set_reload_error(&error); |
| 487 Service::HandleEvent(&service_event); | 461 Service::HandleEvent(&service_event); |
| 488 } | 462 } |
| 489 | 463 |
| 490 | |
| 491 void IsolateReloadContext::ReportSuccess() { | 464 void IsolateReloadContext::ReportSuccess() { |
| 492 ServiceEvent service_event(I, ServiceEvent::kIsolateReload); | 465 ServiceEvent service_event(I, ServiceEvent::kIsolateReload); |
| 493 Service::HandleEvent(&service_event); | 466 Service::HandleEvent(&service_event); |
| 494 } | 467 } |
| 495 | 468 |
| 496 | |
| 497 class Aborted : public ReasonForCancelling { | 469 class Aborted : public ReasonForCancelling { |
| 498 public: | 470 public: |
| 499 Aborted(Zone* zone, const Error& error) | 471 Aborted(Zone* zone, const Error& error) |
| 500 : ReasonForCancelling(zone), | 472 : ReasonForCancelling(zone), |
| 501 error_(Error::ZoneHandle(zone, error.raw())) {} | 473 error_(Error::ZoneHandle(zone, error.raw())) {} |
| 502 | 474 |
| 503 private: | 475 private: |
| 504 const Error& error_; | 476 const Error& error_; |
| 505 | 477 |
| 506 RawError* ToError() { return error_.raw(); } | 478 RawError* ToError() { return error_.raw(); } |
| 507 RawString* ToString() { | 479 RawString* ToString() { |
| 508 return String::NewFormatted("%s", error_.ToErrorCString()); | 480 return String::NewFormatted("%s", error_.ToErrorCString()); |
| 509 } | 481 } |
| 510 }; | 482 }; |
| 511 | 483 |
| 512 | |
| 513 static intptr_t CommonSuffixLength(const char* a, const char* b) { | 484 static intptr_t CommonSuffixLength(const char* a, const char* b) { |
| 514 const intptr_t a_length = strlen(a); | 485 const intptr_t a_length = strlen(a); |
| 515 const intptr_t b_length = strlen(b); | 486 const intptr_t b_length = strlen(b); |
| 516 intptr_t a_cursor = a_length; | 487 intptr_t a_cursor = a_length; |
| 517 intptr_t b_cursor = b_length; | 488 intptr_t b_cursor = b_length; |
| 518 | 489 |
| 519 while ((a_cursor >= 0) && (b_cursor >= 0)) { | 490 while ((a_cursor >= 0) && (b_cursor >= 0)) { |
| 520 if (a[a_cursor] != b[b_cursor]) { | 491 if (a[a_cursor] != b[b_cursor]) { |
| 521 break; | 492 break; |
| 522 } | 493 } |
| 523 a_cursor--; | 494 a_cursor--; |
| 524 b_cursor--; | 495 b_cursor--; |
| 525 } | 496 } |
| 526 | 497 |
| 527 ASSERT((a_length - a_cursor) == (b_length - b_cursor)); | 498 ASSERT((a_length - a_cursor) == (b_length - b_cursor)); |
| 528 return (a_length - a_cursor); | 499 return (a_length - a_cursor); |
| 529 } | 500 } |
| 530 | 501 |
| 531 | |
| 532 // NOTE: This function returns *after* FinalizeLoading is called. | 502 // NOTE: This function returns *after* FinalizeLoading is called. |
| 533 void IsolateReloadContext::Reload(bool force_reload, | 503 void IsolateReloadContext::Reload(bool force_reload, |
| 534 const char* root_script_url, | 504 const char* root_script_url, |
| 535 const char* packages_url_) { | 505 const char* packages_url_) { |
| 536 TIMELINE_SCOPE(Reload); | 506 TIMELINE_SCOPE(Reload); |
| 537 Thread* thread = Thread::Current(); | 507 Thread* thread = Thread::Current(); |
| 538 ASSERT(isolate() == thread->isolate()); | 508 ASSERT(isolate() == thread->isolate()); |
| 539 | 509 |
| 540 // Grab root library before calling CheckpointBeforeReload. | 510 // Grab root library before calling CheckpointBeforeReload. |
| 541 const Library& old_root_lib = Library::Handle(object_store()->root_library()); | 511 const Library& old_root_lib = Library::Handle(object_store()->root_library()); |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 653 UNREACHABLE(); | 623 UNREACHABLE(); |
| 654 } | 624 } |
| 655 } | 625 } |
| 656 | 626 |
| 657 // Other errors (e.g. a parse error) are captured by the reload system. | 627 // Other errors (e.g. a parse error) are captured by the reload system. |
| 658 if (result.IsError()) { | 628 if (result.IsError()) { |
| 659 FinalizeFailedLoad(Error::Cast(result)); | 629 FinalizeFailedLoad(Error::Cast(result)); |
| 660 } | 630 } |
| 661 } | 631 } |
| 662 | 632 |
| 663 | |
| 664 void IsolateReloadContext::RegisterClass(const Class& new_cls) { | 633 void IsolateReloadContext::RegisterClass(const Class& new_cls) { |
| 665 const Class& old_cls = Class::Handle(OldClassOrNull(new_cls)); | 634 const Class& old_cls = Class::Handle(OldClassOrNull(new_cls)); |
| 666 if (old_cls.IsNull()) { | 635 if (old_cls.IsNull()) { |
| 667 I->class_table()->Register(new_cls); | 636 I->class_table()->Register(new_cls); |
| 668 | 637 |
| 669 if (FLAG_identity_reload) { | 638 if (FLAG_identity_reload) { |
| 670 TIR_Print("Could not find replacement class for %s\n", | 639 TIR_Print("Could not find replacement class for %s\n", |
| 671 new_cls.ToCString()); | 640 new_cls.ToCString()); |
| 672 UNREACHABLE(); | 641 UNREACHABLE(); |
| 673 } | 642 } |
| 674 | 643 |
| 675 // New class maps to itself. | 644 // New class maps to itself. |
| 676 AddClassMapping(new_cls, new_cls); | 645 AddClassMapping(new_cls, new_cls); |
| 677 return; | 646 return; |
| 678 } | 647 } |
| 679 VTIR_Print("Registering class: %s\n", new_cls.ToCString()); | 648 VTIR_Print("Registering class: %s\n", new_cls.ToCString()); |
| 680 new_cls.set_id(old_cls.id()); | 649 new_cls.set_id(old_cls.id()); |
| 681 isolate()->class_table()->SetAt(old_cls.id(), new_cls.raw()); | 650 isolate()->class_table()->SetAt(old_cls.id(), new_cls.raw()); |
| 682 if (!old_cls.is_enum_class()) { | 651 if (!old_cls.is_enum_class()) { |
| 683 new_cls.CopyCanonicalConstants(old_cls); | 652 new_cls.CopyCanonicalConstants(old_cls); |
| 684 } | 653 } |
| 685 new_cls.CopyCanonicalType(old_cls); | 654 new_cls.CopyCanonicalType(old_cls); |
| 686 AddBecomeMapping(old_cls, new_cls); | 655 AddBecomeMapping(old_cls, new_cls); |
| 687 AddClassMapping(new_cls, old_cls); | 656 AddClassMapping(new_cls, old_cls); |
| 688 } | 657 } |
| 689 | 658 |
| 690 | |
| 691 // FinalizeLoading will be called *before* Reload() returns but will not be | 659 // FinalizeLoading will be called *before* Reload() returns but will not be |
| 692 // called if the embedder fails to load sources. | 660 // called if the embedder fails to load sources. |
| 693 void IsolateReloadContext::FinalizeLoading() { | 661 void IsolateReloadContext::FinalizeLoading() { |
| 694 if (reload_skipped_) { | 662 if (reload_skipped_) { |
| 695 return; | 663 return; |
| 696 } | 664 } |
| 697 ASSERT(!reload_finalized_); | 665 ASSERT(!reload_finalized_); |
| 698 BuildLibraryMapping(); | 666 BuildLibraryMapping(); |
| 699 TIR_Print("---- LOAD SUCCEEDED\n"); | 667 TIR_Print("---- LOAD SUCCEEDED\n"); |
| 700 if (ValidateReload()) { | 668 if (ValidateReload()) { |
| 701 Commit(); | 669 Commit(); |
| 702 PostCommit(); | 670 PostCommit(); |
| 703 isolate()->set_last_reload_timestamp(reload_timestamp_); | 671 isolate()->set_last_reload_timestamp(reload_timestamp_); |
| 704 } else { | 672 } else { |
| 705 ReportReasonsForCancelling(); | 673 ReportReasonsForCancelling(); |
| 706 Rollback(); | 674 Rollback(); |
| 707 } | 675 } |
| 708 // ValidateReload mutates the direct subclass information and does | 676 // ValidateReload mutates the direct subclass information and does |
| 709 // not remove dead subclasses. Rebuild the direct subclass | 677 // not remove dead subclasses. Rebuild the direct subclass |
| 710 // information from scratch. | 678 // information from scratch. |
| 711 RebuildDirectSubclasses(); | 679 RebuildDirectSubclasses(); |
| 712 CommonFinalizeTail(); | 680 CommonFinalizeTail(); |
| 713 } | 681 } |
| 714 | 682 |
| 715 | |
| 716 // FinalizeFailedLoad will be called *before* Reload() returns and will only | 683 // FinalizeFailedLoad will be called *before* Reload() returns and will only |
| 717 // be called if the embedder fails to load sources. | 684 // be called if the embedder fails to load sources. |
| 718 void IsolateReloadContext::FinalizeFailedLoad(const Error& error) { | 685 void IsolateReloadContext::FinalizeFailedLoad(const Error& error) { |
| 719 TIR_Print("---- LOAD FAILED, ABORTING RELOAD\n"); | 686 TIR_Print("---- LOAD FAILED, ABORTING RELOAD\n"); |
| 720 AddReasonForCancelling(new Aborted(zone_, error)); | 687 AddReasonForCancelling(new Aborted(zone_, error)); |
| 721 ReportReasonsForCancelling(); | 688 ReportReasonsForCancelling(); |
| 722 if (!reload_finalized_) { | 689 if (!reload_finalized_) { |
| 723 Rollback(); | 690 Rollback(); |
| 724 } | 691 } |
| 725 CommonFinalizeTail(); | 692 CommonFinalizeTail(); |
| 726 } | 693 } |
| 727 | 694 |
| 728 | |
| 729 void IsolateReloadContext::CommonFinalizeTail() { | 695 void IsolateReloadContext::CommonFinalizeTail() { |
| 730 ReportOnJSON(js_); | 696 ReportOnJSON(js_); |
| 731 reload_finalized_ = true; | 697 reload_finalized_ = true; |
| 732 } | 698 } |
| 733 | 699 |
| 734 | |
| 735 void IsolateReloadContext::ReportOnJSON(JSONStream* stream) { | 700 void IsolateReloadContext::ReportOnJSON(JSONStream* stream) { |
| 736 JSONObject jsobj(stream); | 701 JSONObject jsobj(stream); |
| 737 jsobj.AddProperty("type", "ReloadReport"); | 702 jsobj.AddProperty("type", "ReloadReport"); |
| 738 jsobj.AddProperty("success", reload_skipped_ || !HasReasonsForCancelling()); | 703 jsobj.AddProperty("success", reload_skipped_ || !HasReasonsForCancelling()); |
| 739 { | 704 { |
| 740 JSONObject details(&jsobj, "details"); | 705 JSONObject details(&jsobj, "details"); |
| 741 if (reload_skipped_) { | 706 if (reload_skipped_) { |
| 742 // Reload was skipped. | 707 // Reload was skipped. |
| 743 const GrowableObjectArray& libs = | 708 const GrowableObjectArray& libs = |
| 744 GrowableObjectArray::Handle(object_store()->libraries()); | 709 GrowableObjectArray::Handle(object_store()->libraries()); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 764 details.AddProperty("loadedLibraryCount", loaded_library_count); | 729 details.AddProperty("loadedLibraryCount", loaded_library_count); |
| 765 details.AddProperty("finalLibraryCount", final_library_count); | 730 details.AddProperty("finalLibraryCount", final_library_count); |
| 766 JSONArray array(&jsobj, "shapeChangeMappings"); | 731 JSONArray array(&jsobj, "shapeChangeMappings"); |
| 767 for (intptr_t i = 0; i < instance_morphers_.length(); i++) { | 732 for (intptr_t i = 0; i < instance_morphers_.length(); i++) { |
| 768 instance_morphers_.At(i)->AppendTo(&array); | 733 instance_morphers_.At(i)->AppendTo(&array); |
| 769 } | 734 } |
| 770 } | 735 } |
| 771 } | 736 } |
| 772 } | 737 } |
| 773 | 738 |
| 774 | |
| 775 void IsolateReloadContext::EnsuredUnoptimizedCodeForStack() { | 739 void IsolateReloadContext::EnsuredUnoptimizedCodeForStack() { |
| 776 TIMELINE_SCOPE(EnsuredUnoptimizedCodeForStack); | 740 TIMELINE_SCOPE(EnsuredUnoptimizedCodeForStack); |
| 777 StackFrameIterator it(StackFrameIterator::kDontValidateFrames, | 741 StackFrameIterator it(StackFrameIterator::kDontValidateFrames, |
| 778 Thread::Current(), | 742 Thread::Current(), |
| 779 StackFrameIterator::kNoCrossThreadIteration); | 743 StackFrameIterator::kNoCrossThreadIteration); |
| 780 | 744 |
| 781 Function& func = Function::Handle(); | 745 Function& func = Function::Handle(); |
| 782 while (it.HasNextFrame()) { | 746 while (it.HasNextFrame()) { |
| 783 StackFrame* frame = it.NextFrame(); | 747 StackFrame* frame = it.NextFrame(); |
| 784 if (frame->IsDartFrame()) { | 748 if (frame->IsDartFrame()) { |
| 785 func = frame->LookupDartFunction(); | 749 func = frame->LookupDartFunction(); |
| 786 ASSERT(!func.IsNull()); | 750 ASSERT(!func.IsNull()); |
| 787 func.EnsureHasCompiledUnoptimizedCode(); | 751 func.EnsureHasCompiledUnoptimizedCode(); |
| 788 } | 752 } |
| 789 } | 753 } |
| 790 } | 754 } |
| 791 | 755 |
| 792 | |
| 793 void IsolateReloadContext::DeoptimizeDependentCode() { | 756 void IsolateReloadContext::DeoptimizeDependentCode() { |
| 794 TIMELINE_SCOPE(DeoptimizeDependentCode); | 757 TIMELINE_SCOPE(DeoptimizeDependentCode); |
| 795 ClassTable* class_table = I->class_table(); | 758 ClassTable* class_table = I->class_table(); |
| 796 | 759 |
| 797 const intptr_t bottom = Dart::vm_isolate()->class_table()->NumCids(); | 760 const intptr_t bottom = Dart::vm_isolate()->class_table()->NumCids(); |
| 798 const intptr_t top = I->class_table()->NumCids(); | 761 const intptr_t top = I->class_table()->NumCids(); |
| 799 Class& cls = Class::Handle(); | 762 Class& cls = Class::Handle(); |
| 800 Array& fields = Array::Handle(); | 763 Array& fields = Array::Handle(); |
| 801 Field& field = Field::Handle(); | 764 Field& field = Field::Handle(); |
| 802 for (intptr_t cls_idx = bottom; cls_idx < top; cls_idx++) { | 765 for (intptr_t cls_idx = bottom; cls_idx < top; cls_idx++) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 817 for (intptr_t field_idx = 0; field_idx < fields.Length(); field_idx++) { | 780 for (intptr_t field_idx = 0; field_idx < fields.Length(); field_idx++) { |
| 818 field = Field::RawCast(fields.At(field_idx)); | 781 field = Field::RawCast(fields.At(field_idx)); |
| 819 ASSERT(!field.IsNull()); | 782 ASSERT(!field.IsNull()); |
| 820 field.DeoptimizeDependentCode(); | 783 field.DeoptimizeDependentCode(); |
| 821 } | 784 } |
| 822 } | 785 } |
| 823 | 786 |
| 824 // TODO(johnmccutchan): Also call LibraryPrefix::InvalidateDependentCode. | 787 // TODO(johnmccutchan): Also call LibraryPrefix::InvalidateDependentCode. |
| 825 } | 788 } |
| 826 | 789 |
| 827 | |
| 828 void IsolateReloadContext::CheckpointClasses() { | 790 void IsolateReloadContext::CheckpointClasses() { |
| 829 TIMELINE_SCOPE(CheckpointClasses); | 791 TIMELINE_SCOPE(CheckpointClasses); |
| 830 TIR_Print("---- CHECKPOINTING CLASSES\n"); | 792 TIR_Print("---- CHECKPOINTING CLASSES\n"); |
| 831 // Checkpoint classes before a reload. We need to copy the following: | 793 // Checkpoint classes before a reload. We need to copy the following: |
| 832 // 1) The size of the class table. | 794 // 1) The size of the class table. |
| 833 // 2) The class table itself. | 795 // 2) The class table itself. |
| 834 // For efficiency, we build a set of classes before the reload. This set | 796 // For efficiency, we build a set of classes before the reload. This set |
| 835 // is used to pair new classes with old classes. | 797 // is used to pair new classes with old classes. |
| 836 | 798 |
| 837 ClassTable* class_table = I->class_table(); | 799 ClassTable* class_table = I->class_table(); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 858 // No class at this index, mark it as NULL. | 820 // No class at this index, mark it as NULL. |
| 859 local_saved_class_table[i] = NULL; | 821 local_saved_class_table[i] = NULL; |
| 860 } | 822 } |
| 861 } | 823 } |
| 862 old_classes_set_storage_ = old_classes_set.Release().raw(); | 824 old_classes_set_storage_ = old_classes_set.Release().raw(); |
| 863 // Assigning the field must be done after saving the class table. | 825 // Assigning the field must be done after saving the class table. |
| 864 saved_class_table_ = local_saved_class_table; | 826 saved_class_table_ = local_saved_class_table; |
| 865 TIR_Print("---- System had %" Pd " classes\n", saved_num_cids_); | 827 TIR_Print("---- System had %" Pd " classes\n", saved_num_cids_); |
| 866 } | 828 } |
| 867 | 829 |
| 868 | |
| 869 Dart_FileModifiedCallback IsolateReloadContext::file_modified_callback_ = NULL; | 830 Dart_FileModifiedCallback IsolateReloadContext::file_modified_callback_ = NULL; |
| 870 | 831 |
| 871 | |
| 872 bool IsolateReloadContext::ScriptModifiedSince(const Script& script, | 832 bool IsolateReloadContext::ScriptModifiedSince(const Script& script, |
| 873 int64_t since) { | 833 int64_t since) { |
| 874 if (file_modified_callback_ == NULL) { | 834 if (file_modified_callback_ == NULL) { |
| 875 return true; | 835 return true; |
| 876 } | 836 } |
| 877 // We use the resolved url to determine if the script has been modified. | 837 // We use the resolved url to determine if the script has been modified. |
| 878 const String& url = String::Handle(script.resolved_url()); | 838 const String& url = String::Handle(script.resolved_url()); |
| 879 const char* url_chars = url.ToCString(); | 839 const char* url_chars = url.ToCString(); |
| 880 return (*file_modified_callback_)(url_chars, since); | 840 return (*file_modified_callback_)(url_chars, since); |
| 881 } | 841 } |
| 882 | 842 |
| 883 | |
| 884 static void PropagateLibraryModified( | 843 static void PropagateLibraryModified( |
| 885 const ZoneGrowableArray<ZoneGrowableArray<intptr_t>*>* imported_by, | 844 const ZoneGrowableArray<ZoneGrowableArray<intptr_t>*>* imported_by, |
| 886 intptr_t lib_index, | 845 intptr_t lib_index, |
| 887 BitVector* modified_libs) { | 846 BitVector* modified_libs) { |
| 888 ZoneGrowableArray<intptr_t>* dep_libs = (*imported_by)[lib_index]; | 847 ZoneGrowableArray<intptr_t>* dep_libs = (*imported_by)[lib_index]; |
| 889 for (intptr_t i = 0; i < dep_libs->length(); i++) { | 848 for (intptr_t i = 0; i < dep_libs->length(); i++) { |
| 890 intptr_t dep_lib_index = (*dep_libs)[i]; | 849 intptr_t dep_lib_index = (*dep_libs)[i]; |
| 891 if (!modified_libs->Contains(dep_lib_index)) { | 850 if (!modified_libs->Contains(dep_lib_index)) { |
| 892 modified_libs->Add(dep_lib_index); | 851 modified_libs->Add(dep_lib_index); |
| 893 PropagateLibraryModified(imported_by, dep_lib_index, modified_libs); | 852 PropagateLibraryModified(imported_by, dep_lib_index, modified_libs); |
| 894 } | 853 } |
| 895 } | 854 } |
| 896 } | 855 } |
| 897 | 856 |
| 898 | |
| 899 BitVector* IsolateReloadContext::FindModifiedLibraries(bool force_reload) { | 857 BitVector* IsolateReloadContext::FindModifiedLibraries(bool force_reload) { |
| 900 Thread* thread = Thread::Current(); | 858 Thread* thread = Thread::Current(); |
| 901 int64_t last_reload = I->last_reload_timestamp(); | 859 int64_t last_reload = I->last_reload_timestamp(); |
| 902 | 860 |
| 903 const GrowableObjectArray& libs = | 861 const GrowableObjectArray& libs = |
| 904 GrowableObjectArray::Handle(object_store()->libraries()); | 862 GrowableObjectArray::Handle(object_store()->libraries()); |
| 905 Library& lib = Library::Handle(); | 863 Library& lib = Library::Handle(); |
| 906 Array& scripts = Array::Handle(); | 864 Array& scripts = Array::Handle(); |
| 907 Script& script = Script::Handle(); | 865 Script& script = Script::Handle(); |
| 908 intptr_t num_libs = libs.Length(); | 866 intptr_t num_libs = libs.Length(); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 984 modified_libs->Add(lib_idx); | 942 modified_libs->Add(lib_idx); |
| 985 PropagateLibraryModified(imported_by, lib_idx, modified_libs); | 943 PropagateLibraryModified(imported_by, lib_idx, modified_libs); |
| 986 break; | 944 break; |
| 987 } | 945 } |
| 988 } | 946 } |
| 989 } | 947 } |
| 990 | 948 |
| 991 return modified_libs; | 949 return modified_libs; |
| 992 } | 950 } |
| 993 | 951 |
| 994 | |
| 995 void IsolateReloadContext::CheckpointLibraries() { | 952 void IsolateReloadContext::CheckpointLibraries() { |
| 996 TIMELINE_SCOPE(CheckpointLibraries); | 953 TIMELINE_SCOPE(CheckpointLibraries); |
| 997 TIR_Print("---- CHECKPOINTING LIBRARIES\n"); | 954 TIR_Print("---- CHECKPOINTING LIBRARIES\n"); |
| 998 // Save the root library in case we abort the reload. | 955 // Save the root library in case we abort the reload. |
| 999 const Library& root_lib = Library::Handle(object_store()->root_library()); | 956 const Library& root_lib = Library::Handle(object_store()->root_library()); |
| 1000 set_saved_root_library(root_lib); | 957 set_saved_root_library(root_lib); |
| 1001 | 958 |
| 1002 // Save the old libraries array in case we abort the reload. | 959 // Save the old libraries array in case we abort the reload. |
| 1003 const GrowableObjectArray& libs = | 960 const GrowableObjectArray& libs = |
| 1004 GrowableObjectArray::Handle(object_store()->libraries()); | 961 GrowableObjectArray::Handle(object_store()->libraries()); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1029 } | 986 } |
| 1030 modified_libs_ = NULL; // Renumbering the libraries has invalidated this. | 987 modified_libs_ = NULL; // Renumbering the libraries has invalidated this. |
| 1031 old_libraries_set_storage_ = old_libraries_set.Release().raw(); | 988 old_libraries_set_storage_ = old_libraries_set.Release().raw(); |
| 1032 | 989 |
| 1033 // Reset the registered libraries to the filtered array. | 990 // Reset the registered libraries to the filtered array. |
| 1034 Library::RegisterLibraries(Thread::Current(), new_libs); | 991 Library::RegisterLibraries(Thread::Current(), new_libs); |
| 1035 // Reset the root library to null. | 992 // Reset the root library to null. |
| 1036 object_store()->set_root_library(Library::Handle()); | 993 object_store()->set_root_library(Library::Handle()); |
| 1037 } | 994 } |
| 1038 | 995 |
| 1039 | |
| 1040 // While reloading everything we do must be reversible so that we can abort | 996 // While reloading everything we do must be reversible so that we can abort |
| 1041 // safely if the reload fails. This function stashes things to the side and | 997 // safely if the reload fails. This function stashes things to the side and |
| 1042 // prepares the isolate for the reload attempt. | 998 // prepares the isolate for the reload attempt. |
| 1043 void IsolateReloadContext::Checkpoint() { | 999 void IsolateReloadContext::Checkpoint() { |
| 1044 TIMELINE_SCOPE(Checkpoint); | 1000 TIMELINE_SCOPE(Checkpoint); |
| 1045 CheckpointClasses(); | 1001 CheckpointClasses(); |
| 1046 CheckpointLibraries(); | 1002 CheckpointLibraries(); |
| 1047 } | 1003 } |
| 1048 | 1004 |
| 1049 | |
| 1050 void IsolateReloadContext::RollbackClasses() { | 1005 void IsolateReloadContext::RollbackClasses() { |
| 1051 TIR_Print("---- ROLLING BACK CLASS TABLE\n"); | 1006 TIR_Print("---- ROLLING BACK CLASS TABLE\n"); |
| 1052 ASSERT(saved_num_cids_ > 0); | 1007 ASSERT(saved_num_cids_ > 0); |
| 1053 ASSERT(saved_class_table_ != NULL); | 1008 ASSERT(saved_class_table_ != NULL); |
| 1054 ClassTable* class_table = I->class_table(); | 1009 ClassTable* class_table = I->class_table(); |
| 1055 class_table->SetNumCids(saved_num_cids_); | 1010 class_table->SetNumCids(saved_num_cids_); |
| 1056 // Overwrite classes in class table with the saved classes. | 1011 // Overwrite classes in class table with the saved classes. |
| 1057 for (intptr_t i = 0; i < saved_num_cids_; i++) { | 1012 for (intptr_t i = 0; i < saved_num_cids_; i++) { |
| 1058 if (class_table->IsValidIndex(i)) { | 1013 if (class_table->IsValidIndex(i)) { |
| 1059 class_table->SetAt(i, saved_class_table_[i]); | 1014 class_table->SetAt(i, saved_class_table_[i]); |
| 1060 } | 1015 } |
| 1061 } | 1016 } |
| 1062 | 1017 |
| 1063 RawClass** local_saved_class_table = saved_class_table_; | 1018 RawClass** local_saved_class_table = saved_class_table_; |
| 1064 saved_class_table_ = NULL; | 1019 saved_class_table_ = NULL; |
| 1065 // Can't free this table immediately as another thread (e.g., the sweeper) may | 1020 // Can't free this table immediately as another thread (e.g., the sweeper) may |
| 1066 // be suspended between loading the table pointer and loading the table | 1021 // be suspended between loading the table pointer and loading the table |
| 1067 // element. Table will be freed at the next major GC or isolate shutdown. | 1022 // element. Table will be freed at the next major GC or isolate shutdown. |
| 1068 class_table->AddOldTable(local_saved_class_table); | 1023 class_table->AddOldTable(local_saved_class_table); |
| 1069 } | 1024 } |
| 1070 | 1025 |
| 1071 | |
| 1072 void IsolateReloadContext::RollbackLibraries() { | 1026 void IsolateReloadContext::RollbackLibraries() { |
| 1073 TIR_Print("---- ROLLING BACK LIBRARY CHANGES\n"); | 1027 TIR_Print("---- ROLLING BACK LIBRARY CHANGES\n"); |
| 1074 Thread* thread = Thread::Current(); | 1028 Thread* thread = Thread::Current(); |
| 1075 Library& lib = Library::Handle(); | 1029 Library& lib = Library::Handle(); |
| 1076 GrowableObjectArray& saved_libs = | 1030 GrowableObjectArray& saved_libs = |
| 1077 GrowableObjectArray::Handle(Z, saved_libraries()); | 1031 GrowableObjectArray::Handle(Z, saved_libraries()); |
| 1078 if (!saved_libs.IsNull()) { | 1032 if (!saved_libs.IsNull()) { |
| 1079 for (intptr_t i = 0; i < saved_libs.Length(); i++) { | 1033 for (intptr_t i = 0; i < saved_libs.Length(); i++) { |
| 1080 lib = Library::RawCast(saved_libs.At(i)); | 1034 lib = Library::RawCast(saved_libs.At(i)); |
| 1081 // Restore indexes that were modified in CheckpointLibraries. | 1035 // Restore indexes that were modified in CheckpointLibraries. |
| 1082 lib.set_index(i); | 1036 lib.set_index(i); |
| 1083 } | 1037 } |
| 1084 | 1038 |
| 1085 // Reset the registered libraries to the filtered array. | 1039 // Reset the registered libraries to the filtered array. |
| 1086 Library::RegisterLibraries(thread, saved_libs); | 1040 Library::RegisterLibraries(thread, saved_libs); |
| 1087 } | 1041 } |
| 1088 | 1042 |
| 1089 Library& saved_root_lib = Library::Handle(Z, saved_root_library()); | 1043 Library& saved_root_lib = Library::Handle(Z, saved_root_library()); |
| 1090 if (!saved_root_lib.IsNull()) { | 1044 if (!saved_root_lib.IsNull()) { |
| 1091 object_store()->set_root_library(saved_root_lib); | 1045 object_store()->set_root_library(saved_root_lib); |
| 1092 } | 1046 } |
| 1093 | 1047 |
| 1094 set_saved_root_library(Library::Handle()); | 1048 set_saved_root_library(Library::Handle()); |
| 1095 set_saved_libraries(GrowableObjectArray::Handle()); | 1049 set_saved_libraries(GrowableObjectArray::Handle()); |
| 1096 } | 1050 } |
| 1097 | 1051 |
| 1098 | |
| 1099 void IsolateReloadContext::Rollback() { | 1052 void IsolateReloadContext::Rollback() { |
| 1100 TIR_Print("---- ROLLING BACK"); | 1053 TIR_Print("---- ROLLING BACK"); |
| 1101 RollbackClasses(); | 1054 RollbackClasses(); |
| 1102 RollbackLibraries(); | 1055 RollbackLibraries(); |
| 1103 } | 1056 } |
| 1104 | 1057 |
| 1105 | |
| 1106 #ifdef DEBUG | 1058 #ifdef DEBUG |
| 1107 void IsolateReloadContext::VerifyMaps() { | 1059 void IsolateReloadContext::VerifyMaps() { |
| 1108 TIMELINE_SCOPE(VerifyMaps); | 1060 TIMELINE_SCOPE(VerifyMaps); |
| 1109 Class& cls = Class::Handle(); | 1061 Class& cls = Class::Handle(); |
| 1110 Class& new_cls = Class::Handle(); | 1062 Class& new_cls = Class::Handle(); |
| 1111 Class& cls2 = Class::Handle(); | 1063 Class& cls2 = Class::Handle(); |
| 1112 | 1064 |
| 1113 // Verify that two old classes aren't both mapped to the same new | 1065 // Verify that two old classes aren't both mapped to the same new |
| 1114 // class. This could happen is the IsSameClass function is broken. | 1066 // class. This could happen is the IsSameClass function is broken. |
| 1115 UnorderedHashMap<ClassMapTraits> class_map(class_map_storage_); | 1067 UnorderedHashMap<ClassMapTraits> class_map(class_map_storage_); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1132 } | 1084 } |
| 1133 bool update = reverse_class_map.UpdateOrInsert(cls, new_cls); | 1085 bool update = reverse_class_map.UpdateOrInsert(cls, new_cls); |
| 1134 ASSERT(!update); | 1086 ASSERT(!update); |
| 1135 } | 1087 } |
| 1136 } | 1088 } |
| 1137 class_map.Release(); | 1089 class_map.Release(); |
| 1138 reverse_class_map.Release(); | 1090 reverse_class_map.Release(); |
| 1139 } | 1091 } |
| 1140 #endif | 1092 #endif |
| 1141 | 1093 |
| 1142 | |
| 1143 void IsolateReloadContext::Commit() { | 1094 void IsolateReloadContext::Commit() { |
| 1144 TIMELINE_SCOPE(Commit); | 1095 TIMELINE_SCOPE(Commit); |
| 1145 TIR_Print("---- COMMITTING RELOAD\n"); | 1096 TIR_Print("---- COMMITTING RELOAD\n"); |
| 1146 | 1097 |
| 1147 // Note that the object heap contains before and after instances | 1098 // Note that the object heap contains before and after instances |
| 1148 // used for morphing. It is therefore important that morphing takes | 1099 // used for morphing. It is therefore important that morphing takes |
| 1149 // place prior to any heap walking. | 1100 // place prior to any heap walking. |
| 1150 // So please keep this code at the top of Commit(). | 1101 // So please keep this code at the top of Commit(). |
| 1151 if (HasInstanceMorphers()) { | 1102 if (HasInstanceMorphers()) { |
| 1152 // Perform shape shifting of instances if necessary. | 1103 // Perform shape shifting of instances if necessary. |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1300 #ifdef DEBUG | 1251 #ifdef DEBUG |
| 1301 // Verify that all canonical instances are correctly setup in the | 1252 // Verify that all canonical instances are correctly setup in the |
| 1302 // corresponding canonical tables. | 1253 // corresponding canonical tables. |
| 1303 Thread* thread = Thread::Current(); | 1254 Thread* thread = Thread::Current(); |
| 1304 I->heap()->CollectAllGarbage(); | 1255 I->heap()->CollectAllGarbage(); |
| 1305 VerifyCanonicalVisitor check_canonical(thread); | 1256 VerifyCanonicalVisitor check_canonical(thread); |
| 1306 I->heap()->IterateObjects(&check_canonical); | 1257 I->heap()->IterateObjects(&check_canonical); |
| 1307 #endif // DEBUG | 1258 #endif // DEBUG |
| 1308 } | 1259 } |
| 1309 | 1260 |
| 1310 | |
| 1311 void IsolateReloadContext::RehashConstants() { | 1261 void IsolateReloadContext::RehashConstants() { |
| 1312 TIMELINE_SCOPE(RehashConstants); | 1262 TIMELINE_SCOPE(RehashConstants); |
| 1313 ClassTable* class_table = I->class_table(); | 1263 ClassTable* class_table = I->class_table(); |
| 1314 Class& cls = Class::Handle(zone_); | 1264 Class& cls = Class::Handle(zone_); |
| 1315 const intptr_t top = class_table->NumCids(); | 1265 const intptr_t top = class_table->NumCids(); |
| 1316 for (intptr_t cid = kInstanceCid; cid < top; cid++) { | 1266 for (intptr_t cid = kInstanceCid; cid < top; cid++) { |
| 1317 if (!class_table->IsValidIndex(cid) || !class_table->HasValidClassAt(cid)) { | 1267 if (!class_table->IsValidIndex(cid) || !class_table->HasValidClassAt(cid)) { |
| 1318 // Skip invalid classes. | 1268 // Skip invalid classes. |
| 1319 continue; | 1269 continue; |
| 1320 } | 1270 } |
| 1321 if (RawObject::IsNumberClassId(cid) || RawObject::IsStringClassId(cid)) { | 1271 if (RawObject::IsNumberClassId(cid) || RawObject::IsStringClassId(cid)) { |
| 1322 // Skip classes that cannot be affected by the 'become' operation. | 1272 // Skip classes that cannot be affected by the 'become' operation. |
| 1323 continue; | 1273 continue; |
| 1324 } | 1274 } |
| 1325 // Rehash constants. | 1275 // Rehash constants. |
| 1326 cls = class_table->At(cid); | 1276 cls = class_table->At(cid); |
| 1327 VTIR_Print("Rehashing constants in class `%s`\n", cls.ToCString()); | 1277 VTIR_Print("Rehashing constants in class `%s`\n", cls.ToCString()); |
| 1328 cls.RehashConstants(zone_); | 1278 cls.RehashConstants(zone_); |
| 1329 } | 1279 } |
| 1330 } | 1280 } |
| 1331 | 1281 |
| 1332 | |
| 1333 bool IsolateReloadContext::IsDirty(const Library& lib) { | 1282 bool IsolateReloadContext::IsDirty(const Library& lib) { |
| 1334 const intptr_t index = lib.index(); | 1283 const intptr_t index = lib.index(); |
| 1335 if (index == static_cast<classid_t>(-1)) { | 1284 if (index == static_cast<classid_t>(-1)) { |
| 1336 // Treat deleted libraries as dirty. | 1285 // Treat deleted libraries as dirty. |
| 1337 return true; | 1286 return true; |
| 1338 } | 1287 } |
| 1339 ASSERT((index >= 0) && (index < library_infos_.length())); | 1288 ASSERT((index >= 0) && (index < library_infos_.length())); |
| 1340 return library_infos_[index].dirty; | 1289 return library_infos_[index].dirty; |
| 1341 } | 1290 } |
| 1342 | 1291 |
| 1343 | |
| 1344 void IsolateReloadContext::PostCommit() { | 1292 void IsolateReloadContext::PostCommit() { |
| 1345 TIMELINE_SCOPE(PostCommit); | 1293 TIMELINE_SCOPE(PostCommit); |
| 1346 set_saved_root_library(Library::Handle()); | 1294 set_saved_root_library(Library::Handle()); |
| 1347 set_saved_libraries(GrowableObjectArray::Handle()); | 1295 set_saved_libraries(GrowableObjectArray::Handle()); |
| 1348 InvalidateWorld(); | 1296 InvalidateWorld(); |
| 1349 TIR_Print("---- DONE COMMIT\n"); | 1297 TIR_Print("---- DONE COMMIT\n"); |
| 1350 } | 1298 } |
| 1351 | 1299 |
| 1352 | |
| 1353 void IsolateReloadContext::AddReasonForCancelling(ReasonForCancelling* reason) { | 1300 void IsolateReloadContext::AddReasonForCancelling(ReasonForCancelling* reason) { |
| 1354 reload_aborted_ = true; | 1301 reload_aborted_ = true; |
| 1355 reasons_to_cancel_reload_.Add(reason); | 1302 reasons_to_cancel_reload_.Add(reason); |
| 1356 } | 1303 } |
| 1357 | 1304 |
| 1358 | |
| 1359 void IsolateReloadContext::AddInstanceMorpher(InstanceMorpher* morpher) { | 1305 void IsolateReloadContext::AddInstanceMorpher(InstanceMorpher* morpher) { |
| 1360 instance_morphers_.Add(morpher); | 1306 instance_morphers_.Add(morpher); |
| 1361 cid_mapper_.Insert(morpher); | 1307 cid_mapper_.Insert(morpher); |
| 1362 } | 1308 } |
| 1363 | 1309 |
| 1364 | |
| 1365 void IsolateReloadContext::ReportReasonsForCancelling() { | 1310 void IsolateReloadContext::ReportReasonsForCancelling() { |
| 1366 ASSERT(FLAG_reload_force_rollback || HasReasonsForCancelling()); | 1311 ASSERT(FLAG_reload_force_rollback || HasReasonsForCancelling()); |
| 1367 for (int i = 0; i < reasons_to_cancel_reload_.length(); i++) { | 1312 for (int i = 0; i < reasons_to_cancel_reload_.length(); i++) { |
| 1368 reasons_to_cancel_reload_.At(i)->Report(this); | 1313 reasons_to_cancel_reload_.At(i)->Report(this); |
| 1369 } | 1314 } |
| 1370 } | 1315 } |
| 1371 | 1316 |
| 1372 | |
| 1373 // The ObjectLocator is used for collecting instances that | 1317 // The ObjectLocator is used for collecting instances that |
| 1374 // needs to be morphed. | 1318 // needs to be morphed. |
| 1375 class ObjectLocator : public ObjectVisitor { | 1319 class ObjectLocator : public ObjectVisitor { |
| 1376 public: | 1320 public: |
| 1377 explicit ObjectLocator(IsolateReloadContext* context) | 1321 explicit ObjectLocator(IsolateReloadContext* context) |
| 1378 : context_(context), count_(0) {} | 1322 : context_(context), count_(0) {} |
| 1379 | 1323 |
| 1380 void VisitObject(RawObject* obj) { | 1324 void VisitObject(RawObject* obj) { |
| 1381 InstanceMorpher* morpher = | 1325 InstanceMorpher* morpher = |
| 1382 context_->cid_mapper_.LookupValue(obj->GetClassId()); | 1326 context_->cid_mapper_.LookupValue(obj->GetClassId()); |
| 1383 if (morpher != NULL) { | 1327 if (morpher != NULL) { |
| 1384 morpher->AddObject(obj); | 1328 morpher->AddObject(obj); |
| 1385 count_++; | 1329 count_++; |
| 1386 } | 1330 } |
| 1387 } | 1331 } |
| 1388 | 1332 |
| 1389 // Return the number of located objects for morphing. | 1333 // Return the number of located objects for morphing. |
| 1390 intptr_t count() { return count_; } | 1334 intptr_t count() { return count_; } |
| 1391 | 1335 |
| 1392 private: | 1336 private: |
| 1393 IsolateReloadContext* context_; | 1337 IsolateReloadContext* context_; |
| 1394 intptr_t count_; | 1338 intptr_t count_; |
| 1395 }; | 1339 }; |
| 1396 | 1340 |
| 1397 | |
| 1398 void IsolateReloadContext::MorphInstances() { | 1341 void IsolateReloadContext::MorphInstances() { |
| 1399 TIMELINE_SCOPE(MorphInstances); | 1342 TIMELINE_SCOPE(MorphInstances); |
| 1400 ASSERT(HasInstanceMorphers()); | 1343 ASSERT(HasInstanceMorphers()); |
| 1401 if (FLAG_trace_reload) { | 1344 if (FLAG_trace_reload) { |
| 1402 LogBlock blocker; | 1345 LogBlock blocker; |
| 1403 TIR_Print("MorphInstance: \n"); | 1346 TIR_Print("MorphInstance: \n"); |
| 1404 for (intptr_t i = 0; i < instance_morphers_.length(); i++) { | 1347 for (intptr_t i = 0; i < instance_morphers_.length(); i++) { |
| 1405 instance_morphers_.At(i)->Dump(); | 1348 instance_morphers_.At(i)->Dump(); |
| 1406 } | 1349 } |
| 1407 } | 1350 } |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1441 } | 1384 } |
| 1442 | 1385 |
| 1443 // This is important: The saved class table (describing before objects) | 1386 // This is important: The saved class table (describing before objects) |
| 1444 // must be zapped to prevent the forwarding in GetClassForHeapWalkAt. | 1387 // must be zapped to prevent the forwarding in GetClassForHeapWalkAt. |
| 1445 // Instance will from now be described by the isolate's class table. | 1388 // Instance will from now be described by the isolate's class table. |
| 1446 free(saved_class_table_); | 1389 free(saved_class_table_); |
| 1447 saved_class_table_ = NULL; | 1390 saved_class_table_ = NULL; |
| 1448 Become::ElementsForwardIdentity(before, after); | 1391 Become::ElementsForwardIdentity(before, after); |
| 1449 } | 1392 } |
| 1450 | 1393 |
| 1451 | |
| 1452 void IsolateReloadContext::RunNewFieldInitializers() { | 1394 void IsolateReloadContext::RunNewFieldInitializers() { |
| 1453 // Run new field initializers on all instances. | 1395 // Run new field initializers on all instances. |
| 1454 for (intptr_t i = 0; i < instance_morphers_.length(); i++) { | 1396 for (intptr_t i = 0; i < instance_morphers_.length(); i++) { |
| 1455 instance_morphers_.At(i)->RunNewFieldInitializers(); | 1397 instance_morphers_.At(i)->RunNewFieldInitializers(); |
| 1456 } | 1398 } |
| 1457 } | 1399 } |
| 1458 | 1400 |
| 1459 | |
| 1460 bool IsolateReloadContext::ValidateReload() { | 1401 bool IsolateReloadContext::ValidateReload() { |
| 1461 TIMELINE_SCOPE(ValidateReload); | 1402 TIMELINE_SCOPE(ValidateReload); |
| 1462 if (reload_aborted()) return false; | 1403 if (reload_aborted()) return false; |
| 1463 | 1404 |
| 1464 TIR_Print("---- VALIDATING RELOAD\n"); | 1405 TIR_Print("---- VALIDATING RELOAD\n"); |
| 1465 | 1406 |
| 1466 // Validate libraries. | 1407 // Validate libraries. |
| 1467 { | 1408 { |
| 1468 ASSERT(library_map_storage_ != Array::null()); | 1409 ASSERT(library_map_storage_ != Array::null()); |
| 1469 UnorderedHashMap<LibraryMapTraits> map(library_map_storage_); | 1410 UnorderedHashMap<LibraryMapTraits> map(library_map_storage_); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1495 if (new_cls.raw() != cls.raw()) { | 1436 if (new_cls.raw() != cls.raw()) { |
| 1496 cls.CheckReload(new_cls, this); | 1437 cls.CheckReload(new_cls, this); |
| 1497 } | 1438 } |
| 1498 } | 1439 } |
| 1499 map.Release(); | 1440 map.Release(); |
| 1500 } | 1441 } |
| 1501 | 1442 |
| 1502 return !FLAG_reload_force_rollback && !HasReasonsForCancelling(); | 1443 return !FLAG_reload_force_rollback && !HasReasonsForCancelling(); |
| 1503 } | 1444 } |
| 1504 | 1445 |
| 1505 | |
| 1506 RawClass* IsolateReloadContext::FindOriginalClass(const Class& cls) { | 1446 RawClass* IsolateReloadContext::FindOriginalClass(const Class& cls) { |
| 1507 return MappedClass(cls); | 1447 return MappedClass(cls); |
| 1508 } | 1448 } |
| 1509 | 1449 |
| 1510 | |
| 1511 RawClass* IsolateReloadContext::GetClassForHeapWalkAt(intptr_t cid) { | 1450 RawClass* IsolateReloadContext::GetClassForHeapWalkAt(intptr_t cid) { |
| 1512 RawClass** class_table = AtomicOperations::LoadRelaxed(&saved_class_table_); | 1451 RawClass** class_table = AtomicOperations::LoadRelaxed(&saved_class_table_); |
| 1513 if (class_table != NULL) { | 1452 if (class_table != NULL) { |
| 1514 ASSERT(cid > 0); | 1453 ASSERT(cid > 0); |
| 1515 ASSERT(cid < saved_num_cids_); | 1454 ASSERT(cid < saved_num_cids_); |
| 1516 return class_table[cid]; | 1455 return class_table[cid]; |
| 1517 } else { | 1456 } else { |
| 1518 return isolate_->class_table()->At(cid); | 1457 return isolate_->class_table()->At(cid); |
| 1519 } | 1458 } |
| 1520 } | 1459 } |
| 1521 | 1460 |
| 1522 | |
| 1523 RawLibrary* IsolateReloadContext::saved_root_library() const { | 1461 RawLibrary* IsolateReloadContext::saved_root_library() const { |
| 1524 return saved_root_library_; | 1462 return saved_root_library_; |
| 1525 } | 1463 } |
| 1526 | 1464 |
| 1527 | |
| 1528 void IsolateReloadContext::set_saved_root_library(const Library& value) { | 1465 void IsolateReloadContext::set_saved_root_library(const Library& value) { |
| 1529 saved_root_library_ = value.raw(); | 1466 saved_root_library_ = value.raw(); |
| 1530 } | 1467 } |
| 1531 | 1468 |
| 1532 | |
| 1533 RawGrowableObjectArray* IsolateReloadContext::saved_libraries() const { | 1469 RawGrowableObjectArray* IsolateReloadContext::saved_libraries() const { |
| 1534 return saved_libraries_; | 1470 return saved_libraries_; |
| 1535 } | 1471 } |
| 1536 | 1472 |
| 1537 | |
| 1538 void IsolateReloadContext::set_saved_libraries( | 1473 void IsolateReloadContext::set_saved_libraries( |
| 1539 const GrowableObjectArray& value) { | 1474 const GrowableObjectArray& value) { |
| 1540 saved_libraries_ = value.raw(); | 1475 saved_libraries_ = value.raw(); |
| 1541 } | 1476 } |
| 1542 | 1477 |
| 1543 | |
| 1544 void IsolateReloadContext::VisitObjectPointers(ObjectPointerVisitor* visitor) { | 1478 void IsolateReloadContext::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
| 1545 visitor->VisitPointers(from(), to()); | 1479 visitor->VisitPointers(from(), to()); |
| 1546 if (saved_class_table_ != NULL) { | 1480 if (saved_class_table_ != NULL) { |
| 1547 visitor->VisitPointers( | 1481 visitor->VisitPointers( |
| 1548 reinterpret_cast<RawObject**>(&saved_class_table_[0]), saved_num_cids_); | 1482 reinterpret_cast<RawObject**>(&saved_class_table_[0]), saved_num_cids_); |
| 1549 } | 1483 } |
| 1550 } | 1484 } |
| 1551 | 1485 |
| 1552 | |
| 1553 ObjectStore* IsolateReloadContext::object_store() { | 1486 ObjectStore* IsolateReloadContext::object_store() { |
| 1554 return isolate_->object_store(); | 1487 return isolate_->object_store(); |
| 1555 } | 1488 } |
| 1556 | 1489 |
| 1557 | |
| 1558 void IsolateReloadContext::ResetUnoptimizedICsOnStack() { | 1490 void IsolateReloadContext::ResetUnoptimizedICsOnStack() { |
| 1559 Thread* thread = Thread::Current(); | 1491 Thread* thread = Thread::Current(); |
| 1560 StackZone stack_zone(thread); | 1492 StackZone stack_zone(thread); |
| 1561 Zone* zone = stack_zone.GetZone(); | 1493 Zone* zone = stack_zone.GetZone(); |
| 1562 | 1494 |
| 1563 Code& code = Code::Handle(zone); | 1495 Code& code = Code::Handle(zone); |
| 1564 Function& function = Function::Handle(zone); | 1496 Function& function = Function::Handle(zone); |
| 1565 DartFrameIterator iterator(thread, | 1497 DartFrameIterator iterator(thread, |
| 1566 StackFrameIterator::kNoCrossThreadIteration); | 1498 StackFrameIterator::kNoCrossThreadIteration); |
| 1567 StackFrame* frame = iterator.NextFrame(); | 1499 StackFrame* frame = iterator.NextFrame(); |
| 1568 while (frame != NULL) { | 1500 while (frame != NULL) { |
| 1569 code = frame->LookupDartCode(); | 1501 code = frame->LookupDartCode(); |
| 1570 if (code.is_optimized()) { | 1502 if (code.is_optimized()) { |
| 1571 // If this code is optimized, we need to reset the ICs in the | 1503 // If this code is optimized, we need to reset the ICs in the |
| 1572 // corresponding unoptimized code, which will be executed when the stack | 1504 // corresponding unoptimized code, which will be executed when the stack |
| 1573 // unwinds to the optimized code. | 1505 // unwinds to the optimized code. |
| 1574 function = code.function(); | 1506 function = code.function(); |
| 1575 code = function.unoptimized_code(); | 1507 code = function.unoptimized_code(); |
| 1576 ASSERT(!code.IsNull()); | 1508 ASSERT(!code.IsNull()); |
| 1577 code.ResetICDatas(zone); | 1509 code.ResetICDatas(zone); |
| 1578 } else { | 1510 } else { |
| 1579 code.ResetICDatas(zone); | 1511 code.ResetICDatas(zone); |
| 1580 } | 1512 } |
| 1581 frame = iterator.NextFrame(); | 1513 frame = iterator.NextFrame(); |
| 1582 } | 1514 } |
| 1583 } | 1515 } |
| 1584 | 1516 |
| 1585 | |
| 1586 void IsolateReloadContext::ResetMegamorphicCaches() { | 1517 void IsolateReloadContext::ResetMegamorphicCaches() { |
| 1587 object_store()->set_megamorphic_cache_table(GrowableObjectArray::Handle()); | 1518 object_store()->set_megamorphic_cache_table(GrowableObjectArray::Handle()); |
| 1588 // Since any current optimized code will not make any more calls, it may be | 1519 // Since any current optimized code will not make any more calls, it may be |
| 1589 // better to clear the table instead of clearing each of the caches, allow | 1520 // better to clear the table instead of clearing each of the caches, allow |
| 1590 // the current megamorphic caches get GC'd and any new optimized code allocate | 1521 // the current megamorphic caches get GC'd and any new optimized code allocate |
| 1591 // new ones. | 1522 // new ones. |
| 1592 } | 1523 } |
| 1593 | 1524 |
| 1594 | |
| 1595 class MarkFunctionsForRecompilation : public ObjectVisitor { | 1525 class MarkFunctionsForRecompilation : public ObjectVisitor { |
| 1596 public: | 1526 public: |
| 1597 MarkFunctionsForRecompilation(Isolate* isolate, | 1527 MarkFunctionsForRecompilation(Isolate* isolate, |
| 1598 IsolateReloadContext* reload_context, | 1528 IsolateReloadContext* reload_context, |
| 1599 Zone* zone) | 1529 Zone* zone) |
| 1600 : ObjectVisitor(), | 1530 : ObjectVisitor(), |
| 1601 handle_(Object::Handle(zone)), | 1531 handle_(Object::Handle(zone)), |
| 1602 owning_class_(Class::Handle(zone)), | 1532 owning_class_(Class::Handle(zone)), |
| 1603 owning_lib_(Library::Handle(zone)), | 1533 owning_lib_(Library::Handle(zone)), |
| 1604 code_(Code::Handle(zone)), | 1534 code_(Code::Handle(zone)), |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1669 } | 1599 } |
| 1670 | 1600 |
| 1671 Object& handle_; | 1601 Object& handle_; |
| 1672 Class& owning_class_; | 1602 Class& owning_class_; |
| 1673 Library& owning_lib_; | 1603 Library& owning_lib_; |
| 1674 Code& code_; | 1604 Code& code_; |
| 1675 IsolateReloadContext* reload_context_; | 1605 IsolateReloadContext* reload_context_; |
| 1676 Zone* zone_; | 1606 Zone* zone_; |
| 1677 }; | 1607 }; |
| 1678 | 1608 |
| 1679 | |
| 1680 void IsolateReloadContext::MarkAllFunctionsForRecompilation() { | 1609 void IsolateReloadContext::MarkAllFunctionsForRecompilation() { |
| 1681 TIMELINE_SCOPE(MarkAllFunctionsForRecompilation); | 1610 TIMELINE_SCOPE(MarkAllFunctionsForRecompilation); |
| 1682 TIR_Print("---- MARKING ALL FUNCTIONS FOR RECOMPILATION\n"); | 1611 TIR_Print("---- MARKING ALL FUNCTIONS FOR RECOMPILATION\n"); |
| 1683 Thread* thread = Thread::Current(); | 1612 Thread* thread = Thread::Current(); |
| 1684 StackZone stack_zone(thread); | 1613 StackZone stack_zone(thread); |
| 1685 Zone* zone = stack_zone.GetZone(); | 1614 Zone* zone = stack_zone.GetZone(); |
| 1686 NoSafepointScope no_safepoint; | 1615 NoSafepointScope no_safepoint; |
| 1687 HeapIterationScope heap_iteration_scope; | 1616 HeapIterationScope heap_iteration_scope; |
| 1688 MarkFunctionsForRecompilation visitor(isolate_, this, zone); | 1617 MarkFunctionsForRecompilation visitor(isolate_, this, zone); |
| 1689 isolate_->heap()->VisitObjects(&visitor); | 1618 isolate_->heap()->VisitObjects(&visitor); |
| 1690 } | 1619 } |
| 1691 | 1620 |
| 1692 | |
| 1693 void IsolateReloadContext::InvalidateWorld() { | 1621 void IsolateReloadContext::InvalidateWorld() { |
| 1694 TIR_Print("---- INVALIDATING WORLD\n"); | 1622 TIR_Print("---- INVALIDATING WORLD\n"); |
| 1695 ResetMegamorphicCaches(); | 1623 ResetMegamorphicCaches(); |
| 1696 DeoptimizeFunctionsOnStack(); | 1624 DeoptimizeFunctionsOnStack(); |
| 1697 ResetUnoptimizedICsOnStack(); | 1625 ResetUnoptimizedICsOnStack(); |
| 1698 MarkAllFunctionsForRecompilation(); | 1626 MarkAllFunctionsForRecompilation(); |
| 1699 } | 1627 } |
| 1700 | 1628 |
| 1701 | |
| 1702 RawClass* IsolateReloadContext::MappedClass(const Class& replacement_or_new) { | 1629 RawClass* IsolateReloadContext::MappedClass(const Class& replacement_or_new) { |
| 1703 UnorderedHashMap<ClassMapTraits> map(class_map_storage_); | 1630 UnorderedHashMap<ClassMapTraits> map(class_map_storage_); |
| 1704 Class& cls = Class::Handle(); | 1631 Class& cls = Class::Handle(); |
| 1705 cls ^= map.GetOrNull(replacement_or_new); | 1632 cls ^= map.GetOrNull(replacement_or_new); |
| 1706 // No need to update storage address because no mutation occurred. | 1633 // No need to update storage address because no mutation occurred. |
| 1707 map.Release(); | 1634 map.Release(); |
| 1708 return cls.raw(); | 1635 return cls.raw(); |
| 1709 } | 1636 } |
| 1710 | 1637 |
| 1711 | |
| 1712 RawLibrary* IsolateReloadContext::MappedLibrary( | 1638 RawLibrary* IsolateReloadContext::MappedLibrary( |
| 1713 const Library& replacement_or_new) { | 1639 const Library& replacement_or_new) { |
| 1714 return Library::null(); | 1640 return Library::null(); |
| 1715 } | 1641 } |
| 1716 | 1642 |
| 1717 | |
| 1718 RawClass* IsolateReloadContext::OldClassOrNull( | 1643 RawClass* IsolateReloadContext::OldClassOrNull( |
| 1719 const Class& replacement_or_new) { | 1644 const Class& replacement_or_new) { |
| 1720 UnorderedHashSet<ClassMapTraits> old_classes_set(old_classes_set_storage_); | 1645 UnorderedHashSet<ClassMapTraits> old_classes_set(old_classes_set_storage_); |
| 1721 Class& cls = Class::Handle(); | 1646 Class& cls = Class::Handle(); |
| 1722 cls ^= old_classes_set.GetOrNull(replacement_or_new); | 1647 cls ^= old_classes_set.GetOrNull(replacement_or_new); |
| 1723 old_classes_set_storage_ = old_classes_set.Release().raw(); | 1648 old_classes_set_storage_ = old_classes_set.Release().raw(); |
| 1724 return cls.raw(); | 1649 return cls.raw(); |
| 1725 } | 1650 } |
| 1726 | 1651 |
| 1727 | |
| 1728 RawString* IsolateReloadContext::FindLibraryPrivateKey( | 1652 RawString* IsolateReloadContext::FindLibraryPrivateKey( |
| 1729 const Library& replacement_or_new) { | 1653 const Library& replacement_or_new) { |
| 1730 const Library& old = Library::Handle(OldLibraryOrNull(replacement_or_new)); | 1654 const Library& old = Library::Handle(OldLibraryOrNull(replacement_or_new)); |
| 1731 if (old.IsNull()) { | 1655 if (old.IsNull()) { |
| 1732 return String::null(); | 1656 return String::null(); |
| 1733 } | 1657 } |
| 1734 #if defined(DEBUG) | 1658 #if defined(DEBUG) |
| 1735 VTIR_Print("`%s` is getting `%s`'s private key.\n", | 1659 VTIR_Print("`%s` is getting `%s`'s private key.\n", |
| 1736 String::Handle(replacement_or_new.url()).ToCString(), | 1660 String::Handle(replacement_or_new.url()).ToCString(), |
| 1737 String::Handle(old.url()).ToCString()); | 1661 String::Handle(old.url()).ToCString()); |
| 1738 #endif | 1662 #endif |
| 1739 return old.private_key(); | 1663 return old.private_key(); |
| 1740 } | 1664 } |
| 1741 | 1665 |
| 1742 | |
| 1743 RawLibrary* IsolateReloadContext::OldLibraryOrNull( | 1666 RawLibrary* IsolateReloadContext::OldLibraryOrNull( |
| 1744 const Library& replacement_or_new) { | 1667 const Library& replacement_or_new) { |
| 1745 UnorderedHashSet<LibraryMapTraits> old_libraries_set( | 1668 UnorderedHashSet<LibraryMapTraits> old_libraries_set( |
| 1746 old_libraries_set_storage_); | 1669 old_libraries_set_storage_); |
| 1747 Library& lib = Library::Handle(); | 1670 Library& lib = Library::Handle(); |
| 1748 lib ^= old_libraries_set.GetOrNull(replacement_or_new); | 1671 lib ^= old_libraries_set.GetOrNull(replacement_or_new); |
| 1749 old_libraries_set.Release(); | 1672 old_libraries_set.Release(); |
| 1750 if (lib.IsNull() && (root_url_prefix_ != String::null()) && | 1673 if (lib.IsNull() && (root_url_prefix_ != String::null()) && |
| 1751 (old_root_url_prefix_ != String::null())) { | 1674 (old_root_url_prefix_ != String::null())) { |
| 1752 return OldLibraryOrNullBaseMoved(replacement_or_new); | 1675 return OldLibraryOrNullBaseMoved(replacement_or_new); |
| 1753 } | 1676 } |
| 1754 return lib.raw(); | 1677 return lib.raw(); |
| 1755 } | 1678 } |
| 1756 | 1679 |
| 1757 | |
| 1758 // Attempt to find the pair to |replacement_or_new| with the knowledge that | 1680 // Attempt to find the pair to |replacement_or_new| with the knowledge that |
| 1759 // the base url prefix has moved. | 1681 // the base url prefix has moved. |
| 1760 RawLibrary* IsolateReloadContext::OldLibraryOrNullBaseMoved( | 1682 RawLibrary* IsolateReloadContext::OldLibraryOrNullBaseMoved( |
| 1761 const Library& replacement_or_new) { | 1683 const Library& replacement_or_new) { |
| 1762 const String& url_prefix = String::Handle(root_url_prefix_); | 1684 const String& url_prefix = String::Handle(root_url_prefix_); |
| 1763 const String& old_url_prefix = String::Handle(old_root_url_prefix_); | 1685 const String& old_url_prefix = String::Handle(old_root_url_prefix_); |
| 1764 const intptr_t prefix_length = url_prefix.Length(); | 1686 const intptr_t prefix_length = url_prefix.Length(); |
| 1765 const intptr_t old_prefix_length = old_url_prefix.Length(); | 1687 const intptr_t old_prefix_length = old_url_prefix.Length(); |
| 1766 const String& new_url = String::Handle(replacement_or_new.url()); | 1688 const String& new_url = String::Handle(replacement_or_new.url()); |
| 1767 const String& suffix = | 1689 const String& suffix = |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1787 } | 1709 } |
| 1788 if (old_suffix.Equals(suffix)) { | 1710 if (old_suffix.Equals(suffix)) { |
| 1789 TIR_Print("`%s` is moving to `%s`\n", old_url.ToCString(), | 1711 TIR_Print("`%s` is moving to `%s`\n", old_url.ToCString(), |
| 1790 new_url.ToCString()); | 1712 new_url.ToCString()); |
| 1791 return old.raw(); | 1713 return old.raw(); |
| 1792 } | 1714 } |
| 1793 } | 1715 } |
| 1794 return Library::null(); | 1716 return Library::null(); |
| 1795 } | 1717 } |
| 1796 | 1718 |
| 1797 | |
| 1798 void IsolateReloadContext::BuildLibraryMapping() { | 1719 void IsolateReloadContext::BuildLibraryMapping() { |
| 1799 const GrowableObjectArray& libs = | 1720 const GrowableObjectArray& libs = |
| 1800 GrowableObjectArray::Handle(object_store()->libraries()); | 1721 GrowableObjectArray::Handle(object_store()->libraries()); |
| 1801 | 1722 |
| 1802 Library& replacement_or_new = Library::Handle(); | 1723 Library& replacement_or_new = Library::Handle(); |
| 1803 Library& old = Library::Handle(); | 1724 Library& old = Library::Handle(); |
| 1804 for (intptr_t i = num_saved_libs_; i < libs.Length(); i++) { | 1725 for (intptr_t i = num_saved_libs_; i < libs.Length(); i++) { |
| 1805 replacement_or_new = Library::RawCast(libs.At(i)); | 1726 replacement_or_new = Library::RawCast(libs.At(i)); |
| 1806 old ^= OldLibraryOrNull(replacement_or_new); | 1727 old ^= OldLibraryOrNull(replacement_or_new); |
| 1807 if (old.IsNull()) { | 1728 if (old.IsNull()) { |
| 1808 if (FLAG_identity_reload) { | 1729 if (FLAG_identity_reload) { |
| 1809 TIR_Print("Could not find original library for %s\n", | 1730 TIR_Print("Could not find original library for %s\n", |
| 1810 replacement_or_new.ToCString()); | 1731 replacement_or_new.ToCString()); |
| 1811 UNREACHABLE(); | 1732 UNREACHABLE(); |
| 1812 } | 1733 } |
| 1813 // New library. | 1734 // New library. |
| 1814 AddLibraryMapping(replacement_or_new, replacement_or_new); | 1735 AddLibraryMapping(replacement_or_new, replacement_or_new); |
| 1815 } else { | 1736 } else { |
| 1816 ASSERT(!replacement_or_new.is_dart_scheme()); | 1737 ASSERT(!replacement_or_new.is_dart_scheme()); |
| 1817 // Replaced class. | 1738 // Replaced class. |
| 1818 AddLibraryMapping(replacement_or_new, old); | 1739 AddLibraryMapping(replacement_or_new, old); |
| 1819 | 1740 |
| 1820 AddBecomeMapping(old, replacement_or_new); | 1741 AddBecomeMapping(old, replacement_or_new); |
| 1821 } | 1742 } |
| 1822 } | 1743 } |
| 1823 } | 1744 } |
| 1824 | 1745 |
| 1825 | |
| 1826 void IsolateReloadContext::AddClassMapping(const Class& replacement_or_new, | 1746 void IsolateReloadContext::AddClassMapping(const Class& replacement_or_new, |
| 1827 const Class& original) { | 1747 const Class& original) { |
| 1828 UnorderedHashMap<ClassMapTraits> map(class_map_storage_); | 1748 UnorderedHashMap<ClassMapTraits> map(class_map_storage_); |
| 1829 bool update = map.UpdateOrInsert(replacement_or_new, original); | 1749 bool update = map.UpdateOrInsert(replacement_or_new, original); |
| 1830 ASSERT(!update); | 1750 ASSERT(!update); |
| 1831 // The storage given to the map may have been reallocated, remember the new | 1751 // The storage given to the map may have been reallocated, remember the new |
| 1832 // address. | 1752 // address. |
| 1833 class_map_storage_ = map.Release().raw(); | 1753 class_map_storage_ = map.Release().raw(); |
| 1834 } | 1754 } |
| 1835 | 1755 |
| 1836 | |
| 1837 void IsolateReloadContext::AddLibraryMapping(const Library& replacement_or_new, | 1756 void IsolateReloadContext::AddLibraryMapping(const Library& replacement_or_new, |
| 1838 const Library& original) { | 1757 const Library& original) { |
| 1839 UnorderedHashMap<LibraryMapTraits> map(library_map_storage_); | 1758 UnorderedHashMap<LibraryMapTraits> map(library_map_storage_); |
| 1840 bool update = map.UpdateOrInsert(replacement_or_new, original); | 1759 bool update = map.UpdateOrInsert(replacement_or_new, original); |
| 1841 ASSERT(!update); | 1760 ASSERT(!update); |
| 1842 // The storage given to the map may have been reallocated, remember the new | 1761 // The storage given to the map may have been reallocated, remember the new |
| 1843 // address. | 1762 // address. |
| 1844 library_map_storage_ = map.Release().raw(); | 1763 library_map_storage_ = map.Release().raw(); |
| 1845 } | 1764 } |
| 1846 | 1765 |
| 1847 | |
| 1848 void IsolateReloadContext::AddStaticFieldMapping(const Field& old_field, | 1766 void IsolateReloadContext::AddStaticFieldMapping(const Field& old_field, |
| 1849 const Field& new_field) { | 1767 const Field& new_field) { |
| 1850 ASSERT(old_field.is_static()); | 1768 ASSERT(old_field.is_static()); |
| 1851 ASSERT(new_field.is_static()); | 1769 ASSERT(new_field.is_static()); |
| 1852 | 1770 |
| 1853 AddBecomeMapping(old_field, new_field); | 1771 AddBecomeMapping(old_field, new_field); |
| 1854 } | 1772 } |
| 1855 | 1773 |
| 1856 | |
| 1857 void IsolateReloadContext::AddBecomeMapping(const Object& old, | 1774 void IsolateReloadContext::AddBecomeMapping(const Object& old, |
| 1858 const Object& neu) { | 1775 const Object& neu) { |
| 1859 ASSERT(become_map_storage_ != Array::null()); | 1776 ASSERT(become_map_storage_ != Array::null()); |
| 1860 UnorderedHashMap<BecomeMapTraits> become_map(become_map_storage_); | 1777 UnorderedHashMap<BecomeMapTraits> become_map(become_map_storage_); |
| 1861 bool update = become_map.UpdateOrInsert(old, neu); | 1778 bool update = become_map.UpdateOrInsert(old, neu); |
| 1862 ASSERT(!update); | 1779 ASSERT(!update); |
| 1863 become_map_storage_ = become_map.Release().raw(); | 1780 become_map_storage_ = become_map.Release().raw(); |
| 1864 } | 1781 } |
| 1865 | 1782 |
| 1866 | |
| 1867 void IsolateReloadContext::AddEnumBecomeMapping(const Object& old, | 1783 void IsolateReloadContext::AddEnumBecomeMapping(const Object& old, |
| 1868 const Object& neu) { | 1784 const Object& neu) { |
| 1869 const GrowableObjectArray& become_enum_mappings = | 1785 const GrowableObjectArray& become_enum_mappings = |
| 1870 GrowableObjectArray::Handle(become_enum_mappings_); | 1786 GrowableObjectArray::Handle(become_enum_mappings_); |
| 1871 become_enum_mappings.Add(old); | 1787 become_enum_mappings.Add(old); |
| 1872 become_enum_mappings.Add(neu); | 1788 become_enum_mappings.Add(neu); |
| 1873 ASSERT((become_enum_mappings.Length() % 2) == 0); | 1789 ASSERT((become_enum_mappings.Length() % 2) == 0); |
| 1874 } | 1790 } |
| 1875 | 1791 |
| 1876 | |
| 1877 void IsolateReloadContext::RebuildDirectSubclasses() { | 1792 void IsolateReloadContext::RebuildDirectSubclasses() { |
| 1878 ClassTable* class_table = I->class_table(); | 1793 ClassTable* class_table = I->class_table(); |
| 1879 intptr_t num_cids = class_table->NumCids(); | 1794 intptr_t num_cids = class_table->NumCids(); |
| 1880 | 1795 |
| 1881 // Clear the direct subclasses for all classes. | 1796 // Clear the direct subclasses for all classes. |
| 1882 Class& cls = Class::Handle(); | 1797 Class& cls = Class::Handle(); |
| 1883 GrowableObjectArray& subclasses = GrowableObjectArray::Handle(); | 1798 GrowableObjectArray& subclasses = GrowableObjectArray::Handle(); |
| 1884 for (intptr_t i = 1; i < num_cids; i++) { | 1799 for (intptr_t i = 1; i < num_cids; i++) { |
| 1885 if (class_table->HasValidClassAt(i)) { | 1800 if (class_table->HasValidClassAt(i)) { |
| 1886 cls = class_table->At(i); | 1801 cls = class_table->At(i); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1903 ASSERT(!super_cls.IsNull()); | 1818 ASSERT(!super_cls.IsNull()); |
| 1904 super_cls.AddDirectSubclass(cls); | 1819 super_cls.AddDirectSubclass(cls); |
| 1905 } | 1820 } |
| 1906 } | 1821 } |
| 1907 } | 1822 } |
| 1908 } | 1823 } |
| 1909 | 1824 |
| 1910 #endif // !PRODUCT | 1825 #endif // !PRODUCT |
| 1911 | 1826 |
| 1912 } // namespace dart | 1827 } // namespace dart |
| OLD | NEW |