Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(28)

Side by Side Diff: src/full-codegen/full-codegen.cc

Issue 1663323003: [fullcode] Change fullcode to compile finally using the token approach. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Address review comments Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/full-codegen/full-codegen.h ('k') | src/full-codegen/ia32/full-codegen-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 835 matching lines...) Expand 10 before | Expand all | Expand 10 after
846 PrepareForBailoutForId(stmt->ThenId(), NO_REGISTERS); 846 PrepareForBailoutForId(stmt->ThenId(), NO_REGISTERS);
847 __ bind(&then_part); 847 __ bind(&then_part);
848 Visit(stmt->then_statement()); 848 Visit(stmt->then_statement());
849 849
850 PrepareForBailoutForId(stmt->ElseId(), NO_REGISTERS); 850 PrepareForBailoutForId(stmt->ElseId(), NO_REGISTERS);
851 } 851 }
852 __ bind(&done); 852 __ bind(&done);
853 PrepareForBailoutForId(stmt->IfId(), NO_REGISTERS); 853 PrepareForBailoutForId(stmt->IfId(), NO_REGISTERS);
854 } 854 }
855 855
856 856 void FullCodeGenerator::EmitContinue(Statement* target) {
857 void FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
858 Comment cmnt(masm_, "[ ContinueStatement");
859 SetStatementPosition(stmt);
860 NestedStatement* current = nesting_stack_; 857 NestedStatement* current = nesting_stack_;
861 int stack_depth = 0; 858 int stack_depth = 0;
862 int context_length = 0; 859 int context_length = 0;
863 // When continuing, we clobber the unpredictable value in the accumulator 860 // When continuing, we clobber the unpredictable value in the accumulator
864 // with one that's safe for GC. If we hit an exit from the try block of 861 // with one that's safe for GC. If we hit an exit from the try block of
865 // try...finally on our way out, we will unconditionally preserve the 862 // try...finally on our way out, we will unconditionally preserve the
866 // accumulator on the stack. 863 // accumulator on the stack.
867 ClearAccumulator(); 864 ClearAccumulator();
868 while (!current->IsContinueTarget(stmt->target())) { 865 while (!current->IsContinueTarget(target)) {
866 if (current->IsTryFinally()) {
867 Comment cmnt(masm(), "[ Deferred continue through finally");
868 current->Exit(&stack_depth, &context_length);
869 DCHECK_EQ(0, stack_depth);
870 DCHECK_EQ(0, context_length);
871 current->AsTryFinally()->deferred_commands()->RecordContinue(target);
872 return;
873 }
869 current = current->Exit(&stack_depth, &context_length); 874 current = current->Exit(&stack_depth, &context_length);
870 } 875 }
871 __ Drop(stack_depth); 876 __ Drop(stack_depth);
872 if (context_length > 0) { 877 if (context_length > 0) {
873 while (context_length > 0) { 878 while (context_length > 0) {
874 LoadContextField(context_register(), Context::PREVIOUS_INDEX); 879 LoadContextField(context_register(), Context::PREVIOUS_INDEX);
875 --context_length; 880 --context_length;
876 } 881 }
877 StoreToFrameField(StandardFrameConstants::kContextOffset, 882 StoreToFrameField(StandardFrameConstants::kContextOffset,
878 context_register()); 883 context_register());
879 } 884 }
880 885
881 __ jmp(current->AsIteration()->continue_label()); 886 __ jmp(current->AsIteration()->continue_label());
882 } 887 }
883 888
889 void FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
890 Comment cmnt(masm_, "[ ContinueStatement");
891 SetStatementPosition(stmt);
892 EmitContinue(stmt->target());
893 }
884 894
885 void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) { 895 void FullCodeGenerator::EmitBreak(Statement* target) {
886 Comment cmnt(masm_, "[ BreakStatement");
887 SetStatementPosition(stmt);
888 NestedStatement* current = nesting_stack_; 896 NestedStatement* current = nesting_stack_;
889 int stack_depth = 0; 897 int stack_depth = 0;
890 int context_length = 0; 898 int context_length = 0;
891 // When breaking, we clobber the unpredictable value in the accumulator 899 // When breaking, we clobber the unpredictable value in the accumulator
892 // with one that's safe for GC. If we hit an exit from the try block of 900 // with one that's safe for GC. If we hit an exit from the try block of
893 // try...finally on our way out, we will unconditionally preserve the 901 // try...finally on our way out, we will unconditionally preserve the
894 // accumulator on the stack. 902 // accumulator on the stack.
895 ClearAccumulator(); 903 ClearAccumulator();
896 while (!current->IsBreakTarget(stmt->target())) { 904 while (!current->IsBreakTarget(target)) {
905 if (current->IsTryFinally()) {
906 Comment cmnt(masm(), "[ Deferred break through finally");
907 current->Exit(&stack_depth, &context_length);
908 DCHECK_EQ(0, stack_depth);
909 DCHECK_EQ(0, context_length);
910 current->AsTryFinally()->deferred_commands()->RecordBreak(target);
911 return;
912 }
897 current = current->Exit(&stack_depth, &context_length); 913 current = current->Exit(&stack_depth, &context_length);
898 } 914 }
899 __ Drop(stack_depth); 915 __ Drop(stack_depth);
900 if (context_length > 0) { 916 if (context_length > 0) {
901 while (context_length > 0) { 917 while (context_length > 0) {
902 LoadContextField(context_register(), Context::PREVIOUS_INDEX); 918 LoadContextField(context_register(), Context::PREVIOUS_INDEX);
903 --context_length; 919 --context_length;
904 } 920 }
905 StoreToFrameField(StandardFrameConstants::kContextOffset, 921 StoreToFrameField(StandardFrameConstants::kContextOffset,
906 context_register()); 922 context_register());
907 } 923 }
908 924
909 __ jmp(current->AsBreakable()->break_label()); 925 __ jmp(current->AsBreakable()->break_label());
910 } 926 }
911 927
928 void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
929 Comment cmnt(masm_, "[ BreakStatement");
930 SetStatementPosition(stmt);
931 EmitBreak(stmt->target());
932 }
912 933
913 void FullCodeGenerator::EmitUnwindBeforeReturn() { 934 void FullCodeGenerator::EmitUnwindAndReturn() {
914 NestedStatement* current = nesting_stack_; 935 NestedStatement* current = nesting_stack_;
915 int stack_depth = 0; 936 int stack_depth = 0;
916 int context_length = 0; 937 int context_length = 0;
917 while (current != NULL) { 938 while (current != NULL) {
939 if (current->IsTryFinally()) {
940 Comment cmnt(masm(), "[ Deferred return through finally");
941 current->Exit(&stack_depth, &context_length);
942 DCHECK_EQ(0, stack_depth);
943 DCHECK_EQ(0, context_length);
944 current->AsTryFinally()->deferred_commands()->RecordReturn();
945 return;
946 }
918 current = current->Exit(&stack_depth, &context_length); 947 current = current->Exit(&stack_depth, &context_length);
919 } 948 }
920 __ Drop(stack_depth); 949 __ Drop(stack_depth);
950 EmitReturnSequence();
921 } 951 }
922 952
923 953
924 void FullCodeGenerator::EmitPropertyKey(ObjectLiteralProperty* property, 954 void FullCodeGenerator::EmitPropertyKey(ObjectLiteralProperty* property,
925 BailoutId bailout_id) { 955 BailoutId bailout_id) {
926 VisitForStackValue(property->key()); 956 VisitForStackValue(property->key());
927 __ CallRuntime(Runtime::kToName); 957 __ CallRuntime(Runtime::kToName);
928 PrepareForBailoutForId(bailout_id, NO_REGISTERS); 958 PrepareForBailoutForId(bailout_id, NO_REGISTERS);
929 __ Push(result_register()); 959 __ Push(result_register());
930 } 960 }
931 961
932 962
933 void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { 963 void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
934 Comment cmnt(masm_, "[ ReturnStatement"); 964 Comment cmnt(masm_, "[ ReturnStatement");
935 SetStatementPosition(stmt); 965 SetStatementPosition(stmt);
936 Expression* expr = stmt->expression(); 966 Expression* expr = stmt->expression();
937 VisitForAccumulatorValue(expr); 967 VisitForAccumulatorValue(expr);
938 EmitUnwindBeforeReturn(); 968 EmitUnwindAndReturn();
939 EmitReturnSequence();
940 } 969 }
941 970
942 971
943 void FullCodeGenerator::VisitWithStatement(WithStatement* stmt) { 972 void FullCodeGenerator::VisitWithStatement(WithStatement* stmt) {
944 Comment cmnt(masm_, "[ WithStatement"); 973 Comment cmnt(masm_, "[ WithStatement");
945 SetStatementPosition(stmt); 974 SetStatementPosition(stmt);
946 975
947 VisitForAccumulatorValue(stmt->expression()); 976 VisitForAccumulatorValue(stmt->expression());
948 Callable callable = CodeFactory::ToObject(isolate()); 977 Callable callable = CodeFactory::ToObject(isolate());
949 __ Move(callable.descriptor().GetRegisterParameter(0), result_register()); 978 __ Move(callable.descriptor().GetRegisterParameter(0), result_register());
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
1181 1210
1182 1211
1183 void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) { 1212 void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
1184 Comment cmnt(masm_, "[ TryFinallyStatement"); 1213 Comment cmnt(masm_, "[ TryFinallyStatement");
1185 SetStatementPosition(stmt, SKIP_BREAK); 1214 SetStatementPosition(stmt, SKIP_BREAK);
1186 1215
1187 // Try finally is compiled by setting up a try-handler on the stack while 1216 // Try finally is compiled by setting up a try-handler on the stack while
1188 // executing the try body, and removing it again afterwards. 1217 // executing the try body, and removing it again afterwards.
1189 // 1218 //
1190 // The try-finally construct can enter the finally block in three ways: 1219 // The try-finally construct can enter the finally block in three ways:
1191 // 1. By exiting the try-block normally. This removes the try-handler and 1220 // 1. By exiting the try-block normally. This exits the try block,
1192 // calls the finally block code before continuing. 1221 // pushes the continuation token and falls through to the finally
1222 // block.
1193 // 2. By exiting the try-block with a function-local control flow transfer 1223 // 2. By exiting the try-block with a function-local control flow transfer
1194 // (break/continue/return). The site of the, e.g., break removes the 1224 // (break/continue/return). The site of the, e.g., break exits the
1195 // try handler and calls the finally block code before continuing 1225 // try block, pushes the continuation token and jumps to the
1196 // its outward control transfer. 1226 // finally block. After the finally block executes, the execution
1197 // 3. By exiting the try-block with a thrown exception. 1227 // continues based on the continuation token to a block that
1198 // This can happen in nested function calls. It traverses the try-handler 1228 // continues with the control flow transfer.
1199 // chain and consumes the try-handler entry before jumping to the 1229 // 3. By exiting the try-block with a thrown exception. In the handler,
1200 // handler code. The handler code then calls the finally-block before 1230 // we push the exception and continuation token and jump to the
1201 // rethrowing the exception. 1231 // finally block (which will again dispatch based on the token once
1202 // 1232 // it is finished).
1203 // The finally block must assume a return address on top of the stack 1233
1204 // (or in the link register on ARM chips) and a value (return value or
1205 // exception) in the result register (rax/eax/r0), both of which must
1206 // be preserved. The return address isn't GC-safe, so it should be
1207 // cooked before GC.
1208 Label try_entry, handler_entry, finally_entry; 1234 Label try_entry, handler_entry, finally_entry;
1235 DeferredCommands deferred(this, &finally_entry);
1209 1236
1210 // Jump to try-handler setup and try-block code. 1237 // Jump to try-handler setup and try-block code.
1211 __ jmp(&try_entry); 1238 __ jmp(&try_entry);
1212 __ bind(&handler_entry); 1239 __ bind(&handler_entry);
1213 PrepareForBailoutForId(stmt->HandlerId(), NO_REGISTERS); 1240 PrepareForBailoutForId(stmt->HandlerId(), NO_REGISTERS);
1214 1241
1215 // Exception handler code. This code is only executed when an exception 1242 // Exception handler code. This code is only executed when an exception
1216 // is thrown. The exception is in the result register, and must be 1243 // is thrown. Record the continuation and jump to the finally block.
1217 // preserved by the finally block. Call the finally block and then 1244 {
1218 // rethrow the exception if it returns. 1245 Comment cmt_handler(masm(), "[ Finally handler");
1219 __ Call(&finally_entry); 1246 deferred.RecordThrow();
1220 __ Push(result_register());
1221 __ CallRuntime(Runtime::kReThrow);
1222
1223 // Finally block implementation.
1224 __ bind(&finally_entry);
1225 EnterFinallyBlock();
1226 { Finally finally_body(this);
1227 Visit(stmt->finally_block());
1228 } 1247 }
1229 ExitFinallyBlock(); // Return to the calling code.
1230 1248
1231 // Set up try handler. 1249 // Set up try handler.
1232 __ bind(&try_entry); 1250 __ bind(&try_entry);
1233 int handler_index = NewHandlerTableEntry(); 1251 int handler_index = NewHandlerTableEntry();
1234 EnterTryBlock(handler_index, &handler_entry); 1252 EnterTryBlock(handler_index, &handler_entry);
1235 { TryFinally try_body(this, &finally_entry); 1253 {
1254 TryFinally try_body(this, &deferred);
1236 Visit(stmt->try_block()); 1255 Visit(stmt->try_block());
1237 } 1256 }
1238 ExitTryBlock(handler_index); 1257 ExitTryBlock(handler_index);
1239 // Execute the finally block on the way out. Clobber the unpredictable 1258 // Execute the finally block on the way out. Clobber the unpredictable
1240 // value in the result register with one that's safe for GC because the 1259 // value in the result register with one that's safe for GC because the
1241 // finally block will unconditionally preserve the result register on the 1260 // finally block will unconditionally preserve the result register on the
1242 // stack. 1261 // stack.
1243 ClearAccumulator(); 1262 ClearAccumulator();
1244 __ Call(&finally_entry); 1263 deferred.EmitFallThrough();
1264 // Fall through to the finally block.
1265
1266 // Finally block implementation.
1267 __ bind(&finally_entry);
1268 Comment cmnt_finally(masm(), "[ Finally block");
1269 EnterFinallyBlock();
1270 {
1271 Finally finally_body(this);
1272 Visit(stmt->finally_block());
1273 }
1274 ExitFinallyBlock(); // Return to the calling code.
1275
1276 {
1277 Comment cmnt_deferred(masm(), "[ Post-finally dispatch");
1278 deferred.EmitCommands();
1279 }
1245 } 1280 }
1246 1281
1247 1282
1248 void FullCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) { 1283 void FullCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
1249 Comment cmnt(masm_, "[ DebuggerStatement"); 1284 Comment cmnt(masm_, "[ DebuggerStatement");
1250 SetStatementPosition(stmt); 1285 SetStatementPosition(stmt);
1251 1286
1252 __ DebugBreak(); 1287 __ DebugBreak();
1253 // Ignore the return value. 1288 // Ignore the return value.
1254 1289
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
1478 __ Drop(*stack_depth); // Down to the handler block. 1513 __ Drop(*stack_depth); // Down to the handler block.
1479 // Restore the context to its dedicated register and the stack. 1514 // Restore the context to its dedicated register and the stack.
1480 STATIC_ASSERT(TryFinally::kElementCount == 1); 1515 STATIC_ASSERT(TryFinally::kElementCount == 1);
1481 __ Pop(codegen_->context_register()); 1516 __ Pop(codegen_->context_register());
1482 codegen_->StoreToFrameField(StandardFrameConstants::kContextOffset, 1517 codegen_->StoreToFrameField(StandardFrameConstants::kContextOffset,
1483 codegen_->context_register()); 1518 codegen_->context_register());
1484 } else { 1519 } else {
1485 // Down to the handler block and also drop context. 1520 // Down to the handler block and also drop context.
1486 __ Drop(*stack_depth + kElementCount); 1521 __ Drop(*stack_depth + kElementCount);
1487 } 1522 }
1488 __ Call(finally_entry_);
1489
1490 *stack_depth = 0; 1523 *stack_depth = 0;
1491 *context_length = 0; 1524 *context_length = 0;
1492 return previous_; 1525 return previous_;
1493 } 1526 }
1494 1527
1528 void FullCodeGenerator::DeferredCommands::RecordBreak(Statement* target) {
1529 TokenId token = dispenser_.GetBreakContinueToken();
1530 commands_.push_back({kBreak, token, target});
1531 EmitJumpToFinally(token);
1532 }
1533
1534 void FullCodeGenerator::DeferredCommands::RecordContinue(Statement* target) {
1535 TokenId token = dispenser_.GetBreakContinueToken();
1536 commands_.push_back({kContinue, token, target});
1537 EmitJumpToFinally(token);
1538 }
1539
1540 void FullCodeGenerator::DeferredCommands::RecordReturn() {
1541 if (return_token_ == TokenDispenserForFinally::kInvalidToken) {
1542 return_token_ = TokenDispenserForFinally::kReturnToken;
1543 commands_.push_back({kReturn, return_token_, nullptr});
1544 }
1545 EmitJumpToFinally(return_token_);
1546 }
1547
1548 void FullCodeGenerator::DeferredCommands::RecordThrow() {
1549 if (throw_token_ == TokenDispenserForFinally::kInvalidToken) {
1550 throw_token_ = TokenDispenserForFinally::kThrowToken;
1551 commands_.push_back({kThrow, throw_token_, nullptr});
1552 }
1553 EmitJumpToFinally(throw_token_);
1554 }
1555
1556 void FullCodeGenerator::DeferredCommands::EmitFallThrough() {
1557 __ Push(Smi::FromInt(TokenDispenserForFinally::kFallThroughToken));
1558 __ Push(result_register());
1559 }
1560
1561 void FullCodeGenerator::DeferredCommands::EmitJumpToFinally(TokenId token) {
1562 __ Push(Smi::FromInt(token));
1563 __ Push(result_register());
1564 __ jmp(finally_entry_);
1565 }
1495 1566
1496 bool FullCodeGenerator::TryLiteralCompare(CompareOperation* expr) { 1567 bool FullCodeGenerator::TryLiteralCompare(CompareOperation* expr) {
1497 Expression* sub_expr; 1568 Expression* sub_expr;
1498 Handle<String> check; 1569 Handle<String> check;
1499 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) { 1570 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
1500 EmitLiteralCompareTypeof(expr, sub_expr, check); 1571 EmitLiteralCompareTypeof(expr, sub_expr, check);
1501 return true; 1572 return true;
1502 } 1573 }
1503 1574
1504 if (expr->IsLiteralCompareUndefined(&sub_expr, isolate())) { 1575 if (expr->IsLiteralCompareUndefined(&sub_expr, isolate())) {
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
1709 return var->mode() == CONST_LEGACY || var->scope()->is_nonlinear() || 1780 return var->mode() == CONST_LEGACY || var->scope()->is_nonlinear() ||
1710 var->initializer_position() >= proxy->position(); 1781 var->initializer_position() >= proxy->position();
1711 } 1782 }
1712 1783
1713 1784
1714 #undef __ 1785 #undef __
1715 1786
1716 1787
1717 } // namespace internal 1788 } // namespace internal
1718 } // namespace v8 1789 } // namespace v8
OLDNEW
« no previous file with comments | « src/full-codegen/full-codegen.h ('k') | src/full-codegen/ia32/full-codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698