Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(169)

Side by Side Diff: runtime/vm/kernel_to_il.cc

Issue 2487183002: VM: [Kernel] Ensure we have the correct try-index when translating finally blocks (Closed)
Patch Set: Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | tests/kernel/unsorted/try_finally_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | tests/kernel/unsorted/try_finally_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698