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 <map> | 5 #include <map> |
6 #include <set> | 6 #include <set> |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "vm/kernel_to_il.h" | 9 #include "vm/kernel_to_il.h" |
10 | 10 |
(...skipping 822 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
833 class TryFinallyBlock { | 833 class TryFinallyBlock { |
834 public: | 834 public: |
835 TryFinallyBlock(FlowGraphBuilder* builder, Statement* finalizer) | 835 TryFinallyBlock(FlowGraphBuilder* builder, Statement* finalizer) |
836 : builder_(builder), | 836 : builder_(builder), |
837 outer_(builder->try_finally_block_), | 837 outer_(builder->try_finally_block_), |
838 finalizer_(finalizer), | 838 finalizer_(finalizer), |
839 context_depth_(builder->context_depth_), | 839 context_depth_(builder->context_depth_), |
840 // Finalizers are executed outside of the try block hence | 840 // Finalizers are executed outside of the try block hence |
841 // try depth of finalizers are one less than current try | 841 // try depth of finalizers are one less than current try |
842 // depth. | 842 // depth. |
843 try_depth_(builder->try_depth_ - 1) { | 843 try_depth_(builder->try_depth_ - 1), |
| 844 try_index_(builder_->CurrentTryIndex()) { |
844 builder_->try_finally_block_ = this; | 845 builder_->try_finally_block_ = this; |
845 } | 846 } |
846 ~TryFinallyBlock() { builder_->try_finally_block_ = outer_; } | 847 ~TryFinallyBlock() { builder_->try_finally_block_ = outer_; } |
847 | 848 |
848 Statement* finalizer() const { return finalizer_; } | 849 Statement* finalizer() const { return finalizer_; } |
849 intptr_t context_depth() const { return context_depth_; } | 850 intptr_t context_depth() const { return context_depth_; } |
850 intptr_t try_depth() const { return try_depth_; } | 851 intptr_t try_depth() const { return try_depth_; } |
| 852 intptr_t try_index() const { return try_index_; } |
851 TryFinallyBlock* outer() const { return outer_; } | 853 TryFinallyBlock* outer() const { return outer_; } |
852 | 854 |
853 private: | 855 private: |
854 FlowGraphBuilder* const builder_; | 856 FlowGraphBuilder* const builder_; |
855 TryFinallyBlock* const outer_; | 857 TryFinallyBlock* const outer_; |
856 Statement* const finalizer_; | 858 Statement* const finalizer_; |
857 const intptr_t context_depth_; | 859 const intptr_t context_depth_; |
858 const intptr_t try_depth_; | 860 const intptr_t try_depth_; |
| 861 const intptr_t try_index_; |
859 }; | 862 }; |
860 | 863 |
861 | 864 |
862 class TryCatchBlock { | 865 class TryCatchBlock { |
863 public: | 866 public: |
864 explicit TryCatchBlock(FlowGraphBuilder* builder, | 867 explicit TryCatchBlock(FlowGraphBuilder* builder, |
865 intptr_t try_handler_index = -1) | 868 intptr_t try_handler_index = -1) |
866 : builder_(builder), | 869 : builder_(builder), |
867 outer_(builder->try_catch_block_), | 870 outer_(builder->try_catch_block_), |
868 try_index_(try_handler_index) { | 871 try_index_(try_handler_index) { |
869 if (try_index_ == -1) try_index_ = builder->AllocateTryIndex(); | 872 if (try_index_ == -1) try_index_ = builder->AllocateTryIndex(); |
870 builder->try_catch_block_ = this; | 873 builder->try_catch_block_ = this; |
871 } | 874 } |
872 ~TryCatchBlock() { builder_->try_catch_block_ = outer_; } | 875 ~TryCatchBlock() { builder_->try_catch_block_ = outer_; } |
873 | 876 |
874 intptr_t TryIndex() { return try_index_; } | 877 intptr_t try_index() { return try_index_; } |
| 878 TryCatchBlock* outer() const { return outer_; } |
875 | 879 |
876 private: | 880 private: |
877 FlowGraphBuilder* builder_; | 881 FlowGraphBuilder* builder_; |
878 TryCatchBlock* outer_; | 882 TryCatchBlock* outer_; |
879 intptr_t try_index_; | 883 intptr_t try_index_; |
880 }; | 884 }; |
881 | 885 |
882 | 886 |
883 class CatchBlock { | 887 class CatchBlock { |
884 public: | 888 public: |
(...skipping 961 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1846 &type_translator_) {} | 1850 &type_translator_) {} |
1847 | 1851 |
1848 | 1852 |
1849 FlowGraphBuilder::~FlowGraphBuilder() {} | 1853 FlowGraphBuilder::~FlowGraphBuilder() {} |
1850 | 1854 |
1851 | 1855 |
1852 Fragment FlowGraphBuilder::TranslateFinallyFinalizers( | 1856 Fragment FlowGraphBuilder::TranslateFinallyFinalizers( |
1853 TryFinallyBlock* outer_finally, | 1857 TryFinallyBlock* outer_finally, |
1854 intptr_t target_context_depth) { | 1858 intptr_t target_context_depth) { |
1855 TryFinallyBlock* const saved_block = try_finally_block_; | 1859 TryFinallyBlock* const saved_block = try_finally_block_; |
| 1860 TryCatchBlock* const saved_try_catch_block = try_catch_block_; |
1856 const intptr_t saved_depth = context_depth_; | 1861 const intptr_t saved_depth = context_depth_; |
1857 const intptr_t saved_try_depth = try_depth_; | 1862 const intptr_t saved_try_depth = try_depth_; |
1858 | 1863 |
1859 Fragment instructions; | 1864 Fragment instructions; |
1860 | 1865 |
1861 // While translating the body of a finalizer we need to set the try-finally | 1866 // While translating the body of a finalizer we need to set the try-finally |
1862 // block which is active when translating the body. | 1867 // block which is active when translating the body. |
1863 while (try_finally_block_ != outer_finally) { | 1868 while (try_finally_block_ != outer_finally) { |
1864 // Set correct try depth (in case there are nested try statements). | 1869 // Set correct try depth (in case there are nested try statements). |
1865 try_depth_ = try_finally_block_->try_depth(); | 1870 try_depth_ = try_finally_block_->try_depth(); |
1866 | 1871 |
1867 // Potentially restore the context to what is expected for the finally | 1872 // Potentially restore the context to what is expected for the finally |
1868 // block. | 1873 // block. |
1869 instructions += AdjustContextTo(try_finally_block_->context_depth()); | 1874 instructions += AdjustContextTo(try_finally_block_->context_depth()); |
1870 | 1875 |
| 1876 // The to-be-translated finalizer has to have the correct try-index (namely |
| 1877 // the one outside the try-finally block). |
| 1878 bool changed_try_index = false; |
| 1879 intptr_t target_try_index = try_finally_block_->try_index(); |
| 1880 while (CurrentTryIndex() != target_try_index) { |
| 1881 try_catch_block_ = try_catch_block_->outer(); |
| 1882 changed_try_index = true; |
| 1883 } |
| 1884 if (changed_try_index) { |
| 1885 JoinEntryInstr* entry = BuildJoinEntry(); |
| 1886 instructions += Goto(entry); |
| 1887 instructions = Fragment(instructions.entry, entry); |
| 1888 } |
| 1889 |
1871 Statement* finalizer = try_finally_block_->finalizer(); | 1890 Statement* finalizer = try_finally_block_->finalizer(); |
1872 try_finally_block_ = try_finally_block_->outer(); | 1891 try_finally_block_ = try_finally_block_->outer(); |
1873 | 1892 |
1874 // This will potentially have exceptional cases as described in | 1893 // This will potentially have exceptional cases as described in |
1875 // [VisitTryFinally] and will handle them. | 1894 // [VisitTryFinally] and will handle them. |
1876 instructions += TranslateStatement(finalizer); | 1895 instructions += TranslateStatement(finalizer); |
1877 | 1896 |
1878 // We only need to make sure that if the finalizer ended normally, we | 1897 // We only need to make sure that if the finalizer ended normally, we |
1879 // continue towards the next outer try-finally. | 1898 // continue towards the next outer try-finally. |
1880 if (!instructions.is_open()) break; | 1899 if (!instructions.is_open()) break; |
1881 } | 1900 } |
1882 | 1901 |
1883 if (instructions.is_open() && target_context_depth != -1) { | 1902 if (instructions.is_open() && target_context_depth != -1) { |
1884 // A target context depth of -1 indicates that we the code after this | 1903 // A target context depth of -1 indicates that the code after this |
1885 // will not care about the context chain so we can leave it any way we | 1904 // will not care about the context chain so we can leave it any way we |
1886 // want after the last finalizer. That is used when returning. | 1905 // want after the last finalizer. That is used when returning. |
1887 instructions += AdjustContextTo(target_context_depth); | 1906 instructions += AdjustContextTo(target_context_depth); |
1888 } | 1907 } |
1889 | 1908 |
1890 try_finally_block_ = saved_block; | 1909 try_finally_block_ = saved_block; |
| 1910 try_catch_block_ = saved_try_catch_block; |
1891 context_depth_ = saved_depth; | 1911 context_depth_ = saved_depth; |
1892 try_depth_ = saved_try_depth; | 1912 try_depth_ = saved_try_depth; |
1893 | 1913 |
1894 return instructions; | 1914 return instructions; |
1895 } | 1915 } |
1896 | 1916 |
1897 | 1917 |
1898 Fragment FlowGraphBuilder::EnterScope(TreeNode* node, bool* new_context) { | 1918 Fragment FlowGraphBuilder::EnterScope(TreeNode* node, bool* new_context) { |
1899 Fragment instructions; | 1919 Fragment instructions; |
1900 const intptr_t context_size = | 1920 const intptr_t context_size = |
(...skipping 760 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2661 stack_->definition()->set_ssa_temp_index(0); | 2681 stack_->definition()->set_ssa_temp_index(0); |
2662 | 2682 |
2663 return variable; | 2683 return variable; |
2664 } | 2684 } |
2665 | 2685 |
2666 | 2686 |
2667 intptr_t FlowGraphBuilder::CurrentTryIndex() { | 2687 intptr_t FlowGraphBuilder::CurrentTryIndex() { |
2668 if (try_catch_block_ == NULL) { | 2688 if (try_catch_block_ == NULL) { |
2669 return CatchClauseNode::kInvalidTryIndex; | 2689 return CatchClauseNode::kInvalidTryIndex; |
2670 } else { | 2690 } else { |
2671 return try_catch_block_->TryIndex(); | 2691 return try_catch_block_->try_index(); |
2672 } | 2692 } |
2673 } | 2693 } |
2674 | 2694 |
2675 | 2695 |
2676 dart::LocalVariable* FlowGraphBuilder::LookupVariable( | 2696 dart::LocalVariable* FlowGraphBuilder::LookupVariable( |
2677 VariableDeclaration* var) { | 2697 VariableDeclaration* var) { |
2678 LocalVariable* local = scopes_->locals.Lookup(var); | 2698 LocalVariable* local = scopes_->locals.Lookup(var); |
2679 ASSERT(local != NULL); | 2699 ASSERT(local != NULL); |
2680 return local; | 2700 return local; |
2681 } | 2701 } |
(...skipping 2743 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5425 // | 5445 // |
5426 // => We are responsible for catching it, executing the finally block and | 5446 // => We are responsible for catching it, executing the finally block and |
5427 // rethrowing the exception. | 5447 // rethrowing the exception. |
5428 intptr_t try_handler_index = AllocateTryIndex(); | 5448 intptr_t try_handler_index = AllocateTryIndex(); |
5429 Fragment try_body = TryCatch(try_handler_index); | 5449 Fragment try_body = TryCatch(try_handler_index); |
5430 JoinEntryInstr* after_try = BuildJoinEntry(); | 5450 JoinEntryInstr* after_try = BuildJoinEntry(); |
5431 | 5451 |
5432 // Fill in the body of the try. | 5452 // Fill in the body of the try. |
5433 ++try_depth_; | 5453 ++try_depth_; |
5434 { | 5454 { |
| 5455 TryFinallyBlock tfb(this, node->finalizer()); |
5435 TryCatchBlock tcb(this, try_handler_index); | 5456 TryCatchBlock tcb(this, try_handler_index); |
5436 TryFinallyBlock tfb(this, node->finalizer()); | |
5437 try_body += TranslateStatement(node->body()); | 5457 try_body += TranslateStatement(node->body()); |
5438 } | 5458 } |
5439 --try_depth_; | 5459 --try_depth_; |
5440 | 5460 |
5441 if (try_body.is_open()) { | 5461 if (try_body.is_open()) { |
5442 // Please note: The try index will be on level out of this block, | 5462 // Please note: The try index will be on level out of this block, |
5443 // thereby ensuring if there's an exception in the finally block we | 5463 // thereby ensuring if there's an exception in the finally block we |
5444 // won't run it twice. | 5464 // won't run it twice. |
5445 JoinEntryInstr* finally_entry = BuildJoinEntry(); | 5465 JoinEntryInstr* finally_entry = BuildJoinEntry(); |
5446 | 5466 |
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5718 instructions += LoadLocal(closure); | 5738 instructions += LoadLocal(closure); |
5719 instructions += LoadLocal(parsed_function_->current_context_var()); | 5739 instructions += LoadLocal(parsed_function_->current_context_var()); |
5720 instructions += StoreInstanceField(Closure::context_offset()); | 5740 instructions += StoreInstanceField(Closure::context_offset()); |
5721 | 5741 |
5722 return instructions; | 5742 return instructions; |
5723 } | 5743 } |
5724 | 5744 |
5725 | 5745 |
5726 } // namespace kernel | 5746 } // namespace kernel |
5727 } // namespace dart | 5747 } // namespace dart |
OLD | NEW |