| 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/compiler.h" | 7 #include "src/compiler.h" |
| 8 #include "src/compiler/ast-loop-assignment-analyzer.h" | 8 #include "src/compiler/ast-loop-assignment-analyzer.h" |
| 9 #include "src/compiler/control-builders.h" | 9 #include "src/compiler/control-builders.h" |
| 10 #include "src/compiler/linkage.h" | 10 #include "src/compiler/linkage.h" |
| (...skipping 1368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1379 for_loop.BreakWhen(condition); | 1379 for_loop.BreakWhen(condition); |
| 1380 VisitForEffect(stmt->assign_each()); | 1380 VisitForEffect(stmt->assign_each()); |
| 1381 VisitIterationBody(stmt, &for_loop); | 1381 VisitIterationBody(stmt, &for_loop); |
| 1382 for_loop.EndBody(); | 1382 for_loop.EndBody(); |
| 1383 for_loop.EndLoop(); | 1383 for_loop.EndLoop(); |
| 1384 } | 1384 } |
| 1385 | 1385 |
| 1386 | 1386 |
| 1387 void AstGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { | 1387 void AstGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { |
| 1388 TryCatchBuilder try_control(this); | 1388 TryCatchBuilder try_control(this); |
| 1389 ExternalReference message_object = | |
| 1390 ExternalReference::address_of_pending_message_obj(isolate()); | |
| 1391 | 1389 |
| 1392 // Evaluate the try-block inside a control scope. This simulates a handler | 1390 // Evaluate the try-block inside a control scope. This simulates a handler |
| 1393 // that is intercepting 'throw' control commands. | 1391 // that is intercepting 'throw' control commands. |
| 1394 try_control.BeginTry(); | 1392 try_control.BeginTry(); |
| 1395 { | 1393 { |
| 1396 ControlScopeForCatch scope(this, &try_control); | 1394 ControlScopeForCatch scope(this, &try_control); |
| 1397 STATIC_ASSERT(TryBlockConstant::kElementCount == 1); | 1395 STATIC_ASSERT(TryBlockConstant::kElementCount == 1); |
| 1398 environment()->Push(current_context()); | 1396 environment()->Push(current_context()); |
| 1399 Visit(stmt->try_block()); | 1397 Visit(stmt->try_block()); |
| 1400 environment()->Pop(); | 1398 environment()->Pop(); |
| 1401 } | 1399 } |
| 1402 try_control.EndTry(); | 1400 try_control.EndTry(); |
| 1403 | 1401 |
| 1404 // Insert lazy bailout point. | 1402 // Insert lazy bailout point. |
| 1405 // TODO(mstarzinger): We are only using a 'call' to get a lazy bailout | 1403 // TODO(mstarzinger): We are only using a 'call' to get a lazy bailout |
| 1406 // point. Ideally, we whould not re-enter optimized code when deoptimized | 1404 // point. Ideally, we whould not re-enter optimized code when deoptimized |
| 1407 // lazily. Tracked by issue v8:4195. | 1405 // lazily. Tracked by issue v8:4195. |
| 1408 NewNode(common()->LazyBailout(), | 1406 NewNode(common()->LazyBailout(), |
| 1409 jsgraph()->ZeroConstant(), // dummy target. | 1407 jsgraph()->ZeroConstant(), // dummy target. |
| 1410 environment()->Checkpoint(stmt->HandlerId())); // frame state. | 1408 environment()->Checkpoint(stmt->HandlerId())); // frame state. |
| 1411 | 1409 |
| 1412 // Clear message object as we enter the catch block. | 1410 // Clear message object as we enter the catch block. |
| 1413 Node* the_hole = jsgraph()->TheHoleConstant(); | 1411 Node* the_hole = jsgraph()->TheHoleConstant(); |
| 1414 BuildStoreExternal(message_object, kMachAnyTagged, the_hole); | 1412 NewNode(javascript()->StoreMessage(), the_hole); |
| 1415 | 1413 |
| 1416 // Create a catch scope that binds the exception. | 1414 // Create a catch scope that binds the exception. |
| 1417 Node* exception = try_control.GetExceptionNode(); | 1415 Node* exception = try_control.GetExceptionNode(); |
| 1418 Handle<String> name = stmt->variable()->name(); | 1416 Handle<String> name = stmt->variable()->name(); |
| 1419 const Operator* op = javascript()->CreateCatchContext(name); | 1417 const Operator* op = javascript()->CreateCatchContext(name); |
| 1420 Node* context = NewNode(op, exception, GetFunctionClosureForContext()); | 1418 Node* context = NewNode(op, exception, GetFunctionClosureForContext()); |
| 1421 | 1419 |
| 1422 // Evaluate the catch-block. | 1420 // Evaluate the catch-block. |
| 1423 VisitInScope(stmt->catch_block(), stmt->scope(), context); | 1421 VisitInScope(stmt->catch_block(), stmt->scope(), context); |
| 1424 try_control.EndCatch(); | 1422 try_control.EndCatch(); |
| 1425 } | 1423 } |
| 1426 | 1424 |
| 1427 | 1425 |
| 1428 void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) { | 1426 void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) { |
| 1429 TryFinallyBuilder try_control(this); | 1427 TryFinallyBuilder try_control(this); |
| 1430 ExternalReference message_object = | |
| 1431 ExternalReference::address_of_pending_message_obj(isolate()); | |
| 1432 | 1428 |
| 1433 // We keep a record of all paths that enter the finally-block to be able to | 1429 // We keep a record of all paths that enter the finally-block to be able to |
| 1434 // dispatch to the correct continuation point after the statements in the | 1430 // dispatch to the correct continuation point after the statements in the |
| 1435 // finally-block have been evaluated. | 1431 // finally-block have been evaluated. |
| 1436 // | 1432 // |
| 1437 // The try-finally construct can enter the finally-block in three ways: | 1433 // The try-finally construct can enter the finally-block in three ways: |
| 1438 // 1. By exiting the try-block normally, falling through at the end. | 1434 // 1. By exiting the try-block normally, falling through at the end. |
| 1439 // 2. By exiting the try-block with a function-local control flow transfer | 1435 // 2. By exiting the try-block with a function-local control flow transfer |
| 1440 // (i.e. through break/continue/return statements). | 1436 // (i.e. through break/continue/return statements). |
| 1441 // 3. By exiting the try-block with a thrown exception. | 1437 // 3. By exiting the try-block with a thrown exception. |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1466 // The result value semantics depend on how the block was entered: | 1462 // The result value semantics depend on how the block was entered: |
| 1467 // - ReturnStatement: It represents the return value being returned. | 1463 // - ReturnStatement: It represents the return value being returned. |
| 1468 // - ThrowStatement: It represents the exception being thrown. | 1464 // - ThrowStatement: It represents the exception being thrown. |
| 1469 // - BreakStatement/ContinueStatement: Filled with the hole. | 1465 // - BreakStatement/ContinueStatement: Filled with the hole. |
| 1470 // - Falling through into finally-block: Filled with the hole. | 1466 // - Falling through into finally-block: Filled with the hole. |
| 1471 Node* result = try_control.GetResultValueNode(); | 1467 Node* result = try_control.GetResultValueNode(); |
| 1472 Node* token = try_control.GetDispatchTokenNode(); | 1468 Node* token = try_control.GetDispatchTokenNode(); |
| 1473 | 1469 |
| 1474 // The result value, dispatch token and message is expected on the operand | 1470 // The result value, dispatch token and message is expected on the operand |
| 1475 // stack (this is in sync with FullCodeGenerator::EnterFinallyBlock). | 1471 // stack (this is in sync with FullCodeGenerator::EnterFinallyBlock). |
| 1476 Node* message = BuildLoadExternal(message_object, kMachAnyTagged); | 1472 Node* message = NewNode(javascript()->LoadMessage()); |
| 1477 environment()->Push(token); // TODO(mstarzinger): Cook token! | 1473 environment()->Push(token); // TODO(mstarzinger): Cook token! |
| 1478 environment()->Push(result); | 1474 environment()->Push(result); |
| 1479 environment()->Push(message); | 1475 environment()->Push(message); |
| 1480 | 1476 |
| 1481 // Clear message object as we enter the finally block. | 1477 // Clear message object as we enter the finally block. |
| 1482 Node* the_hole = jsgraph()->TheHoleConstant(); | 1478 Node* the_hole = jsgraph()->TheHoleConstant(); |
| 1483 BuildStoreExternal(message_object, kMachAnyTagged, the_hole); | 1479 NewNode(javascript()->StoreMessage(), the_hole); |
| 1484 | 1480 |
| 1485 // Evaluate the finally-block. | 1481 // Evaluate the finally-block. |
| 1486 Visit(stmt->finally_block()); | 1482 Visit(stmt->finally_block()); |
| 1487 try_control.EndFinally(); | 1483 try_control.EndFinally(); |
| 1488 | 1484 |
| 1489 // The result value, dispatch token and message is restored from the operand | 1485 // The result value, dispatch token and message is restored from the operand |
| 1490 // stack (this is in sync with FullCodeGenerator::ExitFinallyBlock). | 1486 // stack (this is in sync with FullCodeGenerator::ExitFinallyBlock). |
| 1491 message = environment()->Pop(); | 1487 message = environment()->Pop(); |
| 1492 result = environment()->Pop(); | 1488 result = environment()->Pop(); |
| 1493 token = environment()->Pop(); // TODO(mstarzinger): Uncook token! | 1489 token = environment()->Pop(); // TODO(mstarzinger): Uncook token! |
| 1494 BuildStoreExternal(message_object, kMachAnyTagged, message); | 1490 NewNode(javascript()->StoreMessage(), message); |
| 1495 | 1491 |
| 1496 // Dynamic dispatch after the finally-block. | 1492 // Dynamic dispatch after the finally-block. |
| 1497 commands->ApplyDeferredCommands(token, result); | 1493 commands->ApplyDeferredCommands(token, result); |
| 1498 | 1494 |
| 1499 // TODO(mstarzinger): Remove bailout once everything works. | 1495 // TODO(mstarzinger): Remove bailout once everything works. |
| 1500 if (!FLAG_turbo_try_finally) SetStackOverflow(); | 1496 if (!FLAG_turbo_try_finally) SetStackOverflow(); |
| 1501 } | 1497 } |
| 1502 | 1498 |
| 1503 | 1499 |
| 1504 void AstGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { | 1500 void AstGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { |
| (...skipping 2166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3671 Node* shared = BuildLoadImmutableObjectField( | 3667 Node* shared = BuildLoadImmutableObjectField( |
| 3672 closure, JSFunction::kSharedFunctionInfoOffset); | 3668 closure, JSFunction::kSharedFunctionInfoOffset); |
| 3673 Node* vector = BuildLoadImmutableObjectField( | 3669 Node* vector = BuildLoadImmutableObjectField( |
| 3674 shared, SharedFunctionInfo::kFeedbackVectorOffset); | 3670 shared, SharedFunctionInfo::kFeedbackVectorOffset); |
| 3675 feedback_vector_.set(vector); | 3671 feedback_vector_.set(vector); |
| 3676 } | 3672 } |
| 3677 return feedback_vector_.get(); | 3673 return feedback_vector_.get(); |
| 3678 } | 3674 } |
| 3679 | 3675 |
| 3680 | 3676 |
| 3681 Node* AstGraphBuilder::BuildLoadExternal(ExternalReference reference, | |
| 3682 MachineType type) { | |
| 3683 return NewNode(jsgraph()->machine()->Load(type), | |
| 3684 jsgraph()->ExternalConstant(reference), | |
| 3685 jsgraph()->IntPtrConstant(0)); | |
| 3686 } | |
| 3687 | |
| 3688 | |
| 3689 Node* AstGraphBuilder::BuildStoreExternal(ExternalReference reference, | |
| 3690 MachineType type, Node* value) { | |
| 3691 StoreRepresentation representation(type, kNoWriteBarrier); | |
| 3692 return NewNode(jsgraph()->machine()->Store(representation), | |
| 3693 jsgraph()->ExternalConstant(reference), | |
| 3694 jsgraph()->IntPtrConstant(0), value); | |
| 3695 } | |
| 3696 | |
| 3697 | |
| 3698 Node* AstGraphBuilder::BuildToBoolean(Node* input) { | 3677 Node* AstGraphBuilder::BuildToBoolean(Node* input) { |
| 3699 if (Node* node = TryFastToBoolean(input)) return node; | 3678 if (Node* node = TryFastToBoolean(input)) return node; |
| 3700 return NewNode(javascript()->ToBoolean(), input); | 3679 return NewNode(javascript()->ToBoolean(), input); |
| 3701 } | 3680 } |
| 3702 | 3681 |
| 3703 | 3682 |
| 3704 Node* AstGraphBuilder::BuildToName(Node* input, BailoutId bailout_id) { | 3683 Node* AstGraphBuilder::BuildToName(Node* input, BailoutId bailout_id) { |
| 3705 if (Node* node = TryFastToName(input)) return node; | 3684 if (Node* node = TryFastToName(input)) return node; |
| 3706 Node* name = NewNode(javascript()->ToName(), input); | 3685 Node* name = NewNode(javascript()->ToName(), input); |
| 3707 PrepareFrameState(name, bailout_id); | 3686 PrepareFrameState(name, bailout_id); |
| (...skipping 617 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4325 // Phi does not exist yet, introduce one. | 4304 // Phi does not exist yet, introduce one. |
| 4326 value = NewPhi(inputs, value, control); | 4305 value = NewPhi(inputs, value, control); |
| 4327 value->ReplaceInput(inputs - 1, other); | 4306 value->ReplaceInput(inputs - 1, other); |
| 4328 } | 4307 } |
| 4329 return value; | 4308 return value; |
| 4330 } | 4309 } |
| 4331 | 4310 |
| 4332 } // namespace compiler | 4311 } // namespace compiler |
| 4333 } // namespace internal | 4312 } // namespace internal |
| 4334 } // namespace v8 | 4313 } // namespace v8 |
| OLD | NEW |