OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/full-codegen/full-codegen.h" | 5 #include "src/full-codegen/full-codegen.h" |
6 | 6 |
7 #include "src/ast/ast-numbering.h" | 7 #include "src/ast/ast-numbering.h" |
8 #include "src/ast/ast.h" | 8 #include "src/ast/ast.h" |
9 #include "src/ast/prettyprinter.h" | 9 #include "src/ast/prettyprinter.h" |
10 #include "src/ast/scopes.h" | 10 #include "src/ast/scopes.h" |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
55 nesting_stack_(NULL), | 55 nesting_stack_(NULL), |
56 loop_depth_(0), | 56 loop_depth_(0), |
57 operand_stack_depth_(0), | 57 operand_stack_depth_(0), |
58 globals_(NULL), | 58 globals_(NULL), |
59 context_(NULL), | 59 context_(NULL), |
60 bailout_entries_(info->HasDeoptimizationSupport() | 60 bailout_entries_(info->HasDeoptimizationSupport() |
61 ? info->literal()->ast_node_count() | 61 ? info->literal()->ast_node_count() |
62 : 0, | 62 : 0, |
63 info->zone()), | 63 info->zone()), |
64 back_edges_(2, info->zone()), | 64 back_edges_(2, info->zone()), |
65 handler_table_(info->zone()), | |
66 source_position_table_builder_(info->zone(), | 65 source_position_table_builder_(info->zone(), |
67 info->SourcePositionRecordingMode()), | 66 info->SourcePositionRecordingMode()), |
68 ic_total_count_(0) { | 67 ic_total_count_(0) { |
69 DCHECK(!info->IsStub()); | 68 DCHECK(!info->IsStub()); |
70 Initialize(stack_limit); | 69 Initialize(stack_limit); |
71 } | 70 } |
72 | 71 |
73 // static | 72 // static |
74 CompilationJob* FullCodeGenerator::NewCompilationJob(CompilationInfo* info) { | 73 CompilationJob* FullCodeGenerator::NewCompilationJob(CompilationInfo* info) { |
75 return new FullCodegenCompilationJob(info); | 74 return new FullCodegenCompilationJob(info); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
108 if (cgen.HasStackOverflow()) { | 107 if (cgen.HasStackOverflow()) { |
109 DCHECK(!isolate->has_pending_exception()); | 108 DCHECK(!isolate->has_pending_exception()); |
110 return false; | 109 return false; |
111 } | 110 } |
112 unsigned table_offset = cgen.EmitBackEdgeTable(); | 111 unsigned table_offset = cgen.EmitBackEdgeTable(); |
113 | 112 |
114 Handle<Code> code = | 113 Handle<Code> code = |
115 CodeGenerator::MakeCodeEpilogue(&masm, nullptr, info, masm.CodeObject()); | 114 CodeGenerator::MakeCodeEpilogue(&masm, nullptr, info, masm.CodeObject()); |
116 cgen.PopulateDeoptimizationData(code); | 115 cgen.PopulateDeoptimizationData(code); |
117 cgen.PopulateTypeFeedbackInfo(code); | 116 cgen.PopulateTypeFeedbackInfo(code); |
118 cgen.PopulateHandlerTable(code); | |
119 code->set_has_deoptimization_support(info->HasDeoptimizationSupport()); | 117 code->set_has_deoptimization_support(info->HasDeoptimizationSupport()); |
120 code->set_has_reloc_info_for_serialization(info->will_serialize()); | 118 code->set_has_reloc_info_for_serialization(info->will_serialize()); |
121 code->set_allow_osr_at_loop_nesting_level(0); | 119 code->set_allow_osr_at_loop_nesting_level(0); |
122 code->set_profiler_ticks(0); | 120 code->set_profiler_ticks(0); |
123 code->set_back_edge_table_offset(table_offset); | 121 code->set_back_edge_table_offset(table_offset); |
124 Handle<ByteArray> source_positions = | 122 Handle<ByteArray> source_positions = |
125 cgen.source_position_table_builder_.ToSourcePositionTable( | 123 cgen.source_position_table_builder_.ToSourcePositionTable( |
126 isolate, Handle<AbstractCode>::cast(code)); | 124 isolate, Handle<AbstractCode>::cast(code)); |
127 code->set_source_position_table(*source_positions); | 125 code->set_source_position_table(*source_positions); |
128 CodeGenerator::PrintCode(code, info); | 126 CodeGenerator::PrintCode(code, info); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
169 | 167 |
170 | 168 |
171 void FullCodeGenerator::PopulateTypeFeedbackInfo(Handle<Code> code) { | 169 void FullCodeGenerator::PopulateTypeFeedbackInfo(Handle<Code> code) { |
172 Handle<TypeFeedbackInfo> info = isolate()->factory()->NewTypeFeedbackInfo(); | 170 Handle<TypeFeedbackInfo> info = isolate()->factory()->NewTypeFeedbackInfo(); |
173 info->set_ic_total_count(ic_total_count_); | 171 info->set_ic_total_count(ic_total_count_); |
174 DCHECK(!isolate()->heap()->InNewSpace(*info)); | 172 DCHECK(!isolate()->heap()->InNewSpace(*info)); |
175 code->set_type_feedback_info(*info); | 173 code->set_type_feedback_info(*info); |
176 } | 174 } |
177 | 175 |
178 | 176 |
179 void FullCodeGenerator::PopulateHandlerTable(Handle<Code> code) { | |
180 int handler_table_size = static_cast<int>(handler_table_.size()); | |
181 Handle<HandlerTable> table = | |
182 Handle<HandlerTable>::cast(isolate()->factory()->NewFixedArray( | |
183 HandlerTable::LengthForRange(handler_table_size), TENURED)); | |
184 for (int i = 0; i < handler_table_size; ++i) { | |
185 table->SetRangeStart(i, handler_table_[i].range_start); | |
186 table->SetRangeEnd(i, handler_table_[i].range_end); | |
187 table->SetRangeHandler(i, handler_table_[i].handler_offset, | |
188 handler_table_[i].catch_prediction); | |
189 table->SetRangeData(i, handler_table_[i].stack_depth); | |
190 } | |
191 code->set_handler_table(*table); | |
192 } | |
193 | |
194 | |
195 int FullCodeGenerator::NewHandlerTableEntry() { | |
196 int index = static_cast<int>(handler_table_.size()); | |
197 HandlerTableEntry entry = {0, 0, 0, 0, HandlerTable::UNCAUGHT}; | |
198 handler_table_.push_back(entry); | |
199 return index; | |
200 } | |
201 | |
202 | |
203 bool FullCodeGenerator::MustCreateObjectLiteralWithRuntime( | 177 bool FullCodeGenerator::MustCreateObjectLiteralWithRuntime( |
204 ObjectLiteral* expr) const { | 178 ObjectLiteral* expr) const { |
205 return masm()->serializer_enabled() || | 179 return masm()->serializer_enabled() || |
206 !FastCloneShallowObjectStub::IsSupported(expr); | 180 !FastCloneShallowObjectStub::IsSupported(expr); |
207 } | 181 } |
208 | 182 |
209 | 183 |
210 bool FullCodeGenerator::MustCreateArrayLiteralWithRuntime( | 184 bool FullCodeGenerator::MustCreateArrayLiteralWithRuntime( |
211 ArrayLiteral* expr) const { | 185 ArrayLiteral* expr) const { |
212 return expr->depth() > 1 || | 186 return expr->depth() > 1 || |
(...skipping 769 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
982 PrepareForBailoutForId(stmt->ElseId(), BailoutState::NO_REGISTERS); | 956 PrepareForBailoutForId(stmt->ElseId(), BailoutState::NO_REGISTERS); |
983 } | 957 } |
984 __ bind(&done); | 958 __ bind(&done); |
985 PrepareForBailoutForId(stmt->IfId(), BailoutState::NO_REGISTERS); | 959 PrepareForBailoutForId(stmt->IfId(), BailoutState::NO_REGISTERS); |
986 } | 960 } |
987 | 961 |
988 void FullCodeGenerator::EmitContinue(Statement* target) { | 962 void FullCodeGenerator::EmitContinue(Statement* target) { |
989 NestedStatement* current = nesting_stack_; | 963 NestedStatement* current = nesting_stack_; |
990 int context_length = 0; | 964 int context_length = 0; |
991 // When continuing, we clobber the unpredictable value in the accumulator | 965 // When continuing, we clobber the unpredictable value in the accumulator |
992 // with one that's safe for GC. If we hit an exit from the try block of | 966 // with one that's safe for GC. |
993 // try...finally on our way out, we will unconditionally preserve the | |
994 // accumulator on the stack. | |
995 ClearAccumulator(); | 967 ClearAccumulator(); |
996 while (!current->IsContinueTarget(target)) { | 968 while (!current->IsContinueTarget(target)) { |
997 if (HasStackOverflow()) return; | 969 if (HasStackOverflow()) return; |
998 if (current->IsTryFinally()) { | |
999 Comment cmnt(masm(), "[ Deferred continue through finally"); | |
1000 current->Exit(&context_length); | |
1001 DCHECK_EQ(-1, context_length); | |
1002 current->AsTryFinally()->deferred_commands()->RecordContinue(target); | |
1003 return; | |
1004 } | |
1005 current = current->Exit(&context_length); | 970 current = current->Exit(&context_length); |
1006 } | 971 } |
1007 int stack_depth = current->GetStackDepthAtTarget(); | 972 int stack_depth = current->GetStackDepthAtTarget(); |
1008 int stack_drop = operand_stack_depth_ - stack_depth; | 973 int stack_drop = operand_stack_depth_ - stack_depth; |
1009 DCHECK_GE(stack_drop, 0); | 974 DCHECK_GE(stack_drop, 0); |
1010 __ Drop(stack_drop); | 975 __ Drop(stack_drop); |
1011 if (context_length > 0) { | 976 if (context_length > 0) { |
1012 while (context_length > 0) { | 977 while (context_length > 0) { |
1013 LoadContextField(context_register(), Context::PREVIOUS_INDEX); | 978 LoadContextField(context_register(), Context::PREVIOUS_INDEX); |
1014 --context_length; | 979 --context_length; |
1015 } | 980 } |
1016 StoreToFrameField(StandardFrameConstants::kContextOffset, | 981 StoreToFrameField(StandardFrameConstants::kContextOffset, |
1017 context_register()); | 982 context_register()); |
1018 } | 983 } |
1019 | 984 |
1020 __ jmp(current->AsIteration()->continue_label()); | 985 __ jmp(current->AsIteration()->continue_label()); |
1021 } | 986 } |
1022 | 987 |
1023 void FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) { | 988 void FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) { |
1024 Comment cmnt(masm_, "[ ContinueStatement"); | 989 Comment cmnt(masm_, "[ ContinueStatement"); |
1025 SetStatementPosition(stmt); | 990 SetStatementPosition(stmt); |
1026 EmitContinue(stmt->target()); | 991 EmitContinue(stmt->target()); |
1027 } | 992 } |
1028 | 993 |
1029 void FullCodeGenerator::EmitBreak(Statement* target) { | 994 void FullCodeGenerator::EmitBreak(Statement* target) { |
1030 NestedStatement* current = nesting_stack_; | 995 NestedStatement* current = nesting_stack_; |
1031 int context_length = 0; | 996 int context_length = 0; |
1032 // When breaking, we clobber the unpredictable value in the accumulator | 997 // When breaking, we clobber the unpredictable value in the accumulator |
1033 // with one that's safe for GC. If we hit an exit from the try block of | 998 // with one that's safe for GC. |
1034 // try...finally on our way out, we will unconditionally preserve the | |
1035 // accumulator on the stack. | |
1036 ClearAccumulator(); | 999 ClearAccumulator(); |
1037 while (!current->IsBreakTarget(target)) { | 1000 while (!current->IsBreakTarget(target)) { |
1038 if (HasStackOverflow()) return; | 1001 if (HasStackOverflow()) return; |
1039 if (current->IsTryFinally()) { | |
1040 Comment cmnt(masm(), "[ Deferred break through finally"); | |
1041 current->Exit(&context_length); | |
1042 DCHECK_EQ(-1, context_length); | |
1043 current->AsTryFinally()->deferred_commands()->RecordBreak(target); | |
1044 return; | |
1045 } | |
1046 current = current->Exit(&context_length); | 1002 current = current->Exit(&context_length); |
1047 } | 1003 } |
1048 int stack_depth = current->GetStackDepthAtTarget(); | 1004 int stack_depth = current->GetStackDepthAtTarget(); |
1049 int stack_drop = operand_stack_depth_ - stack_depth; | 1005 int stack_drop = operand_stack_depth_ - stack_depth; |
1050 DCHECK_GE(stack_drop, 0); | 1006 DCHECK_GE(stack_drop, 0); |
1051 __ Drop(stack_drop); | 1007 __ Drop(stack_drop); |
1052 if (context_length > 0) { | 1008 if (context_length > 0) { |
1053 while (context_length > 0) { | 1009 while (context_length > 0) { |
1054 LoadContextField(context_register(), Context::PREVIOUS_INDEX); | 1010 LoadContextField(context_register(), Context::PREVIOUS_INDEX); |
1055 --context_length; | 1011 --context_length; |
1056 } | 1012 } |
1057 StoreToFrameField(StandardFrameConstants::kContextOffset, | 1013 StoreToFrameField(StandardFrameConstants::kContextOffset, |
1058 context_register()); | 1014 context_register()); |
1059 } | 1015 } |
1060 | 1016 |
1061 __ jmp(current->AsBreakable()->break_label()); | 1017 __ jmp(current->AsBreakable()->break_label()); |
1062 } | 1018 } |
1063 | 1019 |
1064 void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) { | 1020 void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) { |
1065 Comment cmnt(masm_, "[ BreakStatement"); | 1021 Comment cmnt(masm_, "[ BreakStatement"); |
1066 SetStatementPosition(stmt); | 1022 SetStatementPosition(stmt); |
1067 EmitBreak(stmt->target()); | 1023 EmitBreak(stmt->target()); |
1068 } | 1024 } |
1069 | 1025 |
1070 void FullCodeGenerator::EmitUnwindAndReturn() { | 1026 void FullCodeGenerator::EmitUnwindAndReturn() { |
1071 NestedStatement* current = nesting_stack_; | 1027 NestedStatement* current = nesting_stack_; |
1072 int context_length = 0; | 1028 int context_length = 0; |
1073 while (current != NULL) { | 1029 while (current != NULL) { |
1074 if (HasStackOverflow()) return; | 1030 if (HasStackOverflow()) return; |
1075 if (current->IsTryFinally()) { | |
1076 Comment cmnt(masm(), "[ Deferred return through finally"); | |
1077 current->Exit(&context_length); | |
1078 DCHECK_EQ(-1, context_length); | |
1079 current->AsTryFinally()->deferred_commands()->RecordReturn(); | |
1080 return; | |
1081 } | |
1082 current = current->Exit(&context_length); | 1031 current = current->Exit(&context_length); |
1083 } | 1032 } |
1084 EmitReturnSequence(); | 1033 EmitReturnSequence(); |
1085 } | 1034 } |
1086 | 1035 |
1087 void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info, | 1036 void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info, |
1088 bool pretenure) { | 1037 bool pretenure) { |
1089 // If we're running with the --always-opt or the --prepare-always-opt | 1038 // If we're running with the --always-opt or the --prepare-always-opt |
1090 // flag, we need to use the runtime function so that the new function | 1039 // flag, we need to use the runtime function so that the new function |
1091 // we are creating here gets a chance to have its code optimized and | 1040 // we are creating here gets a chance to have its code optimized and |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1353 decrement_loop_depth(); | 1302 decrement_loop_depth(); |
1354 } | 1303 } |
1355 | 1304 |
1356 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { | 1305 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
1357 LoadFromFrameField(JavaScriptFrameConstants::kFunctionOffset, | 1306 LoadFromFrameField(JavaScriptFrameConstants::kFunctionOffset, |
1358 result_register()); | 1307 result_register()); |
1359 context()->Plug(result_register()); | 1308 context()->Plug(result_register()); |
1360 } | 1309 } |
1361 | 1310 |
1362 void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { | 1311 void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { |
1363 Comment cmnt(masm_, "[ TryCatchStatement"); | 1312 // Exception handling is not supported. |
1364 SetStatementPosition(stmt, SKIP_BREAK); | 1313 UNREACHABLE(); |
1365 | |
1366 // The try block adds a handler to the exception handler chain before | |
1367 // entering, and removes it again when exiting normally. If an exception | |
1368 // is thrown during execution of the try block, the handler is consumed | |
1369 // and control is passed to the catch block with the exception in the | |
1370 // result register. | |
1371 | |
1372 Label try_entry, handler_entry, exit; | |
1373 __ jmp(&try_entry); | |
1374 __ bind(&handler_entry); | |
1375 if (stmt->clear_pending_message()) ClearPendingMessage(); | |
1376 | |
1377 // Exception handler code, the exception is in the result register. | |
1378 // Extend the context before executing the catch block. | |
1379 { Comment cmnt(masm_, "[ Extend catch context"); | |
1380 PushOperand(stmt->variable()->name()); | |
1381 PushOperand(result_register()); | |
1382 PushOperand(stmt->scope()->scope_info()); | |
1383 PushFunctionArgumentForContextAllocation(); | |
1384 CallRuntimeWithOperands(Runtime::kPushCatchContext); | |
1385 StoreToFrameField(StandardFrameConstants::kContextOffset, | |
1386 context_register()); | |
1387 } | |
1388 | |
1389 Scope* saved_scope = scope(); | |
1390 scope_ = stmt->scope(); | |
1391 DCHECK(scope_->declarations()->is_empty()); | |
1392 { WithOrCatch catch_body(this); | |
1393 Visit(stmt->catch_block()); | |
1394 } | |
1395 // Restore the context. | |
1396 LoadContextField(context_register(), Context::PREVIOUS_INDEX); | |
1397 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); | |
1398 scope_ = saved_scope; | |
1399 __ jmp(&exit); | |
1400 | |
1401 // Try block code. Sets up the exception handler chain. | |
1402 __ bind(&try_entry); | |
1403 | |
1404 int handler_index = NewHandlerTableEntry(); | |
1405 EnterTryBlock(handler_index, &handler_entry, stmt->catch_prediction()); | |
1406 { | |
1407 Comment cmnt_try(masm(), "[ Try block"); | |
1408 Visit(stmt->try_block()); | |
1409 } | |
1410 ExitTryBlock(handler_index); | |
1411 __ bind(&exit); | |
1412 } | 1314 } |
1413 | 1315 |
1414 | 1316 |
1415 void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) { | 1317 void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) { |
1416 Comment cmnt(masm_, "[ TryFinallyStatement"); | 1318 // Exception handling is not supported. |
1417 SetStatementPosition(stmt, SKIP_BREAK); | 1319 UNREACHABLE(); |
1418 | |
1419 // Try finally is compiled by setting up a try-handler on the stack while | |
1420 // executing the try body, and removing it again afterwards. | |
1421 // | |
1422 // The try-finally construct can enter the finally block in three ways: | |
1423 // 1. By exiting the try-block normally. This exits the try block, | |
1424 // pushes the continuation token and falls through to the finally | |
1425 // block. | |
1426 // 2. By exiting the try-block with a function-local control flow transfer | |
1427 // (break/continue/return). The site of the, e.g., break exits the | |
1428 // try block, pushes the continuation token and jumps to the | |
1429 // finally block. After the finally block executes, the execution | |
1430 // continues based on the continuation token to a block that | |
1431 // continues with the control flow transfer. | |
1432 // 3. By exiting the try-block with a thrown exception. In the handler, | |
1433 // we push the exception and continuation token and jump to the | |
1434 // finally block (which will again dispatch based on the token once | |
1435 // it is finished). | |
1436 | |
1437 Label try_entry, handler_entry, finally_entry; | |
1438 DeferredCommands deferred(this, &finally_entry); | |
1439 | |
1440 // Jump to try-handler setup and try-block code. | |
1441 __ jmp(&try_entry); | |
1442 __ bind(&handler_entry); | |
1443 | |
1444 // Exception handler code. This code is only executed when an exception | |
1445 // is thrown. Record the continuation and jump to the finally block. | |
1446 { | |
1447 Comment cmnt_handler(masm(), "[ Finally handler"); | |
1448 deferred.RecordThrow(); | |
1449 } | |
1450 | |
1451 // Set up try handler. | |
1452 __ bind(&try_entry); | |
1453 int handler_index = NewHandlerTableEntry(); | |
1454 EnterTryBlock(handler_index, &handler_entry, stmt->catch_prediction()); | |
1455 { | |
1456 Comment cmnt_try(masm(), "[ Try block"); | |
1457 TryFinally try_body(this, &deferred); | |
1458 Visit(stmt->try_block()); | |
1459 } | |
1460 ExitTryBlock(handler_index); | |
1461 // Execute the finally block on the way out. Clobber the unpredictable | |
1462 // value in the result register with one that's safe for GC because the | |
1463 // finally block will unconditionally preserve the result register on the | |
1464 // stack. | |
1465 ClearAccumulator(); | |
1466 deferred.EmitFallThrough(); | |
1467 // Fall through to the finally block. | |
1468 | |
1469 // Finally block implementation. | |
1470 __ bind(&finally_entry); | |
1471 { | |
1472 Comment cmnt_finally(masm(), "[ Finally block"); | |
1473 OperandStackDepthIncrement(2); // Token and accumulator are on stack. | |
1474 EnterFinallyBlock(); | |
1475 Visit(stmt->finally_block()); | |
1476 ExitFinallyBlock(); | |
1477 OperandStackDepthDecrement(2); // Token and accumulator were on stack. | |
1478 } | |
1479 | |
1480 { | |
1481 Comment cmnt_deferred(masm(), "[ Post-finally dispatch"); | |
1482 deferred.EmitCommands(); // Return to the calling code. | |
1483 } | |
1484 } | 1320 } |
1485 | 1321 |
1486 | 1322 |
1487 void FullCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) { | 1323 void FullCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) { |
1488 Comment cmnt(masm_, "[ DebuggerStatement"); | 1324 Comment cmnt(masm_, "[ DebuggerStatement"); |
1489 SetStatementPosition(stmt); | 1325 SetStatementPosition(stmt); |
1490 | 1326 |
1491 __ DebugBreak(); | 1327 __ DebugBreak(); |
1492 // Ignore the return value. | 1328 // Ignore the return value. |
1493 | 1329 |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1623 VisitForStackValue(expr->exception()); | 1459 VisitForStackValue(expr->exception()); |
1624 SetExpressionPosition(expr); | 1460 SetExpressionPosition(expr); |
1625 CallRuntimeWithOperands(Runtime::kThrow); | 1461 CallRuntimeWithOperands(Runtime::kThrow); |
1626 // Never returns here. | 1462 // Never returns here. |
1627 | 1463 |
1628 // Even though this expression doesn't produce a value, we need to simulate | 1464 // Even though this expression doesn't produce a value, we need to simulate |
1629 // plugging of the value context to ensure stack depth tracking is in sync. | 1465 // plugging of the value context to ensure stack depth tracking is in sync. |
1630 if (context()->IsStackValue()) OperandStackDepthIncrement(1); | 1466 if (context()->IsStackValue()) OperandStackDepthIncrement(1); |
1631 } | 1467 } |
1632 | 1468 |
1633 void FullCodeGenerator::EnterTryBlock( | |
1634 int handler_index, Label* handler, | |
1635 HandlerTable::CatchPrediction catch_prediction) { | |
1636 HandlerTableEntry* entry = &handler_table_[handler_index]; | |
1637 entry->range_start = masm()->pc_offset(); | |
1638 entry->handler_offset = handler->pos(); | |
1639 entry->stack_depth = operand_stack_depth_; | |
1640 entry->catch_prediction = catch_prediction; | |
1641 | |
1642 // We are using the operand stack depth, check for accuracy. | |
1643 EmitOperandStackDepthCheck(); | |
1644 | |
1645 // Push context onto operand stack. | |
1646 STATIC_ASSERT(TryBlockConstant::kElementCount == 1); | |
1647 PushOperand(context_register()); | |
1648 } | |
1649 | |
1650 | |
1651 void FullCodeGenerator::ExitTryBlock(int handler_index) { | |
1652 HandlerTableEntry* entry = &handler_table_[handler_index]; | |
1653 entry->range_end = masm()->pc_offset(); | |
1654 | |
1655 // Drop context from operand stack. | |
1656 DropOperands(TryBlockConstant::kElementCount); | |
1657 } | |
1658 | |
1659 | 1469 |
1660 void FullCodeGenerator::VisitCall(Call* expr) { | 1470 void FullCodeGenerator::VisitCall(Call* expr) { |
1661 #ifdef DEBUG | 1471 #ifdef DEBUG |
1662 // We want to verify that RecordJSReturnSite gets called on all paths | 1472 // We want to verify that RecordJSReturnSite gets called on all paths |
1663 // through this function. Avoid early returns. | 1473 // through this function. Avoid early returns. |
1664 expr->return_is_recorded_ = false; | 1474 expr->return_is_recorded_ = false; |
1665 #endif | 1475 #endif |
1666 | 1476 |
1667 Comment cmnt(masm_, (expr->tail_call_mode() == TailCallMode::kAllow) | 1477 Comment cmnt(masm_, (expr->tail_call_mode() == TailCallMode::kAllow) |
1668 ? "[ TailCall" | 1478 ? "[ TailCall" |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1769 | 1579 |
1770 void FullCodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) { | 1580 void FullCodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) { |
1771 UNREACHABLE(); | 1581 UNREACHABLE(); |
1772 } | 1582 } |
1773 | 1583 |
1774 | 1584 |
1775 void FullCodeGenerator::VisitRewritableExpression(RewritableExpression* expr) { | 1585 void FullCodeGenerator::VisitRewritableExpression(RewritableExpression* expr) { |
1776 Visit(expr->expression()); | 1586 Visit(expr->expression()); |
1777 } | 1587 } |
1778 | 1588 |
1779 FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit( | |
1780 int* context_length) { | |
1781 // The macros used here must preserve the result register. | |
1782 | |
1783 // Calculate how many operands to drop to get down to handler block. | |
1784 int stack_drop = codegen_->operand_stack_depth_ - GetStackDepthAtTarget(); | |
1785 DCHECK_GE(stack_drop, 0); | |
1786 | |
1787 // Because the handler block contains the context of the finally | |
1788 // code, we can restore it directly from there for the finally code | |
1789 // rather than iteratively unwinding contexts via their previous | |
1790 // links. | |
1791 if (*context_length > 0) { | |
1792 __ Drop(stack_drop); // Down to the handler block. | |
1793 // Restore the context to its dedicated register and the stack. | |
1794 STATIC_ASSERT(TryBlockConstant::kElementCount == 1); | |
1795 __ Pop(codegen_->context_register()); | |
1796 codegen_->StoreToFrameField(StandardFrameConstants::kContextOffset, | |
1797 codegen_->context_register()); | |
1798 } else { | |
1799 // Down to the handler block and also drop context. | |
1800 __ Drop(stack_drop + TryBlockConstant::kElementCount); | |
1801 } | |
1802 | |
1803 // The caller will ignore outputs. | |
1804 *context_length = -1; | |
1805 return previous_; | |
1806 } | |
1807 | |
1808 void FullCodeGenerator::DeferredCommands::RecordBreak(Statement* target) { | |
1809 TokenId token = dispenser_.GetBreakContinueToken(); | |
1810 commands_.push_back({kBreak, token, target}); | |
1811 EmitJumpToFinally(token); | |
1812 } | |
1813 | |
1814 void FullCodeGenerator::DeferredCommands::RecordContinue(Statement* target) { | |
1815 TokenId token = dispenser_.GetBreakContinueToken(); | |
1816 commands_.push_back({kContinue, token, target}); | |
1817 EmitJumpToFinally(token); | |
1818 } | |
1819 | |
1820 void FullCodeGenerator::DeferredCommands::RecordReturn() { | |
1821 if (return_token_ == TokenDispenserForFinally::kInvalidToken) { | |
1822 return_token_ = TokenDispenserForFinally::kReturnToken; | |
1823 commands_.push_back({kReturn, return_token_, nullptr}); | |
1824 } | |
1825 EmitJumpToFinally(return_token_); | |
1826 } | |
1827 | |
1828 void FullCodeGenerator::DeferredCommands::RecordThrow() { | |
1829 if (throw_token_ == TokenDispenserForFinally::kInvalidToken) { | |
1830 throw_token_ = TokenDispenserForFinally::kThrowToken; | |
1831 commands_.push_back({kThrow, throw_token_, nullptr}); | |
1832 } | |
1833 EmitJumpToFinally(throw_token_); | |
1834 } | |
1835 | |
1836 void FullCodeGenerator::DeferredCommands::EmitFallThrough() { | |
1837 __ Push(Smi::FromInt(TokenDispenserForFinally::kFallThroughToken)); | |
1838 __ Push(result_register()); | |
1839 } | |
1840 | |
1841 void FullCodeGenerator::DeferredCommands::EmitJumpToFinally(TokenId token) { | |
1842 __ Push(Smi::FromInt(token)); | |
1843 __ Push(result_register()); | |
1844 __ jmp(finally_entry_); | |
1845 } | |
1846 | 1589 |
1847 bool FullCodeGenerator::TryLiteralCompare(CompareOperation* expr) { | 1590 bool FullCodeGenerator::TryLiteralCompare(CompareOperation* expr) { |
1848 Expression* sub_expr; | 1591 Expression* sub_expr; |
1849 Handle<String> check; | 1592 Handle<String> check; |
1850 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) { | 1593 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) { |
1851 SetExpressionPosition(expr); | 1594 SetExpressionPosition(expr); |
1852 EmitLiteralCompareTypeof(expr, sub_expr, check); | 1595 EmitLiteralCompareTypeof(expr, sub_expr, check); |
1853 return true; | 1596 return true; |
1854 } | 1597 } |
1855 | 1598 |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1995 return info_->has_simple_parameters(); | 1738 return info_->has_simple_parameters(); |
1996 } | 1739 } |
1997 | 1740 |
1998 FunctionLiteral* FullCodeGenerator::literal() const { return info_->literal(); } | 1741 FunctionLiteral* FullCodeGenerator::literal() const { return info_->literal(); } |
1999 | 1742 |
2000 #undef __ | 1743 #undef __ |
2001 | 1744 |
2002 | 1745 |
2003 } // namespace internal | 1746 } // namespace internal |
2004 } // namespace v8 | 1747 } // namespace v8 |
OLD | NEW |