| 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 |