| 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 |