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

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

Issue 7669018: Clean up the nesting stack in the full code generator. (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
« no previous file with comments | « src/full-codegen.h ('k') | src/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 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 844 matching lines...) Expand 10 before | Expand all | Expand 10 after
855 StoreToFrameField(StandardFrameConstants::kContextOffset, 855 StoreToFrameField(StandardFrameConstants::kContextOffset,
856 context_register()); 856 context_register());
857 } 857 }
858 { Comment cmnt(masm_, "[ Declarations"); 858 { Comment cmnt(masm_, "[ Declarations");
859 VisitDeclarations(scope_->declarations()); 859 VisitDeclarations(scope_->declarations());
860 } 860 }
861 } 861 }
862 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); 862 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
863 VisitStatements(stmt->statements()); 863 VisitStatements(stmt->statements());
864 scope_ = saved_scope; 864 scope_ = saved_scope;
865 __ bind(nested_statement.break_target()); 865 __ bind(nested_statement.break_label());
866 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); 866 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
867 } 867 }
868 868
869 869
870 void FullCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { 870 void FullCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
871 Comment cmnt(masm_, "[ ExpressionStatement"); 871 Comment cmnt(masm_, "[ ExpressionStatement");
872 SetStatementPosition(stmt); 872 SetStatementPosition(stmt);
873 VisitForEffect(stmt->expression()); 873 VisitForEffect(stmt->expression());
874 } 874 }
875 875
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
925 __ Drop(stack_depth); 925 __ Drop(stack_depth);
926 if (context_length > 0) { 926 if (context_length > 0) {
927 while (context_length > 0) { 927 while (context_length > 0) {
928 LoadContextField(context_register(), Context::PREVIOUS_INDEX); 928 LoadContextField(context_register(), Context::PREVIOUS_INDEX);
929 --context_length; 929 --context_length;
930 } 930 }
931 StoreToFrameField(StandardFrameConstants::kContextOffset, 931 StoreToFrameField(StandardFrameConstants::kContextOffset,
932 context_register()); 932 context_register());
933 } 933 }
934 934
935 Iteration* loop = current->AsIteration(); 935 __ jmp(current->AsIteration()->continue_label());
936 __ jmp(loop->continue_target());
937 } 936 }
938 937
939 938
940 void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) { 939 void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
941 Comment cmnt(masm_, "[ BreakStatement"); 940 Comment cmnt(masm_, "[ BreakStatement");
942 SetStatementPosition(stmt); 941 SetStatementPosition(stmt);
943 NestedStatement* current = nesting_stack_; 942 NestedStatement* current = nesting_stack_;
944 int stack_depth = 0; 943 int stack_depth = 0;
945 int context_length = 0; 944 int context_length = 0;
946 // When breaking, we clobber the unpredictable value in the accumulator 945 // When breaking, we clobber the unpredictable value in the accumulator
947 // with one that's safe for GC. If we hit an exit from the try block of 946 // with one that's safe for GC. If we hit an exit from the try block of
948 // try...finally on our way out, we will unconditionally preserve the 947 // try...finally on our way out, we will unconditionally preserve the
949 // accumulator on the stack. 948 // accumulator on the stack.
950 ClearAccumulator(); 949 ClearAccumulator();
951 while (!current->IsBreakTarget(stmt->target())) { 950 while (!current->IsBreakTarget(stmt->target())) {
952 current = current->Exit(&stack_depth, &context_length); 951 current = current->Exit(&stack_depth, &context_length);
953 } 952 }
954 __ Drop(stack_depth); 953 __ Drop(stack_depth);
955 if (context_length > 0) { 954 if (context_length > 0) {
956 while (context_length > 0) { 955 while (context_length > 0) {
957 LoadContextField(context_register(), Context::PREVIOUS_INDEX); 956 LoadContextField(context_register(), Context::PREVIOUS_INDEX);
958 --context_length; 957 --context_length;
959 } 958 }
960 StoreToFrameField(StandardFrameConstants::kContextOffset, 959 StoreToFrameField(StandardFrameConstants::kContextOffset,
961 context_register()); 960 context_register());
962 } 961 }
963 962
964 Breakable* target = current->AsBreakable(); 963 __ jmp(current->AsBreakable()->break_label());
965 __ jmp(target->break_target());
966 } 964 }
967 965
968 966
969 void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { 967 void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
970 Comment cmnt(masm_, "[ ReturnStatement"); 968 Comment cmnt(masm_, "[ ReturnStatement");
971 SetStatementPosition(stmt); 969 SetStatementPosition(stmt);
972 Expression* expr = stmt->expression(); 970 Expression* expr = stmt->expression();
973 VisitForAccumulatorValue(expr); 971 VisitForAccumulatorValue(expr);
974 972
975 // Exit all nested statements. 973 // Exit all nested statements.
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1023 Label body, stack_check; 1021 Label body, stack_check;
1024 1022
1025 Iteration loop_statement(this, stmt); 1023 Iteration loop_statement(this, stmt);
1026 increment_loop_depth(); 1024 increment_loop_depth();
1027 1025
1028 __ bind(&body); 1026 __ bind(&body);
1029 Visit(stmt->body()); 1027 Visit(stmt->body());
1030 1028
1031 // Record the position of the do while condition and make sure it is 1029 // Record the position of the do while condition and make sure it is
1032 // possible to break on the condition. 1030 // possible to break on the condition.
1033 __ bind(loop_statement.continue_target()); 1031 __ bind(loop_statement.continue_label());
1034 PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS); 1032 PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS);
1035 SetExpressionPosition(stmt->cond(), stmt->condition_position()); 1033 SetExpressionPosition(stmt->cond(), stmt->condition_position());
1036 VisitForControl(stmt->cond(), 1034 VisitForControl(stmt->cond(),
1037 &stack_check, 1035 &stack_check,
1038 loop_statement.break_target(), 1036 loop_statement.break_label(),
1039 &stack_check); 1037 &stack_check);
1040 1038
1041 // Check stack before looping. 1039 // Check stack before looping.
1042 PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS); 1040 PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS);
1043 __ bind(&stack_check); 1041 __ bind(&stack_check);
1044 EmitStackCheck(stmt); 1042 EmitStackCheck(stmt);
1045 __ jmp(&body); 1043 __ jmp(&body);
1046 1044
1047 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); 1045 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1048 __ bind(loop_statement.break_target()); 1046 __ bind(loop_statement.break_label());
1049 decrement_loop_depth(); 1047 decrement_loop_depth();
1050 } 1048 }
1051 1049
1052 1050
1053 void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) { 1051 void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
1054 Comment cmnt(masm_, "[ WhileStatement"); 1052 Comment cmnt(masm_, "[ WhileStatement");
1055 Label test, body; 1053 Label test, body;
1056 1054
1057 Iteration loop_statement(this, stmt); 1055 Iteration loop_statement(this, stmt);
1058 increment_loop_depth(); 1056 increment_loop_depth();
1059 1057
1060 // Emit the test at the bottom of the loop. 1058 // Emit the test at the bottom of the loop.
1061 __ jmp(&test); 1059 __ jmp(&test);
1062 1060
1063 PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS); 1061 PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
1064 __ bind(&body); 1062 __ bind(&body);
1065 Visit(stmt->body()); 1063 Visit(stmt->body());
1066 1064
1067 // Emit the statement position here as this is where the while 1065 // Emit the statement position here as this is where the while
1068 // statement code starts. 1066 // statement code starts.
1069 __ bind(loop_statement.continue_target()); 1067 __ bind(loop_statement.continue_label());
1070 SetStatementPosition(stmt); 1068 SetStatementPosition(stmt);
1071 1069
1072 // Check stack before looping. 1070 // Check stack before looping.
1073 EmitStackCheck(stmt); 1071 EmitStackCheck(stmt);
1074 1072
1075 __ bind(&test); 1073 __ bind(&test);
1076 VisitForControl(stmt->cond(), 1074 VisitForControl(stmt->cond(),
1077 &body, 1075 &body,
1078 loop_statement.break_target(), 1076 loop_statement.break_label(),
1079 loop_statement.break_target()); 1077 loop_statement.break_label());
1080 1078
1081 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); 1079 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1082 __ bind(loop_statement.break_target()); 1080 __ bind(loop_statement.break_label());
1083 decrement_loop_depth(); 1081 decrement_loop_depth();
1084 } 1082 }
1085 1083
1086 1084
1087 void FullCodeGenerator::VisitForStatement(ForStatement* stmt) { 1085 void FullCodeGenerator::VisitForStatement(ForStatement* stmt) {
1088 Comment cmnt(masm_, "[ ForStatement"); 1086 Comment cmnt(masm_, "[ ForStatement");
1089 Label test, body; 1087 Label test, body;
1090 1088
1091 Iteration loop_statement(this, stmt); 1089 Iteration loop_statement(this, stmt);
1092 if (stmt->init() != NULL) { 1090 if (stmt->init() != NULL) {
1093 Visit(stmt->init()); 1091 Visit(stmt->init());
1094 } 1092 }
1095 1093
1096 increment_loop_depth(); 1094 increment_loop_depth();
1097 // Emit the test at the bottom of the loop (even if empty). 1095 // Emit the test at the bottom of the loop (even if empty).
1098 __ jmp(&test); 1096 __ jmp(&test);
1099 1097
1100 PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS); 1098 PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
1101 __ bind(&body); 1099 __ bind(&body);
1102 Visit(stmt->body()); 1100 Visit(stmt->body());
1103 1101
1104 PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS); 1102 PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS);
1105 __ bind(loop_statement.continue_target()); 1103 __ bind(loop_statement.continue_label());
1106 SetStatementPosition(stmt); 1104 SetStatementPosition(stmt);
1107 if (stmt->next() != NULL) { 1105 if (stmt->next() != NULL) {
1108 Visit(stmt->next()); 1106 Visit(stmt->next());
1109 } 1107 }
1110 1108
1111 // Emit the statement position here as this is where the for 1109 // Emit the statement position here as this is where the for
1112 // statement code starts. 1110 // statement code starts.
1113 SetStatementPosition(stmt); 1111 SetStatementPosition(stmt);
1114 1112
1115 // Check stack before looping. 1113 // Check stack before looping.
1116 EmitStackCheck(stmt); 1114 EmitStackCheck(stmt);
1117 1115
1118 __ bind(&test); 1116 __ bind(&test);
1119 if (stmt->cond() != NULL) { 1117 if (stmt->cond() != NULL) {
1120 VisitForControl(stmt->cond(), 1118 VisitForControl(stmt->cond(),
1121 &body, 1119 &body,
1122 loop_statement.break_target(), 1120 loop_statement.break_label(),
1123 loop_statement.break_target()); 1121 loop_statement.break_label());
1124 } else { 1122 } else {
1125 __ jmp(&body); 1123 __ jmp(&body);
1126 } 1124 }
1127 1125
1128 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); 1126 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1129 __ bind(loop_statement.break_target()); 1127 __ bind(loop_statement.break_label());
1130 decrement_loop_depth(); 1128 decrement_loop_depth();
1131 } 1129 }
1132 1130
1133 1131
1134 void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { 1132 void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
1135 Comment cmnt(masm_, "[ TryCatchStatement"); 1133 Comment cmnt(masm_, "[ TryCatchStatement");
1136 SetStatementPosition(stmt); 1134 SetStatementPosition(stmt);
1137 // The try block adds a handler to the exception handler chain 1135 // The try block adds a handler to the exception handler chain
1138 // before entering, and removes it again when exiting normally. 1136 // before entering, and removes it again when exiting normally.
1139 // If an exception is thrown during execution of the try block, 1137 // If an exception is thrown during execution of the try block,
1140 // control is passed to the handler, which also consumes the handler. 1138 // control is passed to the handler, which also consumes the handler.
1141 // At this point, the exception is in a register, and store it in 1139 // At this point, the exception is in a register, and store it in
1142 // the temporary local variable (prints as ".catch-var") before 1140 // the temporary local variable (prints as ".catch-var") before
1143 // executing the catch block. The catch block has been rewritten 1141 // executing the catch block. The catch block has been rewritten
1144 // to introduce a new scope to bind the catch variable and to remove 1142 // to introduce a new scope to bind the catch variable and to remove
1145 // that scope again afterwards. 1143 // that scope again afterwards.
1146 1144
1147 Label try_handler_setup, catch_entry, done; 1145 Label try_handler_setup, done;
1148 __ Call(&try_handler_setup); 1146 __ Call(&try_handler_setup);
1149 // Try handler code, exception in result register. 1147 // Try handler code, exception in result register.
1150 1148
1151 // Extend the context before executing the catch block. 1149 // Extend the context before executing the catch block.
1152 { Comment cmnt(masm_, "[ Extend catch context"); 1150 { Comment cmnt(masm_, "[ Extend catch context");
1153 __ Push(stmt->variable()->name()); 1151 __ Push(stmt->variable()->name());
1154 __ push(result_register()); 1152 __ push(result_register());
1155 PushFunctionArgumentForContextAllocation(); 1153 PushFunctionArgumentForContextAllocation();
1156 __ CallRuntime(Runtime::kPushCatchContext, 3); 1154 __ CallRuntime(Runtime::kPushCatchContext, 3);
1157 StoreToFrameField(StandardFrameConstants::kContextOffset, 1155 StoreToFrameField(StandardFrameConstants::kContextOffset,
1158 context_register()); 1156 context_register());
1159 } 1157 }
1160 1158
1161 Scope* saved_scope = scope(); 1159 Scope* saved_scope = scope();
1162 scope_ = stmt->scope(); 1160 scope_ = stmt->scope();
1163 ASSERT(scope_->declarations()->is_empty()); 1161 ASSERT(scope_->declarations()->is_empty());
1164 { WithOrCatch body(this); 1162 { WithOrCatch body(this);
1165 Visit(stmt->catch_block()); 1163 Visit(stmt->catch_block());
1166 } 1164 }
1167 scope_ = saved_scope; 1165 scope_ = saved_scope;
1168 __ jmp(&done); 1166 __ jmp(&done);
1169 1167
1170 // Try block code. Sets up the exception handler chain. 1168 // Try block code. Sets up the exception handler chain.
1171 __ bind(&try_handler_setup); 1169 __ bind(&try_handler_setup);
1172 { 1170 {
1173 TryCatch try_block(this, &catch_entry); 1171 const int delta = StackHandlerConstants::kSize / kPointerSize;
1172 TryCatch try_block(this);
1174 __ PushTryHandler(IN_JAVASCRIPT, TRY_CATCH_HANDLER); 1173 __ PushTryHandler(IN_JAVASCRIPT, TRY_CATCH_HANDLER);
1175 increment_stack_height(StackHandlerConstants::kSize / kPointerSize); 1174 increment_stack_height(delta);
1176 Visit(stmt->try_block()); 1175 Visit(stmt->try_block());
1177 __ PopTryHandler(); 1176 __ PopTryHandler();
1178 decrement_stack_height(StackHandlerConstants::kSize / kPointerSize); 1177 decrement_stack_height(delta);
1179 } 1178 }
1180 __ bind(&done); 1179 __ bind(&done);
1181 } 1180 }
1182 1181
1183 1182
1184 void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) { 1183 void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
1185 Comment cmnt(masm_, "[ TryFinallyStatement"); 1184 Comment cmnt(masm_, "[ TryFinallyStatement");
1186 SetStatementPosition(stmt); 1185 SetStatementPosition(stmt);
1187 // Try finally is compiled by setting up a try-handler on the stack while 1186 // Try finally is compiled by setting up a try-handler on the stack while
1188 // executing the try body, and removing it again afterwards. 1187 // executing the try body, and removing it again afterwards.
(...skipping 12 matching lines...) Expand all
1201 // rethrowing the exception. 1200 // rethrowing the exception.
1202 // 1201 //
1203 // The finally block must assume a return address on top of the stack 1202 // The finally block must assume a return address on top of the stack
1204 // (or in the link register on ARM chips) and a value (return value or 1203 // (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 1204 // 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 1205 // be preserved. The return address isn't GC-safe, so it should be
1207 // cooked before GC. 1206 // cooked before GC.
1208 Label finally_entry; 1207 Label finally_entry;
1209 Label try_handler_setup; 1208 Label try_handler_setup;
1210 const int original_stack_height = stack_height(); 1209 const int original_stack_height = stack_height();
1211 const int finally_block_stack_height = original_stack_height + 2;
1212 const int try_block_stack_height = original_stack_height + 5;
1213 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
1214 1210
1215 // Setup the try-handler chain. Use a call to 1211 // Setup the try-handler chain. Use a call to
1216 // Jump to try-handler setup and try-block code. Use call to put try-handler 1212 // Jump to try-handler setup and try-block code. Use call to put try-handler
1217 // address on stack. 1213 // address on stack.
1218 __ Call(&try_handler_setup); 1214 __ Call(&try_handler_setup);
1219 // Try handler code. Return address of call is pushed on handler stack. 1215 // Try handler code. Return address of call is pushed on handler stack.
1220 { 1216 {
1221 // This code is only executed during stack-handler traversal when an 1217 // This code is only executed during stack-handler traversal when an
1222 // exception is thrown. The execption is in the result register, which 1218 // exception is thrown. The exception is in the result register, which
1223 // is retained by the finally block. 1219 // is retained by the finally block.
1224 // Call the finally block and then rethrow the exception. 1220 // Call the finally block and then rethrow the exception if it returns.
1225 __ Call(&finally_entry); 1221 __ Call(&finally_entry);
1226 __ push(result_register()); 1222 __ push(result_register());
1227 __ CallRuntime(Runtime::kReThrow, 1); 1223 __ CallRuntime(Runtime::kReThrow, 1);
1228 } 1224 }
1229 1225
1230 __ bind(&finally_entry); 1226 __ bind(&finally_entry);
1231 { 1227 {
1232 // Finally block implementation. 1228 // Finally block implementation.
1233 Finally finally_block(this); 1229 Finally finally_block(this);
1234 EnterFinallyBlock(); 1230 EnterFinallyBlock();
1235 set_stack_height(finally_block_stack_height); 1231 set_stack_height(original_stack_height + Finally::kElementCount);
1236 Visit(stmt->finally_block()); 1232 Visit(stmt->finally_block());
1237 ExitFinallyBlock(); // Return to the calling code. 1233 ExitFinallyBlock(); // Return to the calling code.
1238 } 1234 }
1239 1235
1240 __ bind(&try_handler_setup); 1236 __ bind(&try_handler_setup);
1241 { 1237 {
1242 // Setup try handler (stack pointer registers). 1238 // Setup try handler (stack pointer registers).
1239 const int delta = StackHandlerConstants::kSize / kPointerSize;
1243 TryFinally try_block(this, &finally_entry); 1240 TryFinally try_block(this, &finally_entry);
1244 __ PushTryHandler(IN_JAVASCRIPT, TRY_FINALLY_HANDLER); 1241 __ PushTryHandler(IN_JAVASCRIPT, TRY_FINALLY_HANDLER);
1245 set_stack_height(try_block_stack_height); 1242 set_stack_height(original_stack_height + delta);
1246 Visit(stmt->try_block()); 1243 Visit(stmt->try_block());
1247 __ PopTryHandler(); 1244 __ PopTryHandler();
1248 set_stack_height(original_stack_height); 1245 set_stack_height(original_stack_height);
1249 } 1246 }
1250 // Execute the finally block on the way out. Clobber the unpredictable 1247 // Execute the finally block on the way out. Clobber the unpredictable
1251 // value in the accumulator with one that's safe for GC. The finally 1248 // value in the accumulator with one that's safe for GC. The finally
1252 // block will unconditionally preserve the accumulator on the stack. 1249 // block will unconditionally preserve the accumulator on the stack.
1253 ClearAccumulator(); 1250 ClearAccumulator();
1254 __ Call(&finally_entry); 1251 __ Call(&finally_entry);
1255 } 1252 }
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
1386 } 1383 }
1387 1384
1388 return false; 1385 return false;
1389 } 1386 }
1390 1387
1391 1388
1392 #undef __ 1389 #undef __
1393 1390
1394 1391
1395 } } // namespace v8::internal 1392 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/full-codegen.h ('k') | src/ia32/full-codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698