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 |