| 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/compile-time-value.h" | 7 #include "src/ast/compile-time-value.h" |
| 8 #include "src/ast/scopes.h" | 8 #include "src/ast/scopes.h" |
| 9 #include "src/compilation-info.h" | 9 #include "src/compilation-info.h" |
| 10 #include "src/compiler.h" | 10 #include "src/compiler.h" |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 158 } | 158 } |
| 159 | 159 |
| 160 // Either 'break' or 'continue' to the target statement. | 160 // Either 'break' or 'continue' to the target statement. |
| 161 void BreakTo(BreakableStatement* target); | 161 void BreakTo(BreakableStatement* target); |
| 162 void ContinueTo(BreakableStatement* target); | 162 void ContinueTo(BreakableStatement* target); |
| 163 | 163 |
| 164 // Either 'return' or 'throw' the given value. | 164 // Either 'return' or 'throw' the given value. |
| 165 void ReturnValue(Node* return_value); | 165 void ReturnValue(Node* return_value); |
| 166 void ThrowValue(Node* exception_value); | 166 void ThrowValue(Node* exception_value); |
| 167 | 167 |
| 168 class DeferredCommands; | |
| 169 | |
| 170 protected: | 168 protected: |
| 171 enum Command { CMD_BREAK, CMD_CONTINUE, CMD_RETURN, CMD_THROW }; | 169 enum Command { CMD_BREAK, CMD_CONTINUE, CMD_RETURN, CMD_THROW }; |
| 172 | 170 |
| 173 // Performs one of the above commands on this stack of control scopes. This | 171 // Performs one of the above commands on this stack of control scopes. This |
| 174 // walks through the stack giving each scope a chance to execute or defer the | 172 // walks through the stack giving each scope a chance to execute or defer the |
| 175 // given command by overriding the {Execute} method appropriately. Note that | 173 // given command by overriding the {Execute} method appropriately. Note that |
| 176 // this also drops extra operands from the environment for each skipped scope. | 174 // this also drops extra operands from the environment for each skipped scope. |
| 177 void PerformCommand(Command cmd, Statement* target, Node* value); | 175 void PerformCommand(Command cmd, Statement* target, Node* value); |
| 178 | 176 |
| 179 // Interface to execute a given command in this scope. Returning {true} here | 177 // Interface to execute a given command in this scope. Returning {true} here |
| (...skipping 19 matching lines...) Expand all Loading... |
| 199 int context_length() const { return context_length_; } | 197 int context_length() const { return context_length_; } |
| 200 int stack_height() const { return stack_height_; } | 198 int stack_height() const { return stack_height_; } |
| 201 | 199 |
| 202 private: | 200 private: |
| 203 AstGraphBuilder* builder_; | 201 AstGraphBuilder* builder_; |
| 204 ControlScope* outer_; | 202 ControlScope* outer_; |
| 205 int context_length_; | 203 int context_length_; |
| 206 int stack_height_; | 204 int stack_height_; |
| 207 }; | 205 }; |
| 208 | 206 |
| 209 // Helper class for a try-finally control scope. It can record intercepted | |
| 210 // control-flow commands that cause entry into a finally-block, and re-apply | |
| 211 // them after again leaving that block. Special tokens are used to identify | |
| 212 // paths going through the finally-block to dispatch after leaving the block. | |
| 213 class AstGraphBuilder::ControlScope::DeferredCommands : public ZoneObject { | |
| 214 public: | |
| 215 explicit DeferredCommands(AstGraphBuilder* owner) | |
| 216 : owner_(owner), | |
| 217 deferred_(owner->local_zone()), | |
| 218 return_token_(nullptr), | |
| 219 throw_token_(nullptr) {} | |
| 220 | |
| 221 // One recorded control-flow command. | |
| 222 struct Entry { | |
| 223 Command command; // The command type being applied on this path. | |
| 224 Statement* statement; // The target statement for the command or {nullptr}. | |
| 225 Node* token; // A token identifying this particular path. | |
| 226 }; | |
| 227 | |
| 228 // Records a control-flow command while entering the finally-block. This also | |
| 229 // generates a new dispatch token that identifies one particular path. | |
| 230 Node* RecordCommand(Command cmd, Statement* stmt, Node* value) { | |
| 231 Node* token = nullptr; | |
| 232 switch (cmd) { | |
| 233 case CMD_BREAK: | |
| 234 case CMD_CONTINUE: | |
| 235 token = NewPathToken(dispenser_.GetBreakContinueToken()); | |
| 236 break; | |
| 237 case CMD_THROW: | |
| 238 if (throw_token_) return throw_token_; | |
| 239 token = NewPathToken(TokenDispenserForFinally::kThrowToken); | |
| 240 throw_token_ = token; | |
| 241 break; | |
| 242 case CMD_RETURN: | |
| 243 if (return_token_) return return_token_; | |
| 244 token = NewPathToken(TokenDispenserForFinally::kReturnToken); | |
| 245 return_token_ = token; | |
| 246 break; | |
| 247 } | |
| 248 DCHECK_NOT_NULL(token); | |
| 249 deferred_.push_back({cmd, stmt, token}); | |
| 250 return token; | |
| 251 } | |
| 252 | |
| 253 // Returns the dispatch token to be used to identify the implicit fall-through | |
| 254 // path at the end of a try-block into the corresponding finally-block. | |
| 255 Node* GetFallThroughToken() { return NewPathTokenForImplicitFallThrough(); } | |
| 256 | |
| 257 // Applies all recorded control-flow commands after the finally-block again. | |
| 258 // This generates a dynamic dispatch on the token from the entry point. | |
| 259 void ApplyDeferredCommands(Node* token, Node* value) { | |
| 260 SwitchBuilder dispatch(owner_, static_cast<int>(deferred_.size())); | |
| 261 dispatch.BeginSwitch(); | |
| 262 for (size_t i = 0; i < deferred_.size(); ++i) { | |
| 263 Node* condition = NewPathDispatchCondition(token, deferred_[i].token); | |
| 264 dispatch.BeginLabel(static_cast<int>(i), condition); | |
| 265 dispatch.EndLabel(); | |
| 266 } | |
| 267 for (size_t i = 0; i < deferred_.size(); ++i) { | |
| 268 dispatch.BeginCase(static_cast<int>(i)); | |
| 269 owner_->execution_control()->PerformCommand( | |
| 270 deferred_[i].command, deferred_[i].statement, value); | |
| 271 dispatch.EndCase(); | |
| 272 } | |
| 273 dispatch.EndSwitch(); | |
| 274 } | |
| 275 | |
| 276 protected: | |
| 277 Node* NewPathToken(int token_id) { | |
| 278 return owner_->jsgraph()->Constant(token_id); | |
| 279 } | |
| 280 Node* NewPathTokenForImplicitFallThrough() { | |
| 281 return NewPathToken(TokenDispenserForFinally::kFallThroughToken); | |
| 282 } | |
| 283 Node* NewPathDispatchCondition(Node* t1, Node* t2) { | |
| 284 return owner_->NewNode( | |
| 285 owner_->javascript()->StrictEqual(CompareOperationHint::kAny), t1, t2); | |
| 286 } | |
| 287 | |
| 288 private: | |
| 289 TokenDispenserForFinally dispenser_; | |
| 290 AstGraphBuilder* owner_; | |
| 291 ZoneVector<Entry> deferred_; | |
| 292 Node* return_token_; | |
| 293 Node* throw_token_; | |
| 294 }; | |
| 295 | |
| 296 | 207 |
| 297 // Control scope implementation for a BreakableStatement. | 208 // Control scope implementation for a BreakableStatement. |
| 298 class AstGraphBuilder::ControlScopeForBreakable : public ControlScope { | 209 class AstGraphBuilder::ControlScopeForBreakable : public ControlScope { |
| 299 public: | 210 public: |
| 300 ControlScopeForBreakable(AstGraphBuilder* owner, BreakableStatement* target, | 211 ControlScopeForBreakable(AstGraphBuilder* owner, BreakableStatement* target, |
| 301 ControlBuilder* control) | 212 ControlBuilder* control) |
| 302 : ControlScope(owner), target_(target), control_(control) {} | 213 : ControlScope(owner), target_(target), control_(control) {} |
| 303 | 214 |
| 304 protected: | 215 protected: |
| 305 bool Execute(Command cmd, Statement* target, Node** value) override { | 216 bool Execute(Command cmd, Statement* target, Node** value) override { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 348 } | 259 } |
| 349 return false; | 260 return false; |
| 350 } | 261 } |
| 351 | 262 |
| 352 private: | 263 private: |
| 353 BreakableStatement* target_; | 264 BreakableStatement* target_; |
| 354 LoopBuilder* control_; | 265 LoopBuilder* control_; |
| 355 }; | 266 }; |
| 356 | 267 |
| 357 | 268 |
| 358 // Control scope implementation for a TryCatchStatement. | |
| 359 class AstGraphBuilder::ControlScopeForCatch : public ControlScope { | |
| 360 public: | |
| 361 ControlScopeForCatch(AstGraphBuilder* owner, TryCatchStatement* stmt, | |
| 362 TryCatchBuilder* control) | |
| 363 : ControlScope(owner), control_(control) { | |
| 364 builder()->try_nesting_level_++; // Increment nesting. | |
| 365 } | |
| 366 ~ControlScopeForCatch() { | |
| 367 builder()->try_nesting_level_--; // Decrement nesting. | |
| 368 } | |
| 369 | |
| 370 protected: | |
| 371 bool Execute(Command cmd, Statement* target, Node** value) override { | |
| 372 switch (cmd) { | |
| 373 case CMD_THROW: | |
| 374 control_->Throw(*value); | |
| 375 return true; | |
| 376 case CMD_BREAK: | |
| 377 case CMD_CONTINUE: | |
| 378 case CMD_RETURN: | |
| 379 break; | |
| 380 } | |
| 381 return false; | |
| 382 } | |
| 383 | |
| 384 private: | |
| 385 TryCatchBuilder* control_; | |
| 386 }; | |
| 387 | |
| 388 | |
| 389 // Control scope implementation for a TryFinallyStatement. | |
| 390 class AstGraphBuilder::ControlScopeForFinally : public ControlScope { | |
| 391 public: | |
| 392 ControlScopeForFinally(AstGraphBuilder* owner, TryFinallyStatement* stmt, | |
| 393 DeferredCommands* commands, TryFinallyBuilder* control) | |
| 394 : ControlScope(owner), commands_(commands), control_(control) { | |
| 395 builder()->try_nesting_level_++; // Increment nesting. | |
| 396 } | |
| 397 ~ControlScopeForFinally() { | |
| 398 builder()->try_nesting_level_--; // Decrement nesting. | |
| 399 } | |
| 400 | |
| 401 protected: | |
| 402 bool Execute(Command cmd, Statement* target, Node** value) override { | |
| 403 Node* token = commands_->RecordCommand(cmd, target, *value); | |
| 404 control_->LeaveTry(token, *value); | |
| 405 return true; | |
| 406 } | |
| 407 | |
| 408 private: | |
| 409 DeferredCommands* commands_; | |
| 410 TryFinallyBuilder* control_; | |
| 411 }; | |
| 412 | |
| 413 AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info, | 269 AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info, |
| 414 JSGraph* jsgraph, float invocation_frequency, | 270 JSGraph* jsgraph, float invocation_frequency, |
| 415 LoopAssignmentAnalysis* loop) | 271 LoopAssignmentAnalysis* loop) |
| 416 : isolate_(info->isolate()), | 272 : isolate_(info->isolate()), |
| 417 local_zone_(local_zone), | 273 local_zone_(local_zone), |
| 418 info_(info), | 274 info_(info), |
| 419 jsgraph_(jsgraph), | 275 jsgraph_(jsgraph), |
| 420 invocation_frequency_(invocation_frequency), | 276 invocation_frequency_(invocation_frequency), |
| 421 environment_(nullptr), | 277 environment_(nullptr), |
| 422 ast_context_(nullptr), | 278 ast_context_(nullptr), |
| 423 globals_(0, local_zone), | 279 globals_(0, local_zone), |
| 424 execution_control_(nullptr), | 280 execution_control_(nullptr), |
| 425 execution_context_(nullptr), | 281 execution_context_(nullptr), |
| 426 try_nesting_level_(0), | |
| 427 input_buffer_size_(0), | 282 input_buffer_size_(0), |
| 428 input_buffer_(nullptr), | 283 input_buffer_(nullptr), |
| 429 exit_controls_(local_zone), | 284 exit_controls_(local_zone), |
| 430 loop_assignment_analysis_(loop), | 285 loop_assignment_analysis_(loop), |
| 431 state_values_cache_(jsgraph), | 286 state_values_cache_(jsgraph), |
| 432 liveness_analyzer_(static_cast<size_t>(info->scope()->num_stack_slots()), | 287 liveness_analyzer_(static_cast<size_t>(info->scope()->num_stack_slots()), |
| 433 false, local_zone), | 288 false, local_zone), |
| 434 frame_state_function_info_(common()->CreateFrameStateFunctionInfo( | 289 frame_state_function_info_(common()->CreateFrameStateFunctionInfo( |
| 435 FrameStateType::kJavaScriptFunction, info->num_parameters() + 1, | 290 FrameStateType::kJavaScriptFunction, info->num_parameters() + 1, |
| 436 info->scope()->num_stack_slots(), info->shared_info())) { | 291 info->scope()->num_stack_slots(), info->shared_info())) { |
| (...skipping 1014 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1451 Node* condition = environment()->Pop(); | 1306 Node* condition = environment()->Pop(); |
| 1452 for_loop.BreakWhen(condition); | 1307 for_loop.BreakWhen(condition); |
| 1453 VisitForEffect(stmt->assign_each()); | 1308 VisitForEffect(stmt->assign_each()); |
| 1454 VisitIterationBody(stmt, &for_loop, stmt->StackCheckId()); | 1309 VisitIterationBody(stmt, &for_loop, stmt->StackCheckId()); |
| 1455 for_loop.EndBody(); | 1310 for_loop.EndBody(); |
| 1456 for_loop.EndLoop(); | 1311 for_loop.EndLoop(); |
| 1457 } | 1312 } |
| 1458 | 1313 |
| 1459 | 1314 |
| 1460 void AstGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { | 1315 void AstGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { |
| 1461 TryCatchBuilder try_control(this); | 1316 // Exception handling is supported only by going through Ignition first. |
| 1462 | 1317 UNREACHABLE(); |
| 1463 // Evaluate the try-block inside a control scope. This simulates a handler | |
| 1464 // that is intercepting 'throw' control commands. | |
| 1465 try_control.BeginTry(); | |
| 1466 { | |
| 1467 ControlScopeForCatch scope(this, stmt, &try_control); | |
| 1468 STATIC_ASSERT(TryBlockConstant::kElementCount == 1); | |
| 1469 environment()->Push(current_context()); | |
| 1470 Visit(stmt->try_block()); | |
| 1471 environment()->Pop(); | |
| 1472 } | |
| 1473 try_control.EndTry(); | |
| 1474 | |
| 1475 // If requested, clear message object as we enter the catch block. | |
| 1476 if (stmt->clear_pending_message()) { | |
| 1477 Node* the_hole = jsgraph()->TheHoleConstant(); | |
| 1478 NewNode(javascript()->StoreMessage(), the_hole); | |
| 1479 } | |
| 1480 | |
| 1481 // Create a catch scope that binds the exception. | |
| 1482 Node* exception = try_control.GetExceptionNode(); | |
| 1483 Handle<String> name = stmt->variable()->name(); | |
| 1484 Handle<ScopeInfo> scope_info = stmt->scope()->scope_info(); | |
| 1485 const Operator* op = javascript()->CreateCatchContext(name, scope_info); | |
| 1486 Node* context = NewNode(op, exception, GetFunctionClosureForContext()); | |
| 1487 | |
| 1488 // Evaluate the catch-block. | |
| 1489 VisitInScope(stmt->catch_block(), stmt->scope(), context); | |
| 1490 try_control.EndCatch(); | |
| 1491 } | 1318 } |
| 1492 | 1319 |
| 1493 | 1320 |
| 1494 void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) { | 1321 void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) { |
| 1495 TryFinallyBuilder try_control(this); | 1322 // Exception handling is supported only by going through Ignition first. |
| 1496 | 1323 UNREACHABLE(); |
| 1497 // We keep a record of all paths that enter the finally-block to be able to | |
| 1498 // dispatch to the correct continuation point after the statements in the | |
| 1499 // finally-block have been evaluated. | |
| 1500 // | |
| 1501 // The try-finally construct can enter the finally-block in three ways: | |
| 1502 // 1. By exiting the try-block normally, falling through at the end. | |
| 1503 // 2. By exiting the try-block with a function-local control flow transfer | |
| 1504 // (i.e. through break/continue/return statements). | |
| 1505 // 3. By exiting the try-block with a thrown exception. | |
| 1506 Node* fallthrough_result = jsgraph()->TheHoleConstant(); | |
| 1507 ControlScope::DeferredCommands* commands = | |
| 1508 new (local_zone()) ControlScope::DeferredCommands(this); | |
| 1509 | |
| 1510 // Evaluate the try-block inside a control scope. This simulates a handler | |
| 1511 // that is intercepting all control commands. | |
| 1512 try_control.BeginTry(); | |
| 1513 { | |
| 1514 ControlScopeForFinally scope(this, stmt, commands, &try_control); | |
| 1515 STATIC_ASSERT(TryBlockConstant::kElementCount == 1); | |
| 1516 environment()->Push(current_context()); | |
| 1517 Visit(stmt->try_block()); | |
| 1518 environment()->Pop(); | |
| 1519 } | |
| 1520 try_control.EndTry(commands->GetFallThroughToken(), fallthrough_result); | |
| 1521 | |
| 1522 // The result value semantics depend on how the block was entered: | |
| 1523 // - ReturnStatement: It represents the return value being returned. | |
| 1524 // - ThrowStatement: It represents the exception being thrown. | |
| 1525 // - BreakStatement/ContinueStatement: Filled with the hole. | |
| 1526 // - Falling through into finally-block: Filled with the hole. | |
| 1527 Node* result = try_control.GetResultValueNode(); | |
| 1528 Node* token = try_control.GetDispatchTokenNode(); | |
| 1529 | |
| 1530 // The result value, dispatch token and message is expected on the operand | |
| 1531 // stack (this is in sync with FullCodeGenerator::EnterFinallyBlock). | |
| 1532 Node* message = NewNode(javascript()->LoadMessage()); | |
| 1533 environment()->Push(token); | |
| 1534 environment()->Push(result); | |
| 1535 environment()->Push(message); | |
| 1536 | |
| 1537 // Clear message object as we enter the finally block. | |
| 1538 Node* the_hole = jsgraph()->TheHoleConstant(); | |
| 1539 NewNode(javascript()->StoreMessage(), the_hole); | |
| 1540 | |
| 1541 // Evaluate the finally-block. | |
| 1542 Visit(stmt->finally_block()); | |
| 1543 try_control.EndFinally(); | |
| 1544 | |
| 1545 // The result value, dispatch token and message is restored from the operand | |
| 1546 // stack (this is in sync with FullCodeGenerator::ExitFinallyBlock). | |
| 1547 message = environment()->Pop(); | |
| 1548 result = environment()->Pop(); | |
| 1549 token = environment()->Pop(); | |
| 1550 NewNode(javascript()->StoreMessage(), message); | |
| 1551 | |
| 1552 // Dynamic dispatch after the finally-block. | |
| 1553 commands->ApplyDeferredCommands(token, result); | |
| 1554 } | 1324 } |
| 1555 | 1325 |
| 1556 | 1326 |
| 1557 void AstGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { | 1327 void AstGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { |
| 1558 Node* node = | 1328 Node* node = |
| 1559 NewNode(javascript()->CallRuntime(Runtime::kHandleDebuggerStatement)); | 1329 NewNode(javascript()->CallRuntime(Runtime::kHandleDebuggerStatement)); |
| 1560 PrepareFrameState(node, stmt->DebugBreakId()); | 1330 PrepareFrameState(node, stmt->DebugBreakId()); |
| 1561 environment()->MarkAllLocalsLive(); | 1331 environment()->MarkAllLocalsLive(); |
| 1562 } | 1332 } |
| 1563 | 1333 |
| (...skipping 2480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4044 bool has_control = op->ControlInputCount() == 1; | 3814 bool has_control = op->ControlInputCount() == 1; |
| 4045 bool has_effect = op->EffectInputCount() == 1; | 3815 bool has_effect = op->EffectInputCount() == 1; |
| 4046 | 3816 |
| 4047 DCHECK(op->ControlInputCount() < 2); | 3817 DCHECK(op->ControlInputCount() < 2); |
| 4048 DCHECK(op->EffectInputCount() < 2); | 3818 DCHECK(op->EffectInputCount() < 2); |
| 4049 | 3819 |
| 4050 Node* result = nullptr; | 3820 Node* result = nullptr; |
| 4051 if (!has_context && !has_frame_state && !has_control && !has_effect) { | 3821 if (!has_context && !has_frame_state && !has_control && !has_effect) { |
| 4052 result = graph()->NewNode(op, value_input_count, value_inputs, incomplete); | 3822 result = graph()->NewNode(op, value_input_count, value_inputs, incomplete); |
| 4053 } else { | 3823 } else { |
| 4054 bool inside_try_scope = try_nesting_level_ > 0; | |
| 4055 int input_count_with_deps = value_input_count; | 3824 int input_count_with_deps = value_input_count; |
| 4056 if (has_context) ++input_count_with_deps; | 3825 if (has_context) ++input_count_with_deps; |
| 4057 if (has_frame_state) ++input_count_with_deps; | 3826 if (has_frame_state) ++input_count_with_deps; |
| 4058 if (has_control) ++input_count_with_deps; | 3827 if (has_control) ++input_count_with_deps; |
| 4059 if (has_effect) ++input_count_with_deps; | 3828 if (has_effect) ++input_count_with_deps; |
| 4060 Node** buffer = EnsureInputBufferSize(input_count_with_deps); | 3829 Node** buffer = EnsureInputBufferSize(input_count_with_deps); |
| 4061 memcpy(buffer, value_inputs, kPointerSize * value_input_count); | 3830 memcpy(buffer, value_inputs, kPointerSize * value_input_count); |
| 4062 Node** current_input = buffer + value_input_count; | 3831 Node** current_input = buffer + value_input_count; |
| 4063 if (has_context) { | 3832 if (has_context) { |
| 4064 *current_input++ = current_context(); | 3833 *current_input++ = current_context(); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 4078 result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete); | 3847 result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete); |
| 4079 if (!environment()->IsMarkedAsUnreachable()) { | 3848 if (!environment()->IsMarkedAsUnreachable()) { |
| 4080 // Update the current control dependency for control-producing nodes. | 3849 // Update the current control dependency for control-producing nodes. |
| 4081 if (NodeProperties::IsControl(result)) { | 3850 if (NodeProperties::IsControl(result)) { |
| 4082 environment_->UpdateControlDependency(result); | 3851 environment_->UpdateControlDependency(result); |
| 4083 } | 3852 } |
| 4084 // Update the current effect dependency for effect-producing nodes. | 3853 // Update the current effect dependency for effect-producing nodes. |
| 4085 if (result->op()->EffectOutputCount() > 0) { | 3854 if (result->op()->EffectOutputCount() > 0) { |
| 4086 environment_->UpdateEffectDependency(result); | 3855 environment_->UpdateEffectDependency(result); |
| 4087 } | 3856 } |
| 4088 // Add implicit exception continuation for throwing nodes. | |
| 4089 if (!result->op()->HasProperty(Operator::kNoThrow) && inside_try_scope) { | |
| 4090 // Copy the environment for the success continuation. | |
| 4091 Environment* success_env = environment()->CopyForConditional(); | |
| 4092 const Operator* op = common()->IfException(); | |
| 4093 Node* effect = environment()->GetEffectDependency(); | |
| 4094 Node* on_exception = graph()->NewNode(op, effect, result); | |
| 4095 environment_->UpdateControlDependency(on_exception); | |
| 4096 environment_->UpdateEffectDependency(on_exception); | |
| 4097 execution_control()->ThrowValue(on_exception); | |
| 4098 set_environment(success_env); | |
| 4099 } | |
| 4100 // Add implicit success continuation for throwing nodes. | 3857 // Add implicit success continuation for throwing nodes. |
| 4101 if (!result->op()->HasProperty(Operator::kNoThrow)) { | 3858 if (!result->op()->HasProperty(Operator::kNoThrow)) { |
| 4102 const Operator* op = common()->IfSuccess(); | 3859 const Operator* op = common()->IfSuccess(); |
| 4103 Node* on_success = graph()->NewNode(op, result); | 3860 Node* on_success = graph()->NewNode(op, result); |
| 4104 environment_->UpdateControlDependency(on_success); | 3861 environment_->UpdateControlDependency(on_success); |
| 4105 } | 3862 } |
| 4106 } | 3863 } |
| 4107 } | 3864 } |
| 4108 | 3865 |
| 4109 return result; | 3866 return result; |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4344 float invocation_frequency, LoopAssignmentAnalysis* loop_assignment, | 4101 float invocation_frequency, LoopAssignmentAnalysis* loop_assignment, |
| 4345 SourcePositionTable* source_positions, int inlining_id) | 4102 SourcePositionTable* source_positions, int inlining_id) |
| 4346 : AstGraphBuilder(local_zone, info, jsgraph, invocation_frequency, | 4103 : AstGraphBuilder(local_zone, info, jsgraph, invocation_frequency, |
| 4347 loop_assignment), | 4104 loop_assignment), |
| 4348 source_positions_(source_positions), | 4105 source_positions_(source_positions), |
| 4349 start_position_(info->shared_info()->start_position(), inlining_id) {} | 4106 start_position_(info->shared_info()->start_position(), inlining_id) {} |
| 4350 | 4107 |
| 4351 } // namespace compiler | 4108 } // namespace compiler |
| 4352 } // namespace internal | 4109 } // namespace internal |
| 4353 } // namespace v8 | 4110 } // namespace v8 |
| OLD | NEW |