Chromium Code Reviews

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

Issue 7618007: Simplify handling of exits from with and catch. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fixed bug pointed out in review. Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | | Annotate | Revision Log
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 72 matching lines...)
83 void BreakableStatementChecker::VisitBreakStatement(BreakStatement* stmt) { 83 void BreakableStatementChecker::VisitBreakStatement(BreakStatement* stmt) {
84 } 84 }
85 85
86 86
87 void BreakableStatementChecker::VisitReturnStatement(ReturnStatement* stmt) { 87 void BreakableStatementChecker::VisitReturnStatement(ReturnStatement* stmt) {
88 // Return is breakable if the expression is. 88 // Return is breakable if the expression is.
89 Visit(stmt->expression()); 89 Visit(stmt->expression());
90 } 90 }
91 91
92 92
93 void BreakableStatementChecker::VisitEnterWithContextStatement( 93 void BreakableStatementChecker::VisitWithStatement(WithStatement* stmt) {
94 EnterWithContextStatement* stmt) {
95 Visit(stmt->expression()); 94 Visit(stmt->expression());
96 } 95 }
97 96
98 97
99 void BreakableStatementChecker::VisitExitContextStatement( 98 void BreakableStatementChecker::VisitExitContextStatement(
100 ExitContextStatement* stmt) { 99 ExitContextStatement* stmt) {
101 } 100 }
102 101
103 102
104 void BreakableStatementChecker::VisitSwitchStatement(SwitchStatement* stmt) { 103 void BreakableStatementChecker::VisitSwitchStatement(SwitchStatement* stmt) {
(...skipping 786 matching lines...)
891 __ bind(&done); 890 __ bind(&done);
892 PrepareForBailoutForId(stmt->IfId(), NO_REGISTERS); 891 PrepareForBailoutForId(stmt->IfId(), NO_REGISTERS);
893 } 892 }
894 893
895 894
896 void FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) { 895 void FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
897 Comment cmnt(masm_, "[ ContinueStatement"); 896 Comment cmnt(masm_, "[ ContinueStatement");
898 SetStatementPosition(stmt); 897 SetStatementPosition(stmt);
899 NestedStatement* current = nesting_stack_; 898 NestedStatement* current = nesting_stack_;
900 int stack_depth = 0; 899 int stack_depth = 0;
900 int context_length = 0;
901 // When continuing, we clobber the unpredictable value in the accumulator 901 // When continuing, we clobber the unpredictable value in the accumulator
902 // with one that's safe for GC. If we hit an exit from the try block of 902 // with one that's safe for GC. If we hit an exit from the try block of
903 // try...finally on our way out, we will unconditionally preserve the 903 // try...finally on our way out, we will unconditionally preserve the
904 // accumulator on the stack. 904 // accumulator on the stack.
905 ClearAccumulator(); 905 ClearAccumulator();
906 while (!current->IsContinueTarget(stmt->target())) { 906 while (!current->IsContinueTarget(stmt->target())) {
907 stack_depth = current->Exit(stack_depth); 907 current = current->Exit(&stack_depth, &context_length);
908 current = current->outer();
909 } 908 }
910 __ Drop(stack_depth); 909 __ Drop(stack_depth);
910 if (context_length > 0) {
911 while (context_length > 0) {
912 LoadContextField(context_register(), Context::PREVIOUS_INDEX);
913 --context_length;
914 }
915 StoreToFrameField(StandardFrameConstants::kContextOffset,
916 context_register());
917 }
911 918
912 Iteration* loop = current->AsIteration(); 919 Iteration* loop = current->AsIteration();
913 __ jmp(loop->continue_target()); 920 __ jmp(loop->continue_target());
914 } 921 }
915 922
916 923
917 void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) { 924 void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
918 Comment cmnt(masm_, "[ BreakStatement"); 925 Comment cmnt(masm_, "[ BreakStatement");
919 SetStatementPosition(stmt); 926 SetStatementPosition(stmt);
920 NestedStatement* current = nesting_stack_; 927 NestedStatement* current = nesting_stack_;
921 int stack_depth = 0; 928 int stack_depth = 0;
929 int context_length = 0;
922 // When breaking, we clobber the unpredictable value in the accumulator 930 // When breaking, we clobber the unpredictable value in the accumulator
923 // with one that's safe for GC. If we hit an exit from the try block of 931 // with one that's safe for GC. If we hit an exit from the try block of
924 // try...finally on our way out, we will unconditionally preserve the 932 // try...finally on our way out, we will unconditionally preserve the
925 // accumulator on the stack. 933 // accumulator on the stack.
926 ClearAccumulator(); 934 ClearAccumulator();
927 while (!current->IsBreakTarget(stmt->target())) { 935 while (!current->IsBreakTarget(stmt->target())) {
928 stack_depth = current->Exit(stack_depth); 936 current = current->Exit(&stack_depth, &context_length);
929 current = current->outer();
930 } 937 }
931 __ Drop(stack_depth); 938 __ Drop(stack_depth);
939 if (context_length > 0) {
940 while (context_length > 0) {
941 LoadContextField(context_register(), Context::PREVIOUS_INDEX);
942 --context_length;
943 }
944 StoreToFrameField(StandardFrameConstants::kContextOffset,
945 context_register());
946 }
932 947
933 Breakable* target = current->AsBreakable(); 948 Breakable* target = current->AsBreakable();
934 __ jmp(target->break_target()); 949 __ jmp(target->break_target());
935 } 950 }
936 951
937 952
938 void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { 953 void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
939 Comment cmnt(masm_, "[ ReturnStatement"); 954 Comment cmnt(masm_, "[ ReturnStatement");
940 SetStatementPosition(stmt); 955 SetStatementPosition(stmt);
941 Expression* expr = stmt->expression(); 956 Expression* expr = stmt->expression();
942 VisitForAccumulatorValue(expr); 957 VisitForAccumulatorValue(expr);
943 958
944 // Exit all nested statements. 959 // Exit all nested statements.
945 NestedStatement* current = nesting_stack_; 960 NestedStatement* current = nesting_stack_;
946 int stack_depth = 0; 961 int stack_depth = 0;
962 int context_length = 0;
947 while (current != NULL) { 963 while (current != NULL) {
948 stack_depth = current->Exit(stack_depth); 964 current = current->Exit(&stack_depth, &context_length);
949 current = current->outer();
950 } 965 }
951 __ Drop(stack_depth); 966 __ Drop(stack_depth);
952 967
953 EmitReturnSequence(); 968 EmitReturnSequence();
954 } 969 }
955 970
956 971
957 void FullCodeGenerator::VisitEnterWithContextStatement( 972 void FullCodeGenerator::VisitWithStatement(WithStatement* stmt) {
958 EnterWithContextStatement* stmt) { 973 Comment cmnt(masm_, "[ WithStatement");
959 Comment cmnt(masm_, "[ EnterWithContextStatement");
960 SetStatementPosition(stmt); 974 SetStatementPosition(stmt);
961 975
962 VisitForStackValue(stmt->expression()); 976 VisitForStackValue(stmt->expression());
963 PushFunctionArgumentForContextAllocation(); 977 PushFunctionArgumentForContextAllocation();
964 __ CallRuntime(Runtime::kPushWithContext, 2); 978 __ CallRuntime(Runtime::kPushWithContext, 2);
965 decrement_stack_height(); 979 decrement_stack_height();
966 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); 980 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
981
982 { WithOrCatch body(this);
983 Visit(stmt->statement());
984 }
985
986 // Pop context.
987 LoadContextField(context_register(), Context::PREVIOUS_INDEX);
988 // Update local stack frame context field.
989 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
967 } 990 }
968 991
969 992
970 void FullCodeGenerator::VisitExitContextStatement(ExitContextStatement* stmt) { 993 void FullCodeGenerator::VisitExitContextStatement(ExitContextStatement* stmt) {
971 Comment cmnt(masm_, "[ ExitContextStatement"); 994 Comment cmnt(masm_, "[ ExitContextStatement");
972 SetStatementPosition(stmt); 995 SetStatementPosition(stmt);
973 996
974 // Pop context. 997 // Pop context.
975 LoadContextField(context_register(), Context::PREVIOUS_INDEX); 998 LoadContextField(context_register(), Context::PREVIOUS_INDEX);
976 // Update local stack frame context field. 999 // Update local stack frame context field.
(...skipping 138 matching lines...)
1115 __ push(result_register()); 1138 __ push(result_register());
1116 PushFunctionArgumentForContextAllocation(); 1139 PushFunctionArgumentForContextAllocation();
1117 __ CallRuntime(Runtime::kPushCatchContext, 3); 1140 __ CallRuntime(Runtime::kPushCatchContext, 3);
1118 StoreToFrameField(StandardFrameConstants::kContextOffset, 1141 StoreToFrameField(StandardFrameConstants::kContextOffset,
1119 context_register()); 1142 context_register());
1120 } 1143 }
1121 1144
1122 Scope* saved_scope = scope(); 1145 Scope* saved_scope = scope();
1123 scope_ = stmt->scope(); 1146 scope_ = stmt->scope();
1124 ASSERT(scope_->declarations()->is_empty()); 1147 ASSERT(scope_->declarations()->is_empty());
1125 Visit(stmt->catch_block()); 1148 { WithOrCatch body(this);
1149 Visit(stmt->catch_block());
1150 }
1126 scope_ = saved_scope; 1151 scope_ = saved_scope;
1127 __ jmp(&done); 1152 __ jmp(&done);
1128 1153
1129 // Try block code. Sets up the exception handler chain. 1154 // Try block code. Sets up the exception handler chain.
1130 __ bind(&try_handler_setup); 1155 __ bind(&try_handler_setup);
1131 { 1156 {
1132 TryCatch try_block(this, &catch_entry); 1157 TryCatch try_block(this, &catch_entry);
1133 __ PushTryHandler(IN_JAVASCRIPT, TRY_CATCH_HANDLER); 1158 __ PushTryHandler(IN_JAVASCRIPT, TRY_CATCH_HANDLER);
1134 increment_stack_height(StackHandlerConstants::kSize / kPointerSize); 1159 increment_stack_height(StackHandlerConstants::kSize / kPointerSize);
1135 Visit(stmt->try_block()); 1160 Visit(stmt->try_block());
(...skipping 25 matching lines...)
1161 // 1186 //
1162 // The finally block must assume a return address on top of the stack 1187 // The finally block must assume a return address on top of the stack
1163 // (or in the link register on ARM chips) and a value (return value or 1188 // (or in the link register on ARM chips) and a value (return value or
1164 // exception) in the result register (rax/eax/r0), both of which must 1189 // exception) in the result register (rax/eax/r0), both of which must
1165 // be preserved. The return address isn't GC-safe, so it should be 1190 // be preserved. The return address isn't GC-safe, so it should be
1166 // cooked before GC. 1191 // cooked before GC.
1167 Label finally_entry; 1192 Label finally_entry;
1168 Label try_handler_setup; 1193 Label try_handler_setup;
1169 const int original_stack_height = stack_height(); 1194 const int original_stack_height = stack_height();
1170 const int finally_block_stack_height = original_stack_height + 2; 1195 const int finally_block_stack_height = original_stack_height + 2;
1171 const int try_block_stack_height = original_stack_height + 4; 1196 const int try_block_stack_height = original_stack_height + 5;
1172 STATIC_ASSERT(StackHandlerConstants::kSize / kPointerSize == 4); 1197 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
1173 1198
1174 // Setup the try-handler chain. Use a call to 1199 // Setup the try-handler chain. Use a call to
1175 // Jump to try-handler setup and try-block code. Use call to put try-handler 1200 // Jump to try-handler setup and try-block code. Use call to put try-handler
1176 // address on stack. 1201 // address on stack.
1177 __ Call(&try_handler_setup); 1202 __ Call(&try_handler_setup);
1178 // Try handler code. Return address of call is pushed on handler stack. 1203 // Try handler code. Return address of call is pushed on handler stack.
1179 { 1204 {
1180 // This code is only executed during stack-handler traversal when an 1205 // This code is only executed during stack-handler traversal when an
1181 // exception is thrown. The execption is in the result register, which 1206 // exception is thrown. The execption is in the result register, which
1182 // is retained by the finally block. 1207 // is retained by the finally block.
(...skipping 108 matching lines...)
1291 Comment cmnt(masm_, "[ Throw"); 1316 Comment cmnt(masm_, "[ Throw");
1292 // Throw has no effect on the stack height or the current expression context. 1317 // Throw has no effect on the stack height or the current expression context.
1293 // Usually the expression context is null, because throw is a statement. 1318 // Usually the expression context is null, because throw is a statement.
1294 VisitForStackValue(expr->exception()); 1319 VisitForStackValue(expr->exception());
1295 __ CallRuntime(Runtime::kThrow, 1); 1320 __ CallRuntime(Runtime::kThrow, 1);
1296 decrement_stack_height(); 1321 decrement_stack_height();
1297 // Never returns here. 1322 // Never returns here.
1298 } 1323 }
1299 1324
1300 1325
1301 int FullCodeGenerator::TryFinally::Exit(int stack_depth) { 1326 FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit(
1327 int* stack_depth,
1328 int* context_length) {
1302 // The macros used here must preserve the result register. 1329 // The macros used here must preserve the result register.
1303 __ Drop(stack_depth); 1330 __ Drop(*stack_depth);
1304 __ PopTryHandler(); 1331 __ PopTryHandler();
1332 *stack_depth = 0;
1333
1334 Register context = FullCodeGenerator::context_register();
1335 while (*context_length > 0) {
1336 codegen_->LoadContextField(context, Context::PREVIOUS_INDEX);
1337 --(*context_length);
1338 }
1339
1305 __ Call(finally_entry_); 1340 __ Call(finally_entry_);
1306 return 0; 1341 return previous_;
1307 } 1342 }
1308 1343
1309 1344
1310 int FullCodeGenerator::TryCatch::Exit(int stack_depth) { 1345 FullCodeGenerator::NestedStatement* FullCodeGenerator::TryCatch::Exit(
1346 int* stack_depth,
1347 int* context_length) {
1311 // The macros used here must preserve the result register. 1348 // The macros used here must preserve the result register.
1312 __ Drop(stack_depth); 1349 __ Drop(*stack_depth);
1313 __ PopTryHandler(); 1350 __ PopTryHandler();
1314 return 0; 1351 *stack_depth = 0;
1352 return previous_;
1315 } 1353 }
1316 1354
1317 1355
1318 bool FullCodeGenerator::TryLiteralCompare(CompareOperation* compare, 1356 bool FullCodeGenerator::TryLiteralCompare(CompareOperation* compare,
1319 Label* if_true, 1357 Label* if_true,
1320 Label* if_false, 1358 Label* if_false,
1321 Label* fall_through) { 1359 Label* fall_through) {
1322 Expression *expr; 1360 Expression *expr;
1323 Handle<String> check; 1361 Handle<String> check;
1324 if (compare->IsLiteralCompareTypeof(&expr, &check)) { 1362 if (compare->IsLiteralCompareTypeof(&expr, &check)) {
1325 EmitLiteralCompareTypeof(expr, check, if_true, if_false, fall_through); 1363 EmitLiteralCompareTypeof(expr, check, if_true, if_false, fall_through);
1326 return true; 1364 return true;
1327 } 1365 }
1328 1366
1329 if (compare->IsLiteralCompareUndefined(&expr)) { 1367 if (compare->IsLiteralCompareUndefined(&expr)) {
1330 EmitLiteralCompareUndefined(expr, if_true, if_false, fall_through); 1368 EmitLiteralCompareUndefined(expr, if_true, if_false, fall_through);
1331 return true; 1369 return true;
1332 } 1370 }
1333 1371
1334 return false; 1372 return false;
1335 } 1373 }
1336 1374
1337 1375
1338 #undef __ 1376 #undef __
1339 1377
1340 1378
1341 } } // namespace v8::internal 1379 } } // namespace v8::internal
OLDNEW
« src/arm/macro-assembler-arm.cc ('K') | « src/full-codegen.h ('k') | src/hydrogen.cc » ('j') | no next file with comments »

Powered by Google App Engine