OLD | NEW |
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 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
84 void BreakableStatementChecker::VisitBreakStatement(BreakStatement* stmt) { | 84 void BreakableStatementChecker::VisitBreakStatement(BreakStatement* stmt) { |
85 } | 85 } |
86 | 86 |
87 | 87 |
88 void BreakableStatementChecker::VisitReturnStatement(ReturnStatement* stmt) { | 88 void BreakableStatementChecker::VisitReturnStatement(ReturnStatement* stmt) { |
89 // Return is breakable if the expression is. | 89 // Return is breakable if the expression is. |
90 Visit(stmt->expression()); | 90 Visit(stmt->expression()); |
91 } | 91 } |
92 | 92 |
93 | 93 |
94 void BreakableStatementChecker::VisitEnterWithContextStatement( | 94 void BreakableStatementChecker::VisitWithStatement(WithStatement* stmt) { |
95 EnterWithContextStatement* stmt) { | |
96 Visit(stmt->expression()); | 95 Visit(stmt->expression()); |
97 } | 96 } |
98 | 97 |
99 | 98 |
100 void BreakableStatementChecker::VisitExitContextStatement( | 99 void BreakableStatementChecker::VisitExitContextStatement( |
101 ExitContextStatement* stmt) { | 100 ExitContextStatement* stmt) { |
102 } | 101 } |
103 | 102 |
104 | 103 |
105 void BreakableStatementChecker::VisitSwitchStatement(SwitchStatement* stmt) { | 104 void BreakableStatementChecker::VisitSwitchStatement(SwitchStatement* stmt) { |
(...skipping 801 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
907 __ bind(&done); | 906 __ bind(&done); |
908 PrepareForBailoutForId(stmt->IfId(), NO_REGISTERS); | 907 PrepareForBailoutForId(stmt->IfId(), NO_REGISTERS); |
909 } | 908 } |
910 | 909 |
911 | 910 |
912 void FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) { | 911 void FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) { |
913 Comment cmnt(masm_, "[ ContinueStatement"); | 912 Comment cmnt(masm_, "[ ContinueStatement"); |
914 SetStatementPosition(stmt); | 913 SetStatementPosition(stmt); |
915 NestedStatement* current = nesting_stack_; | 914 NestedStatement* current = nesting_stack_; |
916 int stack_depth = 0; | 915 int stack_depth = 0; |
| 916 int context_length = 0; |
917 // When continuing, we clobber the unpredictable value in the accumulator | 917 // When continuing, we clobber the unpredictable value in the accumulator |
918 // 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 |
919 // try...finally on our way out, we will unconditionally preserve the | 919 // try...finally on our way out, we will unconditionally preserve the |
920 // accumulator on the stack. | 920 // accumulator on the stack. |
921 ClearAccumulator(); | 921 ClearAccumulator(); |
922 while (!current->IsContinueTarget(stmt->target())) { | 922 while (!current->IsContinueTarget(stmt->target())) { |
923 stack_depth = current->Exit(stack_depth); | 923 current = current->Exit(&stack_depth, &context_length); |
924 current = current->outer(); | |
925 } | 924 } |
926 __ Drop(stack_depth); | 925 __ Drop(stack_depth); |
| 926 if (context_length > 0) { |
| 927 while (context_length > 0) { |
| 928 LoadContextField(context_register(), Context::PREVIOUS_INDEX); |
| 929 --context_length; |
| 930 } |
| 931 StoreToFrameField(StandardFrameConstants::kContextOffset, |
| 932 context_register()); |
| 933 } |
927 | 934 |
928 Iteration* loop = current->AsIteration(); | 935 Iteration* loop = current->AsIteration(); |
929 __ jmp(loop->continue_target()); | 936 __ jmp(loop->continue_target()); |
930 } | 937 } |
931 | 938 |
932 | 939 |
933 void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) { | 940 void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) { |
934 Comment cmnt(masm_, "[ BreakStatement"); | 941 Comment cmnt(masm_, "[ BreakStatement"); |
935 SetStatementPosition(stmt); | 942 SetStatementPosition(stmt); |
936 NestedStatement* current = nesting_stack_; | 943 NestedStatement* current = nesting_stack_; |
937 int stack_depth = 0; | 944 int stack_depth = 0; |
| 945 int context_length = 0; |
938 // When breaking, we clobber the unpredictable value in the accumulator | 946 // When breaking, we clobber the unpredictable value in the accumulator |
939 // with one that's safe for GC. If we hit an exit from the try block of | 947 // with one that's safe for GC. If we hit an exit from the try block of |
940 // try...finally on our way out, we will unconditionally preserve the | 948 // try...finally on our way out, we will unconditionally preserve the |
941 // accumulator on the stack. | 949 // accumulator on the stack. |
942 ClearAccumulator(); | 950 ClearAccumulator(); |
943 while (!current->IsBreakTarget(stmt->target())) { | 951 while (!current->IsBreakTarget(stmt->target())) { |
944 stack_depth = current->Exit(stack_depth); | 952 current = current->Exit(&stack_depth, &context_length); |
945 current = current->outer(); | |
946 } | 953 } |
947 __ Drop(stack_depth); | 954 __ Drop(stack_depth); |
| 955 if (context_length > 0) { |
| 956 while (context_length > 0) { |
| 957 LoadContextField(context_register(), Context::PREVIOUS_INDEX); |
| 958 --context_length; |
| 959 } |
| 960 StoreToFrameField(StandardFrameConstants::kContextOffset, |
| 961 context_register()); |
| 962 } |
948 | 963 |
949 Breakable* target = current->AsBreakable(); | 964 Breakable* target = current->AsBreakable(); |
950 __ jmp(target->break_target()); | 965 __ jmp(target->break_target()); |
951 } | 966 } |
952 | 967 |
953 | 968 |
954 void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { | 969 void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { |
955 Comment cmnt(masm_, "[ ReturnStatement"); | 970 Comment cmnt(masm_, "[ ReturnStatement"); |
956 SetStatementPosition(stmt); | 971 SetStatementPosition(stmt); |
957 Expression* expr = stmt->expression(); | 972 Expression* expr = stmt->expression(); |
958 VisitForAccumulatorValue(expr); | 973 VisitForAccumulatorValue(expr); |
959 | 974 |
960 // Exit all nested statements. | 975 // Exit all nested statements. |
961 NestedStatement* current = nesting_stack_; | 976 NestedStatement* current = nesting_stack_; |
962 int stack_depth = 0; | 977 int stack_depth = 0; |
| 978 int context_length = 0; |
963 while (current != NULL) { | 979 while (current != NULL) { |
964 stack_depth = current->Exit(stack_depth); | 980 current = current->Exit(&stack_depth, &context_length); |
965 current = current->outer(); | |
966 } | 981 } |
967 __ Drop(stack_depth); | 982 __ Drop(stack_depth); |
968 | 983 |
969 EmitReturnSequence(); | 984 EmitReturnSequence(); |
970 } | 985 } |
971 | 986 |
972 | 987 |
973 void FullCodeGenerator::VisitEnterWithContextStatement( | 988 void FullCodeGenerator::VisitWithStatement(WithStatement* stmt) { |
974 EnterWithContextStatement* stmt) { | 989 Comment cmnt(masm_, "[ WithStatement"); |
975 Comment cmnt(masm_, "[ EnterWithContextStatement"); | |
976 SetStatementPosition(stmt); | 990 SetStatementPosition(stmt); |
977 | 991 |
978 VisitForStackValue(stmt->expression()); | 992 VisitForStackValue(stmt->expression()); |
979 PushFunctionArgumentForContextAllocation(); | 993 PushFunctionArgumentForContextAllocation(); |
980 __ CallRuntime(Runtime::kPushWithContext, 2); | 994 __ CallRuntime(Runtime::kPushWithContext, 2); |
981 decrement_stack_height(); | 995 decrement_stack_height(); |
982 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); | 996 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); |
| 997 |
| 998 { WithOrCatch body(this); |
| 999 Visit(stmt->statement()); |
| 1000 } |
| 1001 |
| 1002 // Pop context. |
| 1003 LoadContextField(context_register(), Context::PREVIOUS_INDEX); |
| 1004 // Update local stack frame context field. |
| 1005 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); |
983 } | 1006 } |
984 | 1007 |
985 | 1008 |
986 void FullCodeGenerator::VisitExitContextStatement(ExitContextStatement* stmt) { | 1009 void FullCodeGenerator::VisitExitContextStatement(ExitContextStatement* stmt) { |
987 Comment cmnt(masm_, "[ ExitContextStatement"); | 1010 Comment cmnt(masm_, "[ ExitContextStatement"); |
988 SetStatementPosition(stmt); | 1011 SetStatementPosition(stmt); |
989 | 1012 |
990 // Pop context. | 1013 // Pop context. |
991 LoadContextField(context_register(), Context::PREVIOUS_INDEX); | 1014 LoadContextField(context_register(), Context::PREVIOUS_INDEX); |
992 // Update local stack frame context field. | 1015 // Update local stack frame context field. |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1131 __ push(result_register()); | 1154 __ push(result_register()); |
1132 PushFunctionArgumentForContextAllocation(); | 1155 PushFunctionArgumentForContextAllocation(); |
1133 __ CallRuntime(Runtime::kPushCatchContext, 3); | 1156 __ CallRuntime(Runtime::kPushCatchContext, 3); |
1134 StoreToFrameField(StandardFrameConstants::kContextOffset, | 1157 StoreToFrameField(StandardFrameConstants::kContextOffset, |
1135 context_register()); | 1158 context_register()); |
1136 } | 1159 } |
1137 | 1160 |
1138 Scope* saved_scope = scope(); | 1161 Scope* saved_scope = scope(); |
1139 scope_ = stmt->scope(); | 1162 scope_ = stmt->scope(); |
1140 ASSERT(scope_->declarations()->is_empty()); | 1163 ASSERT(scope_->declarations()->is_empty()); |
1141 Visit(stmt->catch_block()); | 1164 { WithOrCatch body(this); |
| 1165 Visit(stmt->catch_block()); |
| 1166 } |
1142 scope_ = saved_scope; | 1167 scope_ = saved_scope; |
1143 __ jmp(&done); | 1168 __ jmp(&done); |
1144 | 1169 |
1145 // Try block code. Sets up the exception handler chain. | 1170 // Try block code. Sets up the exception handler chain. |
1146 __ bind(&try_handler_setup); | 1171 __ bind(&try_handler_setup); |
1147 { | 1172 { |
1148 TryCatch try_block(this, &catch_entry); | 1173 TryCatch try_block(this, &catch_entry); |
1149 __ PushTryHandler(IN_JAVASCRIPT, TRY_CATCH_HANDLER); | 1174 __ PushTryHandler(IN_JAVASCRIPT, TRY_CATCH_HANDLER); |
1150 increment_stack_height(StackHandlerConstants::kSize / kPointerSize); | 1175 increment_stack_height(StackHandlerConstants::kSize / kPointerSize); |
1151 Visit(stmt->try_block()); | 1176 Visit(stmt->try_block()); |
(...skipping 25 matching lines...) Expand all Loading... |
1177 // | 1202 // |
1178 // The finally block must assume a return address on top of the stack | 1203 // The finally block must assume a return address on top of the stack |
1179 // (or in the link register on ARM chips) and a value (return value or | 1204 // (or in the link register on ARM chips) and a value (return value or |
1180 // exception) in the result register (rax/eax/r0), both of which must | 1205 // exception) in the result register (rax/eax/r0), both of which must |
1181 // be preserved. The return address isn't GC-safe, so it should be | 1206 // be preserved. The return address isn't GC-safe, so it should be |
1182 // cooked before GC. | 1207 // cooked before GC. |
1183 Label finally_entry; | 1208 Label finally_entry; |
1184 Label try_handler_setup; | 1209 Label try_handler_setup; |
1185 const int original_stack_height = stack_height(); | 1210 const int original_stack_height = stack_height(); |
1186 const int finally_block_stack_height = original_stack_height + 2; | 1211 const int finally_block_stack_height = original_stack_height + 2; |
1187 const int try_block_stack_height = original_stack_height + 4; | 1212 const int try_block_stack_height = original_stack_height + 5; |
1188 STATIC_ASSERT(StackHandlerConstants::kSize / kPointerSize == 4); | 1213 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); |
1189 | 1214 |
1190 // Setup the try-handler chain. Use a call to | 1215 // Setup the try-handler chain. Use a call to |
1191 // Jump to try-handler setup and try-block code. Use call to put try-handler | 1216 // Jump to try-handler setup and try-block code. Use call to put try-handler |
1192 // address on stack. | 1217 // address on stack. |
1193 __ Call(&try_handler_setup); | 1218 __ Call(&try_handler_setup); |
1194 // Try handler code. Return address of call is pushed on handler stack. | 1219 // Try handler code. Return address of call is pushed on handler stack. |
1195 { | 1220 { |
1196 // This code is only executed during stack-handler traversal when an | 1221 // This code is only executed during stack-handler traversal when an |
1197 // exception is thrown. The execption is in the result register, which | 1222 // exception is thrown. The execption is in the result register, which |
1198 // is retained by the finally block. | 1223 // is retained by the finally block. |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1307 Comment cmnt(masm_, "[ Throw"); | 1332 Comment cmnt(masm_, "[ Throw"); |
1308 // Throw has no effect on the stack height or the current expression context. | 1333 // Throw has no effect on the stack height or the current expression context. |
1309 // Usually the expression context is null, because throw is a statement. | 1334 // Usually the expression context is null, because throw is a statement. |
1310 VisitForStackValue(expr->exception()); | 1335 VisitForStackValue(expr->exception()); |
1311 __ CallRuntime(Runtime::kThrow, 1); | 1336 __ CallRuntime(Runtime::kThrow, 1); |
1312 decrement_stack_height(); | 1337 decrement_stack_height(); |
1313 // Never returns here. | 1338 // Never returns here. |
1314 } | 1339 } |
1315 | 1340 |
1316 | 1341 |
1317 int FullCodeGenerator::TryFinally::Exit(int stack_depth) { | 1342 FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit( |
| 1343 int* stack_depth, |
| 1344 int* context_length) { |
1318 // The macros used here must preserve the result register. | 1345 // The macros used here must preserve the result register. |
1319 __ Drop(stack_depth); | 1346 __ Drop(*stack_depth); |
1320 __ PopTryHandler(); | 1347 __ PopTryHandler(); |
| 1348 *stack_depth = 0; |
| 1349 |
| 1350 Register context = FullCodeGenerator::context_register(); |
| 1351 while (*context_length > 0) { |
| 1352 codegen_->LoadContextField(context, Context::PREVIOUS_INDEX); |
| 1353 --(*context_length); |
| 1354 } |
| 1355 |
1321 __ Call(finally_entry_); | 1356 __ Call(finally_entry_); |
1322 return 0; | 1357 return previous_; |
1323 } | 1358 } |
1324 | 1359 |
1325 | 1360 |
1326 int FullCodeGenerator::TryCatch::Exit(int stack_depth) { | 1361 FullCodeGenerator::NestedStatement* FullCodeGenerator::TryCatch::Exit( |
| 1362 int* stack_depth, |
| 1363 int* context_length) { |
1327 // The macros used here must preserve the result register. | 1364 // The macros used here must preserve the result register. |
1328 __ Drop(stack_depth); | 1365 __ Drop(*stack_depth); |
1329 __ PopTryHandler(); | 1366 __ PopTryHandler(); |
1330 return 0; | 1367 *stack_depth = 0; |
| 1368 return previous_; |
1331 } | 1369 } |
1332 | 1370 |
1333 | 1371 |
1334 bool FullCodeGenerator::TryLiteralCompare(CompareOperation* compare, | 1372 bool FullCodeGenerator::TryLiteralCompare(CompareOperation* compare, |
1335 Label* if_true, | 1373 Label* if_true, |
1336 Label* if_false, | 1374 Label* if_false, |
1337 Label* fall_through) { | 1375 Label* fall_through) { |
1338 Expression *expr; | 1376 Expression *expr; |
1339 Handle<String> check; | 1377 Handle<String> check; |
1340 if (compare->IsLiteralCompareTypeof(&expr, &check)) { | 1378 if (compare->IsLiteralCompareTypeof(&expr, &check)) { |
1341 EmitLiteralCompareTypeof(expr, check, if_true, if_false, fall_through); | 1379 EmitLiteralCompareTypeof(expr, check, if_true, if_false, fall_through); |
1342 return true; | 1380 return true; |
1343 } | 1381 } |
1344 | 1382 |
1345 if (compare->IsLiteralCompareUndefined(&expr)) { | 1383 if (compare->IsLiteralCompareUndefined(&expr)) { |
1346 EmitLiteralCompareUndefined(expr, if_true, if_false, fall_through); | 1384 EmitLiteralCompareUndefined(expr, if_true, if_false, fall_through); |
1347 return true; | 1385 return true; |
1348 } | 1386 } |
1349 | 1387 |
1350 return false; | 1388 return false; |
1351 } | 1389 } |
1352 | 1390 |
1353 | 1391 |
1354 #undef __ | 1392 #undef __ |
1355 | 1393 |
1356 | 1394 |
1357 } } // namespace v8::internal | 1395 } } // namespace v8::internal |
OLD | NEW |