Chromium Code Reviews| 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 |