OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/object.h" | 5 #include "vm/object.h" |
6 | 6 |
7 #include "include/dart_api.h" | 7 #include "include/dart_api.h" |
8 #include "platform/assert.h" | 8 #include "platform/assert.h" |
9 #include "vm/assembler.h" | 9 #include "vm/assembler.h" |
10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
(...skipping 2316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2327 // Prefinalized classes have a VM internal representation and no Dart fields. | 2327 // Prefinalized classes have a VM internal representation and no Dart fields. |
2328 // Their instance size is precomputed and field offsets are known. | 2328 // Their instance size is precomputed and field offsets are known. |
2329 if (!is_prefinalized()) { | 2329 if (!is_prefinalized()) { |
2330 // Compute offsets of instance fields and instance size. | 2330 // Compute offsets of instance fields and instance size. |
2331 CalculateFieldOffsets(); | 2331 CalculateFieldOffsets(); |
2332 } | 2332 } |
2333 set_is_finalized(); | 2333 set_is_finalized(); |
2334 } | 2334 } |
2335 | 2335 |
2336 | 2336 |
2337 // Helper class to handle an array of code weak properties. Implements | |
2338 // registration and disabling of stored code objects. | |
2339 class WeakCodeReferences : public ValueObject { | |
Florian Schneider
2014/02/05 10:36:31
This class and it's two subclasses seem good candi
srdjan
2014/02/05 16:20:51
Templates are hard to work with: harder on compile
Florian Schneider
2014/02/05 17:07:28
I don't really care that much - so land it either
| |
2340 public: | |
2341 explicit WeakCodeReferences(const Array& value) : array_(value) {} | |
Florian Schneider
2014/02/05 10:36:31
explicit WeakCodeReferences(const T& owner)
:
| |
2342 virtual ~WeakCodeReferences() {} | |
2343 | |
2344 void Register(const Code& value) { | |
2345 if (!array_.IsNull()) { | |
2346 // Try to find and reuse cleared WeakProperty to avoid allocating new one. | |
2347 WeakProperty& weak_property = WeakProperty::Handle(); | |
2348 for (intptr_t i = 0; i < array_.Length(); i++) { | |
2349 weak_property ^= array_.At(i); | |
2350 if (weak_property.key() == Code::null()) { | |
2351 // Empty property found. Reuse it. | |
2352 weak_property.set_key(value); | |
2353 return; | |
2354 } | |
2355 } | |
2356 } | |
2357 | |
2358 const WeakProperty& weak_property = WeakProperty::Handle( | |
2359 WeakProperty::New(Heap::kOld)); | |
2360 weak_property.set_key(value); | |
2361 | |
2362 intptr_t length = array_.IsNull() ? 0 : array_.Length(); | |
2363 const Array& new_array = Array::Handle( | |
2364 Array::Grow(array_, length + 1, Heap::kOld)); | |
2365 new_array.SetAt(length, weak_property); | |
2366 UpdateArrayTo(new_array); | |
2367 } | |
2368 | |
2369 virtual void UpdateArrayTo(const Array& array) = 0; | |
Florian Schneider
2014/02/05 10:36:31
void UpdateArrayTo(const Array& array) {
owner_.
| |
2370 virtual void ReportDeoptimization(const Code& code) = 0; | |
2371 virtual void ReportSwitchingCode(const Code& code) = 0; | |
2372 | |
2373 static bool IsOptimizedCode(const Array& dependent_code, const Code& code) { | |
Florian Schneider
2014/02/05 17:07:28
This checks for two things: the code is optimized
| |
2374 if (!code.is_optimized()) { | |
2375 return false; | |
2376 } | |
2377 WeakProperty& weak_property = WeakProperty::Handle(); | |
2378 for (intptr_t i = 0; i < dependent_code.Length(); i++) { | |
2379 weak_property ^= dependent_code.At(i); | |
2380 if (code.raw() == weak_property.key()) { | |
2381 return true; | |
2382 } | |
2383 } | |
2384 return false; | |
2385 } | |
2386 | |
2387 void DisableCode() { | |
2388 const Array& code_objects = Array::Handle(array_.raw()); | |
2389 if (code_objects.IsNull()) { | |
2390 return; | |
2391 } | |
2392 UpdateArrayTo(Object::null_array()); | |
2393 // Disable all code on stack. | |
2394 Code& code = Code::Handle(); | |
2395 { | |
2396 DartFrameIterator iterator; | |
2397 StackFrame* frame = iterator.NextFrame(); | |
2398 while (frame != NULL) { | |
2399 code = frame->LookupDartCode(); | |
2400 if (IsOptimizedCode(code_objects, code)) { | |
2401 ReportDeoptimization(code); | |
2402 DeoptimizeAt(code, frame->pc()); | |
2403 } | |
2404 frame = iterator.NextFrame(); | |
2405 } | |
2406 } | |
2407 | |
2408 // Switch functions that use dependent code to unoptimized code. | |
2409 WeakProperty& weak_property = WeakProperty::Handle(); | |
2410 Function& function = Function::Handle(); | |
2411 for (intptr_t i = 0; i < code_objects.Length(); i++) { | |
2412 weak_property ^= code_objects.At(i); | |
2413 code ^= weak_property.key(); | |
2414 if (code.IsNull()) { | |
2415 // Code was garbage collected already. | |
2416 continue; | |
2417 } | |
2418 | |
2419 function ^= code.function(); | |
2420 // If function uses dependent code switch it to unoptimized. | |
2421 if (function.CurrentCode() == code.raw()) { | |
2422 ASSERT(function.HasOptimizedCode()); | |
2423 ReportSwitchingCode(code); | |
2424 function.SwitchToUnoptimizedCode(); | |
2425 } | |
2426 } | |
2427 } | |
2428 | |
2429 private: | |
2430 const Array& array_; | |
Florian Schneider
2014/02/05 10:36:31
Replace array_ with owner_.dependent_code() in all
| |
2431 DISALLOW_COPY_AND_ASSIGN(WeakCodeReferences); | |
2432 }; | |
2433 | |
2434 | |
2435 class CHACodeArray : public WeakCodeReferences { | |
2436 public: | |
2437 explicit CHACodeArray(const Class& cls) | |
2438 : WeakCodeReferences(Array::Handle(cls.cha_codes())), cls_(cls) { | |
2439 } | |
2440 | |
2441 virtual void UpdateArrayTo(const Array& value) { | |
2442 cls_.set_cha_codes(value); | |
2443 } | |
2444 | |
2445 virtual void ReportDeoptimization(const Code& code) { | |
2446 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { | |
2447 Function& function = Function::Handle(code.function()); | |
2448 OS::PrintErr("Deoptimizing %s because CHA optimized (%s).\n", | |
2449 function.ToFullyQualifiedCString(), | |
2450 cls_.ToCString()); | |
2451 } | |
2452 } | |
2453 | |
2454 virtual void ReportSwitchingCode(const Code& code) { | |
2455 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { | |
2456 Function& function = Function::Handle(code.function()); | |
2457 OS::PrintErr("Switching %s to unoptimized code because CHA invalid" | |
2458 " (%s)\n", | |
2459 function.ToFullyQualifiedCString(), | |
2460 cls_.ToCString()); | |
2461 } | |
2462 } | |
2463 | |
2464 private: | |
2465 const Class& cls_; | |
2466 DISALLOW_COPY_AND_ASSIGN(CHACodeArray); | |
2467 }; | |
2468 | |
2469 | |
2470 void Class::RegisterCHACode(const Code& code) { | |
2471 ASSERT(code.is_optimized()); | |
2472 CHACodeArray a(*this); | |
2473 a.Register(code); | |
2474 } | |
2475 | |
2476 | |
2477 void Class::DisableCHAOptimizedCode() { | |
2478 CHACodeArray a(*this); | |
Florian Schneider
2014/02/05 10:36:31
WeakCodeReferences<Class> a(*this);
| |
2479 a.DisableCode(); | |
2480 } | |
2481 | |
2482 | |
2483 void Class::set_cha_codes(const Array& cache) const { | |
Florian Schneider
2014/02/05 10:36:31
s/set_cha_codes/set_dependent_code_/g
s/cha_codes
srdjan
2014/02/05 16:20:51
Yes they would have 'compatible' interface but tha
Florian Schneider
2014/02/05 17:07:28
Imo, fragile would imply that something bad could
| |
2484 StorePointer(&raw_ptr()->cha_codes_, cache.raw()); | |
2485 } | |
2486 | |
2487 | |
2337 // Apply the members from the patch class to the original class. | 2488 // Apply the members from the patch class to the original class. |
2338 bool Class::ApplyPatch(const Class& patch, Error* error) const { | 2489 bool Class::ApplyPatch(const Class& patch, Error* error) const { |
2339 ASSERT(error != NULL); | 2490 ASSERT(error != NULL); |
2340 ASSERT(!is_finalized()); | 2491 ASSERT(!is_finalized()); |
2341 // Shared handles used during the iteration. | 2492 // Shared handles used during the iteration. |
2342 String& member_name = String::Handle(); | 2493 String& member_name = String::Handle(); |
2343 | 2494 |
2344 const PatchClass& patch_class = | 2495 const PatchClass& patch_class = |
2345 PatchClass::Handle(PatchClass::New(*this, patch)); | 2496 PatchClass::Handle(PatchClass::New(*this, patch)); |
2346 | 2497 |
(...skipping 4039 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6386 } | 6537 } |
6387 } | 6538 } |
6388 | 6539 |
6389 | 6540 |
6390 RawArray* Field::dependent_code() const { | 6541 RawArray* Field::dependent_code() const { |
6391 return raw_ptr()->dependent_code_; | 6542 return raw_ptr()->dependent_code_; |
6392 } | 6543 } |
6393 | 6544 |
6394 | 6545 |
6395 void Field::set_dependent_code(const Array& array) const { | 6546 void Field::set_dependent_code(const Array& array) const { |
6396 raw_ptr()->dependent_code_ = array.raw(); | 6547 StorePointer(&raw_ptr()->dependent_code_, array.raw()); |
6397 } | 6548 } |
6398 | 6549 |
6399 | 6550 |
6400 void Field::RegisterDependentCode(const Code& code) const { | 6551 class FieldDependentArray : public WeakCodeReferences { |
6401 const Array& dependent = Array::Handle(dependent_code()); | 6552 public: |
6553 explicit FieldDependentArray(const Field& field) | |
6554 : WeakCodeReferences(Array::Handle(field.dependent_code())), | |
6555 field_(field) {} | |
6402 | 6556 |
6403 if (!dependent.IsNull()) { | 6557 virtual void UpdateArrayTo(const Array& value) { |
6404 // Try to find and reuse cleared WeakProperty to avoid allocating new one. | 6558 field_.set_dependent_code(value); |
6405 WeakProperty& weak_property = WeakProperty::Handle(); | 6559 } |
6406 for (intptr_t i = 0; i < dependent.Length(); i++) { | 6560 |
6407 weak_property ^= dependent.At(i); | 6561 virtual void ReportDeoptimization(const Code& code) { |
6408 if (weak_property.key() == Code::null()) { | 6562 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { |
6409 // Empty property found. Reuse it. | 6563 Function& function = Function::Handle(code.function()); |
6410 weak_property.set_key(code); | 6564 OS::PrintErr("Deoptimizing %s because guard on field %s failed.\n", |
6411 return; | 6565 function.ToFullyQualifiedCString(), |
6412 } | 6566 field_.ToCString()); |
6413 } | 6567 } |
6414 } | 6568 } |
6415 | 6569 |
6416 const WeakProperty& weak_property = WeakProperty::Handle( | 6570 virtual void ReportSwitchingCode(const Code& code) { |
6417 WeakProperty::New(Heap::kOld)); | 6571 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { |
6418 weak_property.set_key(code); | 6572 Function& function = Function::Handle(code.function()); |
6419 | 6573 OS::PrintErr("Switching %s to unoptimized code because guard" |
6420 intptr_t length = dependent.IsNull() ? 0 : dependent.Length(); | 6574 " on field %s was violated.\n", |
6421 const Array& new_dependent = Array::Handle( | 6575 function.ToFullyQualifiedCString(), |
6422 Array::Grow(dependent, length + 1, Heap::kOld)); | 6576 field_.ToCString()); |
6423 new_dependent.SetAt(length, weak_property); | |
6424 set_dependent_code(new_dependent); | |
6425 } | |
6426 | |
6427 | |
6428 static bool IsDependentCode(const Array& dependent_code, const Code& code) { | |
6429 if (!code.is_optimized()) { | |
6430 return false; | |
6431 } | |
6432 | |
6433 WeakProperty& weak_property = WeakProperty::Handle(); | |
6434 for (intptr_t i = 0; i < dependent_code.Length(); i++) { | |
6435 weak_property ^= dependent_code.At(i); | |
6436 if (code.raw() == weak_property.key()) { | |
6437 return true; | |
6438 } | 6577 } |
6439 } | 6578 } |
6440 | 6579 |
6441 return false; | 6580 private: |
6581 const Field& field_; | |
6582 DISALLOW_COPY_AND_ASSIGN(FieldDependentArray); | |
6583 }; | |
6584 | |
6585 | |
6586 void Field::RegisterDependentCode(const Code& code) const { | |
6587 ASSERT(code.is_optimized()); | |
6588 FieldDependentArray a(*this); | |
6589 a.Register(code); | |
6442 } | 6590 } |
6443 | 6591 |
6444 | 6592 |
6445 void Field::DeoptimizeDependentCode() const { | 6593 void Field::DeoptimizeDependentCode() const { |
6446 const Array& code_objects = Array::Handle(dependent_code()); | 6594 FieldDependentArray a(*this); |
Florian Schneider
2014/02/05 10:36:31
WeakCodeReferences<Field> a(*this);
| |
6447 | 6595 a.DisableCode(); |
6448 if (code_objects.IsNull()) { | |
6449 return; | |
6450 } | |
6451 set_dependent_code(Object::null_array()); | |
6452 | |
6453 // Deoptimize all dependent code on the stack. | |
6454 Code& code = Code::Handle(); | |
6455 { | |
6456 DartFrameIterator iterator; | |
6457 StackFrame* frame = iterator.NextFrame(); | |
6458 while (frame != NULL) { | |
6459 code = frame->LookupDartCode(); | |
6460 if (IsDependentCode(code_objects, code)) { | |
6461 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { | |
6462 Function& function = Function::Handle(code.function()); | |
6463 OS::PrintErr("Deoptimizing %s because guard on field %s failed.\n", | |
6464 function.ToFullyQualifiedCString(), | |
6465 ToCString()); | |
6466 } | |
6467 DeoptimizeAt(code, frame->pc()); | |
6468 } | |
6469 frame = iterator.NextFrame(); | |
6470 } | |
6471 } | |
6472 | |
6473 // Switch functions that use dependent code to unoptimized code. | |
6474 WeakProperty& weak_property = WeakProperty::Handle(); | |
6475 Function& function = Function::Handle(); | |
6476 for (intptr_t i = 0; i < code_objects.Length(); i++) { | |
6477 weak_property ^= code_objects.At(i); | |
6478 code ^= weak_property.key(); | |
6479 if (code.IsNull()) { | |
6480 // Code was garbage collected already. | |
6481 continue; | |
6482 } | |
6483 | |
6484 function ^= code.function(); | |
6485 // If function uses dependent code switch it to unoptimized. | |
6486 if (function.CurrentCode() == code.raw()) { | |
6487 ASSERT(function.HasOptimizedCode()); | |
6488 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { | |
6489 OS::PrintErr("Switching %s to unoptimized code because guard" | |
6490 " on field %s was violated.\n", | |
6491 function.ToFullyQualifiedCString(), | |
6492 ToCString()); | |
6493 } | |
6494 function.SwitchToUnoptimizedCode(); | |
6495 } | |
6496 } | |
6497 } | 6596 } |
6498 | 6597 |
6499 | 6598 |
6500 bool Field::IsUninitialized() const { | 6599 bool Field::IsUninitialized() const { |
6501 const Instance& value = Instance::Handle(raw_ptr()->value_); | 6600 const Instance& value = Instance::Handle(raw_ptr()->value_); |
6502 ASSERT(value.raw() != Object::transition_sentinel().raw()); | 6601 ASSERT(value.raw() != Object::transition_sentinel().raw()); |
6503 return value.raw() == Object::sentinel().raw(); | 6602 return value.raw() == Object::sentinel().raw(); |
6504 } | 6603 } |
6505 | 6604 |
6506 | 6605 |
(...skipping 10718 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
17225 return "_MirrorReference"; | 17324 return "_MirrorReference"; |
17226 } | 17325 } |
17227 | 17326 |
17228 | 17327 |
17229 void MirrorReference::PrintToJSONStream(JSONStream* stream, bool ref) const { | 17328 void MirrorReference::PrintToJSONStream(JSONStream* stream, bool ref) const { |
17230 Instance::PrintToJSONStream(stream, ref); | 17329 Instance::PrintToJSONStream(stream, ref); |
17231 } | 17330 } |
17232 | 17331 |
17233 | 17332 |
17234 } // namespace dart | 17333 } // namespace dart |
OLD | NEW |