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