OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/ast-graph-builder.h" | 5 #include "src/compiler/ast-graph-builder.h" |
6 | 6 |
7 #include "src/ast/scopes.h" | 7 #include "src/ast/scopes.h" |
8 #include "src/compiler.h" | 8 #include "src/compiler.h" |
9 #include "src/compiler/ast-loop-assignment-analyzer.h" | 9 #include "src/compiler/ast-loop-assignment-analyzer.h" |
10 #include "src/compiler/control-builders.h" | 10 #include "src/compiler/control-builders.h" |
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
349 | 349 |
350 private: | 350 private: |
351 BreakableStatement* target_; | 351 BreakableStatement* target_; |
352 LoopBuilder* control_; | 352 LoopBuilder* control_; |
353 }; | 353 }; |
354 | 354 |
355 | 355 |
356 // Control scope implementation for a TryCatchStatement. | 356 // Control scope implementation for a TryCatchStatement. |
357 class AstGraphBuilder::ControlScopeForCatch : public ControlScope { | 357 class AstGraphBuilder::ControlScopeForCatch : public ControlScope { |
358 public: | 358 public: |
359 ControlScopeForCatch(AstGraphBuilder* owner, TryCatchBuilder* control) | 359 ControlScopeForCatch(AstGraphBuilder* owner, TryCatchStatement* stmt, |
360 : ControlScope(owner), control_(control) { | 360 TryCatchBuilder* control) |
| 361 : ControlScope(owner), |
| 362 control_(control), |
| 363 outer_prediction_(owner->try_catch_prediction_) { |
361 builder()->try_nesting_level_++; // Increment nesting. | 364 builder()->try_nesting_level_++; // Increment nesting. |
362 builder()->try_catch_nesting_level_++; | 365 builder()->try_catch_prediction_ = stmt->catch_predicted(); |
363 } | 366 } |
364 ~ControlScopeForCatch() { | 367 ~ControlScopeForCatch() { |
365 builder()->try_nesting_level_--; // Decrement nesting. | 368 builder()->try_nesting_level_--; // Decrement nesting. |
366 builder()->try_catch_nesting_level_--; | 369 builder()->try_catch_prediction_ = outer_prediction_; |
367 } | 370 } |
368 | 371 |
369 protected: | 372 protected: |
370 bool Execute(Command cmd, Statement* target, Node* value) override { | 373 bool Execute(Command cmd, Statement* target, Node* value) override { |
371 switch (cmd) { | 374 switch (cmd) { |
372 case CMD_THROW: | 375 case CMD_THROW: |
373 control_->Throw(value); | 376 control_->Throw(value); |
374 return true; | 377 return true; |
375 case CMD_BREAK: | 378 case CMD_BREAK: |
376 case CMD_CONTINUE: | 379 case CMD_CONTINUE: |
377 case CMD_RETURN: | 380 case CMD_RETURN: |
378 break; | 381 break; |
379 } | 382 } |
380 return false; | 383 return false; |
381 } | 384 } |
382 | 385 |
383 private: | 386 private: |
384 TryCatchBuilder* control_; | 387 TryCatchBuilder* control_; |
| 388 bool outer_prediction_; |
385 }; | 389 }; |
386 | 390 |
387 | 391 |
388 // Control scope implementation for a TryFinallyStatement. | 392 // Control scope implementation for a TryFinallyStatement. |
389 class AstGraphBuilder::ControlScopeForFinally : public ControlScope { | 393 class AstGraphBuilder::ControlScopeForFinally : public ControlScope { |
390 public: | 394 public: |
391 ControlScopeForFinally(AstGraphBuilder* owner, DeferredCommands* commands, | 395 ControlScopeForFinally(AstGraphBuilder* owner, TryFinallyStatement* stmt, |
392 TryFinallyBuilder* control) | 396 DeferredCommands* commands, TryFinallyBuilder* control) |
393 : ControlScope(owner), commands_(commands), control_(control) { | 397 : ControlScope(owner), |
| 398 commands_(commands), |
| 399 control_(control), |
| 400 outer_prediction_(owner->try_catch_prediction_) { |
394 builder()->try_nesting_level_++; // Increment nesting. | 401 builder()->try_nesting_level_++; // Increment nesting. |
| 402 builder()->try_catch_prediction_ = stmt->catch_predicted(); |
395 } | 403 } |
396 ~ControlScopeForFinally() { | 404 ~ControlScopeForFinally() { |
397 builder()->try_nesting_level_--; // Decrement nesting. | 405 builder()->try_nesting_level_--; // Decrement nesting. |
| 406 builder()->try_catch_prediction_ = outer_prediction_; |
398 } | 407 } |
399 | 408 |
400 protected: | 409 protected: |
401 bool Execute(Command cmd, Statement* target, Node* value) override { | 410 bool Execute(Command cmd, Statement* target, Node* value) override { |
402 Node* token = commands_->RecordCommand(cmd, target, value); | 411 Node* token = commands_->RecordCommand(cmd, target, value); |
403 control_->LeaveTry(token, value); | 412 control_->LeaveTry(token, value); |
404 return true; | 413 return true; |
405 } | 414 } |
406 | 415 |
407 private: | 416 private: |
408 DeferredCommands* commands_; | 417 DeferredCommands* commands_; |
409 TryFinallyBuilder* control_; | 418 TryFinallyBuilder* control_; |
| 419 bool outer_prediction_; |
410 }; | 420 }; |
411 | 421 |
412 | 422 |
413 // Helper for generating before and after frame states. | 423 // Helper for generating before and after frame states. |
414 class AstGraphBuilder::FrameStateBeforeAndAfter { | 424 class AstGraphBuilder::FrameStateBeforeAndAfter { |
415 public: | 425 public: |
416 FrameStateBeforeAndAfter(AstGraphBuilder* builder, BailoutId id_before) | 426 FrameStateBeforeAndAfter(AstGraphBuilder* builder, BailoutId id_before) |
417 : builder_(builder), frame_state_before_(nullptr) { | 427 : builder_(builder), frame_state_before_(nullptr) { |
418 frame_state_before_ = id_before == BailoutId::None() | 428 frame_state_before_ = id_before == BailoutId::None() |
419 ? builder_->GetEmptyFrameState() | 429 ? builder_->GetEmptyFrameState() |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
456 NodeProperties::GetFrameStateInput(node, 1)->opcode()); | 466 NodeProperties::GetFrameStateInput(node, 1)->opcode()); |
457 NodeProperties::ReplaceFrameStateInput(node, 1, frame_state_before_); | 467 NodeProperties::ReplaceFrameStateInput(node, 1, frame_state_before_); |
458 } | 468 } |
459 } | 469 } |
460 | 470 |
461 private: | 471 private: |
462 AstGraphBuilder* builder_; | 472 AstGraphBuilder* builder_; |
463 Node* frame_state_before_; | 473 Node* frame_state_before_; |
464 }; | 474 }; |
465 | 475 |
466 | |
467 AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info, | 476 AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info, |
468 JSGraph* jsgraph, LoopAssignmentAnalysis* loop, | 477 JSGraph* jsgraph, LoopAssignmentAnalysis* loop, |
469 TypeHintAnalysis* type_hint_analysis) | 478 TypeHintAnalysis* type_hint_analysis) |
470 : isolate_(info->isolate()), | 479 : isolate_(info->isolate()), |
471 local_zone_(local_zone), | 480 local_zone_(local_zone), |
472 info_(info), | 481 info_(info), |
473 jsgraph_(jsgraph), | 482 jsgraph_(jsgraph), |
474 environment_(nullptr), | 483 environment_(nullptr), |
475 ast_context_(nullptr), | 484 ast_context_(nullptr), |
476 globals_(0, local_zone), | 485 globals_(0, local_zone), |
477 execution_control_(nullptr), | 486 execution_control_(nullptr), |
478 execution_context_(nullptr), | 487 execution_context_(nullptr), |
479 try_catch_nesting_level_(0), | |
480 try_nesting_level_(0), | 488 try_nesting_level_(0), |
| 489 try_catch_prediction_(false), |
481 input_buffer_size_(0), | 490 input_buffer_size_(0), |
482 input_buffer_(nullptr), | 491 input_buffer_(nullptr), |
483 exit_controls_(local_zone), | 492 exit_controls_(local_zone), |
484 loop_assignment_analysis_(loop), | 493 loop_assignment_analysis_(loop), |
485 type_hint_analysis_(type_hint_analysis), | 494 type_hint_analysis_(type_hint_analysis), |
486 state_values_cache_(jsgraph), | 495 state_values_cache_(jsgraph), |
487 liveness_analyzer_(static_cast<size_t>(info->scope()->num_stack_slots()), | 496 liveness_analyzer_(static_cast<size_t>(info->scope()->num_stack_slots()), |
488 local_zone), | 497 local_zone), |
489 frame_state_function_info_(common()->CreateFrameStateFunctionInfo( | 498 frame_state_function_info_(common()->CreateFrameStateFunctionInfo( |
490 FrameStateType::kJavaScriptFunction, info->num_parameters() + 1, | 499 FrameStateType::kJavaScriptFunction, info->num_parameters() + 1, |
(...skipping 985 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1476 } | 1485 } |
1477 | 1486 |
1478 | 1487 |
1479 void AstGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { | 1488 void AstGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { |
1480 TryCatchBuilder try_control(this); | 1489 TryCatchBuilder try_control(this); |
1481 | 1490 |
1482 // Evaluate the try-block inside a control scope. This simulates a handler | 1491 // Evaluate the try-block inside a control scope. This simulates a handler |
1483 // that is intercepting 'throw' control commands. | 1492 // that is intercepting 'throw' control commands. |
1484 try_control.BeginTry(); | 1493 try_control.BeginTry(); |
1485 { | 1494 { |
1486 ControlScopeForCatch scope(this, &try_control); | 1495 ControlScopeForCatch scope(this, stmt, &try_control); |
1487 STATIC_ASSERT(TryBlockConstant::kElementCount == 1); | 1496 STATIC_ASSERT(TryBlockConstant::kElementCount == 1); |
1488 environment()->Push(current_context()); | 1497 environment()->Push(current_context()); |
1489 Visit(stmt->try_block()); | 1498 Visit(stmt->try_block()); |
1490 environment()->Pop(); | 1499 environment()->Pop(); |
1491 } | 1500 } |
1492 try_control.EndTry(); | 1501 try_control.EndTry(); |
1493 | 1502 |
1494 // If requested, clear message object as we enter the catch block. | 1503 // If requested, clear message object as we enter the catch block. |
1495 if (stmt->clear_pending_message()) { | 1504 if (stmt->clear_pending_message()) { |
1496 Node* the_hole = jsgraph()->TheHoleConstant(); | 1505 Node* the_hole = jsgraph()->TheHoleConstant(); |
(...skipping 25 matching lines...) Expand all Loading... |
1522 // (i.e. through break/continue/return statements). | 1531 // (i.e. through break/continue/return statements). |
1523 // 3. By exiting the try-block with a thrown exception. | 1532 // 3. By exiting the try-block with a thrown exception. |
1524 Node* fallthrough_result = jsgraph()->TheHoleConstant(); | 1533 Node* fallthrough_result = jsgraph()->TheHoleConstant(); |
1525 ControlScope::DeferredCommands* commands = | 1534 ControlScope::DeferredCommands* commands = |
1526 new (local_zone()) ControlScope::DeferredCommands(this); | 1535 new (local_zone()) ControlScope::DeferredCommands(this); |
1527 | 1536 |
1528 // Evaluate the try-block inside a control scope. This simulates a handler | 1537 // Evaluate the try-block inside a control scope. This simulates a handler |
1529 // that is intercepting all control commands. | 1538 // that is intercepting all control commands. |
1530 try_control.BeginTry(); | 1539 try_control.BeginTry(); |
1531 { | 1540 { |
1532 ControlScopeForFinally scope(this, commands, &try_control); | 1541 ControlScopeForFinally scope(this, stmt, commands, &try_control); |
1533 STATIC_ASSERT(TryBlockConstant::kElementCount == 1); | 1542 STATIC_ASSERT(TryBlockConstant::kElementCount == 1); |
1534 environment()->Push(current_context()); | 1543 environment()->Push(current_context()); |
1535 Visit(stmt->try_block()); | 1544 Visit(stmt->try_block()); |
1536 environment()->Pop(); | 1545 environment()->Pop(); |
1537 } | 1546 } |
1538 try_control.EndTry(commands->GetFallThroughToken(), fallthrough_result); | 1547 try_control.EndTry(commands->GetFallThroughToken(), fallthrough_result); |
1539 | 1548 |
1540 // The result value semantics depend on how the block was entered: | 1549 // The result value semantics depend on how the block was entered: |
1541 // - ReturnStatement: It represents the return value being returned. | 1550 // - ReturnStatement: It represents the return value being returned. |
1542 // - ThrowStatement: It represents the exception being thrown. | 1551 // - ThrowStatement: It represents the exception being thrown. |
(...skipping 2586 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4129 if (NodeProperties::IsControl(result)) { | 4138 if (NodeProperties::IsControl(result)) { |
4130 environment_->UpdateControlDependency(result); | 4139 environment_->UpdateControlDependency(result); |
4131 } | 4140 } |
4132 // Update the current effect dependency for effect-producing nodes. | 4141 // Update the current effect dependency for effect-producing nodes. |
4133 if (result->op()->EffectOutputCount() > 0) { | 4142 if (result->op()->EffectOutputCount() > 0) { |
4134 environment_->UpdateEffectDependency(result); | 4143 environment_->UpdateEffectDependency(result); |
4135 } | 4144 } |
4136 // Add implicit exception continuation for throwing nodes. | 4145 // Add implicit exception continuation for throwing nodes. |
4137 if (!result->op()->HasProperty(Operator::kNoThrow) && inside_try_scope) { | 4146 if (!result->op()->HasProperty(Operator::kNoThrow) && inside_try_scope) { |
4138 // Conservative prediction whether caught locally. | 4147 // Conservative prediction whether caught locally. |
4139 IfExceptionHint hint = try_catch_nesting_level_ > 0 | 4148 IfExceptionHint hint = try_catch_prediction_ |
4140 ? IfExceptionHint::kLocallyCaught | 4149 ? IfExceptionHint::kLocallyCaught |
4141 : IfExceptionHint::kLocallyUncaught; | 4150 : IfExceptionHint::kLocallyUncaught; |
4142 // Copy the environment for the success continuation. | 4151 // Copy the environment for the success continuation. |
4143 Environment* success_env = environment()->CopyForConditional(); | 4152 Environment* success_env = environment()->CopyForConditional(); |
4144 const Operator* op = common()->IfException(hint); | 4153 const Operator* op = common()->IfException(hint); |
4145 Node* effect = environment()->GetEffectDependency(); | 4154 Node* effect = environment()->GetEffectDependency(); |
4146 Node* on_exception = graph()->NewNode(op, effect, result); | 4155 Node* on_exception = graph()->NewNode(op, effect, result); |
4147 environment_->UpdateControlDependency(on_exception); | 4156 environment_->UpdateControlDependency(on_exception); |
4148 environment_->UpdateEffectDependency(on_exception); | 4157 environment_->UpdateEffectDependency(on_exception); |
4149 execution_control()->ThrowValue(on_exception); | 4158 execution_control()->ThrowValue(on_exception); |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4369 // Phi does not exist yet, introduce one. | 4378 // Phi does not exist yet, introduce one. |
4370 value = NewPhi(inputs, value, control); | 4379 value = NewPhi(inputs, value, control); |
4371 value->ReplaceInput(inputs - 1, other); | 4380 value->ReplaceInput(inputs - 1, other); |
4372 } | 4381 } |
4373 return value; | 4382 return value; |
4374 } | 4383 } |
4375 | 4384 |
4376 } // namespace compiler | 4385 } // namespace compiler |
4377 } // namespace internal | 4386 } // namespace internal |
4378 } // namespace v8 | 4387 } // namespace v8 |
OLD | NEW |