| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/isolate_reload.h" | 5 #include "vm/isolate_reload.h" |
| 6 | 6 |
| 7 #include "vm/become.h" | 7 #include "vm/become.h" |
| 8 #include "vm/bit_vector.h" | 8 #include "vm/bit_vector.h" |
| 9 #include "vm/code_generator.h" | 9 #include "vm/code_generator.h" |
| 10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
| (...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 358 | 358 |
| 359 | 359 |
| 360 IsolateReloadContext::IsolateReloadContext(Isolate* isolate, | 360 IsolateReloadContext::IsolateReloadContext(Isolate* isolate, |
| 361 JSONStream* js) | 361 JSONStream* js) |
| 362 : zone_(Thread::Current()->zone()), | 362 : zone_(Thread::Current()->zone()), |
| 363 start_time_micros_(OS::GetCurrentMonotonicMicros()), | 363 start_time_micros_(OS::GetCurrentMonotonicMicros()), |
| 364 reload_timestamp_(OS::GetCurrentTimeMillis()), | 364 reload_timestamp_(OS::GetCurrentTimeMillis()), |
| 365 isolate_(isolate), | 365 isolate_(isolate), |
| 366 reload_skipped_(false), | 366 reload_skipped_(false), |
| 367 reload_aborted_(false), | 367 reload_aborted_(false), |
| 368 reload_finalized_(false), |
| 368 js_(js), | 369 js_(js), |
| 369 saved_num_cids_(-1), | 370 saved_num_cids_(-1), |
| 370 saved_class_table_(NULL), | 371 saved_class_table_(NULL), |
| 371 num_saved_libs_(-1), | 372 num_saved_libs_(-1), |
| 372 instance_morphers_(zone_, 0), | 373 instance_morphers_(zone_, 0), |
| 373 reasons_to_cancel_reload_(zone_, 0), | 374 reasons_to_cancel_reload_(zone_, 0), |
| 374 cid_mapper_(), | 375 cid_mapper_(), |
| 375 modified_libs_(NULL), | 376 modified_libs_(NULL), |
| 376 script_uri_(String::null()), | 377 script_uri_(String::null()), |
| 377 error_(Error::null()), | 378 error_(Error::null()), |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 467 | 468 |
| 468 // Ensure all functions on the stack have unoptimized code. | 469 // Ensure all functions on the stack have unoptimized code. |
| 469 EnsuredUnoptimizedCodeForStack(); | 470 EnsuredUnoptimizedCodeForStack(); |
| 470 // Deoptimize all code that had optimizing decisions that are dependent on | 471 // Deoptimize all code that had optimizing decisions that are dependent on |
| 471 // assumptions from field guards or CHA or deferred library prefixes. | 472 // assumptions from field guards or CHA or deferred library prefixes. |
| 472 // TODO(johnmccutchan): Deoptimizing dependent code here (before the reload) | 473 // TODO(johnmccutchan): Deoptimizing dependent code here (before the reload) |
| 473 // is paranoid. This likely can be moved to the commit phase. | 474 // is paranoid. This likely can be moved to the commit phase. |
| 474 DeoptimizeDependentCode(); | 475 DeoptimizeDependentCode(); |
| 475 Checkpoint(); | 476 Checkpoint(); |
| 476 | 477 |
| 478 // WEIRD CONTROL FLOW BEGINS. |
| 479 // |
| 480 // The flow of execution until we return from the tag handler can be complex. |
| 481 // |
| 482 // On a successful load, the following will occur: |
| 483 // 1) Tag Handler is invoked and the embedder is in control. |
| 484 // 2) All sources and libraries are loaded. |
| 485 // 3) Dart_FinalizeLoading is called by the embedder. |
| 486 // 4) Dart_FinalizeLoading invokes IsolateReloadContext::FinalizeLoading |
| 487 // and we are temporarily back in control. |
| 488 // This is where we validate the reload and commit or reject. |
| 489 // 5) Dart_FinalizeLoading invokes Dart code related to deferred libraries. |
| 490 // 6) The tag handler returns and we move on. |
| 491 // |
| 492 // Even after a successful reload the Dart code invoked in (5) can result |
| 493 // in an Unwind error or a StackOverflow error. This error will be returned |
| 494 // by the tag handler. The tag handler can return other errors, for example, |
| 495 // top level parse errors. We want to capture these errors while propagating |
| 496 // the Unwind or StackOverflow errors. |
| 477 Object& result = Object::Handle(thread->zone()); | 497 Object& result = Object::Handle(thread->zone()); |
| 478 { | 498 { |
| 479 TransitionVMToNative transition(thread); | 499 TransitionVMToNative transition(thread); |
| 480 Api::Scope api_scope(thread); | 500 Api::Scope api_scope(thread); |
| 481 | 501 |
| 482 Dart_Handle retval = | 502 Dart_Handle retval = |
| 483 (I->library_tag_handler())(Dart_kScriptTag, | 503 (I->library_tag_handler())(Dart_kScriptTag, |
| 484 Api::NewHandle(thread, Library::null()), | 504 Api::NewHandle(thread, Library::null()), |
| 485 Api::NewHandle(thread, root_lib_url.raw())); | 505 Api::NewHandle(thread, root_lib_url.raw())); |
| 486 result = Api::UnwrapHandle(retval); | 506 result = Api::UnwrapHandle(retval); |
| 487 } | 507 } |
| 508 // |
| 509 // WEIRD CONTROL FLOW ENDS. |
| 488 | 510 |
| 489 BackgroundCompiler::Enable(); | 511 BackgroundCompiler::Enable(); |
| 490 | 512 |
| 491 if (result.IsUnwindError()) { | 513 if (result.IsUnwindError() || |
| 492 // Ignore an unwind error because the isolate is dead. | 514 (result.raw() == isolate()->object_store()->stack_overflow())) { |
| 493 return; | 515 // When returning from the tag handler with an Unwind error or a |
| 516 // StackOverflow error, propagate it and give up. |
| 517 Exceptions::PropagateError(Error::Cast(result)); |
| 518 UNREACHABLE(); |
| 494 } | 519 } |
| 495 | 520 |
| 521 // Other errors (e.g. a parse error) are captured by the reload system. |
| 496 if (result.IsError()) { | 522 if (result.IsError()) { |
| 497 FinalizeFailedLoad(Error::Cast(result)); | 523 FinalizeFailedLoad(Error::Cast(result)); |
| 498 } | 524 } |
| 499 } | 525 } |
| 500 | 526 |
| 501 | 527 |
| 502 void IsolateReloadContext::RegisterClass(const Class& new_cls) { | 528 void IsolateReloadContext::RegisterClass(const Class& new_cls) { |
| 503 const Class& old_cls = Class::Handle(OldClassOrNull(new_cls)); | 529 const Class& old_cls = Class::Handle(OldClassOrNull(new_cls)); |
| 504 if (old_cls.IsNull()) { | 530 if (old_cls.IsNull()) { |
| 505 I->class_table()->Register(new_cls); | 531 I->class_table()->Register(new_cls); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 524 AddClassMapping(new_cls, old_cls); | 550 AddClassMapping(new_cls, old_cls); |
| 525 } | 551 } |
| 526 | 552 |
| 527 | 553 |
| 528 // FinalizeLoading will be called *before* Reload() returns but will not be | 554 // FinalizeLoading will be called *before* Reload() returns but will not be |
| 529 // called if the embedder fails to load sources. | 555 // called if the embedder fails to load sources. |
| 530 void IsolateReloadContext::FinalizeLoading() { | 556 void IsolateReloadContext::FinalizeLoading() { |
| 531 if (reload_skipped_) { | 557 if (reload_skipped_) { |
| 532 return; | 558 return; |
| 533 } | 559 } |
| 560 ASSERT(!reload_finalized_); |
| 534 BuildLibraryMapping(); | 561 BuildLibraryMapping(); |
| 535 TIR_Print("---- LOAD SUCCEEDED\n"); | 562 TIR_Print("---- LOAD SUCCEEDED\n"); |
| 536 if (ValidateReload()) { | 563 if (ValidateReload()) { |
| 537 Commit(); | 564 Commit(); |
| 538 PostCommit(); | 565 PostCommit(); |
| 539 isolate()->set_last_reload_timestamp(reload_timestamp_); | 566 isolate()->set_last_reload_timestamp(reload_timestamp_); |
| 540 } else { | 567 } else { |
| 541 ReportReasonsForCancelling(); | 568 ReportReasonsForCancelling(); |
| 542 Rollback(); | 569 Rollback(); |
| 543 } | 570 } |
| 544 // ValidateReload mutates the direct subclass information and does | 571 // ValidateReload mutates the direct subclass information and does |
| 545 // not remove dead subclasses. Rebuild the direct subclass | 572 // not remove dead subclasses. Rebuild the direct subclass |
| 546 // information from scratch. | 573 // information from scratch. |
| 547 RebuildDirectSubclasses(); | 574 RebuildDirectSubclasses(); |
| 548 | |
| 549 CommonFinalizeTail(); | 575 CommonFinalizeTail(); |
| 550 } | 576 } |
| 551 | 577 |
| 552 | 578 |
| 553 // FinalizeFailedLoad will be called *before* Reload() returns and will only | 579 // FinalizeFailedLoad will be called *before* Reload() returns and will only |
| 554 // be called if the embedder fails to load sources. | 580 // be called if the embedder fails to load sources. |
| 555 void IsolateReloadContext::FinalizeFailedLoad(const Error& error) { | 581 void IsolateReloadContext::FinalizeFailedLoad(const Error& error) { |
| 556 TIR_Print("---- LOAD FAILED, ABORTING RELOAD\n"); | 582 TIR_Print("---- LOAD FAILED, ABORTING RELOAD\n"); |
| 557 AddReasonForCancelling(new Aborted(zone_, error)); | 583 AddReasonForCancelling(new Aborted(zone_, error)); |
| 558 ReportReasonsForCancelling(); | 584 ReportReasonsForCancelling(); |
| 559 Rollback(); | 585 if (!reload_finalized_) { |
| 586 Rollback(); |
| 587 } |
| 560 CommonFinalizeTail(); | 588 CommonFinalizeTail(); |
| 561 } | 589 } |
| 562 | 590 |
| 563 | 591 |
| 564 void IsolateReloadContext::CommonFinalizeTail() { | 592 void IsolateReloadContext::CommonFinalizeTail() { |
| 565 ReportOnJSON(js_); | 593 ReportOnJSON(js_); |
| 594 reload_finalized_ = true; |
| 566 } | 595 } |
| 567 | 596 |
| 568 | 597 |
| 569 void IsolateReloadContext::ReportOnJSON(JSONStream* stream) { | 598 void IsolateReloadContext::ReportOnJSON(JSONStream* stream) { |
| 599 // Clear the buffer. |
| 600 stream->buffer()->Clear(); |
| 570 JSONObject jsobj(stream); | 601 JSONObject jsobj(stream); |
| 571 jsobj.AddProperty("type", "ReloadReport"); | 602 jsobj.AddProperty("type", "ReloadReport"); |
| 572 jsobj.AddProperty("success", !HasReasonsForCancelling()); | 603 jsobj.AddProperty("success", !HasReasonsForCancelling()); |
| 573 { | 604 { |
| 574 JSONObject details(&jsobj, "details"); | 605 JSONObject details(&jsobj, "details"); |
| 575 if (HasReasonsForCancelling()) { | 606 if (HasReasonsForCancelling()) { |
| 576 // Reload was rejected. | 607 // Reload was rejected. |
| 577 JSONArray array(&jsobj, "notices"); | 608 JSONArray array(&jsobj, "notices"); |
| 578 for (intptr_t i = 0; i < reasons_to_cancel_reload_.length(); i++) { | 609 for (intptr_t i = 0; i < reasons_to_cancel_reload_.length(); i++) { |
| 579 ReasonForCancelling* reason = reasons_to_cancel_reload_.At(i); | 610 ReasonForCancelling* reason = reasons_to_cancel_reload_.At(i); |
| (...skipping 1033 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1613 ASSERT(!super_cls.IsNull()); | 1644 ASSERT(!super_cls.IsNull()); |
| 1614 super_cls.AddDirectSubclass(cls); | 1645 super_cls.AddDirectSubclass(cls); |
| 1615 } | 1646 } |
| 1616 } | 1647 } |
| 1617 } | 1648 } |
| 1618 } | 1649 } |
| 1619 | 1650 |
| 1620 #endif // !PRODUCT | 1651 #endif // !PRODUCT |
| 1621 | 1652 |
| 1622 } // namespace dart | 1653 } // namespace dart |
| OLD | NEW |