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 RecordPositions(MacroAssembler* masm, int pos, bool statement = true) { | |
ulan
2015/07/06 09:24:18
Please use enum instead of bool and avoid implicit
Yang
2015/07/06 10:05:08
Done.
| |
411 if (pos != RelocInfo::kNoPosition) { | |
412 if (statement) masm->positions_recorder()->RecordStatementPosition(pos); | |
413 masm->positions_recorder()->RecordPosition(pos); | |
414 return masm->positions_recorder()->WriteRecordedPositions(); | |
415 } | |
416 return false; | |
417 } | |
418 | |
419 | |
673 void FullCodeGenerator::SetFunctionPosition(FunctionLiteral* fun) { | 420 void FullCodeGenerator::SetFunctionPosition(FunctionLiteral* fun) { |
674 CodeGenerator::RecordPositions(masm_, fun->start_position()); | 421 RecordPositions(masm_, fun->start_position(), false); |
675 } | 422 } |
676 | 423 |
677 | 424 |
678 void FullCodeGenerator::SetReturnPosition(FunctionLiteral* fun) { | 425 void FullCodeGenerator::SetReturnPosition(FunctionLiteral* fun) { |
679 CodeGenerator::RecordPositions(masm_, fun->end_position() - 1); | 426 RecordPositions(masm_, fun->end_position() - 1); |
680 } | 427 } |
681 | 428 |
682 | 429 |
683 void FullCodeGenerator::SetStatementPosition(Statement* stmt) { | 430 void FullCodeGenerator::SetStatementPosition( |
684 if (!info_->is_debug()) { | 431 Statement* stmt, FullCodeGenerator::InsertBreak insert_break) { |
685 CodeGenerator::RecordPositions(masm_, stmt->position()); | 432 if (stmt->position() == RelocInfo::kNoPosition) return; |
686 } else { | 433 bool recorded = RecordPositions(masm_, stmt->position()); |
687 // Check if the statement will be breakable without adding a debug break | 434 if (recorded && insert_break == INSERT_BREAK && info_->is_debug() && |
688 // slot. | 435 !stmt->IsDebuggerStatement()) { |
689 BreakableStatementChecker checker(info_->isolate(), zone()); | 436 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 } | 437 } |
702 } | 438 } |
703 | 439 |
704 | 440 |
441 void FullCodeGenerator::SetExpressionPosition( | |
442 Expression* expr, FullCodeGenerator::InsertBreak insert_break) { | |
443 if (expr->position() == RelocInfo::kNoPosition) return; | |
444 bool recorded = RecordPositions(masm_, expr->position(), false); | |
445 if (recorded && insert_break == INSERT_BREAK && info_->is_debug()) { | |
446 DebugCodegen::GenerateSlot(masm_); | |
447 } | |
448 } | |
449 | |
450 | |
451 void FullCodeGenerator::SetExpressionAsStatementPosition(Expression* expr) { | |
452 if (expr->position() == RelocInfo::kNoPosition) return; | |
453 bool recorded = RecordPositions(masm_, expr->position()); | |
454 if (recorded && info_->is_debug()) DebugCodegen::GenerateSlot(masm_); | |
455 } | |
456 | |
457 | |
705 void FullCodeGenerator::VisitSuperPropertyReference( | 458 void FullCodeGenerator::VisitSuperPropertyReference( |
706 SuperPropertyReference* super) { | 459 SuperPropertyReference* super) { |
707 __ CallRuntime(Runtime::kThrowUnsupportedSuperError, 0); | 460 __ CallRuntime(Runtime::kThrowUnsupportedSuperError, 0); |
708 } | 461 } |
709 | 462 |
710 | 463 |
711 void FullCodeGenerator::VisitSuperCallReference(SuperCallReference* super) { | 464 void FullCodeGenerator::VisitSuperCallReference(SuperCallReference* super) { |
712 __ CallRuntime(Runtime::kThrowUnsupportedSuperError, 0); | 465 __ CallRuntime(Runtime::kThrowUnsupportedSuperError, 0); |
713 } | 466 } |
714 | 467 |
715 | 468 |
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) { | 469 void FullCodeGenerator::EmitGeneratorNext(CallRuntime* expr) { |
750 ZoneList<Expression*>* args = expr->arguments(); | 470 ZoneList<Expression*>* args = expr->arguments(); |
751 DCHECK(args->length() == 2); | 471 DCHECK(args->length() == 2); |
752 EmitGeneratorResume(args->at(0), args->at(1), JSGeneratorObject::NEXT); | 472 EmitGeneratorResume(args->at(0), args->at(1), JSGeneratorObject::NEXT); |
753 } | 473 } |
754 | 474 |
755 | 475 |
756 void FullCodeGenerator::EmitGeneratorThrow(CallRuntime* expr) { | 476 void FullCodeGenerator::EmitGeneratorThrow(CallRuntime* expr) { |
757 ZoneList<Expression*>* args = expr->arguments(); | 477 ZoneList<Expression*>* args = expr->arguments(); |
758 DCHECK(args->length() == 2); | 478 DCHECK(args->length() == 2); |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
871 | 591 |
872 void FullCodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) { | 592 void FullCodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) { |
873 Token::Value op = expr->op(); | 593 Token::Value op = expr->op(); |
874 Comment cmnt(masm_, "[ ArithmeticExpression"); | 594 Comment cmnt(masm_, "[ ArithmeticExpression"); |
875 Expression* left = expr->left(); | 595 Expression* left = expr->left(); |
876 Expression* right = expr->right(); | 596 Expression* right = expr->right(); |
877 | 597 |
878 VisitForStackValue(left); | 598 VisitForStackValue(left); |
879 VisitForAccumulatorValue(right); | 599 VisitForAccumulatorValue(right); |
880 | 600 |
881 SetSourcePosition(expr->position()); | 601 SetExpressionPosition(expr); |
882 if (ShouldInlineSmiCase(op)) { | 602 if (ShouldInlineSmiCase(op)) { |
883 EmitInlineSmiBinaryOp(expr, op, left, right); | 603 EmitInlineSmiBinaryOp(expr, op, left, right); |
884 } else { | 604 } else { |
885 EmitBinaryOp(expr, op); | 605 EmitBinaryOp(expr, op); |
886 } | 606 } |
887 } | 607 } |
888 | 608 |
889 | 609 |
890 void FullCodeGenerator::VisitBlock(Block* stmt) { | 610 void FullCodeGenerator::VisitBlock(Block* stmt) { |
891 Comment cmnt(masm_, "[ Block"); | 611 Comment cmnt(masm_, "[ Block"); |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1053 | 773 |
1054 // Pop context. | 774 // Pop context. |
1055 LoadContextField(context_register(), Context::PREVIOUS_INDEX); | 775 LoadContextField(context_register(), Context::PREVIOUS_INDEX); |
1056 // Update local stack frame context field. | 776 // Update local stack frame context field. |
1057 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); | 777 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); |
1058 } | 778 } |
1059 | 779 |
1060 | 780 |
1061 void FullCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { | 781 void FullCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { |
1062 Comment cmnt(masm_, "[ DoWhileStatement"); | 782 Comment cmnt(masm_, "[ DoWhileStatement"); |
1063 SetStatementPosition(stmt); | 783 SetStatementPosition(stmt, SKIP_BREAK); |
ulan
2015/07/06 09:24:18
Please add a comment that the break is added below
Yang
2015/07/06 10:05:08
Done.
| |
784 | |
1064 Label body, book_keeping; | 785 Label body, book_keeping; |
1065 | 786 |
1066 Iteration loop_statement(this, stmt); | 787 Iteration loop_statement(this, stmt); |
1067 increment_loop_depth(); | 788 increment_loop_depth(); |
1068 | 789 |
1069 __ bind(&body); | 790 __ bind(&body); |
1070 Visit(stmt->body()); | 791 Visit(stmt->body()); |
1071 | 792 |
1072 // Record the position of the do while condition and make sure it is | 793 // Record the position of the do while condition and make sure it is |
1073 // possible to break on the condition. | 794 // possible to break on the condition. |
1074 __ bind(loop_statement.continue_label()); | 795 __ bind(loop_statement.continue_label()); |
1075 PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS); | 796 PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS); |
1076 SetExpressionPosition(stmt->cond()); | 797 |
798 // Here is the actual 'while' keyword. | |
799 SetExpressionAsStatementPosition(stmt->cond()); | |
1077 VisitForControl(stmt->cond(), | 800 VisitForControl(stmt->cond(), |
1078 &book_keeping, | 801 &book_keeping, |
1079 loop_statement.break_label(), | 802 loop_statement.break_label(), |
1080 &book_keeping); | 803 &book_keeping); |
1081 | 804 |
1082 // Check stack before looping. | 805 // Check stack before looping. |
1083 PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS); | 806 PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS); |
1084 __ bind(&book_keeping); | 807 __ bind(&book_keeping); |
1085 EmitBackEdgeBookkeeping(stmt, &body); | 808 EmitBackEdgeBookkeeping(stmt, &body); |
1086 __ jmp(&body); | 809 __ jmp(&body); |
1087 | 810 |
1088 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); | 811 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); |
1089 __ bind(loop_statement.break_label()); | 812 __ bind(loop_statement.break_label()); |
1090 decrement_loop_depth(); | 813 decrement_loop_depth(); |
1091 } | 814 } |
1092 | 815 |
1093 | 816 |
1094 void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) { | 817 void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) { |
1095 Comment cmnt(masm_, "[ WhileStatement"); | 818 Comment cmnt(masm_, "[ WhileStatement"); |
1096 Label loop, body; | 819 Label loop, body; |
1097 | 820 |
1098 Iteration loop_statement(this, stmt); | 821 Iteration loop_statement(this, stmt); |
1099 increment_loop_depth(); | 822 increment_loop_depth(); |
1100 | 823 |
1101 __ bind(&loop); | 824 __ bind(&loop); |
1102 | 825 |
1103 SetExpressionPosition(stmt->cond()); | 826 SetExpressionAsStatementPosition(stmt->cond()); |
1104 VisitForControl(stmt->cond(), | 827 VisitForControl(stmt->cond(), |
1105 &body, | 828 &body, |
1106 loop_statement.break_label(), | 829 loop_statement.break_label(), |
1107 &body); | 830 &body); |
1108 | 831 |
1109 PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS); | 832 PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS); |
1110 __ bind(&body); | 833 __ bind(&body); |
1111 Visit(stmt->body()); | 834 Visit(stmt->body()); |
1112 | 835 |
1113 __ bind(loop_statement.continue_label()); | 836 __ bind(loop_statement.continue_label()); |
1114 | 837 |
1115 // Check stack before looping. | 838 // Check stack before looping. |
1116 EmitBackEdgeBookkeeping(stmt, &loop); | 839 EmitBackEdgeBookkeeping(stmt, &loop); |
1117 __ jmp(&loop); | 840 __ jmp(&loop); |
1118 | 841 |
1119 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); | 842 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); |
1120 __ bind(loop_statement.break_label()); | 843 __ bind(loop_statement.break_label()); |
1121 decrement_loop_depth(); | 844 decrement_loop_depth(); |
1122 } | 845 } |
1123 | 846 |
1124 | 847 |
1125 void FullCodeGenerator::VisitForStatement(ForStatement* stmt) { | 848 void FullCodeGenerator::VisitForStatement(ForStatement* stmt) { |
1126 Comment cmnt(masm_, "[ ForStatement"); | 849 Comment cmnt(masm_, "[ ForStatement"); |
850 SetStatementPosition(stmt, SKIP_BREAK); | |
ulan
2015/07/06 09:24:18
Please add a comment that the break is added below
Yang
2015/07/06 10:05:08
Done.
| |
851 | |
1127 Label test, body; | 852 Label test, body; |
1128 | 853 |
1129 Iteration loop_statement(this, stmt); | 854 Iteration loop_statement(this, stmt); |
1130 | 855 |
1131 // Set statement position for a break slot before entering the for-body. | |
1132 SetStatementPosition(stmt); | |
1133 | |
1134 if (stmt->init() != NULL) { | 856 if (stmt->init() != NULL) { |
1135 SetStatementPosition(stmt->init()); | 857 SetStatementPosition(stmt->init()); |
1136 Visit(stmt->init()); | 858 Visit(stmt->init()); |
1137 } | 859 } |
1138 | 860 |
1139 increment_loop_depth(); | 861 increment_loop_depth(); |
1140 // Emit the test at the bottom of the loop (even if empty). | 862 // Emit the test at the bottom of the loop (even if empty). |
1141 __ jmp(&test); | 863 __ jmp(&test); |
1142 | 864 |
1143 PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS); | 865 PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS); |
1144 __ bind(&body); | 866 __ bind(&body); |
1145 Visit(stmt->body()); | 867 Visit(stmt->body()); |
1146 | 868 |
1147 PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS); | 869 PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS); |
1148 __ bind(loop_statement.continue_label()); | 870 __ bind(loop_statement.continue_label()); |
1149 if (stmt->next() != NULL) { | 871 if (stmt->next() != NULL) { |
1150 SetStatementPosition(stmt->next()); | 872 SetStatementPosition(stmt->next()); |
1151 Visit(stmt->next()); | 873 Visit(stmt->next()); |
1152 } | 874 } |
1153 | 875 |
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. | 876 // Check stack before looping. |
1159 EmitBackEdgeBookkeeping(stmt, &body); | 877 EmitBackEdgeBookkeeping(stmt, &body); |
1160 | 878 |
1161 __ bind(&test); | 879 __ bind(&test); |
1162 if (stmt->cond() != NULL) { | 880 if (stmt->cond() != NULL) { |
1163 SetExpressionPosition(stmt->cond()); | 881 SetExpressionAsStatementPosition(stmt->cond()); |
1164 VisitForControl(stmt->cond(), | 882 VisitForControl(stmt->cond(), |
1165 &body, | 883 &body, |
1166 loop_statement.break_label(), | 884 loop_statement.break_label(), |
1167 loop_statement.break_label()); | 885 loop_statement.break_label()); |
1168 } else { | 886 } else { |
1169 __ jmp(&body); | 887 __ jmp(&body); |
1170 } | 888 } |
1171 | 889 |
1172 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); | 890 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); |
1173 __ bind(loop_statement.break_label()); | 891 __ bind(loop_statement.break_label()); |
1174 decrement_loop_depth(); | 892 decrement_loop_depth(); |
1175 } | 893 } |
1176 | 894 |
1177 | 895 |
1178 void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { | 896 void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { |
1179 Comment cmnt(masm_, "[ ForOfStatement"); | 897 Comment cmnt(masm_, "[ ForOfStatement"); |
1180 SetStatementPosition(stmt); | |
1181 | 898 |
1182 Iteration loop_statement(this, stmt); | 899 Iteration loop_statement(this, stmt); |
1183 increment_loop_depth(); | 900 increment_loop_depth(); |
1184 | 901 |
1185 // var iterator = iterable[Symbol.iterator](); | 902 // var iterator = iterable[Symbol.iterator](); |
1186 VisitForEffect(stmt->assign_iterator()); | 903 VisitForEffect(stmt->assign_iterator()); |
1187 | 904 |
1188 // Loop entry. | 905 // Loop entry. |
1189 __ bind(loop_statement.continue_label()); | 906 __ bind(loop_statement.continue_label()); |
1190 | 907 |
1191 // result = iterator.next() | 908 // result = iterator.next() |
1192 SetExpressionPosition(stmt->next_result()); | 909 SetExpressionAsStatementPosition(stmt->next_result()); |
1193 VisitForEffect(stmt->next_result()); | 910 VisitForEffect(stmt->next_result()); |
1194 | 911 |
1195 // if (result.done) break; | 912 // if (result.done) break; |
1196 Label result_not_done; | 913 Label result_not_done; |
1197 VisitForControl(stmt->result_done(), loop_statement.break_label(), | 914 VisitForControl(stmt->result_done(), loop_statement.break_label(), |
1198 &result_not_done, &result_not_done); | 915 &result_not_done, &result_not_done); |
1199 __ bind(&result_not_done); | 916 __ bind(&result_not_done); |
1200 | 917 |
1201 // each = result.value | 918 // each = result.value |
1202 VisitForEffect(stmt->assign_each()); | 919 VisitForEffect(stmt->assign_each()); |
1203 | 920 |
1204 // Generate code for the body of the loop. | 921 // Generate code for the body of the loop. |
1205 Visit(stmt->body()); | 922 Visit(stmt->body()); |
1206 | 923 |
1207 // Check stack before looping. | 924 // Check stack before looping. |
1208 PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS); | 925 PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS); |
1209 EmitBackEdgeBookkeeping(stmt, loop_statement.continue_label()); | 926 EmitBackEdgeBookkeeping(stmt, loop_statement.continue_label()); |
1210 __ jmp(loop_statement.continue_label()); | 927 __ jmp(loop_statement.continue_label()); |
1211 | 928 |
1212 // Exit and decrement the loop depth. | 929 // Exit and decrement the loop depth. |
1213 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); | 930 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); |
1214 __ bind(loop_statement.break_label()); | 931 __ bind(loop_statement.break_label()); |
1215 decrement_loop_depth(); | 932 decrement_loop_depth(); |
1216 } | 933 } |
1217 | 934 |
1218 | 935 |
1219 void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { | 936 void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { |
1220 Comment cmnt(masm_, "[ TryCatchStatement"); | 937 Comment cmnt(masm_, "[ TryCatchStatement"); |
1221 SetStatementPosition(stmt); | 938 SetStatementPosition(stmt, SKIP_BREAK); |
939 | |
1222 // The try block adds a handler to the exception handler chain before | 940 // The try block adds a handler to the exception handler chain before |
1223 // entering, and removes it again when exiting normally. If an exception | 941 // entering, and removes it again when exiting normally. If an exception |
1224 // is thrown during execution of the try block, the handler is consumed | 942 // 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 | 943 // and control is passed to the catch block with the exception in the |
1226 // result register. | 944 // result register. |
1227 | 945 |
1228 Label try_entry, handler_entry, exit; | 946 Label try_entry, handler_entry, exit; |
1229 __ jmp(&try_entry); | 947 __ jmp(&try_entry); |
1230 __ bind(&handler_entry); | 948 __ bind(&handler_entry); |
1231 PrepareForBailoutForId(stmt->HandlerId(), NO_REGISTERS); | 949 PrepareForBailoutForId(stmt->HandlerId(), NO_REGISTERS); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1264 Visit(stmt->try_block()); | 982 Visit(stmt->try_block()); |
1265 } | 983 } |
1266 ExitTryBlock(handler_index); | 984 ExitTryBlock(handler_index); |
1267 try_catch_depth_--; | 985 try_catch_depth_--; |
1268 __ bind(&exit); | 986 __ bind(&exit); |
1269 } | 987 } |
1270 | 988 |
1271 | 989 |
1272 void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) { | 990 void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) { |
1273 Comment cmnt(masm_, "[ TryFinallyStatement"); | 991 Comment cmnt(masm_, "[ TryFinallyStatement"); |
1274 SetStatementPosition(stmt); | 992 SetStatementPosition(stmt, SKIP_BREAK); |
993 | |
1275 // Try finally is compiled by setting up a try-handler on the stack while | 994 // Try finally is compiled by setting up a try-handler on the stack while |
1276 // executing the try body, and removing it again afterwards. | 995 // executing the try body, and removing it again afterwards. |
1277 // | 996 // |
1278 // The try-finally construct can enter the finally block in three ways: | 997 // 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 | 998 // 1. By exiting the try-block normally. This removes the try-handler and |
1280 // calls the finally block code before continuing. | 999 // calls the finally block code before continuing. |
1281 // 2. By exiting the try-block with a function-local control flow transfer | 1000 // 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 | 1001 // (break/continue/return). The site of the, e.g., break removes the |
1283 // try handler and calls the finally block code before continuing | 1002 // try handler and calls the finally block code before continuing |
1284 // its outward control transfer. | 1003 // 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(); | 1199 int parameters = fun->shared()->internal_formal_parameter_count(); |
1481 shared->set_internal_formal_parameter_count(parameters); | 1200 shared->set_internal_formal_parameter_count(parameters); |
1482 | 1201 |
1483 EmitNewClosure(shared, false); | 1202 EmitNewClosure(shared, false); |
1484 } | 1203 } |
1485 | 1204 |
1486 | 1205 |
1487 void FullCodeGenerator::VisitThrow(Throw* expr) { | 1206 void FullCodeGenerator::VisitThrow(Throw* expr) { |
1488 Comment cmnt(masm_, "[ Throw"); | 1207 Comment cmnt(masm_, "[ Throw"); |
1489 VisitForStackValue(expr->exception()); | 1208 VisitForStackValue(expr->exception()); |
1490 SetSourcePosition(expr->position()); | 1209 SetExpressionPosition(expr); |
1491 __ CallRuntime(Runtime::kThrow, 1); | 1210 __ CallRuntime(Runtime::kThrow, 1); |
1492 // Never returns here. | 1211 // Never returns here. |
1493 } | 1212 } |
1494 | 1213 |
1495 | 1214 |
1496 void FullCodeGenerator::EnterTryBlock(int handler_index, Label* handler) { | 1215 void FullCodeGenerator::EnterTryBlock(int handler_index, Label* handler) { |
1497 HandlerTableEntry* entry = &handler_table_[handler_index]; | 1216 HandlerTableEntry* entry = &handler_table_[handler_index]; |
1498 entry->range_start = masm()->pc_offset(); | 1217 entry->range_start = masm()->pc_offset(); |
1499 entry->handler_offset = handler->pos(); | 1218 entry->handler_offset = handler->pos(); |
1500 entry->try_catch_depth = try_catch_depth_; | 1219 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); | 1427 codegen_->PrepareForBailoutForId(exit_id_, NO_REGISTERS); |
1709 codegen_->scope_ = saved_scope_; | 1428 codegen_->scope_ = saved_scope_; |
1710 } | 1429 } |
1711 | 1430 |
1712 | 1431 |
1713 #undef __ | 1432 #undef __ |
1714 | 1433 |
1715 | 1434 |
1716 } // namespace internal | 1435 } // namespace internal |
1717 } // namespace v8 | 1436 } // namespace v8 |
OLD | NEW |