| 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/code_generator.h" | 9 #include "vm/code_generator.h" |
| 10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
| 11 #include "vm/dart_api_impl.h" | 11 #include "vm/dart_api_impl.h" |
| 12 #include "vm/hash_table.h" | 12 #include "vm/hash_table.h" |
| 13 #include "vm/isolate.h" | 13 #include "vm/isolate.h" |
| 14 #include "vm/log.h" | 14 #include "vm/log.h" |
| 15 #include "vm/object.h" | 15 #include "vm/object.h" |
| 16 #include "vm/object_store.h" | 16 #include "vm/object_store.h" |
| 17 #include "vm/parser.h" | 17 #include "vm/parser.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"); |
| 28 DEFINE_FLAG(bool, trace_reload_verbose, false, | 28 DEFINE_FLAG(bool, |
| 29 trace_reload_verbose, |
| 30 false, |
| 29 "trace isolate reloading verbose"); | 31 "trace isolate reloading verbose"); |
| 30 DEFINE_FLAG(bool, identity_reload, false, "Enable checks for identity reload."); | 32 DEFINE_FLAG(bool, identity_reload, false, "Enable checks for identity reload."); |
| 31 DEFINE_FLAG(int, reload_every, 0, "Reload every N stack overflow checks."); | 33 DEFINE_FLAG(int, reload_every, 0, "Reload every N stack overflow checks."); |
| 32 DEFINE_FLAG(bool, reload_every_optimized, true, "Only from optimized code."); | 34 DEFINE_FLAG(bool, reload_every_optimized, true, "Only from optimized code."); |
| 33 DEFINE_FLAG(bool, reload_every_back_off, false, | 35 DEFINE_FLAG(bool, |
| 36 reload_every_back_off, |
| 37 false, |
| 34 "Double the --reload-every value after each reload."); | 38 "Double the --reload-every value after each reload."); |
| 35 DEFINE_FLAG(bool, reload_force_rollback, false, | 39 DEFINE_FLAG(bool, |
| 40 reload_force_rollback, |
| 41 false, |
| 36 "Force all reloads to fail and rollback."); | 42 "Force all reloads to fail and rollback."); |
| 37 DEFINE_FLAG(bool, check_reloaded, false, | 43 DEFINE_FLAG(bool, |
| 44 check_reloaded, |
| 45 false, |
| 38 "Assert that an isolate has reloaded at least once.") | 46 "Assert that an isolate has reloaded at least once.") |
| 39 #ifndef PRODUCT | 47 #ifndef PRODUCT |
| 40 | 48 |
| 41 #define I (isolate()) | 49 #define I (isolate()) |
| 42 #define Z (thread->zone()) | 50 #define Z (thread->zone()) |
| 43 | 51 |
| 44 #define TIMELINE_SCOPE(name) \ | 52 #define TIMELINE_SCOPE(name) \ |
| 45 TimelineDurationScope tds##name(Thread::Current(), \ | 53 TimelineDurationScope tds##name(Thread::Current(), \ |
| 46 Timeline::GetIsolateStream(), \ | 54 Timeline::GetIsolateStream(), #name) |
| 47 #name) | |
| 48 | 55 |
| 49 | 56 |
| 50 InstanceMorpher::InstanceMorpher(Zone* zone, const Class& from, const Class& to) | 57 InstanceMorpher::InstanceMorpher(Zone* zone, const Class& from, const Class& to) |
| 51 : from_(Class::Handle(zone, from.raw())), | 58 : from_(Class::Handle(zone, from.raw())), |
| 52 to_(Class::Handle(zone, to.raw())), | 59 to_(Class::Handle(zone, to.raw())), |
| 53 mapping_(zone, 0) { | 60 mapping_(zone, 0) { |
| 54 ComputeMapping(); | 61 ComputeMapping(); |
| 55 before_ = new(zone) ZoneGrowableArray<const Instance*>(zone, 0); | 62 before_ = new (zone) ZoneGrowableArray<const Instance*>(zone, 0); |
| 56 after_ = new(zone) ZoneGrowableArray<const Instance*>(zone, 0); | 63 after_ = new (zone) ZoneGrowableArray<const Instance*>(zone, 0); |
| 57 ASSERT(from_.id() == to_.id()); | 64 ASSERT(from_.id() == to_.id()); |
| 58 cid_ = from_.id(); | 65 cid_ = from_.id(); |
| 59 } | 66 } |
| 60 | 67 |
| 61 | 68 |
| 62 void InstanceMorpher::AddObject(RawObject* object) const { | 69 void InstanceMorpher::AddObject(RawObject* object) const { |
| 63 ASSERT(object->GetClassId() == cid()); | 70 ASSERT(object->GetClassId() == cid()); |
| 64 const Instance& instance = Instance::Cast(Object::Handle(object)); | 71 const Instance& instance = Instance::Cast(Object::Handle(object)); |
| 65 before_->Add(&instance); | 72 before_->Add(&instance); |
| 66 } | 73 } |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 102 mapping_.Add(to_field.Offset()); | 109 mapping_.Add(to_field.Offset()); |
| 103 } | 110 } |
| 104 } | 111 } |
| 105 } | 112 } |
| 106 } | 113 } |
| 107 | 114 |
| 108 | 115 |
| 109 RawInstance* InstanceMorpher::Morph(const Instance& instance) const { | 116 RawInstance* InstanceMorpher::Morph(const Instance& instance) const { |
| 110 const Instance& result = Instance::Handle(Instance::New(to_)); | 117 const Instance& result = Instance::Handle(Instance::New(to_)); |
| 111 // Morph the context from instance to result using mapping_. | 118 // Morph the context from instance to result using mapping_. |
| 112 for (intptr_t i = 0; i < mapping_.length(); i +=2) { | 119 for (intptr_t i = 0; i < mapping_.length(); i += 2) { |
| 113 intptr_t from_offset = mapping_.At(i); | 120 intptr_t from_offset = mapping_.At(i); |
| 114 intptr_t to_offset = mapping_.At(i+1); | 121 intptr_t to_offset = mapping_.At(i + 1); |
| 115 const Object& value = | 122 const Object& value = |
| 116 Object::Handle(instance.RawGetFieldAtOffset(from_offset)); | 123 Object::Handle(instance.RawGetFieldAtOffset(from_offset)); |
| 117 result.RawSetFieldAtOffset(to_offset, value); | 124 result.RawSetFieldAtOffset(to_offset, value); |
| 118 } | 125 } |
| 119 // Convert the instance into a filler object. | 126 // Convert the instance into a filler object. |
| 120 Become::MakeDummyObject(instance); | 127 Become::MakeDummyObject(instance); |
| 121 return result.raw(); | 128 return result.raw(); |
| 122 } | 129 } |
| 123 | 130 |
| 124 | 131 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 143 for (intptr_t i = 0; i < fields.Length(); i++) { | 150 for (intptr_t i = 0; i < fields.Length(); i++) { |
| 144 if (fields.At(i) != Field::null()) { | 151 if (fields.At(i) != Field::null()) { |
| 145 field = Field::RawCast(fields.At(i)); | 152 field = Field::RawCast(fields.At(i)); |
| 146 ASSERT(field.is_instance()); | 153 ASSERT(field.is_instance()); |
| 147 name = field.name(); | 154 name = field.name(); |
| 148 THR_Print(" - @%" Pd " %s\n", field.Offset(), name.ToCString()); | 155 THR_Print(" - @%" Pd " %s\n", field.Offset(), name.ToCString()); |
| 149 } | 156 } |
| 150 } | 157 } |
| 151 | 158 |
| 152 THR_Print("Mapping: "); | 159 THR_Print("Mapping: "); |
| 153 for (int i = 0; i < mapping_.length(); i +=2) { | 160 for (int i = 0; i < mapping_.length(); i += 2) { |
| 154 THR_Print(" %" Pd "->%" Pd, mapping_.At(i), mapping_.At(i+1)); | 161 THR_Print(" %" Pd "->%" Pd, mapping_.At(i), mapping_.At(i + 1)); |
| 155 } | 162 } |
| 156 THR_Print("\n"); | 163 THR_Print("\n"); |
| 157 } | 164 } |
| 158 | 165 |
| 159 | 166 |
| 160 void InstanceMorpher::Dump() const { | 167 void InstanceMorpher::Dump() const { |
| 161 LogBlock blocker; | 168 LogBlock blocker; |
| 162 THR_Print("Morphing from "); | 169 THR_Print("Morphing from "); |
| 163 DumpFormatFor(from_); | 170 DumpFormatFor(from_); |
| 164 THR_Print("To "); | 171 THR_Print("To "); |
| 165 DumpFormatFor(to_); | 172 DumpFormatFor(to_); |
| 166 THR_Print("\n"); | 173 THR_Print("\n"); |
| 167 } | 174 } |
| 168 | 175 |
| 169 | 176 |
| 170 void InstanceMorpher::AppendTo(JSONArray* array) { | 177 void InstanceMorpher::AppendTo(JSONArray* array) { |
| 171 JSONObject jsobj(array); | 178 JSONObject jsobj(array); |
| 172 jsobj.AddProperty("type", "ShapeChangeMapping"); | 179 jsobj.AddProperty("type", "ShapeChangeMapping"); |
| 173 jsobj.AddProperty("class", to_); | 180 jsobj.AddProperty("class", to_); |
| 174 jsobj.AddProperty("instanceCount", before()->length()); | 181 jsobj.AddProperty("instanceCount", before()->length()); |
| 175 JSONArray map(&jsobj, "fieldOffsetMappings"); | 182 JSONArray map(&jsobj, "fieldOffsetMappings"); |
| 176 for (int i = 0; i < mapping_.length(); i += 2) { | 183 for (int i = 0; i < mapping_.length(); i += 2) { |
| 177 JSONArray pair(&map); | 184 JSONArray pair(&map); |
| 178 pair.AddValue(mapping_.At(i)); | 185 pair.AddValue(mapping_.At(i)); |
| 179 pair.AddValue(mapping_.At(i+1)); | 186 pair.AddValue(mapping_.At(i + 1)); |
| 180 } | 187 } |
| 181 } | 188 } |
| 182 | 189 |
| 183 | 190 |
| 184 void ReasonForCancelling::Report(IsolateReloadContext* context) { | 191 void ReasonForCancelling::Report(IsolateReloadContext* context) { |
| 185 const Error& error = Error::Handle(ToError()); | 192 const Error& error = Error::Handle(ToError()); |
| 186 context->ReportError(error); | 193 context->ReportError(error); |
| 187 } | 194 } |
| 188 | 195 |
| 189 | 196 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 206 const String& message = String::Handle(ToString()); | 213 const String& message = String::Handle(ToString()); |
| 207 jsobj.AddProperty("message", message.ToCString()); | 214 jsobj.AddProperty("message", message.ToCString()); |
| 208 } | 215 } |
| 209 | 216 |
| 210 | 217 |
| 211 ClassReasonForCancelling::ClassReasonForCancelling(Zone* zone, | 218 ClassReasonForCancelling::ClassReasonForCancelling(Zone* zone, |
| 212 const Class& from, | 219 const Class& from, |
| 213 const Class& to) | 220 const Class& to) |
| 214 : ReasonForCancelling(zone), | 221 : ReasonForCancelling(zone), |
| 215 from_(Class::ZoneHandle(zone, from.raw())), | 222 from_(Class::ZoneHandle(zone, from.raw())), |
| 216 to_(Class::ZoneHandle(zone, to.raw())) { | 223 to_(Class::ZoneHandle(zone, to.raw())) {} |
| 217 } | |
| 218 | 224 |
| 219 | 225 |
| 220 void ClassReasonForCancelling::AppendTo(JSONArray* array) { | 226 void ClassReasonForCancelling::AppendTo(JSONArray* array) { |
| 221 JSONObject jsobj(array); | 227 JSONObject jsobj(array); |
| 222 jsobj.AddProperty("type", "ReasonForCancelling"); | 228 jsobj.AddProperty("type", "ReasonForCancelling"); |
| 223 jsobj.AddProperty("class", from_); | 229 jsobj.AddProperty("class", from_); |
| 224 const String& message = String::Handle(ToString()); | 230 const String& message = String::Handle(ToString()); |
| 225 jsobj.AddProperty("message", message.ToCString()); | 231 jsobj.AddProperty("message", message.ToCString()); |
| 226 } | 232 } |
| 227 | 233 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 239 static const char* Name() { return "ScriptUrlSetTraits"; } | 245 static const char* Name() { return "ScriptUrlSetTraits"; } |
| 240 | 246 |
| 241 static bool IsMatch(const Object& a, const Object& b) { | 247 static bool IsMatch(const Object& a, const Object& b) { |
| 242 if (!a.IsString() || !b.IsString()) { | 248 if (!a.IsString() || !b.IsString()) { |
| 243 return false; | 249 return false; |
| 244 } | 250 } |
| 245 | 251 |
| 246 return String::Cast(a).Equals(String::Cast(b)); | 252 return String::Cast(a).Equals(String::Cast(b)); |
| 247 } | 253 } |
| 248 | 254 |
| 249 static uword Hash(const Object& obj) { | 255 static uword Hash(const Object& obj) { return String::Cast(obj).Hash(); } |
| 250 return String::Cast(obj).Hash(); | |
| 251 } | |
| 252 }; | 256 }; |
| 253 | 257 |
| 254 | 258 |
| 255 class ClassMapTraits { | 259 class ClassMapTraits { |
| 256 public: | 260 public: |
| 257 static bool ReportStats() { return false; } | 261 static bool ReportStats() { return false; } |
| 258 static const char* Name() { return "ClassMapTraits"; } | 262 static const char* Name() { return "ClassMapTraits"; } |
| 259 | 263 |
| 260 static bool IsMatch(const Object& a, const Object& b) { | 264 static bool IsMatch(const Object& a, const Object& b) { |
| 261 if (!a.IsClass() || !b.IsClass()) { | 265 if (!a.IsClass() || !b.IsClass()) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 272 | 276 |
| 273 class LibraryMapTraits { | 277 class LibraryMapTraits { |
| 274 public: | 278 public: |
| 275 static bool ReportStats() { return false; } | 279 static bool ReportStats() { return false; } |
| 276 static const char* Name() { return "LibraryMapTraits"; } | 280 static const char* Name() { return "LibraryMapTraits"; } |
| 277 | 281 |
| 278 static bool IsMatch(const Object& a, const Object& b) { | 282 static bool IsMatch(const Object& a, const Object& b) { |
| 279 if (!a.IsLibrary() || !b.IsLibrary()) { | 283 if (!a.IsLibrary() || !b.IsLibrary()) { |
| 280 return false; | 284 return false; |
| 281 } | 285 } |
| 282 return IsolateReloadContext::IsSameLibrary( | 286 return IsolateReloadContext::IsSameLibrary(Library::Cast(a), |
| 283 Library::Cast(a), Library::Cast(b)); | 287 Library::Cast(b)); |
| 284 } | 288 } |
| 285 | 289 |
| 286 static uword Hash(const Object& obj) { | 290 static uword Hash(const Object& obj) { return Library::Cast(obj).UrlHash(); } |
| 287 return Library::Cast(obj).UrlHash(); | |
| 288 } | |
| 289 }; | 291 }; |
| 290 | 292 |
| 291 | 293 |
| 292 class BecomeMapTraits { | 294 class BecomeMapTraits { |
| 293 public: | 295 public: |
| 294 static bool ReportStats() { return false; } | 296 static bool ReportStats() { return false; } |
| 295 static const char* Name() { return "BecomeMapTraits"; } | 297 static const char* Name() { return "BecomeMapTraits"; } |
| 296 | 298 |
| 297 static bool IsMatch(const Object& a, const Object& b) { | 299 static bool IsMatch(const Object& a, const Object& b) { |
| 298 return a.raw() == b.raw(); | 300 return a.raw() == b.raw(); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 349 if (!a_name.Equals(b_name)) { | 351 if (!a_name.Equals(b_name)) { |
| 350 return false; | 352 return false; |
| 351 } | 353 } |
| 352 | 354 |
| 353 const Library& a_lib = Library::Handle(a.library()); | 355 const Library& a_lib = Library::Handle(a.library()); |
| 354 const Library& b_lib = Library::Handle(b.library()); | 356 const Library& b_lib = Library::Handle(b.library()); |
| 355 return IsSameLibrary(a_lib, b_lib); | 357 return IsSameLibrary(a_lib, b_lib); |
| 356 } | 358 } |
| 357 | 359 |
| 358 | 360 |
| 359 bool IsolateReloadContext::IsSameLibrary( | 361 bool IsolateReloadContext::IsSameLibrary(const Library& a_lib, |
| 360 const Library& a_lib, const Library& b_lib) { | 362 const Library& b_lib) { |
| 361 const String& a_lib_url = | 363 const String& a_lib_url = |
| 362 String::Handle(a_lib.IsNull() ? String::null() : a_lib.url()); | 364 String::Handle(a_lib.IsNull() ? String::null() : a_lib.url()); |
| 363 const String& b_lib_url = | 365 const String& b_lib_url = |
| 364 String::Handle(b_lib.IsNull() ? String::null() : b_lib.url()); | 366 String::Handle(b_lib.IsNull() ? String::null() : b_lib.url()); |
| 365 return a_lib_url.Equals(b_lib_url); | 367 return a_lib_url.Equals(b_lib_url); |
| 366 } | 368 } |
| 367 | 369 |
| 368 | 370 |
| 369 IsolateReloadContext::IsolateReloadContext(Isolate* isolate, | 371 IsolateReloadContext::IsolateReloadContext(Isolate* isolate, JSONStream* js) |
| 370 JSONStream* js) | |
| 371 : zone_(Thread::Current()->zone()), | 372 : zone_(Thread::Current()->zone()), |
| 372 start_time_micros_(OS::GetCurrentMonotonicMicros()), | 373 start_time_micros_(OS::GetCurrentMonotonicMicros()), |
| 373 reload_timestamp_(OS::GetCurrentTimeMillis()), | 374 reload_timestamp_(OS::GetCurrentTimeMillis()), |
| 374 isolate_(isolate), | 375 isolate_(isolate), |
| 375 reload_skipped_(false), | 376 reload_skipped_(false), |
| 376 reload_aborted_(false), | 377 reload_aborted_(false), |
| 377 reload_finalized_(false), | 378 reload_finalized_(false), |
| 378 js_(js), | 379 js_(js), |
| 379 saved_num_cids_(-1), | 380 saved_num_cids_(-1), |
| 380 saved_class_table_(NULL), | 381 saved_class_table_(NULL), |
| (...skipping 12 matching lines...) Expand all Loading... |
| 393 become_enum_mappings_(GrowableObjectArray::null()), | 394 become_enum_mappings_(GrowableObjectArray::null()), |
| 394 saved_root_library_(Library::null()), | 395 saved_root_library_(Library::null()), |
| 395 saved_libraries_(GrowableObjectArray::null()) { | 396 saved_libraries_(GrowableObjectArray::null()) { |
| 396 // NOTE: DO NOT ALLOCATE ANY RAW OBJECTS HERE. The IsolateReloadContext is not | 397 // NOTE: DO NOT ALLOCATE ANY RAW OBJECTS HERE. The IsolateReloadContext is not |
| 397 // associated with the isolate yet and if a GC is triggered here the raw | 398 // associated with the isolate yet and if a GC is triggered here the raw |
| 398 // objects will not be properly accounted for. | 399 // objects will not be properly accounted for. |
| 399 ASSERT(zone_ != NULL); | 400 ASSERT(zone_ != NULL); |
| 400 } | 401 } |
| 401 | 402 |
| 402 | 403 |
| 403 IsolateReloadContext::~IsolateReloadContext() { | 404 IsolateReloadContext::~IsolateReloadContext() {} |
| 404 } | |
| 405 | 405 |
| 406 | 406 |
| 407 void IsolateReloadContext::ReportError(const Error& error) { | 407 void IsolateReloadContext::ReportError(const Error& error) { |
| 408 if (FLAG_trace_reload) { | 408 if (FLAG_trace_reload) { |
| 409 THR_Print("ISO-RELOAD: Error: %s\n", error.ToErrorCString()); | 409 THR_Print("ISO-RELOAD: Error: %s\n", error.ToErrorCString()); |
| 410 } | 410 } |
| 411 ServiceEvent service_event(I, ServiceEvent::kIsolateReload); | 411 ServiceEvent service_event(I, ServiceEvent::kIsolateReload); |
| 412 service_event.set_reload_error(&error); | 412 service_event.set_reload_error(&error); |
| 413 Service::HandleEvent(&service_event); | 413 Service::HandleEvent(&service_event); |
| 414 } | 414 } |
| 415 | 415 |
| 416 | 416 |
| 417 void IsolateReloadContext::ReportSuccess() { | 417 void IsolateReloadContext::ReportSuccess() { |
| 418 ServiceEvent service_event(I, ServiceEvent::kIsolateReload); | 418 ServiceEvent service_event(I, ServiceEvent::kIsolateReload); |
| 419 Service::HandleEvent(&service_event); | 419 Service::HandleEvent(&service_event); |
| 420 } | 420 } |
| 421 | 421 |
| 422 | 422 |
| 423 class Aborted : public ReasonForCancelling { | 423 class Aborted : public ReasonForCancelling { |
| 424 public: | 424 public: |
| 425 Aborted(Zone* zone, const Error& error) | 425 Aborted(Zone* zone, const Error& error) |
| 426 : ReasonForCancelling(zone), | 426 : ReasonForCancelling(zone), |
| 427 error_(Error::ZoneHandle(zone, error.raw())) { | 427 error_(Error::ZoneHandle(zone, error.raw())) {} |
| 428 } | |
| 429 | 428 |
| 430 private: | 429 private: |
| 431 const Error& error_; | 430 const Error& error_; |
| 432 | 431 |
| 433 RawError* ToError() { return error_.raw(); } | 432 RawError* ToError() { return error_.raw(); } |
| 434 RawString* ToString() { | 433 RawString* ToString() { |
| 435 return String::NewFormatted("%s", error_.ToErrorCString()); | 434 return String::NewFormatted("%s", error_.ToErrorCString()); |
| 436 } | 435 } |
| 437 }; | 436 }; |
| 438 | 437 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 456 ReportOnJSON(js_); | 455 ReportOnJSON(js_); |
| 457 TIR_Print("---- SKIPPING RELOAD (No libraries were modified)\n"); | 456 TIR_Print("---- SKIPPING RELOAD (No libraries were modified)\n"); |
| 458 return; | 457 return; |
| 459 } | 458 } |
| 460 | 459 |
| 461 TIR_Print("---- STARTING RELOAD\n"); | 460 TIR_Print("---- STARTING RELOAD\n"); |
| 462 | 461 |
| 463 // Preallocate storage for maps. | 462 // Preallocate storage for maps. |
| 464 old_classes_set_storage_ = | 463 old_classes_set_storage_ = |
| 465 HashTables::New<UnorderedHashSet<ClassMapTraits> >(4); | 464 HashTables::New<UnorderedHashSet<ClassMapTraits> >(4); |
| 466 class_map_storage_ = | 465 class_map_storage_ = HashTables::New<UnorderedHashMap<ClassMapTraits> >(4); |
| 467 HashTables::New<UnorderedHashMap<ClassMapTraits> >(4); | |
| 468 old_libraries_set_storage_ = | 466 old_libraries_set_storage_ = |
| 469 HashTables::New<UnorderedHashSet<LibraryMapTraits> >(4); | 467 HashTables::New<UnorderedHashSet<LibraryMapTraits> >(4); |
| 470 library_map_storage_ = | 468 library_map_storage_ = |
| 471 HashTables::New<UnorderedHashMap<LibraryMapTraits> >(4); | 469 HashTables::New<UnorderedHashMap<LibraryMapTraits> >(4); |
| 472 become_map_storage_ = | 470 become_map_storage_ = HashTables::New<UnorderedHashMap<BecomeMapTraits> >(4); |
| 473 HashTables::New<UnorderedHashMap<BecomeMapTraits> >(4); | |
| 474 // Keep a separate array for enum mappings to avoid having to invoke | 471 // Keep a separate array for enum mappings to avoid having to invoke |
| 475 // hashCode on the instances. | 472 // hashCode on the instances. |
| 476 become_enum_mappings_ = GrowableObjectArray::New(Heap::kOld); | 473 become_enum_mappings_ = GrowableObjectArray::New(Heap::kOld); |
| 477 | 474 |
| 478 // Disable the background compiler while we are performing the reload. | 475 // Disable the background compiler while we are performing the reload. |
| 479 BackgroundCompiler::Disable(); | 476 BackgroundCompiler::Disable(); |
| 480 | 477 |
| 481 // Ensure all functions on the stack have unoptimized code. | 478 // Ensure all functions on the stack have unoptimized code. |
| 482 EnsuredUnoptimizedCodeForStack(); | 479 EnsuredUnoptimizedCodeForStack(); |
| 483 // Deoptimize all code that had optimizing decisions that are dependent on | 480 // Deoptimize all code that had optimizing decisions that are dependent on |
| (...skipping 20 matching lines...) Expand all Loading... |
| 504 // Even after a successful reload the Dart code invoked in (5) can result | 501 // Even after a successful reload the Dart code invoked in (5) can result |
| 505 // in an Unwind error or an UnhandledException error. This error will be | 502 // in an Unwind error or an UnhandledException error. This error will be |
| 506 // returned by the tag handler. The tag handler can return other errors, | 503 // returned by the tag handler. The tag handler can return other errors, |
| 507 // for example, top level parse errors. We want to capture these errors while | 504 // for example, top level parse errors. We want to capture these errors while |
| 508 // propagating the UnwindError or an UnhandledException error. | 505 // propagating the UnwindError or an UnhandledException error. |
| 509 Object& result = Object::Handle(thread->zone()); | 506 Object& result = Object::Handle(thread->zone()); |
| 510 { | 507 { |
| 511 TransitionVMToNative transition(thread); | 508 TransitionVMToNative transition(thread); |
| 512 Api::Scope api_scope(thread); | 509 Api::Scope api_scope(thread); |
| 513 | 510 |
| 514 Dart_Handle retval = | 511 Dart_Handle retval = (I->library_tag_handler())( |
| 515 (I->library_tag_handler())(Dart_kScriptTag, | 512 Dart_kScriptTag, Api::NewHandle(thread, Library::null()), |
| 516 Api::NewHandle(thread, Library::null()), | 513 Api::NewHandle(thread, root_lib_url.raw())); |
| 517 Api::NewHandle(thread, root_lib_url.raw())); | |
| 518 result = Api::UnwrapHandle(retval); | 514 result = Api::UnwrapHandle(retval); |
| 519 } | 515 } |
| 520 // | 516 // |
| 521 // WEIRD CONTROL FLOW ENDS. | 517 // WEIRD CONTROL FLOW ENDS. |
| 522 | 518 |
| 523 BackgroundCompiler::Enable(); | 519 BackgroundCompiler::Enable(); |
| 524 | 520 |
| 525 if (result.IsUnwindError() || | 521 if (result.IsUnwindError() || result.IsUnhandledException()) { |
| 526 result.IsUnhandledException()) { | |
| 527 // If the tag handler returns with an UnwindError or an UnhandledException | 522 // If the tag handler returns with an UnwindError or an UnhandledException |
| 528 // error, propagate it and give up. | 523 // error, propagate it and give up. |
| 529 Exceptions::PropagateError(Error::Cast(result)); | 524 Exceptions::PropagateError(Error::Cast(result)); |
| 530 UNREACHABLE(); | 525 UNREACHABLE(); |
| 531 } | 526 } |
| 532 | 527 |
| 533 // Other errors (e.g. a parse error) are captured by the reload system. | 528 // Other errors (e.g. a parse error) are captured by the reload system. |
| 534 if (result.IsError()) { | 529 if (result.IsError()) { |
| 535 FinalizeFailedLoad(Error::Cast(result)); | 530 FinalizeFailedLoad(Error::Cast(result)); |
| 536 } | 531 } |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 712 // Copy the size of the class table. | 707 // Copy the size of the class table. |
| 713 saved_num_cids_ = I->class_table()->NumCids(); | 708 saved_num_cids_ = I->class_table()->NumCids(); |
| 714 | 709 |
| 715 // Copy of the class table. | 710 // Copy of the class table. |
| 716 RawClass** local_saved_class_table = | 711 RawClass** local_saved_class_table = |
| 717 reinterpret_cast<RawClass**>(malloc(sizeof(RawClass*) * saved_num_cids_)); | 712 reinterpret_cast<RawClass**>(malloc(sizeof(RawClass*) * saved_num_cids_)); |
| 718 | 713 |
| 719 Class& cls = Class::Handle(); | 714 Class& cls = Class::Handle(); |
| 720 UnorderedHashSet<ClassMapTraits> old_classes_set(old_classes_set_storage_); | 715 UnorderedHashSet<ClassMapTraits> old_classes_set(old_classes_set_storage_); |
| 721 for (intptr_t i = 0; i < saved_num_cids_; i++) { | 716 for (intptr_t i = 0; i < saved_num_cids_; i++) { |
| 722 if (class_table->IsValidIndex(i) && | 717 if (class_table->IsValidIndex(i) && class_table->HasValidClassAt(i)) { |
| 723 class_table->HasValidClassAt(i)) { | |
| 724 // Copy the class into the saved class table and add it to the set. | 718 // Copy the class into the saved class table and add it to the set. |
| 725 local_saved_class_table[i] = class_table->At(i); | 719 local_saved_class_table[i] = class_table->At(i); |
| 726 if (i != kFreeListElement && i != kForwardingCorpse) { | 720 if (i != kFreeListElement && i != kForwardingCorpse) { |
| 727 cls = class_table->At(i); | 721 cls = class_table->At(i); |
| 728 bool already_present = old_classes_set.Insert(cls); | 722 bool already_present = old_classes_set.Insert(cls); |
| 729 ASSERT(!already_present); | 723 ASSERT(!already_present); |
| 730 } | 724 } |
| 731 } else { | 725 } else { |
| 732 // No class at this index, mark it as NULL. | 726 // No class at this index, mark it as NULL. |
| 733 local_saved_class_table[i] = NULL; | 727 local_saved_class_table[i] = NULL; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 749 return true; | 743 return true; |
| 750 } | 744 } |
| 751 // We use the resolved url to determine if the script has been modified. | 745 // We use the resolved url to determine if the script has been modified. |
| 752 const String& url = String::Handle(script.resolved_url()); | 746 const String& url = String::Handle(script.resolved_url()); |
| 753 const char* url_chars = url.ToCString(); | 747 const char* url_chars = url.ToCString(); |
| 754 return (*file_modified_callback_)(url_chars, since); | 748 return (*file_modified_callback_)(url_chars, since); |
| 755 } | 749 } |
| 756 | 750 |
| 757 | 751 |
| 758 static void PropagateLibraryModified( | 752 static void PropagateLibraryModified( |
| 759 const ZoneGrowableArray<ZoneGrowableArray<intptr_t>* >* imported_by, | 753 const ZoneGrowableArray<ZoneGrowableArray<intptr_t>*>* imported_by, |
| 760 intptr_t lib_index, | 754 intptr_t lib_index, |
| 761 BitVector* modified_libs) { | 755 BitVector* modified_libs) { |
| 762 ZoneGrowableArray<intptr_t>* dep_libs = (*imported_by)[lib_index]; | 756 ZoneGrowableArray<intptr_t>* dep_libs = (*imported_by)[lib_index]; |
| 763 for (intptr_t i = 0; i < dep_libs->length(); i++) { | 757 for (intptr_t i = 0; i < dep_libs->length(); i++) { |
| 764 intptr_t dep_lib_index = (*dep_libs)[i]; | 758 intptr_t dep_lib_index = (*dep_libs)[i]; |
| 765 if (!modified_libs->Contains(dep_lib_index)) { | 759 if (!modified_libs->Contains(dep_lib_index)) { |
| 766 modified_libs->Add(dep_lib_index); | 760 modified_libs->Add(dep_lib_index); |
| 767 PropagateLibraryModified(imported_by, dep_lib_index, modified_libs); | 761 PropagateLibraryModified(imported_by, dep_lib_index, modified_libs); |
| 768 } | 762 } |
| 769 } | 763 } |
| 770 } | 764 } |
| 771 | 765 |
| 772 | 766 |
| 773 BitVector* IsolateReloadContext::FindModifiedLibraries(bool force_reload) { | 767 BitVector* IsolateReloadContext::FindModifiedLibraries(bool force_reload) { |
| 774 Thread* thread = Thread::Current(); | 768 Thread* thread = Thread::Current(); |
| 775 int64_t last_reload = I->last_reload_timestamp(); | 769 int64_t last_reload = I->last_reload_timestamp(); |
| 776 | 770 |
| 777 const GrowableObjectArray& libs = | 771 const GrowableObjectArray& libs = |
| 778 GrowableObjectArray::Handle(object_store()->libraries()); | 772 GrowableObjectArray::Handle(object_store()->libraries()); |
| 779 Library& lib = Library::Handle(); | 773 Library& lib = Library::Handle(); |
| 780 Array& scripts = Array::Handle(); | 774 Array& scripts = Array::Handle(); |
| 781 Script& script = Script::Handle(); | 775 Script& script = Script::Handle(); |
| 782 intptr_t num_libs = libs.Length(); | 776 intptr_t num_libs = libs.Length(); |
| 783 | 777 |
| 784 // Construct the imported-by graph. | 778 // Construct the imported-by graph. |
| 785 ZoneGrowableArray<ZoneGrowableArray<intptr_t>* >* imported_by = | 779 ZoneGrowableArray<ZoneGrowableArray<intptr_t>*>* imported_by = new (zone_) |
| 786 new(zone_) ZoneGrowableArray<ZoneGrowableArray<intptr_t>* >( | 780 ZoneGrowableArray<ZoneGrowableArray<intptr_t>*>(zone_, num_libs); |
| 787 zone_, num_libs); | |
| 788 imported_by->SetLength(num_libs); | 781 imported_by->SetLength(num_libs); |
| 789 for (intptr_t i = 0; i < num_libs; i++) { | 782 for (intptr_t i = 0; i < num_libs; i++) { |
| 790 (*imported_by)[i] = new(zone_) ZoneGrowableArray<intptr_t>(zone_, 0); | 783 (*imported_by)[i] = new (zone_) ZoneGrowableArray<intptr_t>(zone_, 0); |
| 791 } | 784 } |
| 792 Array& ports = Array::Handle(); | 785 Array& ports = Array::Handle(); |
| 793 Namespace& ns = Namespace::Handle(); | 786 Namespace& ns = Namespace::Handle(); |
| 794 Library& target = Library::Handle(); | 787 Library& target = Library::Handle(); |
| 795 | 788 |
| 796 for (intptr_t lib_idx = 0; lib_idx < num_libs; lib_idx++) { | 789 for (intptr_t lib_idx = 0; lib_idx < num_libs; lib_idx++) { |
| 797 lib ^= libs.At(lib_idx); | 790 lib ^= libs.At(lib_idx); |
| 798 ASSERT(lib_idx == lib.index()); | 791 ASSERT(lib_idx == lib.index()); |
| 799 if (lib.is_dart_scheme()) { | 792 if (lib.is_dart_scheme()) { |
| 800 // We don't care about imports among dart scheme libraries. | 793 // We don't care about imports among dart scheme libraries. |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 835 ns ^= ports.At(import_idx); | 828 ns ^= ports.At(import_idx); |
| 836 if (!ns.IsNull()) { | 829 if (!ns.IsNull()) { |
| 837 target = ns.library(); | 830 target = ns.library(); |
| 838 (*imported_by)[target.index()]->Add(lib.index()); | 831 (*imported_by)[target.index()]->Add(lib.index()); |
| 839 } | 832 } |
| 840 } | 833 } |
| 841 } | 834 } |
| 842 } | 835 } |
| 843 } | 836 } |
| 844 | 837 |
| 845 BitVector* modified_libs = new(Z) BitVector(Z, num_libs); | 838 BitVector* modified_libs = new (Z) BitVector(Z, num_libs); |
| 846 | 839 |
| 847 for (intptr_t lib_idx = 0; lib_idx < num_libs; lib_idx++) { | 840 for (intptr_t lib_idx = 0; lib_idx < num_libs; lib_idx++) { |
| 848 lib ^= libs.At(lib_idx); | 841 lib ^= libs.At(lib_idx); |
| 849 if (lib.is_dart_scheme() || modified_libs->Contains(lib_idx)) { | 842 if (lib.is_dart_scheme() || modified_libs->Contains(lib_idx)) { |
| 850 // We don't consider dart scheme libraries during reload. If | 843 // We don't consider dart scheme libraries during reload. If |
| 851 // the modified libs set already contains this library, then we | 844 // the modified libs set already contains this library, then we |
| 852 // have already visited it. | 845 // have already visited it. |
| 853 continue; | 846 continue; |
| 854 } | 847 } |
| 855 scripts = lib.LoadedScripts(); | 848 scripts = lib.LoadedScripts(); |
| 856 for (intptr_t script_idx = 0; script_idx < scripts.Length(); script_idx++) { | 849 for (intptr_t script_idx = 0; script_idx < scripts.Length(); script_idx++) { |
| 857 script ^= scripts.At(script_idx); | 850 script ^= scripts.At(script_idx); |
| 858 if (force_reload || ScriptModifiedSince(script, last_reload)) { | 851 if (force_reload || ScriptModifiedSince(script, last_reload)) { |
| 859 modified_libs->Add(lib_idx); | 852 modified_libs->Add(lib_idx); |
| 860 PropagateLibraryModified(imported_by, lib_idx, modified_libs); | 853 PropagateLibraryModified(imported_by, lib_idx, modified_libs); |
| 861 break; | 854 break; |
| 862 } | 855 } |
| 863 } | 856 } |
| 864 } | 857 } |
| 865 | 858 |
| 866 return modified_libs; | 859 return modified_libs; |
| 867 } | 860 } |
| 868 | 861 |
| 869 | 862 |
| 870 void IsolateReloadContext::CheckpointLibraries() { | 863 void IsolateReloadContext::CheckpointLibraries() { |
| 871 TIMELINE_SCOPE(CheckpointLibraries); | 864 TIMELINE_SCOPE(CheckpointLibraries); |
| 872 TIR_Print("---- CHECKPOINTING LIBRARIES\n"); | 865 TIR_Print("---- CHECKPOINTING LIBRARIES\n"); |
| 873 // Save the root library in case we abort the reload. | 866 // Save the root library in case we abort the reload. |
| 874 const Library& root_lib = | 867 const Library& root_lib = Library::Handle(object_store()->root_library()); |
| 875 Library::Handle(object_store()->root_library()); | |
| 876 set_saved_root_library(root_lib); | 868 set_saved_root_library(root_lib); |
| 877 | 869 |
| 878 // Save the old libraries array in case we abort the reload. | 870 // Save the old libraries array in case we abort the reload. |
| 879 const GrowableObjectArray& libs = | 871 const GrowableObjectArray& libs = |
| 880 GrowableObjectArray::Handle(object_store()->libraries()); | 872 GrowableObjectArray::Handle(object_store()->libraries()); |
| 881 set_saved_libraries(libs); | 873 set_saved_libraries(libs); |
| 882 | 874 |
| 883 // Make a filtered copy of the old libraries array. Keep "clean" libraries | 875 // Make a filtered copy of the old libraries array. Keep "clean" libraries |
| 884 // that we will use instead of reloading. | 876 // that we will use instead of reloading. |
| 885 const GrowableObjectArray& new_libs = GrowableObjectArray::Handle( | 877 const GrowableObjectArray& new_libs = |
| 886 GrowableObjectArray::New(Heap::kOld)); | 878 GrowableObjectArray::Handle(GrowableObjectArray::New(Heap::kOld)); |
| 887 Library& lib = Library::Handle(); | 879 Library& lib = Library::Handle(); |
| 888 UnorderedHashSet<LibraryMapTraits> | 880 UnorderedHashSet<LibraryMapTraits> old_libraries_set( |
| 889 old_libraries_set(old_libraries_set_storage_); | 881 old_libraries_set_storage_); |
| 890 num_saved_libs_ = 0; | 882 num_saved_libs_ = 0; |
| 891 for (intptr_t i = 0; i < libs.Length(); i++) { | 883 for (intptr_t i = 0; i < libs.Length(); i++) { |
| 892 lib ^= libs.At(i); | 884 lib ^= libs.At(i); |
| 893 if (modified_libs_->Contains(i)) { | 885 if (modified_libs_->Contains(i)) { |
| 894 // We are going to reload this library. Clear the index. | 886 // We are going to reload this library. Clear the index. |
| 895 lib.set_index(-1); | 887 lib.set_index(-1); |
| 896 } else { | 888 } else { |
| 897 // We are preserving this library across the reload, assign its new index | 889 // We are preserving this library across the reload, assign its new index |
| 898 lib.set_index(new_libs.Length()); | 890 lib.set_index(new_libs.Length()); |
| 899 new_libs.Add(lib, Heap::kOld); | 891 new_libs.Add(lib, Heap::kOld); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 942 // be suspended between loading the table pointer and loading the table | 934 // be suspended between loading the table pointer and loading the table |
| 943 // element. Table will be freed at the next major GC or isolate shutdown. | 935 // element. Table will be freed at the next major GC or isolate shutdown. |
| 944 class_table->AddOldTable(local_saved_class_table); | 936 class_table->AddOldTable(local_saved_class_table); |
| 945 } | 937 } |
| 946 | 938 |
| 947 | 939 |
| 948 void IsolateReloadContext::RollbackLibraries() { | 940 void IsolateReloadContext::RollbackLibraries() { |
| 949 TIR_Print("---- ROLLING BACK LIBRARY CHANGES\n"); | 941 TIR_Print("---- ROLLING BACK LIBRARY CHANGES\n"); |
| 950 Thread* thread = Thread::Current(); | 942 Thread* thread = Thread::Current(); |
| 951 Library& lib = Library::Handle(); | 943 Library& lib = Library::Handle(); |
| 952 GrowableObjectArray& saved_libs = GrowableObjectArray::Handle( | 944 GrowableObjectArray& saved_libs = |
| 953 Z, saved_libraries()); | 945 GrowableObjectArray::Handle(Z, saved_libraries()); |
| 954 if (!saved_libs.IsNull()) { | 946 if (!saved_libs.IsNull()) { |
| 955 for (intptr_t i = 0; i < saved_libs.Length(); i++) { | 947 for (intptr_t i = 0; i < saved_libs.Length(); i++) { |
| 956 lib = Library::RawCast(saved_libs.At(i)); | 948 lib = Library::RawCast(saved_libs.At(i)); |
| 957 // Restore indexes that were modified in CheckpointLibraries. | 949 // Restore indexes that were modified in CheckpointLibraries. |
| 958 lib.set_index(i); | 950 lib.set_index(i); |
| 959 } | 951 } |
| 960 | 952 |
| 961 // Reset the registered libraries to the filtered array. | 953 // Reset the registered libraries to the filtered array. |
| 962 Library::RegisterLibraries(thread, saved_libs); | 954 Library::RegisterLibraries(thread, saved_libs); |
| 963 } | 955 } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 984 TIMELINE_SCOPE(VerifyMaps); | 976 TIMELINE_SCOPE(VerifyMaps); |
| 985 Class& cls = Class::Handle(); | 977 Class& cls = Class::Handle(); |
| 986 Class& new_cls = Class::Handle(); | 978 Class& new_cls = Class::Handle(); |
| 987 Class& cls2 = Class::Handle(); | 979 Class& cls2 = Class::Handle(); |
| 988 | 980 |
| 989 // Verify that two old classes aren't both mapped to the same new | 981 // Verify that two old classes aren't both mapped to the same new |
| 990 // class. This could happen is the IsSameClass function is broken. | 982 // class. This could happen is the IsSameClass function is broken. |
| 991 UnorderedHashMap<ClassMapTraits> class_map(class_map_storage_); | 983 UnorderedHashMap<ClassMapTraits> class_map(class_map_storage_); |
| 992 UnorderedHashMap<ClassMapTraits> reverse_class_map( | 984 UnorderedHashMap<ClassMapTraits> reverse_class_map( |
| 993 HashTables::New<UnorderedHashMap<ClassMapTraits> >( | 985 HashTables::New<UnorderedHashMap<ClassMapTraits> >( |
| 994 class_map.NumOccupied())); | 986 class_map.NumOccupied())); |
| 995 { | 987 { |
| 996 UnorderedHashMap<ClassMapTraits>::Iterator it(&class_map); | 988 UnorderedHashMap<ClassMapTraits>::Iterator it(&class_map); |
| 997 while (it.MoveNext()) { | 989 while (it.MoveNext()) { |
| 998 const intptr_t entry = it.Current(); | 990 const intptr_t entry = it.Current(); |
| 999 new_cls = Class::RawCast(class_map.GetKey(entry)); | 991 new_cls = Class::RawCast(class_map.GetKey(entry)); |
| 1000 cls = Class::RawCast(class_map.GetPayload(entry, 0)); | 992 cls = Class::RawCast(class_map.GetPayload(entry, 0)); |
| 1001 cls2 ^= reverse_class_map.GetOrNull(new_cls); | 993 cls2 ^= reverse_class_map.GetOrNull(new_cls); |
| 1002 if (!cls2.IsNull()) { | 994 if (!cls2.IsNull()) { |
| 1003 OS::PrintErr("Classes '%s' and '%s' are distinct classes but both map " | 995 OS::PrintErr( |
| 1004 " to class '%s'\n", | 996 "Classes '%s' and '%s' are distinct classes but both map " |
| 1005 cls.ToCString(), cls2.ToCString(), new_cls.ToCString()); | 997 " to class '%s'\n", |
| 998 cls.ToCString(), cls2.ToCString(), new_cls.ToCString()); |
| 1006 UNREACHABLE(); | 999 UNREACHABLE(); |
| 1007 } | 1000 } |
| 1008 bool update = reverse_class_map.UpdateOrInsert(cls, new_cls); | 1001 bool update = reverse_class_map.UpdateOrInsert(cls, new_cls); |
| 1009 ASSERT(!update); | 1002 ASSERT(!update); |
| 1010 } | 1003 } |
| 1011 } | 1004 } |
| 1012 class_map.Release(); | 1005 class_map.Release(); |
| 1013 reverse_class_map.Release(); | 1006 reverse_class_map.Release(); |
| 1014 } | 1007 } |
| 1015 #endif | 1008 #endif |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1090 } | 1083 } |
| 1091 | 1084 |
| 1092 // Release the library map. | 1085 // Release the library map. |
| 1093 lib_map.Release(); | 1086 lib_map.Release(); |
| 1094 } | 1087 } |
| 1095 | 1088 |
| 1096 { | 1089 { |
| 1097 TIMELINE_SCOPE(UpdateLibrariesArray); | 1090 TIMELINE_SCOPE(UpdateLibrariesArray); |
| 1098 // Update the libraries array. | 1091 // Update the libraries array. |
| 1099 Library& lib = Library::Handle(); | 1092 Library& lib = Library::Handle(); |
| 1100 const GrowableObjectArray& libs = GrowableObjectArray::Handle( | 1093 const GrowableObjectArray& libs = |
| 1101 I->object_store()->libraries()); | 1094 GrowableObjectArray::Handle(I->object_store()->libraries()); |
| 1102 for (intptr_t i = 0; i < libs.Length(); i++) { | 1095 for (intptr_t i = 0; i < libs.Length(); i++) { |
| 1103 lib = Library::RawCast(libs.At(i)); | 1096 lib = Library::RawCast(libs.At(i)); |
| 1104 VTIR_Print("Lib '%s' at index %" Pd "\n", lib.ToCString(), i); | 1097 VTIR_Print("Lib '%s' at index %" Pd "\n", lib.ToCString(), i); |
| 1105 lib.set_index(i); | 1098 lib.set_index(i); |
| 1106 } | 1099 } |
| 1107 | 1100 |
| 1108 // Initialize library side table. | 1101 // Initialize library side table. |
| 1109 library_infos_.SetLength(libs.Length()); | 1102 library_infos_.SetLength(libs.Length()); |
| 1110 for (intptr_t i = 0; i < libs.Length(); i++) { | 1103 for (intptr_t i = 0; i < libs.Length(); i++) { |
| 1111 lib = Library::RawCast(libs.At(i)); | 1104 lib = Library::RawCast(libs.At(i)); |
| 1112 // Mark the library dirty if it comes after the libraries we saved. | 1105 // Mark the library dirty if it comes after the libraries we saved. |
| 1113 library_infos_[i].dirty = i >= num_saved_libs_; | 1106 library_infos_[i].dirty = i >= num_saved_libs_; |
| 1114 } | 1107 } |
| 1115 } | 1108 } |
| 1116 | 1109 |
| 1117 { | 1110 { |
| 1118 const GrowableObjectArray& become_enum_mappings = | 1111 const GrowableObjectArray& become_enum_mappings = |
| 1119 GrowableObjectArray::Handle(become_enum_mappings_); | 1112 GrowableObjectArray::Handle(become_enum_mappings_); |
| 1120 UnorderedHashMap<BecomeMapTraits> become_map(become_map_storage_); | 1113 UnorderedHashMap<BecomeMapTraits> become_map(become_map_storage_); |
| 1121 intptr_t replacement_count = become_map.NumOccupied() + | 1114 intptr_t replacement_count = |
| 1122 become_enum_mappings.Length() / 2; | 1115 become_map.NumOccupied() + become_enum_mappings.Length() / 2; |
| 1123 const Array& before = | 1116 const Array& before = |
| 1124 Array::Handle(Array::New(replacement_count, Heap::kOld)); | 1117 Array::Handle(Array::New(replacement_count, Heap::kOld)); |
| 1125 const Array& after = | 1118 const Array& after = |
| 1126 Array::Handle(Array::New(replacement_count, Heap::kOld)); | 1119 Array::Handle(Array::New(replacement_count, Heap::kOld)); |
| 1127 Object& obj = Object::Handle(); | 1120 Object& obj = Object::Handle(); |
| 1128 intptr_t replacement_index = 0; | 1121 intptr_t replacement_index = 0; |
| 1129 UnorderedHashMap<BecomeMapTraits>::Iterator it(&become_map); | 1122 UnorderedHashMap<BecomeMapTraits>::Iterator it(&become_map); |
| 1130 while (it.MoveNext()) { | 1123 while (it.MoveNext()) { |
| 1131 const intptr_t entry = it.Current(); | 1124 const intptr_t entry = it.Current(); |
| 1132 obj = become_map.GetKey(entry); | 1125 obj = become_map.GetKey(entry); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1144 } | 1137 } |
| 1145 ASSERT(replacement_index == replacement_count); | 1138 ASSERT(replacement_index == replacement_count); |
| 1146 become_map.Release(); | 1139 become_map.Release(); |
| 1147 | 1140 |
| 1148 Become::ElementsForwardIdentity(before, after); | 1141 Become::ElementsForwardIdentity(before, after); |
| 1149 } | 1142 } |
| 1150 | 1143 |
| 1151 if (FLAG_identity_reload) { | 1144 if (FLAG_identity_reload) { |
| 1152 if (saved_num_cids_ != I->class_table()->NumCids()) { | 1145 if (saved_num_cids_ != I->class_table()->NumCids()) { |
| 1153 TIR_Print("Identity reload failed! B#C=%" Pd " A#C=%" Pd "\n", | 1146 TIR_Print("Identity reload failed! B#C=%" Pd " A#C=%" Pd "\n", |
| 1154 saved_num_cids_, | 1147 saved_num_cids_, I->class_table()->NumCids()); |
| 1155 I->class_table()->NumCids()); | |
| 1156 } | 1148 } |
| 1157 const GrowableObjectArray& saved_libs = | 1149 const GrowableObjectArray& saved_libs = |
| 1158 GrowableObjectArray::Handle(saved_libraries()); | 1150 GrowableObjectArray::Handle(saved_libraries()); |
| 1159 const GrowableObjectArray& libs = | 1151 const GrowableObjectArray& libs = |
| 1160 GrowableObjectArray::Handle(I->object_store()->libraries()); | 1152 GrowableObjectArray::Handle(I->object_store()->libraries()); |
| 1161 if (saved_libs.Length() != libs.Length()) { | 1153 if (saved_libs.Length() != libs.Length()) { |
| 1162 TIR_Print("Identity reload failed! B#L=%" Pd " A#L=%" Pd "\n", | 1154 TIR_Print("Identity reload failed! B#L=%" Pd " A#L=%" Pd "\n", |
| 1163 saved_libs.Length(), | 1155 saved_libs.Length(), libs.Length()); |
| 1164 libs.Length()); | |
| 1165 } | 1156 } |
| 1166 } | 1157 } |
| 1167 } | 1158 } |
| 1168 | 1159 |
| 1169 | 1160 |
| 1170 bool IsolateReloadContext::IsDirty(const Library& lib) { | 1161 bool IsolateReloadContext::IsDirty(const Library& lib) { |
| 1171 const intptr_t index = lib.index(); | 1162 const intptr_t index = lib.index(); |
| 1172 if (index == static_cast<classid_t>(-1)) { | 1163 if (index == static_cast<classid_t>(-1)) { |
| 1173 // Treat deleted libraries as dirty. | 1164 // Treat deleted libraries as dirty. |
| 1174 return true; | 1165 return true; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1205 reasons_to_cancel_reload_.At(i)->Report(this); | 1196 reasons_to_cancel_reload_.At(i)->Report(this); |
| 1206 } | 1197 } |
| 1207 } | 1198 } |
| 1208 | 1199 |
| 1209 | 1200 |
| 1210 // The ObjectLocator is used for collecting instances that | 1201 // The ObjectLocator is used for collecting instances that |
| 1211 // needs to be morphed. | 1202 // needs to be morphed. |
| 1212 class ObjectLocator : public ObjectVisitor { | 1203 class ObjectLocator : public ObjectVisitor { |
| 1213 public: | 1204 public: |
| 1214 explicit ObjectLocator(IsolateReloadContext* context) | 1205 explicit ObjectLocator(IsolateReloadContext* context) |
| 1215 : context_(context), count_(0) { | 1206 : context_(context), count_(0) {} |
| 1216 } | |
| 1217 | 1207 |
| 1218 void VisitObject(RawObject* obj) { | 1208 void VisitObject(RawObject* obj) { |
| 1219 InstanceMorpher* morpher = | 1209 InstanceMorpher* morpher = |
| 1220 context_->cid_mapper_.LookupValue(obj->GetClassId()); | 1210 context_->cid_mapper_.LookupValue(obj->GetClassId()); |
| 1221 if (morpher != NULL) { | 1211 if (morpher != NULL) { |
| 1222 morpher->AddObject(obj); | 1212 morpher->AddObject(obj); |
| 1223 count_++; | 1213 count_++; |
| 1224 } | 1214 } |
| 1225 } | 1215 } |
| 1226 | 1216 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1245 } | 1235 } |
| 1246 | 1236 |
| 1247 // Find all objects that need to be morphed. | 1237 // Find all objects that need to be morphed. |
| 1248 ObjectLocator locator(this); | 1238 ObjectLocator locator(this); |
| 1249 isolate()->heap()->VisitObjects(&locator); | 1239 isolate()->heap()->VisitObjects(&locator); |
| 1250 | 1240 |
| 1251 // Return if no objects are located. | 1241 // Return if no objects are located. |
| 1252 intptr_t count = locator.count(); | 1242 intptr_t count = locator.count(); |
| 1253 if (count == 0) return; | 1243 if (count == 0) return; |
| 1254 | 1244 |
| 1255 TIR_Print("Found %" Pd " object%s subject to morphing.\n", | 1245 TIR_Print("Found %" Pd " object%s subject to morphing.\n", count, |
| 1256 count, (count > 1) ? "s" : ""); | 1246 (count > 1) ? "s" : ""); |
| 1257 | 1247 |
| 1258 Array& before = Array::Handle(); | 1248 Array& before = Array::Handle(); |
| 1259 Array& after = Array::Handle(); | 1249 Array& after = Array::Handle(); |
| 1260 { // Prevent GC to take place due object format confusion. | 1250 { // Prevent GC to take place due object format confusion. |
| 1261 // Hint: More than one class share the same cid. | 1251 // Hint: More than one class share the same cid. |
| 1262 NoHeapGrowthControlScope scope; | 1252 NoHeapGrowthControlScope scope; |
| 1263 for (intptr_t i = 0; i < instance_morphers_.length(); i++) { | 1253 for (intptr_t i = 0; i < instance_morphers_.length(); i++) { |
| 1264 instance_morphers_.At(i)->CreateMorphedCopies(); | 1254 instance_morphers_.At(i)->CreateMorphedCopies(); |
| 1265 } | 1255 } |
| 1266 // Create the inputs for Become. | 1256 // Create the inputs for Become. |
| 1267 intptr_t index = 0; | 1257 intptr_t index = 0; |
| 1268 before = Array::New(count); | 1258 before = Array::New(count); |
| 1269 after = Array::New(count); | 1259 after = Array::New(count); |
| 1270 for (intptr_t i = 0; i < instance_morphers_.length(); i++) { | 1260 for (intptr_t i = 0; i < instance_morphers_.length(); i++) { |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1419 // the current megamorphic caches get GC'd and any new optimized code allocate | 1409 // the current megamorphic caches get GC'd and any new optimized code allocate |
| 1420 // new ones. | 1410 // new ones. |
| 1421 } | 1411 } |
| 1422 | 1412 |
| 1423 | 1413 |
| 1424 class MarkFunctionsForRecompilation : public ObjectVisitor { | 1414 class MarkFunctionsForRecompilation : public ObjectVisitor { |
| 1425 public: | 1415 public: |
| 1426 MarkFunctionsForRecompilation(Isolate* isolate, | 1416 MarkFunctionsForRecompilation(Isolate* isolate, |
| 1427 IsolateReloadContext* reload_context, | 1417 IsolateReloadContext* reload_context, |
| 1428 Zone* zone) | 1418 Zone* zone) |
| 1429 : ObjectVisitor(), | 1419 : ObjectVisitor(), |
| 1430 handle_(Object::Handle(zone)), | 1420 handle_(Object::Handle(zone)), |
| 1431 owning_class_(Class::Handle(zone)), | 1421 owning_class_(Class::Handle(zone)), |
| 1432 owning_lib_(Library::Handle(zone)), | 1422 owning_lib_(Library::Handle(zone)), |
| 1433 code_(Code::Handle(zone)), | 1423 code_(Code::Handle(zone)), |
| 1434 reload_context_(reload_context), | 1424 reload_context_(reload_context), |
| 1435 zone_(zone) { | 1425 zone_(zone) {} |
| 1436 } | |
| 1437 | 1426 |
| 1438 virtual void VisitObject(RawObject* obj) { | 1427 virtual void VisitObject(RawObject* obj) { |
| 1439 if (obj->IsPseudoObject()) { | 1428 if (obj->IsPseudoObject()) { |
| 1440 // Cannot even be wrapped in handles. | 1429 // Cannot even be wrapped in handles. |
| 1441 return; | 1430 return; |
| 1442 } | 1431 } |
| 1443 handle_ = obj; | 1432 handle_ = obj; |
| 1444 if (handle_.IsFunction()) { | 1433 if (handle_.IsFunction()) { |
| 1445 const Function& func = Function::Cast(handle_); | 1434 const Function& func = Function::Cast(handle_); |
| 1446 | 1435 |
| 1447 // Switch to unoptimized code or the lazy compilation stub. | 1436 // Switch to unoptimized code or the lazy compilation stub. |
| 1448 func.SwitchToLazyCompiledUnoptimizedCode(); | 1437 func.SwitchToLazyCompiledUnoptimizedCode(); |
| 1449 | 1438 |
| 1450 // Grab the current code. | 1439 // Grab the current code. |
| 1451 code_ = func.CurrentCode(); | 1440 code_ = func.CurrentCode(); |
| 1452 ASSERT(!code_.IsNull()); | 1441 ASSERT(!code_.IsNull()); |
| 1453 const bool clear_code = IsFromDirtyLibrary(func); | 1442 const bool clear_code = IsFromDirtyLibrary(func); |
| 1454 const bool stub_code = code_.IsStubCode(); | 1443 const bool stub_code = code_.IsStubCode(); |
| 1455 | 1444 |
| 1456 // Zero edge counters. | 1445 // Zero edge counters. |
| 1457 func.ZeroEdgeCounters(); | 1446 func.ZeroEdgeCounters(); |
| 1458 | 1447 |
| 1459 if (!stub_code) { | 1448 if (!stub_code) { |
| 1460 if (clear_code) { | 1449 if (clear_code) { |
| 1461 VTIR_Print("Marking %s for recompilation, clearning code\n", | 1450 VTIR_Print("Marking %s for recompilation, clearning code\n", |
| 1462 func.ToCString()); | 1451 func.ToCString()); |
| 1463 ClearAllCode(func); | 1452 ClearAllCode(func); |
| 1464 } else { | 1453 } else { |
| 1465 PreserveUnoptimizedCode(); | 1454 PreserveUnoptimizedCode(); |
| 1466 } | 1455 } |
| 1467 } | 1456 } |
| 1468 | 1457 |
| 1469 // Clear counters. | 1458 // Clear counters. |
| 1470 func.set_usage_counter(0); | 1459 func.set_usage_counter(0); |
| 1471 func.set_deoptimization_counter(0); | 1460 func.set_deoptimization_counter(0); |
| 1472 func.set_optimized_instruction_count(0); | 1461 func.set_optimized_instruction_count(0); |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1557 const Library& old = Library::Handle(OldLibraryOrNull(replacement_or_new)); | 1546 const Library& old = Library::Handle(OldLibraryOrNull(replacement_or_new)); |
| 1558 if (old.IsNull()) { | 1547 if (old.IsNull()) { |
| 1559 return String::null(); | 1548 return String::null(); |
| 1560 } | 1549 } |
| 1561 return old.private_key(); | 1550 return old.private_key(); |
| 1562 } | 1551 } |
| 1563 | 1552 |
| 1564 | 1553 |
| 1565 RawLibrary* IsolateReloadContext::OldLibraryOrNull( | 1554 RawLibrary* IsolateReloadContext::OldLibraryOrNull( |
| 1566 const Library& replacement_or_new) { | 1555 const Library& replacement_or_new) { |
| 1567 UnorderedHashSet<LibraryMapTraits> | 1556 UnorderedHashSet<LibraryMapTraits> old_libraries_set( |
| 1568 old_libraries_set(old_libraries_set_storage_); | 1557 old_libraries_set_storage_); |
| 1569 Library& lib = Library::Handle(); | 1558 Library& lib = Library::Handle(); |
| 1570 lib ^= old_libraries_set.GetOrNull(replacement_or_new); | 1559 lib ^= old_libraries_set.GetOrNull(replacement_or_new); |
| 1571 old_libraries_set.Release(); | 1560 old_libraries_set.Release(); |
| 1572 return lib.raw(); | 1561 return lib.raw(); |
| 1573 } | 1562 } |
| 1574 | 1563 |
| 1575 | 1564 |
| 1576 void IsolateReloadContext::BuildLibraryMapping() { | 1565 void IsolateReloadContext::BuildLibraryMapping() { |
| 1577 const GrowableObjectArray& libs = | 1566 const GrowableObjectArray& libs = |
| 1578 GrowableObjectArray::Handle(object_store()->libraries()); | 1567 GrowableObjectArray::Handle(object_store()->libraries()); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1616 const Library& original) { | 1605 const Library& original) { |
| 1617 UnorderedHashMap<LibraryMapTraits> map(library_map_storage_); | 1606 UnorderedHashMap<LibraryMapTraits> map(library_map_storage_); |
| 1618 bool update = map.UpdateOrInsert(replacement_or_new, original); | 1607 bool update = map.UpdateOrInsert(replacement_or_new, original); |
| 1619 ASSERT(!update); | 1608 ASSERT(!update); |
| 1620 // The storage given to the map may have been reallocated, remember the new | 1609 // The storage given to the map may have been reallocated, remember the new |
| 1621 // address. | 1610 // address. |
| 1622 library_map_storage_ = map.Release().raw(); | 1611 library_map_storage_ = map.Release().raw(); |
| 1623 } | 1612 } |
| 1624 | 1613 |
| 1625 | 1614 |
| 1626 void IsolateReloadContext::AddStaticFieldMapping( | 1615 void IsolateReloadContext::AddStaticFieldMapping(const Field& old_field, |
| 1627 const Field& old_field, const Field& new_field) { | 1616 const Field& new_field) { |
| 1628 ASSERT(old_field.is_static()); | 1617 ASSERT(old_field.is_static()); |
| 1629 ASSERT(new_field.is_static()); | 1618 ASSERT(new_field.is_static()); |
| 1630 | 1619 |
| 1631 AddBecomeMapping(old_field, new_field); | 1620 AddBecomeMapping(old_field, new_field); |
| 1632 } | 1621 } |
| 1633 | 1622 |
| 1634 | 1623 |
| 1635 void IsolateReloadContext::AddBecomeMapping(const Object& old, | 1624 void IsolateReloadContext::AddBecomeMapping(const Object& old, |
| 1636 const Object& neu) { | 1625 const Object& neu) { |
| 1637 ASSERT(become_map_storage_ != Array::null()); | 1626 ASSERT(become_map_storage_ != Array::null()); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1681 ASSERT(!super_cls.IsNull()); | 1670 ASSERT(!super_cls.IsNull()); |
| 1682 super_cls.AddDirectSubclass(cls); | 1671 super_cls.AddDirectSubclass(cls); |
| 1683 } | 1672 } |
| 1684 } | 1673 } |
| 1685 } | 1674 } |
| 1686 } | 1675 } |
| 1687 | 1676 |
| 1688 #endif // !PRODUCT | 1677 #endif // !PRODUCT |
| 1689 | 1678 |
| 1690 } // namespace dart | 1679 } // namespace dart |
| OLD | NEW |