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 |