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/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/ast.h" | 7 #include "src/ast.h" |
8 #include "src/ast-numbering.h" | 8 #include "src/ast-numbering.h" |
9 #include "src/code-factory.h" | 9 #include "src/code-factory.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
11 #include "src/compiler.h" | 11 #include "src/compiler.h" |
12 #include "src/debug.h" | 12 #include "src/debug.h" |
13 #include "src/full-codegen.h" | 13 #include "src/full-codegen.h" |
14 #include "src/liveedit.h" | 14 #include "src/liveedit.h" |
15 #include "src/macro-assembler.h" | 15 #include "src/macro-assembler.h" |
16 #include "src/prettyprinter.h" | 16 #include "src/prettyprinter.h" |
17 #include "src/scopeinfo.h" | 17 #include "src/scopeinfo.h" |
18 #include "src/scopes.h" | 18 #include "src/scopes.h" |
19 #include "src/snapshot/snapshot.h" | 19 #include "src/snapshot/snapshot.h" |
20 | 20 |
21 namespace v8 { | 21 namespace v8 { |
22 namespace internal { | 22 namespace internal { |
23 | 23 |
24 void BreakableStatementChecker::Check(Statement* stmt) { | |
25 Visit(stmt); | |
26 } | |
27 | |
28 | |
29 void BreakableStatementChecker::Check(Expression* expr) { | |
30 Visit(expr); | |
31 } | |
32 | |
33 | |
34 void BreakableStatementChecker::VisitVariableDeclaration( | |
35 VariableDeclaration* decl) { | |
36 } | |
37 | |
38 | |
39 void BreakableStatementChecker::VisitFunctionDeclaration( | |
40 FunctionDeclaration* decl) { | |
41 } | |
42 | |
43 | |
44 void BreakableStatementChecker::VisitImportDeclaration( | |
45 ImportDeclaration* decl) { | |
46 } | |
47 | |
48 | |
49 void BreakableStatementChecker::VisitExportDeclaration( | |
50 ExportDeclaration* decl) { | |
51 } | |
52 | |
53 | |
54 void BreakableStatementChecker::VisitBlock(Block* stmt) { | |
55 } | |
56 | |
57 | |
58 void BreakableStatementChecker::VisitExpressionStatement( | |
59 ExpressionStatement* stmt) { | |
60 // Check if expression is breakable. | |
61 Visit(stmt->expression()); | |
62 } | |
63 | |
64 | |
65 void BreakableStatementChecker::VisitEmptyStatement(EmptyStatement* stmt) { | |
66 } | |
67 | |
68 | |
69 void BreakableStatementChecker::VisitIfStatement(IfStatement* stmt) { | |
70 // If the condition is breakable the if statement is breakable. | |
71 Visit(stmt->condition()); | |
72 } | |
73 | |
74 | |
75 void BreakableStatementChecker::VisitContinueStatement( | |
76 ContinueStatement* stmt) { | |
77 } | |
78 | |
79 | |
80 void BreakableStatementChecker::VisitBreakStatement(BreakStatement* stmt) { | |
81 } | |
82 | |
83 | |
84 void BreakableStatementChecker::VisitReturnStatement(ReturnStatement* stmt) { | |
85 // Return is breakable if the expression is. | |
86 Visit(stmt->expression()); | |
87 } | |
88 | |
89 | |
90 void BreakableStatementChecker::VisitWithStatement(WithStatement* stmt) { | |
91 Visit(stmt->expression()); | |
92 } | |
93 | |
94 | |
95 void BreakableStatementChecker::VisitSwitchStatement(SwitchStatement* stmt) { | |
96 // Switch statements breakable if the tag expression is. | |
97 Visit(stmt->tag()); | |
98 } | |
99 | |
100 | |
101 void BreakableStatementChecker::VisitDoWhileStatement(DoWhileStatement* stmt) { | |
102 // Mark do while as breakable to avoid adding a break slot in front of it. | |
103 is_breakable_ = true; | |
104 } | |
105 | |
106 | |
107 void BreakableStatementChecker::VisitWhileStatement(WhileStatement* stmt) { | |
108 // Mark while statements breakable if the condition expression is. | |
109 Visit(stmt->cond()); | |
110 } | |
111 | |
112 | |
113 void BreakableStatementChecker::VisitForStatement(ForStatement* stmt) { | |
114 // We set positions for both init and condition, if they exist. | |
115 if (stmt->cond() != NULL || stmt->init() != NULL) is_breakable_ = true; | |
116 } | |
117 | |
118 | |
119 void BreakableStatementChecker::VisitForInStatement(ForInStatement* stmt) { | |
120 // For-in is breakable because we set the position for the enumerable. | |
121 is_breakable_ = true; | |
122 } | |
123 | |
124 | |
125 void BreakableStatementChecker::VisitForOfStatement(ForOfStatement* stmt) { | |
126 // For-of is breakable because we set the position for the next() call. | |
127 is_breakable_ = true; | |
128 } | |
129 | |
130 | |
131 void BreakableStatementChecker::VisitTryCatchStatement( | |
132 TryCatchStatement* stmt) { | |
133 // Mark try catch as breakable to avoid adding a break slot in front of it. | |
134 is_breakable_ = true; | |
135 } | |
136 | |
137 | |
138 void BreakableStatementChecker::VisitTryFinallyStatement( | |
139 TryFinallyStatement* stmt) { | |
140 // Mark try finally as breakable to avoid adding a break slot in front of it. | |
141 is_breakable_ = true; | |
142 } | |
143 | |
144 | |
145 void BreakableStatementChecker::VisitDebuggerStatement( | |
146 DebuggerStatement* stmt) { | |
147 // The debugger statement is breakable. | |
148 is_breakable_ = true; | |
149 } | |
150 | |
151 | |
152 void BreakableStatementChecker::VisitCaseClause(CaseClause* clause) { | |
153 } | |
154 | |
155 | |
156 void BreakableStatementChecker::VisitFunctionLiteral(FunctionLiteral* expr) { | |
157 } | |
158 | |
159 | |
160 void BreakableStatementChecker::VisitClassLiteral(ClassLiteral* expr) { | |
161 if (expr->extends() != NULL) { | |
162 Visit(expr->extends()); | |
163 } | |
164 } | |
165 | |
166 | |
167 void BreakableStatementChecker::VisitNativeFunctionLiteral( | |
168 NativeFunctionLiteral* expr) { | |
169 } | |
170 | |
171 | |
172 void BreakableStatementChecker::VisitConditional(Conditional* expr) { | |
173 } | |
174 | |
175 | |
176 void BreakableStatementChecker::VisitVariableProxy(VariableProxy* expr) { | |
177 } | |
178 | |
179 | |
180 void BreakableStatementChecker::VisitLiteral(Literal* expr) { | |
181 } | |
182 | |
183 | |
184 void BreakableStatementChecker::VisitRegExpLiteral(RegExpLiteral* expr) { | |
185 } | |
186 | |
187 | |
188 void BreakableStatementChecker::VisitObjectLiteral(ObjectLiteral* expr) { | |
189 } | |
190 | |
191 | |
192 void BreakableStatementChecker::VisitArrayLiteral(ArrayLiteral* expr) { | |
193 } | |
194 | |
195 | |
196 void BreakableStatementChecker::VisitAssignment(Assignment* expr) { | |
197 // If assigning to a property (including a global property) the assignment is | |
198 // breakable. | |
199 VariableProxy* proxy = expr->target()->AsVariableProxy(); | |
200 Property* prop = expr->target()->AsProperty(); | |
201 if (prop != NULL || (proxy != NULL && proxy->var()->IsUnallocated())) { | |
202 is_breakable_ = true; | |
203 return; | |
204 } | |
205 | |
206 // Otherwise the assignment is breakable if the assigned value is. | |
207 Visit(expr->value()); | |
208 } | |
209 | |
210 | |
211 void BreakableStatementChecker::VisitYield(Yield* expr) { | |
212 // Yield is breakable if the expression is. | |
213 Visit(expr->expression()); | |
214 } | |
215 | |
216 | |
217 void BreakableStatementChecker::VisitThrow(Throw* expr) { | |
218 // Throw is breakable if the expression is. | |
219 Visit(expr->exception()); | |
220 } | |
221 | |
222 | |
223 void BreakableStatementChecker::VisitProperty(Property* expr) { | |
224 // Property load is breakable. | |
225 is_breakable_ = true; | |
226 } | |
227 | |
228 | |
229 void BreakableStatementChecker::VisitCall(Call* expr) { | |
230 // Function calls both through IC and call stub are breakable. | |
231 is_breakable_ = true; | |
232 } | |
233 | |
234 | |
235 void BreakableStatementChecker::VisitCallNew(CallNew* expr) { | |
236 // Function calls through new are breakable. | |
237 is_breakable_ = true; | |
238 } | |
239 | |
240 | |
241 void BreakableStatementChecker::VisitCallRuntime(CallRuntime* expr) { | |
242 } | |
243 | |
244 | |
245 void BreakableStatementChecker::VisitUnaryOperation(UnaryOperation* expr) { | |
246 Visit(expr->expression()); | |
247 } | |
248 | |
249 | |
250 void BreakableStatementChecker::VisitCountOperation(CountOperation* expr) { | |
251 Visit(expr->expression()); | |
252 } | |
253 | |
254 | |
255 void BreakableStatementChecker::VisitBinaryOperation(BinaryOperation* expr) { | |
256 Visit(expr->left()); | |
257 if (expr->op() != Token::AND && | |
258 expr->op() != Token::OR) { | |
259 Visit(expr->right()); | |
260 } | |
261 } | |
262 | |
263 | |
264 void BreakableStatementChecker::VisitCompareOperation(CompareOperation* expr) { | |
265 Visit(expr->left()); | |
266 Visit(expr->right()); | |
267 } | |
268 | |
269 | |
270 void BreakableStatementChecker::VisitSpread(Spread* expr) { | |
271 Visit(expr->expression()); | |
272 } | |
273 | |
274 | |
275 void BreakableStatementChecker::VisitThisFunction(ThisFunction* expr) { | |
276 } | |
277 | |
278 | |
279 void BreakableStatementChecker::VisitSuperPropertyReference( | |
280 SuperPropertyReference* expr) {} | |
281 | |
282 | |
283 void BreakableStatementChecker::VisitSuperCallReference( | |
284 SuperCallReference* expr) {} | |
285 | |
286 | |
287 #define __ ACCESS_MASM(masm()) | 24 #define __ ACCESS_MASM(masm()) |
288 | 25 |
289 bool FullCodeGenerator::MakeCode(CompilationInfo* info) { | 26 bool FullCodeGenerator::MakeCode(CompilationInfo* info) { |
290 Isolate* isolate = info->isolate(); | 27 Isolate* isolate = info->isolate(); |
291 | 28 |
292 TimerEventScope<TimerEventCompileFullCode> timer(info->isolate()); | 29 TimerEventScope<TimerEventCompileFullCode> timer(info->isolate()); |
293 | 30 |
294 // Ensure that the feedback vector is large enough. | 31 // Ensure that the feedback vector is large enough. |
295 info->EnsureFeedbackVector(); | 32 info->EnsureFeedbackVector(); |
296 | 33 |
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
663 | 400 |
664 | 401 |
665 int FullCodeGenerator::DeclareGlobalsFlags() { | 402 int FullCodeGenerator::DeclareGlobalsFlags() { |
666 DCHECK(DeclareGlobalsLanguageMode::is_valid(language_mode())); | 403 DCHECK(DeclareGlobalsLanguageMode::is_valid(language_mode())); |
667 return DeclareGlobalsEvalFlag::encode(is_eval()) | | 404 return DeclareGlobalsEvalFlag::encode(is_eval()) | |
668 DeclareGlobalsNativeFlag::encode(is_native()) | | 405 DeclareGlobalsNativeFlag::encode(is_native()) | |
669 DeclareGlobalsLanguageMode::encode(language_mode()); | 406 DeclareGlobalsLanguageMode::encode(language_mode()); |
670 } | 407 } |
671 | 408 |
672 | 409 |
| 410 bool RecordStatementPosition(MacroAssembler* masm, int pos) { |
| 411 if (pos == RelocInfo::kNoPosition) return false; |
| 412 masm->positions_recorder()->RecordStatementPosition(pos); |
| 413 masm->positions_recorder()->RecordPosition(pos); |
| 414 return masm->positions_recorder()->WriteRecordedPositions(); |
| 415 } |
| 416 |
| 417 |
| 418 bool RecordPosition(MacroAssembler* masm, int pos) { |
| 419 if (pos == RelocInfo::kNoPosition) return false; |
| 420 masm->positions_recorder()->RecordPosition(pos); |
| 421 return masm->positions_recorder()->WriteRecordedPositions(); |
| 422 } |
| 423 |
| 424 |
673 void FullCodeGenerator::SetFunctionPosition(FunctionLiteral* fun) { | 425 void FullCodeGenerator::SetFunctionPosition(FunctionLiteral* fun) { |
674 CodeGenerator::RecordPositions(masm_, fun->start_position()); | 426 RecordPosition(masm_, fun->start_position()); |
675 } | 427 } |
676 | 428 |
677 | 429 |
678 void FullCodeGenerator::SetReturnPosition(FunctionLiteral* fun) { | 430 void FullCodeGenerator::SetReturnPosition(FunctionLiteral* fun) { |
679 CodeGenerator::RecordPositions(masm_, fun->end_position() - 1); | 431 RecordStatementPosition(masm_, fun->end_position() - 1); |
680 } | 432 } |
681 | 433 |
682 | 434 |
683 void FullCodeGenerator::SetStatementPosition(Statement* stmt) { | 435 void FullCodeGenerator::SetStatementPosition( |
684 if (!info_->is_debug()) { | 436 Statement* stmt, FullCodeGenerator::InsertBreak insert_break) { |
685 CodeGenerator::RecordPositions(masm_, stmt->position()); | 437 if (stmt->position() == RelocInfo::kNoPosition) return; |
686 } else { | 438 bool recorded = RecordStatementPosition(masm_, stmt->position()); |
687 // Check if the statement will be breakable without adding a debug break | 439 if (recorded && insert_break == INSERT_BREAK && info_->is_debug() && |
688 // slot. | 440 !stmt->IsDebuggerStatement()) { |
689 BreakableStatementChecker checker(info_->isolate(), zone()); | 441 DebugCodegen::GenerateSlot(masm_); |
690 checker.Check(stmt); | |
691 // Record the statement position right here if the statement is not | |
692 // breakable. For breakable statements the actual recording of the | |
693 // position will be postponed to the breakable code (typically an IC). | |
694 bool position_recorded = CodeGenerator::RecordPositions( | |
695 masm_, stmt->position(), !checker.is_breakable()); | |
696 // If the position recording did record a new position generate a debug | |
697 // break slot to make the statement breakable. | |
698 if (position_recorded) { | |
699 DebugCodegen::GenerateSlot(masm_); | |
700 } | |
701 } | 442 } |
702 } | 443 } |
703 | 444 |
704 | 445 |
| 446 void FullCodeGenerator::SetExpressionPosition( |
| 447 Expression* expr, FullCodeGenerator::InsertBreak insert_break) { |
| 448 if (expr->position() == RelocInfo::kNoPosition) return; |
| 449 bool recorded = RecordPosition(masm_, expr->position()); |
| 450 if (recorded && insert_break == INSERT_BREAK && info_->is_debug()) { |
| 451 DebugCodegen::GenerateSlot(masm_); |
| 452 } |
| 453 } |
| 454 |
| 455 |
| 456 void FullCodeGenerator::SetExpressionAsStatementPosition(Expression* expr) { |
| 457 if (expr->position() == RelocInfo::kNoPosition) return; |
| 458 bool recorded = RecordStatementPosition(masm_, expr->position()); |
| 459 if (recorded && info_->is_debug()) DebugCodegen::GenerateSlot(masm_); |
| 460 } |
| 461 |
| 462 |
705 void FullCodeGenerator::VisitSuperPropertyReference( | 463 void FullCodeGenerator::VisitSuperPropertyReference( |
706 SuperPropertyReference* super) { | 464 SuperPropertyReference* super) { |
707 __ CallRuntime(Runtime::kThrowUnsupportedSuperError, 0); | 465 __ CallRuntime(Runtime::kThrowUnsupportedSuperError, 0); |
708 } | 466 } |
709 | 467 |
710 | 468 |
711 void FullCodeGenerator::VisitSuperCallReference(SuperCallReference* super) { | 469 void FullCodeGenerator::VisitSuperCallReference(SuperCallReference* super) { |
712 __ CallRuntime(Runtime::kThrowUnsupportedSuperError, 0); | 470 __ CallRuntime(Runtime::kThrowUnsupportedSuperError, 0); |
713 } | 471 } |
714 | 472 |
715 | 473 |
716 void FullCodeGenerator::SetExpressionPosition(Expression* expr) { | |
717 if (!info_->is_debug()) { | |
718 CodeGenerator::RecordPositions(masm_, expr->position()); | |
719 } else { | |
720 // Check if the expression will be breakable without adding a debug break | |
721 // slot. | |
722 BreakableStatementChecker checker(info_->isolate(), zone()); | |
723 checker.Check(expr); | |
724 // Record a statement position right here if the expression is not | |
725 // breakable. For breakable expressions the actual recording of the | |
726 // position will be postponed to the breakable code (typically an IC). | |
727 // NOTE this will record a statement position for something which might | |
728 // not be a statement. As stepping in the debugger will only stop at | |
729 // statement positions this is used for e.g. the condition expression of | |
730 // a do while loop. | |
731 bool position_recorded = CodeGenerator::RecordPositions( | |
732 masm_, expr->position(), !checker.is_breakable()); | |
733 // If the position recording did record a new position generate a debug | |
734 // break slot to make the statement breakable. | |
735 if (position_recorded) { | |
736 DebugCodegen::GenerateSlot(masm_); | |
737 } | |
738 } | |
739 } | |
740 | |
741 | |
742 void FullCodeGenerator::SetSourcePosition(int pos) { | |
743 if (pos != RelocInfo::kNoPosition) { | |
744 masm_->positions_recorder()->RecordPosition(pos); | |
745 } | |
746 } | |
747 | |
748 | |
749 void FullCodeGenerator::EmitGeneratorNext(CallRuntime* expr) { | 474 void FullCodeGenerator::EmitGeneratorNext(CallRuntime* expr) { |
750 ZoneList<Expression*>* args = expr->arguments(); | 475 ZoneList<Expression*>* args = expr->arguments(); |
751 DCHECK(args->length() == 2); | 476 DCHECK(args->length() == 2); |
752 EmitGeneratorResume(args->at(0), args->at(1), JSGeneratorObject::NEXT); | 477 EmitGeneratorResume(args->at(0), args->at(1), JSGeneratorObject::NEXT); |
753 } | 478 } |
754 | 479 |
755 | 480 |
756 void FullCodeGenerator::EmitGeneratorThrow(CallRuntime* expr) { | 481 void FullCodeGenerator::EmitGeneratorThrow(CallRuntime* expr) { |
757 ZoneList<Expression*>* args = expr->arguments(); | 482 ZoneList<Expression*>* args = expr->arguments(); |
758 DCHECK(args->length() == 2); | 483 DCHECK(args->length() == 2); |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
871 | 596 |
872 void FullCodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) { | 597 void FullCodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) { |
873 Token::Value op = expr->op(); | 598 Token::Value op = expr->op(); |
874 Comment cmnt(masm_, "[ ArithmeticExpression"); | 599 Comment cmnt(masm_, "[ ArithmeticExpression"); |
875 Expression* left = expr->left(); | 600 Expression* left = expr->left(); |
876 Expression* right = expr->right(); | 601 Expression* right = expr->right(); |
877 | 602 |
878 VisitForStackValue(left); | 603 VisitForStackValue(left); |
879 VisitForAccumulatorValue(right); | 604 VisitForAccumulatorValue(right); |
880 | 605 |
881 SetSourcePosition(expr->position()); | 606 SetExpressionPosition(expr); |
882 if (ShouldInlineSmiCase(op)) { | 607 if (ShouldInlineSmiCase(op)) { |
883 EmitInlineSmiBinaryOp(expr, op, left, right); | 608 EmitInlineSmiBinaryOp(expr, op, left, right); |
884 } else { | 609 } else { |
885 EmitBinaryOp(expr, op); | 610 EmitBinaryOp(expr, op); |
886 } | 611 } |
887 } | 612 } |
888 | 613 |
889 | 614 |
890 void FullCodeGenerator::VisitBlock(Block* stmt) { | 615 void FullCodeGenerator::VisitBlock(Block* stmt) { |
891 Comment cmnt(masm_, "[ Block"); | 616 Comment cmnt(masm_, "[ Block"); |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1053 | 778 |
1054 // Pop context. | 779 // Pop context. |
1055 LoadContextField(context_register(), Context::PREVIOUS_INDEX); | 780 LoadContextField(context_register(), Context::PREVIOUS_INDEX); |
1056 // Update local stack frame context field. | 781 // Update local stack frame context field. |
1057 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); | 782 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); |
1058 } | 783 } |
1059 | 784 |
1060 | 785 |
1061 void FullCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { | 786 void FullCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { |
1062 Comment cmnt(masm_, "[ DoWhileStatement"); | 787 Comment cmnt(masm_, "[ DoWhileStatement"); |
1063 SetStatementPosition(stmt); | 788 // Do not insert break location as we do that below. |
| 789 SetStatementPosition(stmt, SKIP_BREAK); |
| 790 |
1064 Label body, book_keeping; | 791 Label body, book_keeping; |
1065 | 792 |
1066 Iteration loop_statement(this, stmt); | 793 Iteration loop_statement(this, stmt); |
1067 increment_loop_depth(); | 794 increment_loop_depth(); |
1068 | 795 |
1069 __ bind(&body); | 796 __ bind(&body); |
1070 Visit(stmt->body()); | 797 Visit(stmt->body()); |
1071 | 798 |
1072 // Record the position of the do while condition and make sure it is | 799 // Record the position of the do while condition and make sure it is |
1073 // possible to break on the condition. | 800 // possible to break on the condition. |
1074 __ bind(loop_statement.continue_label()); | 801 __ bind(loop_statement.continue_label()); |
1075 PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS); | 802 PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS); |
1076 SetExpressionPosition(stmt->cond()); | 803 |
| 804 // Here is the actual 'while' keyword. |
| 805 SetExpressionAsStatementPosition(stmt->cond()); |
1077 VisitForControl(stmt->cond(), | 806 VisitForControl(stmt->cond(), |
1078 &book_keeping, | 807 &book_keeping, |
1079 loop_statement.break_label(), | 808 loop_statement.break_label(), |
1080 &book_keeping); | 809 &book_keeping); |
1081 | 810 |
1082 // Check stack before looping. | 811 // Check stack before looping. |
1083 PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS); | 812 PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS); |
1084 __ bind(&book_keeping); | 813 __ bind(&book_keeping); |
1085 EmitBackEdgeBookkeeping(stmt, &body); | 814 EmitBackEdgeBookkeeping(stmt, &body); |
1086 __ jmp(&body); | 815 __ jmp(&body); |
1087 | 816 |
1088 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); | 817 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); |
1089 __ bind(loop_statement.break_label()); | 818 __ bind(loop_statement.break_label()); |
1090 decrement_loop_depth(); | 819 decrement_loop_depth(); |
1091 } | 820 } |
1092 | 821 |
1093 | 822 |
1094 void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) { | 823 void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) { |
1095 Comment cmnt(masm_, "[ WhileStatement"); | 824 Comment cmnt(masm_, "[ WhileStatement"); |
1096 Label loop, body; | 825 Label loop, body; |
1097 | 826 |
1098 Iteration loop_statement(this, stmt); | 827 Iteration loop_statement(this, stmt); |
1099 increment_loop_depth(); | 828 increment_loop_depth(); |
1100 | 829 |
1101 __ bind(&loop); | 830 __ bind(&loop); |
1102 | 831 |
1103 SetExpressionPosition(stmt->cond()); | 832 SetExpressionAsStatementPosition(stmt->cond()); |
1104 VisitForControl(stmt->cond(), | 833 VisitForControl(stmt->cond(), |
1105 &body, | 834 &body, |
1106 loop_statement.break_label(), | 835 loop_statement.break_label(), |
1107 &body); | 836 &body); |
1108 | 837 |
1109 PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS); | 838 PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS); |
1110 __ bind(&body); | 839 __ bind(&body); |
1111 Visit(stmt->body()); | 840 Visit(stmt->body()); |
1112 | 841 |
1113 __ bind(loop_statement.continue_label()); | 842 __ bind(loop_statement.continue_label()); |
1114 | 843 |
1115 // Check stack before looping. | 844 // Check stack before looping. |
1116 EmitBackEdgeBookkeeping(stmt, &loop); | 845 EmitBackEdgeBookkeeping(stmt, &loop); |
1117 __ jmp(&loop); | 846 __ jmp(&loop); |
1118 | 847 |
1119 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); | 848 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); |
1120 __ bind(loop_statement.break_label()); | 849 __ bind(loop_statement.break_label()); |
1121 decrement_loop_depth(); | 850 decrement_loop_depth(); |
1122 } | 851 } |
1123 | 852 |
1124 | 853 |
1125 void FullCodeGenerator::VisitForStatement(ForStatement* stmt) { | 854 void FullCodeGenerator::VisitForStatement(ForStatement* stmt) { |
1126 Comment cmnt(masm_, "[ ForStatement"); | 855 Comment cmnt(masm_, "[ ForStatement"); |
| 856 // Do not insert break location as we do it below. |
| 857 SetStatementPosition(stmt, SKIP_BREAK); |
| 858 |
1127 Label test, body; | 859 Label test, body; |
1128 | 860 |
1129 Iteration loop_statement(this, stmt); | 861 Iteration loop_statement(this, stmt); |
1130 | 862 |
1131 // Set statement position for a break slot before entering the for-body. | |
1132 SetStatementPosition(stmt); | |
1133 | |
1134 if (stmt->init() != NULL) { | 863 if (stmt->init() != NULL) { |
1135 SetStatementPosition(stmt->init()); | 864 SetStatementPosition(stmt->init()); |
1136 Visit(stmt->init()); | 865 Visit(stmt->init()); |
1137 } | 866 } |
1138 | 867 |
1139 increment_loop_depth(); | 868 increment_loop_depth(); |
1140 // Emit the test at the bottom of the loop (even if empty). | 869 // Emit the test at the bottom of the loop (even if empty). |
1141 __ jmp(&test); | 870 __ jmp(&test); |
1142 | 871 |
1143 PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS); | 872 PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS); |
1144 __ bind(&body); | 873 __ bind(&body); |
1145 Visit(stmt->body()); | 874 Visit(stmt->body()); |
1146 | 875 |
1147 PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS); | 876 PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS); |
1148 __ bind(loop_statement.continue_label()); | 877 __ bind(loop_statement.continue_label()); |
1149 if (stmt->next() != NULL) { | 878 if (stmt->next() != NULL) { |
1150 SetStatementPosition(stmt->next()); | 879 SetStatementPosition(stmt->next()); |
1151 Visit(stmt->next()); | 880 Visit(stmt->next()); |
1152 } | 881 } |
1153 | 882 |
1154 // Emit the statement position here as this is where the for | |
1155 // statement code starts. | |
1156 SetStatementPosition(stmt); | |
1157 | |
1158 // Check stack before looping. | 883 // Check stack before looping. |
1159 EmitBackEdgeBookkeeping(stmt, &body); | 884 EmitBackEdgeBookkeeping(stmt, &body); |
1160 | 885 |
1161 __ bind(&test); | 886 __ bind(&test); |
1162 if (stmt->cond() != NULL) { | 887 if (stmt->cond() != NULL) { |
1163 SetExpressionPosition(stmt->cond()); | 888 SetExpressionAsStatementPosition(stmt->cond()); |
1164 VisitForControl(stmt->cond(), | 889 VisitForControl(stmt->cond(), |
1165 &body, | 890 &body, |
1166 loop_statement.break_label(), | 891 loop_statement.break_label(), |
1167 loop_statement.break_label()); | 892 loop_statement.break_label()); |
1168 } else { | 893 } else { |
1169 __ jmp(&body); | 894 __ jmp(&body); |
1170 } | 895 } |
1171 | 896 |
1172 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); | 897 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); |
1173 __ bind(loop_statement.break_label()); | 898 __ bind(loop_statement.break_label()); |
1174 decrement_loop_depth(); | 899 decrement_loop_depth(); |
1175 } | 900 } |
1176 | 901 |
1177 | 902 |
1178 void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { | 903 void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { |
1179 Comment cmnt(masm_, "[ ForOfStatement"); | 904 Comment cmnt(masm_, "[ ForOfStatement"); |
1180 SetStatementPosition(stmt); | |
1181 | 905 |
1182 Iteration loop_statement(this, stmt); | 906 Iteration loop_statement(this, stmt); |
1183 increment_loop_depth(); | 907 increment_loop_depth(); |
1184 | 908 |
1185 // var iterator = iterable[Symbol.iterator](); | 909 // var iterator = iterable[Symbol.iterator](); |
1186 VisitForEffect(stmt->assign_iterator()); | 910 VisitForEffect(stmt->assign_iterator()); |
1187 | 911 |
1188 // Loop entry. | 912 // Loop entry. |
1189 __ bind(loop_statement.continue_label()); | 913 __ bind(loop_statement.continue_label()); |
1190 | 914 |
1191 // result = iterator.next() | 915 // result = iterator.next() |
1192 SetExpressionPosition(stmt->next_result()); | 916 SetExpressionAsStatementPosition(stmt->next_result()); |
1193 VisitForEffect(stmt->next_result()); | 917 VisitForEffect(stmt->next_result()); |
1194 | 918 |
1195 // if (result.done) break; | 919 // if (result.done) break; |
1196 Label result_not_done; | 920 Label result_not_done; |
1197 VisitForControl(stmt->result_done(), loop_statement.break_label(), | 921 VisitForControl(stmt->result_done(), loop_statement.break_label(), |
1198 &result_not_done, &result_not_done); | 922 &result_not_done, &result_not_done); |
1199 __ bind(&result_not_done); | 923 __ bind(&result_not_done); |
1200 | 924 |
1201 // each = result.value | 925 // each = result.value |
1202 VisitForEffect(stmt->assign_each()); | 926 VisitForEffect(stmt->assign_each()); |
1203 | 927 |
1204 // Generate code for the body of the loop. | 928 // Generate code for the body of the loop. |
1205 Visit(stmt->body()); | 929 Visit(stmt->body()); |
1206 | 930 |
1207 // Check stack before looping. | 931 // Check stack before looping. |
1208 PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS); | 932 PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS); |
1209 EmitBackEdgeBookkeeping(stmt, loop_statement.continue_label()); | 933 EmitBackEdgeBookkeeping(stmt, loop_statement.continue_label()); |
1210 __ jmp(loop_statement.continue_label()); | 934 __ jmp(loop_statement.continue_label()); |
1211 | 935 |
1212 // Exit and decrement the loop depth. | 936 // Exit and decrement the loop depth. |
1213 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); | 937 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); |
1214 __ bind(loop_statement.break_label()); | 938 __ bind(loop_statement.break_label()); |
1215 decrement_loop_depth(); | 939 decrement_loop_depth(); |
1216 } | 940 } |
1217 | 941 |
1218 | 942 |
1219 void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { | 943 void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { |
1220 Comment cmnt(masm_, "[ TryCatchStatement"); | 944 Comment cmnt(masm_, "[ TryCatchStatement"); |
1221 SetStatementPosition(stmt); | 945 SetStatementPosition(stmt, SKIP_BREAK); |
| 946 |
1222 // The try block adds a handler to the exception handler chain before | 947 // The try block adds a handler to the exception handler chain before |
1223 // entering, and removes it again when exiting normally. If an exception | 948 // entering, and removes it again when exiting normally. If an exception |
1224 // is thrown during execution of the try block, the handler is consumed | 949 // is thrown during execution of the try block, the handler is consumed |
1225 // and control is passed to the catch block with the exception in the | 950 // and control is passed to the catch block with the exception in the |
1226 // result register. | 951 // result register. |
1227 | 952 |
1228 Label try_entry, handler_entry, exit; | 953 Label try_entry, handler_entry, exit; |
1229 __ jmp(&try_entry); | 954 __ jmp(&try_entry); |
1230 __ bind(&handler_entry); | 955 __ bind(&handler_entry); |
1231 PrepareForBailoutForId(stmt->HandlerId(), NO_REGISTERS); | 956 PrepareForBailoutForId(stmt->HandlerId(), NO_REGISTERS); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1264 Visit(stmt->try_block()); | 989 Visit(stmt->try_block()); |
1265 } | 990 } |
1266 ExitTryBlock(handler_index); | 991 ExitTryBlock(handler_index); |
1267 try_catch_depth_--; | 992 try_catch_depth_--; |
1268 __ bind(&exit); | 993 __ bind(&exit); |
1269 } | 994 } |
1270 | 995 |
1271 | 996 |
1272 void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) { | 997 void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) { |
1273 Comment cmnt(masm_, "[ TryFinallyStatement"); | 998 Comment cmnt(masm_, "[ TryFinallyStatement"); |
1274 SetStatementPosition(stmt); | 999 SetStatementPosition(stmt, SKIP_BREAK); |
| 1000 |
1275 // Try finally is compiled by setting up a try-handler on the stack while | 1001 // Try finally is compiled by setting up a try-handler on the stack while |
1276 // executing the try body, and removing it again afterwards. | 1002 // executing the try body, and removing it again afterwards. |
1277 // | 1003 // |
1278 // The try-finally construct can enter the finally block in three ways: | 1004 // The try-finally construct can enter the finally block in three ways: |
1279 // 1. By exiting the try-block normally. This removes the try-handler and | 1005 // 1. By exiting the try-block normally. This removes the try-handler and |
1280 // calls the finally block code before continuing. | 1006 // calls the finally block code before continuing. |
1281 // 2. By exiting the try-block with a function-local control flow transfer | 1007 // 2. By exiting the try-block with a function-local control flow transfer |
1282 // (break/continue/return). The site of the, e.g., break removes the | 1008 // (break/continue/return). The site of the, e.g., break removes the |
1283 // try handler and calls the finally block code before continuing | 1009 // try handler and calls the finally block code before continuing |
1284 // its outward control transfer. | 1010 // its outward control transfer. |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1480 int parameters = fun->shared()->internal_formal_parameter_count(); | 1206 int parameters = fun->shared()->internal_formal_parameter_count(); |
1481 shared->set_internal_formal_parameter_count(parameters); | 1207 shared->set_internal_formal_parameter_count(parameters); |
1482 | 1208 |
1483 EmitNewClosure(shared, false); | 1209 EmitNewClosure(shared, false); |
1484 } | 1210 } |
1485 | 1211 |
1486 | 1212 |
1487 void FullCodeGenerator::VisitThrow(Throw* expr) { | 1213 void FullCodeGenerator::VisitThrow(Throw* expr) { |
1488 Comment cmnt(masm_, "[ Throw"); | 1214 Comment cmnt(masm_, "[ Throw"); |
1489 VisitForStackValue(expr->exception()); | 1215 VisitForStackValue(expr->exception()); |
1490 SetSourcePosition(expr->position()); | 1216 SetExpressionPosition(expr); |
1491 __ CallRuntime(Runtime::kThrow, 1); | 1217 __ CallRuntime(Runtime::kThrow, 1); |
1492 // Never returns here. | 1218 // Never returns here. |
1493 } | 1219 } |
1494 | 1220 |
1495 | 1221 |
1496 void FullCodeGenerator::EnterTryBlock(int handler_index, Label* handler) { | 1222 void FullCodeGenerator::EnterTryBlock(int handler_index, Label* handler) { |
1497 HandlerTableEntry* entry = &handler_table_[handler_index]; | 1223 HandlerTableEntry* entry = &handler_table_[handler_index]; |
1498 entry->range_start = masm()->pc_offset(); | 1224 entry->range_start = masm()->pc_offset(); |
1499 entry->handler_offset = handler->pos(); | 1225 entry->handler_offset = handler->pos(); |
1500 entry->try_catch_depth = try_catch_depth_; | 1226 entry->try_catch_depth = try_catch_depth_; |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1708 codegen_->PrepareForBailoutForId(exit_id_, NO_REGISTERS); | 1434 codegen_->PrepareForBailoutForId(exit_id_, NO_REGISTERS); |
1709 codegen_->scope_ = saved_scope_; | 1435 codegen_->scope_ = saved_scope_; |
1710 } | 1436 } |
1711 | 1437 |
1712 | 1438 |
1713 #undef __ | 1439 #undef __ |
1714 | 1440 |
1715 | 1441 |
1716 } // namespace internal | 1442 } // namespace internal |
1717 } // namespace v8 | 1443 } // namespace v8 |
OLD | NEW |