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

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: Created 9 years, 4 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 | 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...) Expand 10 before | Expand all | Expand 10 after
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());
Kevin Millikin (Chromium) 2011/08/11 10:37:18 I'm not sure this is right, I'll check with Soeren
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) {
105 // Switch statements breakable if the tag expression is. 104 // Switch statements breakable if the tag expression is.
(...skipping 787 matching lines...) Expand 10 before | Expand all | Expand 10 after
893 __ bind(&done); 892 __ bind(&done);
894 PrepareForBailoutForId(stmt->IfId(), NO_REGISTERS); 893 PrepareForBailoutForId(stmt->IfId(), NO_REGISTERS);
895 } 894 }
896 895
897 896
898 void FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) { 897 void FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
899 Comment cmnt(masm_, "[ ContinueStatement"); 898 Comment cmnt(masm_, "[ ContinueStatement");
900 SetStatementPosition(stmt); 899 SetStatementPosition(stmt);
901 NestedStatement* current = nesting_stack_; 900 NestedStatement* current = nesting_stack_;
902 int stack_depth = 0; 901 int stack_depth = 0;
902 int context_length = 0;
903 // When continuing, we clobber the unpredictable value in the accumulator 903 // When continuing, we clobber the unpredictable value in the accumulator
904 // with one that's safe for GC. If we hit an exit from the try block of 904 // with one that's safe for GC. If we hit an exit from the try block of
905 // try...finally on our way out, we will unconditionally preserve the 905 // try...finally on our way out, we will unconditionally preserve the
906 // accumulator on the stack. 906 // accumulator on the stack.
907 ClearAccumulator(); 907 ClearAccumulator();
908 while (!current->IsContinueTarget(stmt->target())) { 908 while (!current->IsContinueTarget(stmt->target())) {
909 stack_depth = current->Exit(stack_depth); 909 current = current->Exit(&stack_depth, &context_length);
910 current = current->outer();
911 } 910 }
912 __ Drop(stack_depth); 911 __ Drop(stack_depth);
912 while (context_length > 0) {
913 LoadContextField(context_register(), Context::PREVIOUS_INDEX);
914 --context_length;
915 }
913 916
914 Iteration* loop = current->AsIteration(); 917 Iteration* loop = current->AsIteration();
915 __ jmp(loop->continue_target()); 918 __ jmp(loop->continue_target());
916 } 919 }
917 920
918 921
919 void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) { 922 void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
920 Comment cmnt(masm_, "[ BreakStatement"); 923 Comment cmnt(masm_, "[ BreakStatement");
921 SetStatementPosition(stmt); 924 SetStatementPosition(stmt);
922 NestedStatement* current = nesting_stack_; 925 NestedStatement* current = nesting_stack_;
923 int stack_depth = 0; 926 int stack_depth = 0;
927 int context_length = 0;
924 // When breaking, we clobber the unpredictable value in the accumulator 928 // When breaking, we clobber the unpredictable value in the accumulator
925 // with one that's safe for GC. If we hit an exit from the try block of 929 // with one that's safe for GC. If we hit an exit from the try block of
926 // try...finally on our way out, we will unconditionally preserve the 930 // try...finally on our way out, we will unconditionally preserve the
927 // accumulator on the stack. 931 // accumulator on the stack.
928 ClearAccumulator(); 932 ClearAccumulator();
929 while (!current->IsBreakTarget(stmt->target())) { 933 while (!current->IsBreakTarget(stmt->target())) {
930 stack_depth = current->Exit(stack_depth); 934 current = current->Exit(&stack_depth, &context_length);
931 current = current->outer();
932 } 935 }
933 __ Drop(stack_depth); 936 __ Drop(stack_depth);
937 while (context_length > 0) {
938 LoadContextField(context_register(), Context::PREVIOUS_INDEX);
939 --context_length;
940 }
Vyacheslav Egorov (Chromium) 2011/08/11 11:21:55 Break should also patch context in the stack slot:
Kevin Millikin (Chromium) 2011/08/11 11:30:50 Oops, yes. Good catch.
934 941
935 Breakable* target = current->AsBreakable(); 942 Breakable* target = current->AsBreakable();
936 __ jmp(target->break_target()); 943 __ jmp(target->break_target());
937 } 944 }
938 945
939 946
940 void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { 947 void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
941 Comment cmnt(masm_, "[ ReturnStatement"); 948 Comment cmnt(masm_, "[ ReturnStatement");
942 SetStatementPosition(stmt); 949 SetStatementPosition(stmt);
943 Expression* expr = stmt->expression(); 950 Expression* expr = stmt->expression();
944 VisitForAccumulatorValue(expr); 951 VisitForAccumulatorValue(expr);
945 952
946 // Exit all nested statements. 953 // Exit all nested statements.
947 NestedStatement* current = nesting_stack_; 954 NestedStatement* current = nesting_stack_;
948 int stack_depth = 0; 955 int stack_depth = 0;
956 int context_length = 0;
949 while (current != NULL) { 957 while (current != NULL) {
950 stack_depth = current->Exit(stack_depth); 958 current = current->Exit(&stack_depth, &context_length);
951 current = current->outer();
952 } 959 }
953 __ Drop(stack_depth); 960 __ Drop(stack_depth);
954 961
955 EmitReturnSequence(); 962 EmitReturnSequence();
956 } 963 }
957 964
958 965
959 void FullCodeGenerator::VisitEnterWithContextStatement( 966 void FullCodeGenerator::VisitWithStatement(WithStatement* stmt) {
960 EnterWithContextStatement* stmt) { 967 Comment cmnt(masm_, "[ WithStatement");
961 Comment cmnt(masm_, "[ EnterWithContextStatement");
962 SetStatementPosition(stmt); 968 SetStatementPosition(stmt);
963 969
964 VisitForStackValue(stmt->expression()); 970 VisitForStackValue(stmt->expression());
965 PushFunctionArgumentForContextAllocation(); 971 PushFunctionArgumentForContextAllocation();
966 __ CallRuntime(Runtime::kPushWithContext, 2); 972 __ CallRuntime(Runtime::kPushWithContext, 2);
967 decrement_stack_height(); 973 decrement_stack_height();
968 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); 974 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
975
976 { WithOrCatch body(this);
977 Visit(stmt->statement());
978 }
979
980 // Pop context.
981 LoadContextField(context_register(), Context::PREVIOUS_INDEX);
982 // Update local stack frame context field.
983 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
969 } 984 }
970 985
971 986
972 void FullCodeGenerator::VisitExitContextStatement(ExitContextStatement* stmt) { 987 void FullCodeGenerator::VisitExitContextStatement(ExitContextStatement* stmt) {
973 Comment cmnt(masm_, "[ ExitContextStatement"); 988 Comment cmnt(masm_, "[ ExitContextStatement");
974 SetStatementPosition(stmt); 989 SetStatementPosition(stmt);
975 990
976 // Pop context. 991 // Pop context.
977 LoadContextField(context_register(), Context::PREVIOUS_INDEX); 992 LoadContextField(context_register(), Context::PREVIOUS_INDEX);
978 // Update local stack frame context field. 993 // Update local stack frame context field.
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
1117 __ push(result_register()); 1132 __ push(result_register());
1118 PushFunctionArgumentForContextAllocation(); 1133 PushFunctionArgumentForContextAllocation();
1119 __ CallRuntime(Runtime::kPushCatchContext, 3); 1134 __ CallRuntime(Runtime::kPushCatchContext, 3);
1120 StoreToFrameField(StandardFrameConstants::kContextOffset, 1135 StoreToFrameField(StandardFrameConstants::kContextOffset,
1121 context_register()); 1136 context_register());
1122 } 1137 }
1123 1138
1124 Scope* saved_scope = scope(); 1139 Scope* saved_scope = scope();
1125 scope_ = stmt->scope(); 1140 scope_ = stmt->scope();
1126 ASSERT(scope_->declarations()->is_empty()); 1141 ASSERT(scope_->declarations()->is_empty());
1127 Visit(stmt->catch_block()); 1142 { WithOrCatch body(this);
1143 Visit(stmt->catch_block());
1144 }
1128 scope_ = saved_scope; 1145 scope_ = saved_scope;
1129 __ jmp(&done); 1146 __ jmp(&done);
1130 1147
1131 // Try block code. Sets up the exception handler chain. 1148 // Try block code. Sets up the exception handler chain.
1132 __ bind(&try_handler_setup); 1149 __ bind(&try_handler_setup);
1133 { 1150 {
1134 TryCatch try_block(this, &catch_entry); 1151 TryCatch try_block(this, &catch_entry);
1135 __ PushTryHandler(IN_JAVASCRIPT, TRY_CATCH_HANDLER); 1152 __ PushTryHandler(IN_JAVASCRIPT, TRY_CATCH_HANDLER);
1136 increment_stack_height(StackHandlerConstants::kSize / kPointerSize); 1153 increment_stack_height(StackHandlerConstants::kSize / kPointerSize);
1137 Visit(stmt->try_block()); 1154 Visit(stmt->try_block());
(...skipping 25 matching lines...) Expand all
1163 // 1180 //
1164 // The finally block must assume a return address on top of the stack 1181 // The finally block must assume a return address on top of the stack
1165 // (or in the link register on ARM chips) and a value (return value or 1182 // (or in the link register on ARM chips) and a value (return value or
1166 // exception) in the result register (rax/eax/r0), both of which must 1183 // exception) in the result register (rax/eax/r0), both of which must
1167 // be preserved. The return address isn't GC-safe, so it should be 1184 // be preserved. The return address isn't GC-safe, so it should be
1168 // cooked before GC. 1185 // cooked before GC.
1169 Label finally_entry; 1186 Label finally_entry;
1170 Label try_handler_setup; 1187 Label try_handler_setup;
1171 const int original_stack_height = stack_height(); 1188 const int original_stack_height = stack_height();
1172 const int finally_block_stack_height = original_stack_height + 2; 1189 const int finally_block_stack_height = original_stack_height + 2;
1173 const int try_block_stack_height = original_stack_height + 4; 1190 const int try_block_stack_height = original_stack_height + 5;
1174 STATIC_ASSERT(StackHandlerConstants::kSize / kPointerSize == 4); 1191 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
1175 1192
1176 // Setup the try-handler chain. Use a call to 1193 // Setup the try-handler chain. Use a call to
1177 // Jump to try-handler setup and try-block code. Use call to put try-handler 1194 // Jump to try-handler setup and try-block code. Use call to put try-handler
1178 // address on stack. 1195 // address on stack.
1179 __ Call(&try_handler_setup); 1196 __ Call(&try_handler_setup);
1180 // Try handler code. Return address of call is pushed on handler stack. 1197 // Try handler code. Return address of call is pushed on handler stack.
1181 { 1198 {
1182 // This code is only executed during stack-handler traversal when an 1199 // This code is only executed during stack-handler traversal when an
1183 // exception is thrown. The execption is in the result register, which 1200 // exception is thrown. The execption is in the result register, which
1184 // is retained by the finally block. 1201 // is retained by the finally block.
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
1293 Comment cmnt(masm_, "[ Throw"); 1310 Comment cmnt(masm_, "[ Throw");
1294 // Throw has no effect on the stack height or the current expression context. 1311 // Throw has no effect on the stack height or the current expression context.
1295 // Usually the expression context is null, because throw is a statement. 1312 // Usually the expression context is null, because throw is a statement.
1296 VisitForStackValue(expr->exception()); 1313 VisitForStackValue(expr->exception());
1297 __ CallRuntime(Runtime::kThrow, 1); 1314 __ CallRuntime(Runtime::kThrow, 1);
1298 decrement_stack_height(); 1315 decrement_stack_height();
1299 // Never returns here. 1316 // Never returns here.
1300 } 1317 }
1301 1318
1302 1319
1303 int FullCodeGenerator::TryFinally::Exit(int stack_depth) { 1320 FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit(
1321 int* stack_depth,
1322 int* context_length) {
1304 // The macros used here must preserve the result register. 1323 // The macros used here must preserve the result register.
1305 __ Drop(stack_depth); 1324 __ Drop(*stack_depth);
1306 __ PopTryHandler(); 1325 __ PopTryHandler();
1326 *stack_depth = 0;
1327
1328 Register context = FullCodeGenerator::context_register();
1329 while (*context_length > 0) {
1330 codegen_->LoadContextField(context, Context::PREVIOUS_INDEX);
1331 --(*context_length);
1332 }
1333
1307 __ Call(finally_entry_); 1334 __ Call(finally_entry_);
1308 return 0; 1335 return previous_;
1309 } 1336 }
1310 1337
1311 1338
1312 int FullCodeGenerator::TryCatch::Exit(int stack_depth) { 1339 FullCodeGenerator::NestedStatement* FullCodeGenerator::TryCatch::Exit(
1340 int* stack_depth,
1341 int* context_length) {
1313 // The macros used here must preserve the result register. 1342 // The macros used here must preserve the result register.
1314 __ Drop(stack_depth); 1343 __ Drop(*stack_depth);
1315 __ PopTryHandler(); 1344 __ PopTryHandler();
1316 return 0; 1345 *stack_depth = 0;
1346 return previous_;
1317 } 1347 }
1318 1348
1319 1349
1320 bool FullCodeGenerator::TryLiteralCompare(CompareOperation* compare, 1350 bool FullCodeGenerator::TryLiteralCompare(CompareOperation* compare,
1321 Label* if_true, 1351 Label* if_true,
1322 Label* if_false, 1352 Label* if_false,
1323 Label* fall_through) { 1353 Label* fall_through) {
1324 Expression *expr; 1354 Expression *expr;
1325 Handle<String> check; 1355 Handle<String> check;
1326 if (compare->IsLiteralCompareTypeof(&expr, &check)) { 1356 if (compare->IsLiteralCompareTypeof(&expr, &check)) {
1327 EmitLiteralCompareTypeof(expr, check, if_true, if_false, fall_through); 1357 EmitLiteralCompareTypeof(expr, check, if_true, if_false, fall_through);
1328 return true; 1358 return true;
1329 } 1359 }
1330 1360
1331 if (compare->IsLiteralCompareUndefined(&expr)) { 1361 if (compare->IsLiteralCompareUndefined(&expr)) {
1332 EmitLiteralCompareUndefined(expr, if_true, if_false, fall_through); 1362 EmitLiteralCompareUndefined(expr, if_true, if_false, fall_through);
1333 return true; 1363 return true;
1334 } 1364 }
1335 1365
1336 return false; 1366 return false;
1337 } 1367 }
1338 1368
1339 1369
1340 #undef __ 1370 #undef __
1341 1371
1342 1372
1343 } } // namespace v8::internal 1373 } } // namespace v8::internal
OLDNEW
« src/full-codegen.h ('K') | « src/full-codegen.h ('k') | src/hydrogen.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698