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

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

Issue 17893003: Fix a VM bug in the handling of try/catch/finally. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 5 months 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | runtime/vm/parser.cc » ('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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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/flow_graph_builder.h" 5 #include "vm/flow_graph_builder.h"
6 6
7 #include "lib/invocation_mirror.h" 7 #include "lib/invocation_mirror.h"
8 #include "vm/ast_printer.h" 8 #include "vm/ast_printer.h"
9 #include "vm/bit_vector.h" 9 #include "vm/bit_vector.h"
10 #include "vm/code_descriptors.h" 10 #include "vm/code_descriptors.h"
(...skipping 3226 matching lines...) Expand 10 before | Expand all | Expand 10 after
3237 BuildLoadContext(node->context_var()); 3237 BuildLoadContext(node->context_var());
3238 3238
3239 EffectGraphVisitor for_catch(owner(), temp_index()); 3239 EffectGraphVisitor for_catch(owner(), temp_index());
3240 node->VisitChildren(&for_catch); 3240 node->VisitChildren(&for_catch);
3241 Append(for_catch); 3241 Append(for_catch);
3242 } 3242 }
3243 3243
3244 3244
3245 void EffectGraphVisitor::VisitTryCatchNode(TryCatchNode* node) { 3245 void EffectGraphVisitor::VisitTryCatchNode(TryCatchNode* node) {
3246 InlineBailout("EffectGraphVisitor::VisitTryCatchNode (exception)"); 3246 InlineBailout("EffectGraphVisitor::VisitTryCatchNode (exception)");
3247 intptr_t old_try_index = owner()->try_index(); 3247 intptr_t original_handler_index = owner()->try_index();
Kevin Millikin (Google) 2013/06/26 14:27:04 The name 'try_index' isn't quite right. There can
3248 intptr_t try_index = owner()->AllocateTryIndex(); 3248 intptr_t try_handler_index = owner()->AllocateTryIndex();
3249 owner()->set_try_index(try_index); 3249 owner()->set_try_index(try_handler_index);
3250 3250
3251 // Preserve CTX into local variable '%saved_context'. 3251 // Preserve CTX into local variable '%saved_context'.
3252 BuildStoreContext(node->context_var()); 3252 BuildStoreContext(node->context_var());
3253 3253
3254 EffectGraphVisitor for_try_block(owner(), temp_index()); 3254 EffectGraphVisitor for_try(owner(), temp_index());
3255 node->try_block()->Visit(&for_try_block); 3255 node->try_block()->Visit(&for_try);
3256 3256
3257 if (for_try_block.is_open()) { 3257 if (for_try.is_open()) {
3258 JoinEntryInstr* after_try = 3258 JoinEntryInstr* after_try =
3259 new JoinEntryInstr(owner()->AllocateBlockId(), old_try_index); 3259 new JoinEntryInstr(owner()->AllocateBlockId(), original_handler_index);
3260 for_try_block.Goto(after_try); 3260 for_try.Goto(after_try);
3261 for_try_block.exit_ = after_try; 3261 for_try.exit_ = after_try;
3262 } 3262 }
3263 3263
3264 JoinEntryInstr* try_entry = 3264 JoinEntryInstr* try_entry =
3265 new JoinEntryInstr(owner()->AllocateBlockId(), try_index); 3265 new JoinEntryInstr(owner()->AllocateBlockId(), try_handler_index);
3266 3266
3267 Goto(try_entry); 3267 Goto(try_entry);
3268 AppendFragment(try_entry, for_try_block); 3268 AppendFragment(try_entry, for_try);
3269 exit_ = for_try_block.exit_; 3269 exit_ = for_try.exit_;
3270 3270
3271 // We are done generating code for the try block. 3271 // We are done generating code for the try block.
3272 owner()->set_try_index(old_try_index); 3272 owner()->set_try_index(original_handler_index);
3273 3273
3274 CatchClauseNode* catch_block = node->catch_block(); 3274 CatchClauseNode* catch_block = node->catch_block();
3275 SequenceNode* finally_block = node->finally_block();
3275 if (catch_block != NULL) { 3276 if (catch_block != NULL) {
3276 EffectGraphVisitor for_catch_block(owner(), temp_index()); 3277 // If there is a finally block, it is the handler for code in the catch
3277 catch_block->Visit(&for_catch_block); 3278 // block.
3279 intptr_t catch_handler_index = (finally_block == NULL)
3280 ? original_handler_index
3281 : owner()->AllocateTryIndex();
3282 owner()->set_try_index(catch_handler_index);
3283 EffectGraphVisitor for_catch(owner(), temp_index());
3284 catch_block->Visit(&for_catch);
3278 CatchBlockEntryInstr* catch_entry = 3285 CatchBlockEntryInstr* catch_entry =
3279 new CatchBlockEntryInstr(owner()->AllocateBlockId(), 3286 new CatchBlockEntryInstr(owner()->AllocateBlockId(),
3280 old_try_index, 3287 catch_handler_index,
3281 catch_block->handler_types(), 3288 catch_block->handler_types(),
3282 try_index); 3289 try_handler_index);
3283 owner()->AddCatchEntry(catch_entry); 3290 owner()->AddCatchEntry(catch_entry);
3284 ASSERT(!for_catch_block.is_open()); 3291 ASSERT(!for_catch.is_open());
3285 AppendFragment(catch_entry, for_catch_block); 3292 AppendFragment(catch_entry, for_catch);
3286 if (node->end_catch_label() != NULL) { 3293 if (node->end_catch_label() != NULL) {
3287 JoinEntryInstr* join = node->end_catch_label()->join_for_continue(); 3294 JoinEntryInstr* join = node->end_catch_label()->join_for_continue();
3288 if (join != NULL) { 3295 if (join != NULL) {
3289 if (is_open()) Goto(join); 3296 if (is_open()) Goto(join);
3290 exit_ = join; 3297 exit_ = join;
3291 } 3298 }
3292 } 3299 }
3300
3301 if (finally_block != NULL) {
3302 // Create a handler for the code in the catch block, containing the
3303 // code in the finally block.
3304 owner()->set_try_index(original_handler_index);
3305 EffectGraphVisitor for_finally(owner(), temp_index());
3306 for_finally.AddInstruction(
3307 new CatchEntryInstr(catch_block->exception_var(),
3308 catch_block->stacktrace_var()));
3309 for_finally.BuildLoadContext(catch_block->context_var());
3310
3311 finally_block->Visit(&for_finally);
3312 if (for_finally.is_open()) {
3313 // Rethrow the exception. Manually build the graph for rethrow.
3314 Value* exception = for_finally.Bind(
3315 for_finally.BuildLoadLocal(catch_block->exception_var()));
3316 for_finally.PushArgument(exception);
3317 Value* stacktrace = for_finally.Bind(
3318 for_finally.BuildLoadLocal(catch_block->stacktrace_var()));
3319 for_finally.PushArgument(stacktrace);
3320 for_finally.AddInstruction(new ReThrowInstr(catch_block->token_pos()));
3321 for_finally.CloseFragment();
3322 }
3323 ASSERT(!for_finally.is_open());
3324
3325 const Array& types = Array::ZoneHandle(Array::New(1, Heap::kOld));
3326 types.SetAt(0, Type::Handle(Type::DynamicType()));
3327 CatchBlockEntryInstr* finally_entry =
3328 new CatchBlockEntryInstr(owner()->AllocateBlockId(),
3329 original_handler_index,
3330 types,
3331 catch_handler_index);
3332 owner()->AddCatchEntry(finally_entry);
3333 AppendFragment(finally_entry, for_finally);
3334 }
3293 } 3335 }
3294 3336
3295 // Generate code for the finally block if one exists. 3337 // Generate code for the finally block if one exists.
3296 if ((node->finally_block() != NULL) && is_open()) { 3338 if ((node->finally_block() != NULL) && is_open()) {
Florian Schneider 2013/06/27 14:05:59 s/node->finally_block()/finally_block/
Kevin Millikin (Google) 2013/06/28 11:59:08 Well spotted. Done.
3297 EffectGraphVisitor for_finally_block(owner(), temp_index()); 3339 EffectGraphVisitor for_finally_block(owner(), temp_index());
3298 node->finally_block()->Visit(&for_finally_block); 3340 node->finally_block()->Visit(&for_finally_block);
Florian Schneider 2013/06/27 14:05:59 s/node->finally_block()/finally_block/
3299 Append(for_finally_block); 3341 Append(for_finally_block);
3300 } 3342 }
3301 } 3343 }
3302 3344
3303 3345
3304 // Looks up dynamic method noSuchMethod in target_class 3346 // Looks up dynamic method noSuchMethod in target_class
3305 // (including its super class chain) and builds a static call to it. 3347 // (including its super class chain) and builds a static call to it.
3306 StaticCallInstr* EffectGraphVisitor::BuildStaticNoSuchMethodCall( 3348 StaticCallInstr* EffectGraphVisitor::BuildStaticNoSuchMethodCall(
3307 const Class& target_class, 3349 const Class& target_class,
3308 AstNode* receiver, 3350 AstNode* receiver,
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
3510 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; 3552 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1;
3511 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); 3553 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
3512 OS::SNPrint(chars, len, kFormat, function_name, reason); 3554 OS::SNPrint(chars, len, kFormat, function_name, reason);
3513 const Error& error = Error::Handle( 3555 const Error& error = Error::Handle(
3514 LanguageError::New(String::Handle(String::New(chars)))); 3556 LanguageError::New(String::Handle(String::New(chars))));
3515 Isolate::Current()->long_jump_base()->Jump(1, error); 3557 Isolate::Current()->long_jump_base()->Jump(1, error);
3516 } 3558 }
3517 3559
3518 3560
3519 } // namespace dart 3561 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/parser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698