OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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/interpreter/bytecode-generator.h" | 5 #include "src/interpreter/bytecode-generator.h" |
6 | 6 |
7 #include <stack> | 7 #include <stack> |
8 | 8 |
9 #include "src/compiler.h" | 9 #include "src/compiler.h" |
10 #include "src/objects.h" | 10 #include "src/objects.h" |
(...skipping 27 matching lines...) Expand all Loading... |
38 if (scope()->is_function_scope() && scope()->function() != NULL) { | 38 if (scope()->is_function_scope() && scope()->function() != NULL) { |
39 VisitVariableDeclaration(scope()->function()); | 39 VisitVariableDeclaration(scope()->function()); |
40 } | 40 } |
41 | 41 |
42 // Visit declarations within the function scope. | 42 // Visit declarations within the function scope. |
43 VisitDeclarations(scope()->declarations()); | 43 VisitDeclarations(scope()->declarations()); |
44 | 44 |
45 // Visit statements in the function body. | 45 // Visit statements in the function body. |
46 VisitStatements(info->literal()->body()); | 46 VisitStatements(info->literal()->body()); |
47 | 47 |
48 // If the last bytecode wasn't a return, then return 'undefined' to avoid | |
49 // falling off the end. | |
50 if (!builder_.HasExplicitReturn()) { | |
51 builder_.LoadUndefined(); | |
52 builder_.Return(); | |
53 } | |
54 | |
55 set_scope(nullptr); | 48 set_scope(nullptr); |
56 set_info(nullptr); | 49 set_info(nullptr); |
57 return builder_.ToBytecodeArray(); | 50 return builder_.ToBytecodeArray(); |
58 } | 51 } |
59 | 52 |
60 | 53 |
61 void BytecodeGenerator::VisitBlock(Block* node) { | 54 void BytecodeGenerator::VisitBlock(Block* node) { |
| 55 builder().EnterBlock(); |
62 if (node->scope() == NULL) { | 56 if (node->scope() == NULL) { |
63 // Visit statements in the same scope, no declarations. | 57 // Visit statements in the same scope, no declarations. |
64 VisitStatements(node->statements()); | 58 VisitStatements(node->statements()); |
65 } else { | 59 } else { |
66 // Visit declarations and statements in a block scope. | 60 // Visit declarations and statements in a block scope. |
67 if (node->scope()->ContextLocalCount() > 0) { | 61 if (node->scope()->ContextLocalCount() > 0) { |
68 UNIMPLEMENTED(); | 62 UNIMPLEMENTED(); |
69 } else { | 63 } else { |
70 VisitDeclarations(node->scope()->declarations()); | 64 VisitDeclarations(node->scope()->declarations()); |
71 VisitStatements(node->statements()); | 65 VisitStatements(node->statements()); |
72 } | 66 } |
73 } | 67 } |
| 68 builder().LeaveBlock(); |
74 } | 69 } |
75 | 70 |
76 | 71 |
77 void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) { | 72 void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) { |
78 Variable* variable = decl->proxy()->var(); | 73 Variable* variable = decl->proxy()->var(); |
79 switch (variable->location()) { | 74 switch (variable->location()) { |
80 case VariableLocation::GLOBAL: | 75 case VariableLocation::GLOBAL: |
81 case VariableLocation::UNALLOCATED: | 76 case VariableLocation::UNALLOCATED: |
82 UNIMPLEMENTED(); | 77 UNIMPLEMENTED(); |
83 break; | 78 break; |
(...skipping 23 matching lines...) Expand all Loading... |
107 UNIMPLEMENTED(); | 102 UNIMPLEMENTED(); |
108 } | 103 } |
109 | 104 |
110 | 105 |
111 void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { | 106 void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { |
112 Visit(stmt->expression()); | 107 Visit(stmt->expression()); |
113 } | 108 } |
114 | 109 |
115 | 110 |
116 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { | 111 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { |
117 UNIMPLEMENTED(); | 112 // TODO(oth): For control-flow it could be useful to signal empty paths here. |
118 } | 113 } |
119 | 114 |
120 | 115 |
121 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) { UNIMPLEMENTED(); } | 116 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) { |
| 117 BytecodeLabel else_start, else_end; |
| 118 // TODO(oth): Spot easy cases where there code would not need to |
| 119 // emit the then block or the else block, e.g. condition is |
| 120 // obviously true/1/false/0. |
| 121 Visit(stmt->condition()); |
| 122 builder().CastAccumulatorToBoolean(); |
| 123 builder().JumpIfFalse(&else_start); |
| 124 |
| 125 Visit(stmt->then_statement()); |
| 126 builder().Jump(&else_end); |
| 127 builder().Bind(&else_start); |
| 128 |
| 129 Visit(stmt->else_statement()); |
| 130 builder().Bind(&else_end); |
| 131 } |
122 | 132 |
123 | 133 |
124 void BytecodeGenerator::VisitSloppyBlockFunctionStatement( | 134 void BytecodeGenerator::VisitSloppyBlockFunctionStatement( |
125 SloppyBlockFunctionStatement* stmt) { | 135 SloppyBlockFunctionStatement* stmt) { |
126 Visit(stmt->statement()); | 136 Visit(stmt->statement()); |
127 } | 137 } |
128 | 138 |
129 | 139 |
130 void BytecodeGenerator::VisitContinueStatement(ContinueStatement* stmt) { | 140 void BytecodeGenerator::VisitContinueStatement(ContinueStatement* stmt) { |
131 UNIMPLEMENTED(); | 141 UNIMPLEMENTED(); |
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
451 UNIMPLEMENTED(); | 461 UNIMPLEMENTED(); |
452 break; | 462 break; |
453 default: | 463 default: |
454 VisitArithmeticExpression(binop); | 464 VisitArithmeticExpression(binop); |
455 break; | 465 break; |
456 } | 466 } |
457 } | 467 } |
458 | 468 |
459 | 469 |
460 void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) { | 470 void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
461 UNIMPLEMENTED(); | 471 Token::Value op = expr->op(); |
| 472 Expression* left = expr->left(); |
| 473 Expression* right = expr->right(); |
| 474 |
| 475 TemporaryRegisterScope temporary_register_scope(&builder_); |
| 476 Register temporary = temporary_register_scope.NewRegister(); |
| 477 |
| 478 Visit(left); |
| 479 builder().StoreAccumulatorInRegister(temporary); |
| 480 Visit(right); |
| 481 builder().CompareOperation(op, temporary, language_mode()); |
462 } | 482 } |
463 | 483 |
464 | 484 |
465 void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); } | 485 void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); } |
466 | 486 |
467 | 487 |
468 void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) { | 488 void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) { |
469 UNREACHABLE(); | 489 UNREACHABLE(); |
470 } | 490 } |
471 | 491 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
506 } | 526 } |
507 | 527 |
508 | 528 |
509 int BytecodeGenerator::feedback_index(FeedbackVectorICSlot slot) const { | 529 int BytecodeGenerator::feedback_index(FeedbackVectorICSlot slot) const { |
510 return info()->feedback_vector()->GetIndex(slot); | 530 return info()->feedback_vector()->GetIndex(slot); |
511 } | 531 } |
512 | 532 |
513 } // namespace interpreter | 533 } // namespace interpreter |
514 } // namespace internal | 534 } // namespace internal |
515 } // namespace v8 | 535 } // namespace v8 |
OLD | NEW |