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 827 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
838 class TryFinallyBlock { | 838 class TryFinallyBlock { |
839 public: | 839 public: |
840 TryFinallyBlock(FlowGraphBuilder* builder, Statement* finalizer) | 840 TryFinallyBlock(FlowGraphBuilder* builder, Statement* finalizer) |
841 : builder_(builder), | 841 : builder_(builder), |
842 outer_(builder->try_finally_block_), | 842 outer_(builder->try_finally_block_), |
843 finalizer_(finalizer), | 843 finalizer_(finalizer), |
844 context_depth_(builder->context_depth_), | 844 context_depth_(builder->context_depth_), |
845 // Finalizers are executed outside of the try block hence | 845 // Finalizers are executed outside of the try block hence |
846 // try depth of finalizers are one less than current try | 846 // try depth of finalizers are one less than current try |
847 // depth. | 847 // depth. |
848 try_depth_(builder->try_depth_ - 1) { | 848 try_depth_(builder->try_depth_ - 1), |
849 try_index_(builder_->CurrentTryIndex()) { | |
849 builder_->try_finally_block_ = this; | 850 builder_->try_finally_block_ = this; |
850 } | 851 } |
851 ~TryFinallyBlock() { builder_->try_finally_block_ = outer_; } | 852 ~TryFinallyBlock() { builder_->try_finally_block_ = outer_; } |
852 | 853 |
853 Statement* finalizer() const { return finalizer_; } | 854 Statement* finalizer() const { return finalizer_; } |
854 intptr_t context_depth() const { return context_depth_; } | 855 intptr_t context_depth() const { return context_depth_; } |
855 intptr_t try_depth() const { return try_depth_; } | 856 intptr_t try_depth() const { return try_depth_; } |
857 intptr_t try_index() const { return try_depth_; } | |
Kevin Millikin (Google)
2016/11/09 12:30:02
return try_index_
kustermann
2016/11/11 19:41:35
Thanks for catching this! I've modified the test t
| |
856 TryFinallyBlock* outer() const { return outer_; } | 858 TryFinallyBlock* outer() const { return outer_; } |
857 | 859 |
858 private: | 860 private: |
859 FlowGraphBuilder* const builder_; | 861 FlowGraphBuilder* const builder_; |
860 TryFinallyBlock* const outer_; | 862 TryFinallyBlock* const outer_; |
861 Statement* const finalizer_; | 863 Statement* const finalizer_; |
862 const intptr_t context_depth_; | 864 const intptr_t context_depth_; |
863 const intptr_t try_depth_; | 865 const intptr_t try_depth_; |
866 const intptr_t try_index_; | |
864 }; | 867 }; |
865 | 868 |
866 | 869 |
867 class TryCatchBlock { | 870 class TryCatchBlock { |
868 public: | 871 public: |
869 explicit TryCatchBlock(FlowGraphBuilder* builder, | 872 explicit TryCatchBlock(FlowGraphBuilder* builder, |
870 intptr_t try_handler_index = -1) | 873 intptr_t try_handler_index = -1) |
871 : builder_(builder), | 874 : builder_(builder), |
872 outer_(builder->try_catch_block_), | 875 outer_(builder->try_catch_block_), |
873 try_index_(try_handler_index) { | 876 try_index_(try_handler_index) { |
874 if (try_index_ == -1) try_index_ = builder->AllocateTryIndex(); | 877 if (try_index_ == -1) try_index_ = builder->AllocateTryIndex(); |
875 builder->try_catch_block_ = this; | 878 builder->try_catch_block_ = this; |
876 } | 879 } |
877 ~TryCatchBlock() { builder_->try_catch_block_ = outer_; } | 880 ~TryCatchBlock() { builder_->try_catch_block_ = outer_; } |
878 | 881 |
879 intptr_t TryIndex() { return try_index_; } | 882 intptr_t try_index() { return try_index_; } |
883 TryCatchBlock* outer() const { return outer_; } | |
880 | 884 |
881 private: | 885 private: |
882 FlowGraphBuilder* builder_; | 886 FlowGraphBuilder* builder_; |
883 TryCatchBlock* outer_; | 887 TryCatchBlock* outer_; |
884 intptr_t try_index_; | 888 intptr_t try_index_; |
885 }; | 889 }; |
886 | 890 |
887 | 891 |
888 class CatchBlock { | 892 class CatchBlock { |
889 public: | 893 public: |
(...skipping 947 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1837 constant_evaluator_(this, zone_, &translation_helper_, | 1841 constant_evaluator_(this, zone_, &translation_helper_, |
1838 &type_translator_) {} | 1842 &type_translator_) {} |
1839 | 1843 |
1840 | 1844 |
1841 FlowGraphBuilder::~FlowGraphBuilder() {} | 1845 FlowGraphBuilder::~FlowGraphBuilder() {} |
1842 | 1846 |
1843 | 1847 |
1844 Fragment FlowGraphBuilder::TranslateFinallyFinalizers( | 1848 Fragment FlowGraphBuilder::TranslateFinallyFinalizers( |
1845 TryFinallyBlock* outer_finally, intptr_t target_context_depth) { | 1849 TryFinallyBlock* outer_finally, intptr_t target_context_depth) { |
1846 TryFinallyBlock* const saved_block = try_finally_block_; | 1850 TryFinallyBlock* const saved_block = try_finally_block_; |
1851 TryCatchBlock* const saved_try_catch_block = try_catch_block_; | |
1847 const intptr_t saved_depth = context_depth_; | 1852 const intptr_t saved_depth = context_depth_; |
1848 const intptr_t saved_try_depth = try_depth_; | 1853 const intptr_t saved_try_depth = try_depth_; |
1849 | 1854 |
1850 Fragment instructions; | 1855 Fragment instructions; |
1851 | 1856 |
1852 // While translating the body of a finalizer we need to set the try-finally | 1857 // While translating the body of a finalizer we need to set the try-finally |
1853 // block which is active when translating the body. | 1858 // block which is active when translating the body. |
1854 while (try_finally_block_ != outer_finally) { | 1859 while (try_finally_block_ != outer_finally) { |
1855 // Set correct try depth (in case there are nested try statements). | 1860 // Set correct try depth (in case there are nested try statements). |
1856 try_depth_ = try_finally_block_->try_depth(); | 1861 try_depth_ = try_finally_block_->try_depth(); |
1857 | 1862 |
1858 // Potentially restore the context to what is expected for the finally | 1863 // Potentially restore the context to what is expected for the finally |
1859 // block. | 1864 // block. |
1860 instructions += AdjustContextTo(try_finally_block_->context_depth()); | 1865 instructions += AdjustContextTo(try_finally_block_->context_depth()); |
1861 | 1866 |
1862 Statement* finalizer = try_finally_block_->finalizer(); | 1867 Statement* finalizer = try_finally_block_->finalizer(); |
1863 try_finally_block_ = try_finally_block_->outer(); | 1868 try_finally_block_ = try_finally_block_->outer(); |
1864 | 1869 |
1870 // The to-be-translated finalizer has to have the correct try-index (namely | |
1871 // the one outside the try-finally block). | |
1872 bool changed_try_index = false; | |
1873 intptr_t target_try_index = try_finally_block_ == NULL | |
1874 ? CatchClauseNode::kInvalidTryIndex | |
1875 : try_finally_block_->try_index(); | |
1876 while (CurrentTryIndex() != target_try_index) { | |
1877 try_catch_block_ = try_catch_block_->outer(); | |
1878 changed_try_index = true; | |
1879 } | |
1880 if (changed_try_index) { | |
1881 JoinEntryInstr* entry = BuildJoinEntry(); | |
1882 instructions += Goto(entry); | |
1883 instructions = Fragment(instructions.entry, entry); | |
1884 } | |
1885 | |
1865 // This will potentially have exceptional cases as described in | 1886 // This will potentially have exceptional cases as described in |
1866 // [VisitTryFinally] and will handle them. | 1887 // [VisitTryFinally] and will handle them. |
1867 instructions += TranslateStatement(finalizer); | 1888 instructions += TranslateStatement(finalizer); |
1868 | 1889 |
1869 // We only need to make sure that if the finalizer ended normally, we | 1890 // We only need to make sure that if the finalizer ended normally, we |
1870 // continue towards the next outer try-finally. | 1891 // continue towards the next outer try-finally. |
1871 if (!instructions.is_open()) break; | 1892 if (!instructions.is_open()) break; |
1872 } | 1893 } |
1873 | 1894 |
1874 if (instructions.is_open() && target_context_depth != -1) { | 1895 if (instructions.is_open() && target_context_depth != -1) { |
1875 // A target context depth of -1 indicates that we the code after this | 1896 // A target context depth of -1 indicates that the code after this |
1876 // will not care about the context chain so we can leave it any way we | 1897 // will not care about the context chain so we can leave it any way we |
1877 // want after the last finalizer. That is used when returning. | 1898 // want after the last finalizer. That is used when returning. |
1878 instructions += AdjustContextTo(target_context_depth); | 1899 instructions += AdjustContextTo(target_context_depth); |
1879 } | 1900 } |
1880 | 1901 |
1881 try_finally_block_ = saved_block; | 1902 try_finally_block_ = saved_block; |
1903 try_catch_block_ = saved_try_catch_block; | |
1882 context_depth_ = saved_depth; | 1904 context_depth_ = saved_depth; |
1883 try_depth_ = saved_try_depth; | 1905 try_depth_ = saved_try_depth; |
1884 | 1906 |
1885 return instructions; | 1907 return instructions; |
1886 } | 1908 } |
1887 | 1909 |
1888 | 1910 |
1889 Fragment FlowGraphBuilder::EnterScope(TreeNode* node, bool* new_context) { | 1911 Fragment FlowGraphBuilder::EnterScope(TreeNode* node, bool* new_context) { |
1890 Fragment instructions; | 1912 Fragment instructions; |
1891 const intptr_t context_size = | 1913 const intptr_t context_size = |
(...skipping 760 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2652 stack_->definition()->set_ssa_temp_index(0); | 2674 stack_->definition()->set_ssa_temp_index(0); |
2653 | 2675 |
2654 return variable; | 2676 return variable; |
2655 } | 2677 } |
2656 | 2678 |
2657 | 2679 |
2658 intptr_t FlowGraphBuilder::CurrentTryIndex() { | 2680 intptr_t FlowGraphBuilder::CurrentTryIndex() { |
2659 if (try_catch_block_ == NULL) { | 2681 if (try_catch_block_ == NULL) { |
2660 return CatchClauseNode::kInvalidTryIndex; | 2682 return CatchClauseNode::kInvalidTryIndex; |
2661 } else { | 2683 } else { |
2662 return try_catch_block_->TryIndex(); | 2684 return try_catch_block_->try_index(); |
2663 } | 2685 } |
2664 } | 2686 } |
2665 | 2687 |
2666 | 2688 |
2667 dart::LocalVariable* FlowGraphBuilder::LookupVariable( | 2689 dart::LocalVariable* FlowGraphBuilder::LookupVariable( |
2668 VariableDeclaration* var) { | 2690 VariableDeclaration* var) { |
2669 LocalVariable* local = scopes_->locals.Lookup(var); | 2691 LocalVariable* local = scopes_->locals.Lookup(var); |
2670 ASSERT(local != NULL); | 2692 ASSERT(local != NULL); |
2671 return local; | 2693 return local; |
2672 } | 2694 } |
(...skipping 2740 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5413 // | 5435 // |
5414 // => We are responsible for catching it, executing the finally block and | 5436 // => We are responsible for catching it, executing the finally block and |
5415 // rethrowing the exception. | 5437 // rethrowing the exception. |
5416 intptr_t try_handler_index = AllocateTryIndex(); | 5438 intptr_t try_handler_index = AllocateTryIndex(); |
5417 Fragment try_body = TryCatch(try_handler_index); | 5439 Fragment try_body = TryCatch(try_handler_index); |
5418 JoinEntryInstr* after_try = BuildJoinEntry(); | 5440 JoinEntryInstr* after_try = BuildJoinEntry(); |
5419 | 5441 |
5420 // Fill in the body of the try. | 5442 // Fill in the body of the try. |
5421 ++try_depth_; | 5443 ++try_depth_; |
5422 { | 5444 { |
5445 TryFinallyBlock tfb(this, node->finalizer()); | |
5423 TryCatchBlock tcb(this, try_handler_index); | 5446 TryCatchBlock tcb(this, try_handler_index); |
5424 TryFinallyBlock tfb(this, node->finalizer()); | |
5425 try_body += TranslateStatement(node->body()); | 5447 try_body += TranslateStatement(node->body()); |
5426 } | 5448 } |
5427 --try_depth_; | 5449 --try_depth_; |
5428 | 5450 |
5429 if (try_body.is_open()) { | 5451 if (try_body.is_open()) { |
5430 // Please note: The try index will be on level out of this block, | 5452 // Please note: The try index will be on level out of this block, |
5431 // thereby ensuring if there's an exception in the finally block we | 5453 // thereby ensuring if there's an exception in the finally block we |
5432 // won't run it twice. | 5454 // won't run it twice. |
5433 JoinEntryInstr* finally_entry = BuildJoinEntry(); | 5455 JoinEntryInstr* finally_entry = BuildJoinEntry(); |
5434 | 5456 |
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5706 instructions += LoadLocal(closure); | 5728 instructions += LoadLocal(closure); |
5707 instructions += LoadLocal(parsed_function_->current_context_var()); | 5729 instructions += LoadLocal(parsed_function_->current_context_var()); |
5708 instructions += StoreInstanceField(Closure::context_offset()); | 5730 instructions += StoreInstanceField(Closure::context_offset()); |
5709 | 5731 |
5710 return instructions; | 5732 return instructions; |
5711 } | 5733 } |
5712 | 5734 |
5713 | 5735 |
5714 } // namespace kernel | 5736 } // namespace kernel |
5715 } // namespace dart | 5737 } // namespace dart |
OLD | NEW |