OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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/full-codegen/full-codegen.h" | 5 #include "src/full-codegen/full-codegen.h" |
6 | 6 |
7 #include "src/ast/ast.h" | 7 #include "src/ast/ast.h" |
8 #include "src/ast/ast-numbering.h" | 8 #include "src/ast/ast-numbering.h" |
9 #include "src/ast/prettyprinter.h" | 9 #include "src/ast/prettyprinter.h" |
10 #include "src/ast/scopeinfo.h" | 10 #include "src/ast/scopeinfo.h" |
(...skipping 895 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
906 Visit(stmt->then_statement()); | 906 Visit(stmt->then_statement()); |
907 | 907 |
908 PrepareForBailoutForId(stmt->ElseId(), NO_REGISTERS); | 908 PrepareForBailoutForId(stmt->ElseId(), NO_REGISTERS); |
909 } | 909 } |
910 __ bind(&done); | 910 __ bind(&done); |
911 PrepareForBailoutForId(stmt->IfId(), NO_REGISTERS); | 911 PrepareForBailoutForId(stmt->IfId(), NO_REGISTERS); |
912 } | 912 } |
913 | 913 |
914 void FullCodeGenerator::EmitContinue(Statement* target) { | 914 void FullCodeGenerator::EmitContinue(Statement* target) { |
915 NestedStatement* current = nesting_stack_; | 915 NestedStatement* current = nesting_stack_; |
916 int stack_depth = 0; | |
917 int context_length = 0; | 916 int context_length = 0; |
918 // When continuing, we clobber the unpredictable value in the accumulator | 917 // When continuing, we clobber the unpredictable value in the accumulator |
919 // with one that's safe for GC. If we hit an exit from the try block of | 918 // with one that's safe for GC. If we hit an exit from the try block of |
920 // try...finally on our way out, we will unconditionally preserve the | 919 // try...finally on our way out, we will unconditionally preserve the |
921 // accumulator on the stack. | 920 // accumulator on the stack. |
922 ClearAccumulator(); | 921 ClearAccumulator(); |
923 while (!current->IsContinueTarget(target)) { | 922 while (!current->IsContinueTarget(target)) { |
924 if (current->IsTryFinally()) { | 923 if (current->IsTryFinally()) { |
925 Comment cmnt(masm(), "[ Deferred continue through finally"); | 924 Comment cmnt(masm(), "[ Deferred continue through finally"); |
926 current->Exit(&stack_depth, &context_length); | 925 current->Exit(&context_length); |
927 DCHECK_EQ(0, stack_depth); | 926 DCHECK_EQ(-1, context_length); |
928 DCHECK_EQ(0, context_length); | |
929 current->AsTryFinally()->deferred_commands()->RecordContinue(target); | 927 current->AsTryFinally()->deferred_commands()->RecordContinue(target); |
930 return; | 928 return; |
931 } | 929 } |
932 current = current->Exit(&stack_depth, &context_length); | 930 current = current->Exit(&context_length); |
933 } | 931 } |
934 __ Drop(stack_depth); | 932 int stack_depth = current->GetStackDepthAtTarget(); |
| 933 int stack_drop = operand_stack_depth_ - stack_depth; |
| 934 DCHECK_GE(stack_drop, 0); |
| 935 __ Drop(stack_drop); |
935 if (context_length > 0) { | 936 if (context_length > 0) { |
936 while (context_length > 0) { | 937 while (context_length > 0) { |
937 LoadContextField(context_register(), Context::PREVIOUS_INDEX); | 938 LoadContextField(context_register(), Context::PREVIOUS_INDEX); |
938 --context_length; | 939 --context_length; |
939 } | 940 } |
940 StoreToFrameField(StandardFrameConstants::kContextOffset, | 941 StoreToFrameField(StandardFrameConstants::kContextOffset, |
941 context_register()); | 942 context_register()); |
942 } | 943 } |
943 | 944 |
944 __ jmp(current->AsIteration()->continue_label()); | 945 __ jmp(current->AsIteration()->continue_label()); |
945 } | 946 } |
946 | 947 |
947 void FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) { | 948 void FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) { |
948 Comment cmnt(masm_, "[ ContinueStatement"); | 949 Comment cmnt(masm_, "[ ContinueStatement"); |
949 SetStatementPosition(stmt); | 950 SetStatementPosition(stmt); |
950 EmitContinue(stmt->target()); | 951 EmitContinue(stmt->target()); |
951 } | 952 } |
952 | 953 |
953 void FullCodeGenerator::EmitBreak(Statement* target) { | 954 void FullCodeGenerator::EmitBreak(Statement* target) { |
954 NestedStatement* current = nesting_stack_; | 955 NestedStatement* current = nesting_stack_; |
955 int stack_depth = 0; | |
956 int context_length = 0; | 956 int context_length = 0; |
957 // When breaking, we clobber the unpredictable value in the accumulator | 957 // When breaking, we clobber the unpredictable value in the accumulator |
958 // with one that's safe for GC. If we hit an exit from the try block of | 958 // with one that's safe for GC. If we hit an exit from the try block of |
959 // try...finally on our way out, we will unconditionally preserve the | 959 // try...finally on our way out, we will unconditionally preserve the |
960 // accumulator on the stack. | 960 // accumulator on the stack. |
961 ClearAccumulator(); | 961 ClearAccumulator(); |
962 while (!current->IsBreakTarget(target)) { | 962 while (!current->IsBreakTarget(target)) { |
963 if (current->IsTryFinally()) { | 963 if (current->IsTryFinally()) { |
964 Comment cmnt(masm(), "[ Deferred break through finally"); | 964 Comment cmnt(masm(), "[ Deferred break through finally"); |
965 current->Exit(&stack_depth, &context_length); | 965 current->Exit(&context_length); |
966 DCHECK_EQ(0, stack_depth); | 966 DCHECK_EQ(-1, context_length); |
967 DCHECK_EQ(0, context_length); | |
968 current->AsTryFinally()->deferred_commands()->RecordBreak(target); | 967 current->AsTryFinally()->deferred_commands()->RecordBreak(target); |
969 return; | 968 return; |
970 } | 969 } |
971 current = current->Exit(&stack_depth, &context_length); | 970 current = current->Exit(&context_length); |
972 } | 971 } |
973 __ Drop(stack_depth); | 972 int stack_depth = current->GetStackDepthAtTarget(); |
| 973 int stack_drop = operand_stack_depth_ - stack_depth; |
| 974 DCHECK_GE(stack_drop, 0); |
| 975 __ Drop(stack_drop); |
974 if (context_length > 0) { | 976 if (context_length > 0) { |
975 while (context_length > 0) { | 977 while (context_length > 0) { |
976 LoadContextField(context_register(), Context::PREVIOUS_INDEX); | 978 LoadContextField(context_register(), Context::PREVIOUS_INDEX); |
977 --context_length; | 979 --context_length; |
978 } | 980 } |
979 StoreToFrameField(StandardFrameConstants::kContextOffset, | 981 StoreToFrameField(StandardFrameConstants::kContextOffset, |
980 context_register()); | 982 context_register()); |
981 } | 983 } |
982 | 984 |
983 __ jmp(current->AsBreakable()->break_label()); | 985 __ jmp(current->AsBreakable()->break_label()); |
984 } | 986 } |
985 | 987 |
986 void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) { | 988 void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) { |
987 Comment cmnt(masm_, "[ BreakStatement"); | 989 Comment cmnt(masm_, "[ BreakStatement"); |
988 SetStatementPosition(stmt); | 990 SetStatementPosition(stmt); |
989 EmitBreak(stmt->target()); | 991 EmitBreak(stmt->target()); |
990 } | 992 } |
991 | 993 |
992 void FullCodeGenerator::EmitUnwindAndReturn() { | 994 void FullCodeGenerator::EmitUnwindAndReturn() { |
993 NestedStatement* current = nesting_stack_; | 995 NestedStatement* current = nesting_stack_; |
994 int stack_depth = 0; | |
995 int context_length = 0; | 996 int context_length = 0; |
996 while (current != NULL) { | 997 while (current != NULL) { |
997 if (current->IsTryFinally()) { | 998 if (current->IsTryFinally()) { |
998 Comment cmnt(masm(), "[ Deferred return through finally"); | 999 Comment cmnt(masm(), "[ Deferred return through finally"); |
999 current->Exit(&stack_depth, &context_length); | 1000 current->Exit(&context_length); |
1000 DCHECK_EQ(0, stack_depth); | 1001 DCHECK_EQ(-1, context_length); |
1001 DCHECK_EQ(0, context_length); | |
1002 current->AsTryFinally()->deferred_commands()->RecordReturn(); | 1002 current->AsTryFinally()->deferred_commands()->RecordReturn(); |
1003 return; | 1003 return; |
1004 } | 1004 } |
1005 current = current->Exit(&stack_depth, &context_length); | 1005 current = current->Exit(&context_length); |
1006 } | 1006 } |
1007 __ Drop(stack_depth); | |
1008 EmitReturnSequence(); | 1007 EmitReturnSequence(); |
1009 } | 1008 } |
1010 | 1009 |
1011 void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) { | 1010 void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) { |
1012 // Stack: receiver, home_object | 1011 // Stack: receiver, home_object |
1013 SetExpressionPosition(prop); | 1012 SetExpressionPosition(prop); |
1014 Literal* key = prop->key()->AsLiteral(); | 1013 Literal* key = prop->key()->AsLiteral(); |
1015 DCHECK(!key->value()->IsSmi()); | 1014 DCHECK(!key->value()->IsSmi()); |
1016 DCHECK(prop->IsSuperAccess()); | 1015 DCHECK(prop->IsSuperAccess()); |
1017 | 1016 |
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1274 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); | 1273 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); |
1275 scope_ = saved_scope; | 1274 scope_ = saved_scope; |
1276 __ jmp(&exit); | 1275 __ jmp(&exit); |
1277 | 1276 |
1278 // Try block code. Sets up the exception handler chain. | 1277 // Try block code. Sets up the exception handler chain. |
1279 __ bind(&try_entry); | 1278 __ bind(&try_entry); |
1280 | 1279 |
1281 try_catch_depth_++; | 1280 try_catch_depth_++; |
1282 int handler_index = NewHandlerTableEntry(); | 1281 int handler_index = NewHandlerTableEntry(); |
1283 EnterTryBlock(handler_index, &handler_entry); | 1282 EnterTryBlock(handler_index, &handler_entry); |
1284 { TryCatch try_body(this); | 1283 { |
| 1284 Comment cmnt_try(masm(), "[ Try block"); |
1285 Visit(stmt->try_block()); | 1285 Visit(stmt->try_block()); |
1286 } | 1286 } |
1287 ExitTryBlock(handler_index); | 1287 ExitTryBlock(handler_index); |
1288 try_catch_depth_--; | 1288 try_catch_depth_--; |
1289 __ bind(&exit); | 1289 __ bind(&exit); |
1290 } | 1290 } |
1291 | 1291 |
1292 | 1292 |
1293 void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) { | 1293 void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) { |
1294 Comment cmnt(masm_, "[ TryFinallyStatement"); | 1294 Comment cmnt(masm_, "[ TryFinallyStatement"); |
(...skipping 20 matching lines...) Expand all Loading... |
1315 Label try_entry, handler_entry, finally_entry; | 1315 Label try_entry, handler_entry, finally_entry; |
1316 DeferredCommands deferred(this, &finally_entry); | 1316 DeferredCommands deferred(this, &finally_entry); |
1317 | 1317 |
1318 // Jump to try-handler setup and try-block code. | 1318 // Jump to try-handler setup and try-block code. |
1319 __ jmp(&try_entry); | 1319 __ jmp(&try_entry); |
1320 __ bind(&handler_entry); | 1320 __ bind(&handler_entry); |
1321 | 1321 |
1322 // Exception handler code. This code is only executed when an exception | 1322 // Exception handler code. This code is only executed when an exception |
1323 // is thrown. Record the continuation and jump to the finally block. | 1323 // is thrown. Record the continuation and jump to the finally block. |
1324 { | 1324 { |
1325 Comment cmt_handler(masm(), "[ Finally handler"); | 1325 Comment cmnt_handler(masm(), "[ Finally handler"); |
1326 deferred.RecordThrow(); | 1326 deferred.RecordThrow(); |
1327 } | 1327 } |
1328 | 1328 |
1329 // Set up try handler. | 1329 // Set up try handler. |
1330 __ bind(&try_entry); | 1330 __ bind(&try_entry); |
1331 int handler_index = NewHandlerTableEntry(); | 1331 int handler_index = NewHandlerTableEntry(); |
1332 EnterTryBlock(handler_index, &handler_entry); | 1332 EnterTryBlock(handler_index, &handler_entry); |
1333 { | 1333 { |
| 1334 Comment cmnt_try(masm(), "[ Try block"); |
1334 TryFinally try_body(this, &deferred); | 1335 TryFinally try_body(this, &deferred); |
1335 Visit(stmt->try_block()); | 1336 Visit(stmt->try_block()); |
1336 } | 1337 } |
1337 ExitTryBlock(handler_index); | 1338 ExitTryBlock(handler_index); |
1338 // Execute the finally block on the way out. Clobber the unpredictable | 1339 // Execute the finally block on the way out. Clobber the unpredictable |
1339 // value in the result register with one that's safe for GC because the | 1340 // value in the result register with one that's safe for GC because the |
1340 // finally block will unconditionally preserve the result register on the | 1341 // finally block will unconditionally preserve the result register on the |
1341 // stack. | 1342 // stack. |
1342 ClearAccumulator(); | 1343 ClearAccumulator(); |
1343 deferred.EmitFallThrough(); | 1344 deferred.EmitFallThrough(); |
1344 // Fall through to the finally block. | 1345 // Fall through to the finally block. |
1345 | 1346 |
1346 // Finally block implementation. | 1347 // Finally block implementation. |
1347 __ bind(&finally_entry); | 1348 __ bind(&finally_entry); |
1348 Comment cmnt_finally(masm(), "[ Finally block"); | |
1349 OperandStackDepthIncrement(2); // Token and accumulator are on stack. | |
1350 EnterFinallyBlock(); | |
1351 { | 1349 { |
1352 Finally finally_body(this); | 1350 Comment cmnt_finally(masm(), "[ Finally block"); |
| 1351 OperandStackDepthIncrement(2); // Token and accumulator are on stack. |
| 1352 EnterFinallyBlock(); |
1353 Visit(stmt->finally_block()); | 1353 Visit(stmt->finally_block()); |
| 1354 ExitFinallyBlock(); |
| 1355 OperandStackDepthDecrement(2); // Token and accumulator were on stack. |
1354 } | 1356 } |
1355 ExitFinallyBlock(); | |
1356 OperandStackDepthDecrement(2); // Token and accumulator were on stack. | |
1357 | 1357 |
1358 { | 1358 { |
1359 Comment cmnt_deferred(masm(), "[ Post-finally dispatch"); | 1359 Comment cmnt_deferred(masm(), "[ Post-finally dispatch"); |
1360 deferred.EmitCommands(); // Return to the calling code. | 1360 deferred.EmitCommands(); // Return to the calling code. |
1361 } | 1361 } |
1362 } | 1362 } |
1363 | 1363 |
1364 | 1364 |
1365 void FullCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) { | 1365 void FullCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) { |
1366 Comment cmnt(masm_, "[ DebuggerStatement"); | 1366 Comment cmnt(masm_, "[ DebuggerStatement"); |
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1592 | 1592 |
1593 void FullCodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) { | 1593 void FullCodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) { |
1594 UNREACHABLE(); | 1594 UNREACHABLE(); |
1595 } | 1595 } |
1596 | 1596 |
1597 | 1597 |
1598 void FullCodeGenerator::VisitRewritableExpression(RewritableExpression* expr) { | 1598 void FullCodeGenerator::VisitRewritableExpression(RewritableExpression* expr) { |
1599 Visit(expr->expression()); | 1599 Visit(expr->expression()); |
1600 } | 1600 } |
1601 | 1601 |
| 1602 FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit( |
| 1603 int* context_length) { |
| 1604 // The macros used here must preserve the result register. |
1602 | 1605 |
1603 FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit( | 1606 // Calculate how many operands to drop to get down to handler block. |
1604 int* stack_depth, int* context_length) { | 1607 int stack_drop = codegen_->operand_stack_depth_ - GetStackDepthAtTarget(); |
1605 // The macros used here must preserve the result register. | 1608 DCHECK_GE(stack_drop, 0); |
1606 | 1609 |
1607 // Because the handler block contains the context of the finally | 1610 // Because the handler block contains the context of the finally |
1608 // code, we can restore it directly from there for the finally code | 1611 // code, we can restore it directly from there for the finally code |
1609 // rather than iteratively unwinding contexts via their previous | 1612 // rather than iteratively unwinding contexts via their previous |
1610 // links. | 1613 // links. |
1611 if (*context_length > 0) { | 1614 if (*context_length > 0) { |
1612 __ Drop(*stack_depth); // Down to the handler block. | 1615 __ Drop(stack_drop); // Down to the handler block. |
1613 // Restore the context to its dedicated register and the stack. | 1616 // Restore the context to its dedicated register and the stack. |
1614 STATIC_ASSERT(TryFinally::kElementCount == 1); | 1617 STATIC_ASSERT(TryBlockConstant::kElementCount == 1); |
1615 __ Pop(codegen_->context_register()); | 1618 __ Pop(codegen_->context_register()); |
1616 codegen_->StoreToFrameField(StandardFrameConstants::kContextOffset, | 1619 codegen_->StoreToFrameField(StandardFrameConstants::kContextOffset, |
1617 codegen_->context_register()); | 1620 codegen_->context_register()); |
1618 } else { | 1621 } else { |
1619 // Down to the handler block and also drop context. | 1622 // Down to the handler block and also drop context. |
1620 __ Drop(*stack_depth + kElementCount); | 1623 __ Drop(stack_drop + TryBlockConstant::kElementCount); |
1621 } | 1624 } |
1622 *stack_depth = 0; | 1625 |
1623 *context_length = 0; | 1626 // The caller will ignore outputs. |
| 1627 *context_length = -1; |
1624 return previous_; | 1628 return previous_; |
1625 } | 1629 } |
1626 | 1630 |
1627 void FullCodeGenerator::DeferredCommands::RecordBreak(Statement* target) { | 1631 void FullCodeGenerator::DeferredCommands::RecordBreak(Statement* target) { |
1628 TokenId token = dispenser_.GetBreakContinueToken(); | 1632 TokenId token = dispenser_.GetBreakContinueToken(); |
1629 commands_.push_back({kBreak, token, target}); | 1633 commands_.push_back({kBreak, token, target}); |
1630 EmitJumpToFinally(token); | 1634 EmitJumpToFinally(token); |
1631 } | 1635 } |
1632 | 1636 |
1633 void FullCodeGenerator::DeferredCommands::RecordContinue(Statement* target) { | 1637 void FullCodeGenerator::DeferredCommands::RecordContinue(Statement* target) { |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1879 return var->mode() == CONST_LEGACY || var->scope()->is_nonlinear() || | 1883 return var->mode() == CONST_LEGACY || var->scope()->is_nonlinear() || |
1880 var->initializer_position() >= proxy->position(); | 1884 var->initializer_position() >= proxy->position(); |
1881 } | 1885 } |
1882 | 1886 |
1883 | 1887 |
1884 #undef __ | 1888 #undef __ |
1885 | 1889 |
1886 | 1890 |
1887 } // namespace internal | 1891 } // namespace internal |
1888 } // namespace v8 | 1892 } // namespace v8 |
OLD | NEW |