| 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/interpreter/control-flow-builders.h" |
| 10 #include "src/objects.h" | 11 #include "src/objects.h" |
| 11 #include "src/scopes.h" | 12 #include "src/scopes.h" |
| 12 #include "src/token.h" | 13 #include "src/token.h" |
| 13 | 14 |
| 14 namespace v8 { | 15 namespace v8 { |
| 15 namespace internal { | 16 namespace internal { |
| 16 namespace interpreter { | 17 namespace interpreter { |
| 17 | 18 |
| 19 |
| 20 // Scoped class for tracking control statements entered by the |
| 21 // visitor. The pattern derives AstGraphBuilder::ControlScope. |
| 22 class BytecodeGenerator::ControlScope BASE_EMBEDDED { |
| 23 public: |
| 24 explicit ControlScope(BytecodeGenerator* generator) |
| 25 : generator_(generator), outer_(generator->control_scope()) { |
| 26 generator_->set_control_scope(this); |
| 27 } |
| 28 virtual ~ControlScope() { generator_->set_control_scope(outer()); } |
| 29 |
| 30 void Break(Statement* stmt) { PerformCommand(CMD_BREAK, stmt); } |
| 31 void Continue(Statement* stmt) { PerformCommand(CMD_CONTINUE, stmt); } |
| 32 |
| 33 protected: |
| 34 enum Command { CMD_BREAK, CMD_CONTINUE }; |
| 35 void PerformCommand(Command command, Statement* statement); |
| 36 virtual bool Execute(Command command, Statement* statement) = 0; |
| 37 |
| 38 BytecodeGenerator* generator() const { return generator_; } |
| 39 ControlScope* outer() const { return outer_; } |
| 40 |
| 41 private: |
| 42 BytecodeGenerator* generator_; |
| 43 ControlScope* outer_; |
| 44 |
| 45 DISALLOW_COPY_AND_ASSIGN(ControlScope); |
| 46 }; |
| 47 |
| 48 |
| 49 // Scoped class for enabling 'break' and 'continue' in iteration |
| 50 // constructs, e.g. do...while, while..., for... |
| 51 class BytecodeGenerator::ControlScopeForIteration |
| 52 : public BytecodeGenerator::ControlScope { |
| 53 public: |
| 54 ControlScopeForIteration(BytecodeGenerator* generator, |
| 55 IterationStatement* statement, |
| 56 LoopBuilder* loop_builder) |
| 57 : ControlScope(generator), |
| 58 statement_(statement), |
| 59 loop_builder_(loop_builder) {} |
| 60 |
| 61 protected: |
| 62 virtual bool Execute(Command command, Statement* statement) { |
| 63 if (statement != statement_) return false; |
| 64 switch (command) { |
| 65 case CMD_BREAK: |
| 66 loop_builder_->Break(); |
| 67 return true; |
| 68 case CMD_CONTINUE: |
| 69 loop_builder_->Continue(); |
| 70 return true; |
| 71 } |
| 72 return false; |
| 73 } |
| 74 |
| 75 private: |
| 76 Statement* statement_; |
| 77 LoopBuilder* loop_builder_; |
| 78 }; |
| 79 |
| 80 |
| 81 void BytecodeGenerator::ControlScope::PerformCommand(Command command, |
| 82 Statement* statement) { |
| 83 ControlScope* current = this; |
| 84 do { |
| 85 if (current->Execute(command, statement)) return; |
| 86 current = current->outer(); |
| 87 } while (current != nullptr); |
| 88 UNREACHABLE(); |
| 89 } |
| 90 |
| 91 |
| 18 BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone) | 92 BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone) |
| 19 : builder_(isolate, zone) { | 93 : builder_(isolate, zone), |
| 94 info_(nullptr), |
| 95 scope_(nullptr), |
| 96 control_scope_(nullptr) { |
| 20 InitializeAstVisitor(isolate, zone); | 97 InitializeAstVisitor(isolate, zone); |
| 21 } | 98 } |
| 22 | 99 |
| 23 | 100 |
| 24 BytecodeGenerator::~BytecodeGenerator() {} | 101 BytecodeGenerator::~BytecodeGenerator() {} |
| 25 | 102 |
| 26 | 103 |
| 27 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) { | 104 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) { |
| 28 set_info(info); | 105 set_info(info); |
| 29 set_scope(info->scope()); | 106 set_scope(info->scope()); |
| 30 | 107 |
| 31 // This a temporary guard (oth). | 108 // This a temporary guard (oth). |
| 32 DCHECK(scope()->is_function_scope()); | 109 DCHECK(scope()->is_function_scope()); |
| 33 | 110 |
| 34 builder().set_parameter_count(info->num_parameters_including_this()); | 111 builder()->set_parameter_count(info->num_parameters_including_this()); |
| 35 builder().set_locals_count(scope()->num_stack_slots()); | 112 builder()->set_locals_count(scope()->num_stack_slots()); |
| 36 | 113 |
| 37 // Visit implicit declaration of the function name. | 114 // Visit implicit declaration of the function name. |
| 38 if (scope()->is_function_scope() && scope()->function() != NULL) { | 115 if (scope()->is_function_scope() && scope()->function() != NULL) { |
| 39 VisitVariableDeclaration(scope()->function()); | 116 VisitVariableDeclaration(scope()->function()); |
| 40 } | 117 } |
| 41 | 118 |
| 42 // Visit declarations within the function scope. | 119 // Visit declarations within the function scope. |
| 43 VisitDeclarations(scope()->declarations()); | 120 VisitDeclarations(scope()->declarations()); |
| 44 | 121 |
| 45 // Visit statements in the function body. | 122 // Visit statements in the function body. |
| 46 VisitStatements(info->literal()->body()); | 123 VisitStatements(info->literal()->body()); |
| 47 | 124 |
| 48 set_scope(nullptr); | 125 set_scope(nullptr); |
| 49 set_info(nullptr); | 126 set_info(nullptr); |
| 50 return builder_.ToBytecodeArray(); | 127 return builder_.ToBytecodeArray(); |
| 51 } | 128 } |
| 52 | 129 |
| 53 | 130 |
| 54 void BytecodeGenerator::VisitBlock(Block* node) { | 131 void BytecodeGenerator::VisitBlock(Block* node) { |
| 55 builder().EnterBlock(); | 132 builder()->EnterBlock(); |
| 56 if (node->scope() == NULL) { | 133 if (node->scope() == NULL) { |
| 57 // Visit statements in the same scope, no declarations. | 134 // Visit statements in the same scope, no declarations. |
| 58 VisitStatements(node->statements()); | 135 VisitStatements(node->statements()); |
| 59 } else { | 136 } else { |
| 60 // Visit declarations and statements in a block scope. | 137 // Visit declarations and statements in a block scope. |
| 61 if (node->scope()->ContextLocalCount() > 0) { | 138 if (node->scope()->ContextLocalCount() > 0) { |
| 62 UNIMPLEMENTED(); | 139 UNIMPLEMENTED(); |
| 63 } else { | 140 } else { |
| 64 VisitDeclarations(node->scope()->declarations()); | 141 VisitDeclarations(node->scope()->declarations()); |
| 65 VisitStatements(node->statements()); | 142 VisitStatements(node->statements()); |
| 66 } | 143 } |
| 67 } | 144 } |
| 68 builder().LeaveBlock(); | 145 builder()->LeaveBlock(); |
| 69 } | 146 } |
| 70 | 147 |
| 71 | 148 |
| 72 void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) { | 149 void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) { |
| 73 Variable* variable = decl->proxy()->var(); | 150 Variable* variable = decl->proxy()->var(); |
| 74 switch (variable->location()) { | 151 switch (variable->location()) { |
| 75 case VariableLocation::GLOBAL: | 152 case VariableLocation::GLOBAL: |
| 76 case VariableLocation::UNALLOCATED: | 153 case VariableLocation::UNALLOCATED: |
| 77 UNIMPLEMENTED(); | 154 UNIMPLEMENTED(); |
| 78 break; | 155 break; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 107 Visit(stmt->expression()); | 184 Visit(stmt->expression()); |
| 108 } | 185 } |
| 109 | 186 |
| 110 | 187 |
| 111 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { | 188 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { |
| 112 // TODO(oth): For control-flow it could be useful to signal empty paths here. | 189 // TODO(oth): For control-flow it could be useful to signal empty paths here. |
| 113 } | 190 } |
| 114 | 191 |
| 115 | 192 |
| 116 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) { | 193 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) { |
| 117 BytecodeLabel else_start, else_end; | |
| 118 // TODO(oth): Spot easy cases where there code would not need to | 194 // 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 | 195 // emit the then block or the else block, e.g. condition is |
| 120 // obviously true/1/false/0. | 196 // obviously true/1/false/0. |
| 197 |
| 198 BytecodeLabel else_label, end_label; |
| 199 |
| 121 Visit(stmt->condition()); | 200 Visit(stmt->condition()); |
| 122 builder().CastAccumulatorToBoolean(); | 201 builder()->CastAccumulatorToBoolean(); |
| 123 builder().JumpIfFalse(&else_start); | 202 builder()->JumpIfFalse(&else_label); |
| 124 | |
| 125 Visit(stmt->then_statement()); | 203 Visit(stmt->then_statement()); |
| 126 builder().Jump(&else_end); | 204 if (stmt->HasElseStatement()) { |
| 127 builder().Bind(&else_start); | 205 builder()->Jump(&end_label); |
| 128 | 206 builder()->Bind(&else_label); |
| 129 Visit(stmt->else_statement()); | 207 Visit(stmt->else_statement()); |
| 130 builder().Bind(&else_end); | 208 } else { |
| 209 builder()->Bind(&else_label); |
| 210 } |
| 211 builder()->Bind(&end_label); |
| 131 } | 212 } |
| 132 | 213 |
| 133 | 214 |
| 134 void BytecodeGenerator::VisitSloppyBlockFunctionStatement( | 215 void BytecodeGenerator::VisitSloppyBlockFunctionStatement( |
| 135 SloppyBlockFunctionStatement* stmt) { | 216 SloppyBlockFunctionStatement* stmt) { |
| 136 Visit(stmt->statement()); | 217 Visit(stmt->statement()); |
| 137 } | 218 } |
| 138 | 219 |
| 139 | 220 |
| 140 void BytecodeGenerator::VisitContinueStatement(ContinueStatement* stmt) { | 221 void BytecodeGenerator::VisitContinueStatement(ContinueStatement* stmt) { |
| 141 UNIMPLEMENTED(); | 222 control_scope()->Continue(stmt->target()); |
| 142 } | 223 } |
| 143 | 224 |
| 144 | 225 |
| 145 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) { | 226 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) { |
| 146 UNIMPLEMENTED(); | 227 control_scope()->Break(stmt->target()); |
| 147 } | 228 } |
| 148 | 229 |
| 149 | 230 |
| 150 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { | 231 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { |
| 151 Visit(stmt->expression()); | 232 Visit(stmt->expression()); |
| 152 builder().Return(); | 233 builder()->Return(); |
| 153 } | 234 } |
| 154 | 235 |
| 155 | 236 |
| 156 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) { | 237 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) { |
| 157 UNIMPLEMENTED(); | 238 UNIMPLEMENTED(); |
| 158 } | 239 } |
| 159 | 240 |
| 160 | 241 |
| 161 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { | 242 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { |
| 162 UNIMPLEMENTED(); | 243 UNIMPLEMENTED(); |
| 163 } | 244 } |
| 164 | 245 |
| 165 | 246 |
| 166 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { UNIMPLEMENTED(); } | 247 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { UNIMPLEMENTED(); } |
| 167 | 248 |
| 168 | 249 |
| 169 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { | 250 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { |
| 170 UNIMPLEMENTED(); | 251 LoopBuilder loop_builder(builder()); |
| 252 ControlScopeForIteration control_scope(this, stmt, &loop_builder); |
| 253 |
| 254 BytecodeLabel body_label, condition_label, done_label; |
| 255 builder()->Bind(&body_label); |
| 256 Visit(stmt->body()); |
| 257 builder()->Bind(&condition_label); |
| 258 Visit(stmt->cond()); |
| 259 builder()->JumpIfTrue(&body_label); |
| 260 builder()->Bind(&done_label); |
| 261 |
| 262 loop_builder.SetBreakTarget(done_label); |
| 263 loop_builder.SetContinueTarget(condition_label); |
| 171 } | 264 } |
| 172 | 265 |
| 173 | 266 |
| 174 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) { | 267 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) { |
| 175 UNIMPLEMENTED(); | 268 LoopBuilder loop_builder(builder()); |
| 269 ControlScopeForIteration control_scope(this, stmt, &loop_builder); |
| 270 |
| 271 BytecodeLabel body_label, condition_label, done_label; |
| 272 builder()->Jump(&condition_label); |
| 273 builder()->Bind(&body_label); |
| 274 Visit(stmt->body()); |
| 275 builder()->Bind(&condition_label); |
| 276 Visit(stmt->cond()); |
| 277 builder()->JumpIfTrue(&body_label); |
| 278 builder()->Bind(&done_label); |
| 279 |
| 280 loop_builder.SetBreakTarget(done_label); |
| 281 loop_builder.SetContinueTarget(condition_label); |
| 176 } | 282 } |
| 177 | 283 |
| 178 | 284 |
| 179 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { | 285 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { |
| 180 UNIMPLEMENTED(); | 286 LoopBuilder loop_builder(builder()); |
| 287 ControlScopeForIteration control_scope(this, stmt, &loop_builder); |
| 288 |
| 289 if (stmt->init() != nullptr) { |
| 290 Visit(stmt->init()); |
| 291 } |
| 292 |
| 293 BytecodeLabel body_label, condition_label, next_label, done_label; |
| 294 if (stmt->cond() != nullptr) { |
| 295 builder()->Jump(&condition_label); |
| 296 } |
| 297 builder()->Bind(&body_label); |
| 298 Visit(stmt->body()); |
| 299 builder()->Bind(&next_label); |
| 300 if (stmt->next() != nullptr) { |
| 301 Visit(stmt->next()); |
| 302 } |
| 303 if (stmt->cond()) { |
| 304 builder()->Bind(&condition_label); |
| 305 Visit(stmt->cond()); |
| 306 builder()->JumpIfTrue(&body_label); |
| 307 } else { |
| 308 builder()->Jump(&body_label); |
| 309 } |
| 310 builder()->Bind(&done_label); |
| 311 |
| 312 loop_builder.SetBreakTarget(done_label); |
| 313 loop_builder.SetContinueTarget(next_label); |
| 181 } | 314 } |
| 182 | 315 |
| 183 | 316 |
| 184 void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) { | 317 void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) { |
| 185 UNIMPLEMENTED(); | 318 UNIMPLEMENTED(); |
| 186 } | 319 } |
| 187 | 320 |
| 188 | 321 |
| 189 void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { | 322 void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { |
| 190 UNIMPLEMENTED(); | 323 UNIMPLEMENTED(); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 221 UNIMPLEMENTED(); | 354 UNIMPLEMENTED(); |
| 222 } | 355 } |
| 223 | 356 |
| 224 | 357 |
| 225 void BytecodeGenerator::VisitConditional(Conditional* expr) { UNIMPLEMENTED(); } | 358 void BytecodeGenerator::VisitConditional(Conditional* expr) { UNIMPLEMENTED(); } |
| 226 | 359 |
| 227 | 360 |
| 228 void BytecodeGenerator::VisitLiteral(Literal* expr) { | 361 void BytecodeGenerator::VisitLiteral(Literal* expr) { |
| 229 Handle<Object> value = expr->value(); | 362 Handle<Object> value = expr->value(); |
| 230 if (value->IsSmi()) { | 363 if (value->IsSmi()) { |
| 231 builder().LoadLiteral(Smi::cast(*value)); | 364 builder()->LoadLiteral(Smi::cast(*value)); |
| 232 } else if (value->IsUndefined()) { | 365 } else if (value->IsUndefined()) { |
| 233 builder().LoadUndefined(); | 366 builder()->LoadUndefined(); |
| 234 } else if (value->IsTrue()) { | 367 } else if (value->IsTrue()) { |
| 235 builder().LoadTrue(); | 368 builder()->LoadTrue(); |
| 236 } else if (value->IsFalse()) { | 369 } else if (value->IsFalse()) { |
| 237 builder().LoadFalse(); | 370 builder()->LoadFalse(); |
| 238 } else if (value->IsNull()) { | 371 } else if (value->IsNull()) { |
| 239 builder().LoadNull(); | 372 builder()->LoadNull(); |
| 240 } else if (value->IsTheHole()) { | 373 } else if (value->IsTheHole()) { |
| 241 builder().LoadTheHole(); | 374 builder()->LoadTheHole(); |
| 242 } else { | 375 } else { |
| 243 builder().LoadLiteral(value); | 376 builder()->LoadLiteral(value); |
| 244 } | 377 } |
| 245 } | 378 } |
| 246 | 379 |
| 247 | 380 |
| 248 void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 381 void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 249 UNIMPLEMENTED(); | 382 UNIMPLEMENTED(); |
| 250 } | 383 } |
| 251 | 384 |
| 252 | 385 |
| 253 void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { | 386 void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
| 254 UNIMPLEMENTED(); | 387 UNIMPLEMENTED(); |
| 255 } | 388 } |
| 256 | 389 |
| 257 | 390 |
| 258 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 391 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
| 259 UNIMPLEMENTED(); | 392 UNIMPLEMENTED(); |
| 260 } | 393 } |
| 261 | 394 |
| 262 | 395 |
| 263 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { | 396 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { |
| 264 VisitVariableLoad(proxy->var()); | 397 VisitVariableLoad(proxy->var()); |
| 265 } | 398 } |
| 266 | 399 |
| 267 | 400 |
| 268 void BytecodeGenerator::VisitVariableLoad(Variable* variable) { | 401 void BytecodeGenerator::VisitVariableLoad(Variable* variable) { |
| 269 switch (variable->location()) { | 402 switch (variable->location()) { |
| 270 case VariableLocation::LOCAL: { | 403 case VariableLocation::LOCAL: { |
| 271 Register source(variable->index()); | 404 Register source(variable->index()); |
| 272 builder().LoadAccumulatorWithRegister(source); | 405 builder()->LoadAccumulatorWithRegister(source); |
| 273 break; | 406 break; |
| 274 } | 407 } |
| 275 case VariableLocation::PARAMETER: { | 408 case VariableLocation::PARAMETER: { |
| 276 // The parameter indices are shifted by 1 (receiver is variable | 409 // The parameter indices are shifted by 1 (receiver is variable |
| 277 // index -1 but is parameter index 0 in BytecodeArrayBuilder). | 410 // index -1 but is parameter index 0 in BytecodeArrayBuilder). |
| 278 Register source(builder().Parameter(variable->index() + 1)); | 411 Register source(builder()->Parameter(variable->index() + 1)); |
| 279 builder().LoadAccumulatorWithRegister(source); | 412 builder()->LoadAccumulatorWithRegister(source); |
| 280 break; | 413 break; |
| 281 } | 414 } |
| 282 case VariableLocation::GLOBAL: { | 415 case VariableLocation::GLOBAL: { |
| 283 // Global var, const, or let variable. | 416 // Global var, const, or let variable. |
| 284 // TODO(rmcilroy): If context chain depth is short enough, do this using | 417 // TODO(rmcilroy): If context chain depth is short enough, do this using |
| 285 // a generic version of LoadGlobalViaContextStub rather than calling the | 418 // a generic version of LoadGlobalViaContextStub rather than calling the |
| 286 // runtime. | 419 // runtime. |
| 287 DCHECK(variable->IsStaticGlobalObjectProperty()); | 420 DCHECK(variable->IsStaticGlobalObjectProperty()); |
| 288 builder().LoadGlobal(variable->index()); | 421 builder()->LoadGlobal(variable->index()); |
| 289 break; | 422 break; |
| 290 } | 423 } |
| 291 case VariableLocation::UNALLOCATED: | 424 case VariableLocation::UNALLOCATED: |
| 292 case VariableLocation::CONTEXT: | 425 case VariableLocation::CONTEXT: |
| 293 case VariableLocation::LOOKUP: | 426 case VariableLocation::LOOKUP: |
| 294 UNIMPLEMENTED(); | 427 UNIMPLEMENTED(); |
| 295 } | 428 } |
| 296 } | 429 } |
| 297 | 430 |
| 298 | 431 |
| 299 void BytecodeGenerator::VisitAssignment(Assignment* expr) { | 432 void BytecodeGenerator::VisitAssignment(Assignment* expr) { |
| 300 DCHECK(expr->target()->IsValidReferenceExpression()); | 433 DCHECK(expr->target()->IsValidReferenceExpression()); |
| 301 TemporaryRegisterScope temporary_register_scope(&builder_); | 434 TemporaryRegisterScope temporary_register_scope(&builder_); |
| 302 Register object, key; | 435 Register object, key; |
| 303 | 436 |
| 304 // Left-hand side can only be a property, a global or a variable slot. | 437 // Left-hand side can only be a property, a global or a variable slot. |
| 305 Property* property = expr->target()->AsProperty(); | 438 Property* property = expr->target()->AsProperty(); |
| 306 LhsKind assign_type = Property::GetAssignType(property); | 439 LhsKind assign_type = Property::GetAssignType(property); |
| 307 | 440 |
| 308 // Evaluate LHS expression. | 441 // Evaluate LHS expression. |
| 309 switch (assign_type) { | 442 switch (assign_type) { |
| 310 case VARIABLE: | 443 case VARIABLE: |
| 311 // Nothing to do to evaluate variable assignment LHS. | 444 // Nothing to do to evaluate variable assignment LHS. |
| 312 break; | 445 break; |
| 313 case NAMED_PROPERTY: | 446 case NAMED_PROPERTY: |
| 314 object = temporary_register_scope.NewRegister(); | 447 object = temporary_register_scope.NewRegister(); |
| 315 key = temporary_register_scope.NewRegister(); | 448 key = temporary_register_scope.NewRegister(); |
| 316 Visit(property->obj()); | 449 Visit(property->obj()); |
| 317 builder().StoreAccumulatorInRegister(object); | 450 builder()->StoreAccumulatorInRegister(object); |
| 318 builder().LoadLiteral(property->key()->AsLiteral()->AsPropertyName()); | 451 builder()->LoadLiteral(property->key()->AsLiteral()->AsPropertyName()); |
| 319 builder().StoreAccumulatorInRegister(key); | 452 builder()->StoreAccumulatorInRegister(key); |
| 320 break; | 453 break; |
| 321 case KEYED_PROPERTY: | 454 case KEYED_PROPERTY: |
| 322 object = temporary_register_scope.NewRegister(); | 455 object = temporary_register_scope.NewRegister(); |
| 323 key = temporary_register_scope.NewRegister(); | 456 key = temporary_register_scope.NewRegister(); |
| 324 Visit(property->obj()); | 457 Visit(property->obj()); |
| 325 builder().StoreAccumulatorInRegister(object); | 458 builder()->StoreAccumulatorInRegister(object); |
| 326 Visit(property->key()); | 459 Visit(property->key()); |
| 327 builder().StoreAccumulatorInRegister(key); | 460 builder()->StoreAccumulatorInRegister(key); |
| 328 break; | 461 break; |
| 329 case NAMED_SUPER_PROPERTY: | 462 case NAMED_SUPER_PROPERTY: |
| 330 case KEYED_SUPER_PROPERTY: | 463 case KEYED_SUPER_PROPERTY: |
| 331 UNIMPLEMENTED(); | 464 UNIMPLEMENTED(); |
| 332 } | 465 } |
| 333 | 466 |
| 334 // Evaluate the value and potentially handle compound assignments by loading | 467 // Evaluate the value and potentially handle compound assignments by loading |
| 335 // the left-hand side value and performing a binary operation. | 468 // the left-hand side value and performing a binary operation. |
| 336 if (expr->is_compound()) { | 469 if (expr->is_compound()) { |
| 337 UNIMPLEMENTED(); | 470 UNIMPLEMENTED(); |
| 338 } else { | 471 } else { |
| 339 Visit(expr->value()); | 472 Visit(expr->value()); |
| 340 } | 473 } |
| 341 | 474 |
| 342 // Store the value. | 475 // Store the value. |
| 343 FeedbackVectorICSlot slot = expr->AssignmentSlot(); | 476 FeedbackVectorICSlot slot = expr->AssignmentSlot(); |
| 344 switch (assign_type) { | 477 switch (assign_type) { |
| 345 case VARIABLE: { | 478 case VARIABLE: { |
| 346 Variable* variable = expr->target()->AsVariableProxy()->var(); | 479 Variable* variable = expr->target()->AsVariableProxy()->var(); |
| 347 DCHECK(variable->location() == VariableLocation::LOCAL); | 480 DCHECK(variable->location() == VariableLocation::LOCAL); |
| 348 Register destination(variable->index()); | 481 Register destination(variable->index()); |
| 349 builder().StoreAccumulatorInRegister(destination); | 482 builder()->StoreAccumulatorInRegister(destination); |
| 350 break; | 483 break; |
| 351 } | 484 } |
| 352 case NAMED_PROPERTY: | 485 case NAMED_PROPERTY: |
| 353 builder().StoreNamedProperty(object, key, feedback_index(slot), | 486 builder()->StoreNamedProperty(object, key, feedback_index(slot), |
| 354 language_mode()); | 487 language_mode()); |
| 355 break; | 488 break; |
| 356 case KEYED_PROPERTY: | 489 case KEYED_PROPERTY: |
| 357 builder().StoreKeyedProperty(object, key, feedback_index(slot), | 490 builder()->StoreKeyedProperty(object, key, feedback_index(slot), |
| 358 language_mode()); | 491 language_mode()); |
| 359 break; | 492 break; |
| 360 case NAMED_SUPER_PROPERTY: | 493 case NAMED_SUPER_PROPERTY: |
| 361 case KEYED_SUPER_PROPERTY: | 494 case KEYED_SUPER_PROPERTY: |
| 362 UNIMPLEMENTED(); | 495 UNIMPLEMENTED(); |
| 363 } | 496 } |
| 364 } | 497 } |
| 365 | 498 |
| 366 | 499 |
| 367 void BytecodeGenerator::VisitYield(Yield* expr) { UNIMPLEMENTED(); } | 500 void BytecodeGenerator::VisitYield(Yield* expr) { UNIMPLEMENTED(); } |
| 368 | 501 |
| 369 | 502 |
| 370 void BytecodeGenerator::VisitThrow(Throw* expr) { UNIMPLEMENTED(); } | 503 void BytecodeGenerator::VisitThrow(Throw* expr) { UNIMPLEMENTED(); } |
| 371 | 504 |
| 372 | 505 |
| 373 void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) { | 506 void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) { |
| 374 LhsKind property_kind = Property::GetAssignType(expr); | 507 LhsKind property_kind = Property::GetAssignType(expr); |
| 375 FeedbackVectorICSlot slot = expr->PropertyFeedbackSlot(); | 508 FeedbackVectorICSlot slot = expr->PropertyFeedbackSlot(); |
| 376 switch (property_kind) { | 509 switch (property_kind) { |
| 377 case VARIABLE: | 510 case VARIABLE: |
| 378 UNREACHABLE(); | 511 UNREACHABLE(); |
| 379 case NAMED_PROPERTY: { | 512 case NAMED_PROPERTY: { |
| 380 builder().LoadLiteral(expr->key()->AsLiteral()->AsPropertyName()); | 513 builder()->LoadLiteral(expr->key()->AsLiteral()->AsPropertyName()); |
| 381 builder().LoadNamedProperty(obj, feedback_index(slot), language_mode()); | 514 builder()->LoadNamedProperty(obj, feedback_index(slot), language_mode()); |
| 382 break; | 515 break; |
| 383 } | 516 } |
| 384 case KEYED_PROPERTY: { | 517 case KEYED_PROPERTY: { |
| 385 Visit(expr->key()); | 518 Visit(expr->key()); |
| 386 builder().LoadKeyedProperty(obj, feedback_index(slot), language_mode()); | 519 builder()->LoadKeyedProperty(obj, feedback_index(slot), language_mode()); |
| 387 break; | 520 break; |
| 388 } | 521 } |
| 389 case NAMED_SUPER_PROPERTY: | 522 case NAMED_SUPER_PROPERTY: |
| 390 case KEYED_SUPER_PROPERTY: | 523 case KEYED_SUPER_PROPERTY: |
| 391 UNIMPLEMENTED(); | 524 UNIMPLEMENTED(); |
| 392 } | 525 } |
| 393 } | 526 } |
| 394 | 527 |
| 395 | 528 |
| 396 void BytecodeGenerator::VisitProperty(Property* expr) { | 529 void BytecodeGenerator::VisitProperty(Property* expr) { |
| 397 TemporaryRegisterScope temporary_register_scope(&builder_); | 530 TemporaryRegisterScope temporary_register_scope(&builder_); |
| 398 Register obj = temporary_register_scope.NewRegister(); | 531 Register obj = temporary_register_scope.NewRegister(); |
| 399 Visit(expr->obj()); | 532 Visit(expr->obj()); |
| 400 builder().StoreAccumulatorInRegister(obj); | 533 builder()->StoreAccumulatorInRegister(obj); |
| 401 VisitPropertyLoad(obj, expr); | 534 VisitPropertyLoad(obj, expr); |
| 402 } | 535 } |
| 403 | 536 |
| 404 | 537 |
| 405 void BytecodeGenerator::VisitCall(Call* expr) { | 538 void BytecodeGenerator::VisitCall(Call* expr) { |
| 406 Expression* callee_expr = expr->expression(); | 539 Expression* callee_expr = expr->expression(); |
| 407 Call::CallType call_type = expr->GetCallType(isolate()); | 540 Call::CallType call_type = expr->GetCallType(isolate()); |
| 408 | 541 |
| 409 // Prepare the callee and the receiver to the function call. This depends on | 542 // Prepare the callee and the receiver to the function call. This depends on |
| 410 // the semantics of the underlying call type. | 543 // the semantics of the underlying call type. |
| 411 TemporaryRegisterScope temporary_register_scope(&builder_); | 544 TemporaryRegisterScope temporary_register_scope(&builder_); |
| 412 Register callee = temporary_register_scope.NewRegister(); | 545 Register callee = temporary_register_scope.NewRegister(); |
| 413 Register receiver = temporary_register_scope.NewRegister(); | 546 Register receiver = temporary_register_scope.NewRegister(); |
| 414 | 547 |
| 415 switch (call_type) { | 548 switch (call_type) { |
| 416 case Call::PROPERTY_CALL: { | 549 case Call::PROPERTY_CALL: { |
| 417 Property* property = callee_expr->AsProperty(); | 550 Property* property = callee_expr->AsProperty(); |
| 418 if (property->IsSuperAccess()) { | 551 if (property->IsSuperAccess()) { |
| 419 UNIMPLEMENTED(); | 552 UNIMPLEMENTED(); |
| 420 } | 553 } |
| 421 Visit(property->obj()); | 554 Visit(property->obj()); |
| 422 builder().StoreAccumulatorInRegister(receiver); | 555 builder()->StoreAccumulatorInRegister(receiver); |
| 423 // Perform a property load of the callee. | 556 // Perform a property load of the callee. |
| 424 VisitPropertyLoad(receiver, property); | 557 VisitPropertyLoad(receiver, property); |
| 425 builder().StoreAccumulatorInRegister(callee); | 558 builder()->StoreAccumulatorInRegister(callee); |
| 426 break; | 559 break; |
| 427 } | 560 } |
| 428 case Call::GLOBAL_CALL: { | 561 case Call::GLOBAL_CALL: { |
| 429 // Receiver is undefined for global calls. | 562 // Receiver is undefined for global calls. |
| 430 builder().LoadUndefined().StoreAccumulatorInRegister(receiver); | 563 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); |
| 431 // Load callee as a global variable. | 564 // Load callee as a global variable. |
| 432 VariableProxy* proxy = callee_expr->AsVariableProxy(); | 565 VariableProxy* proxy = callee_expr->AsVariableProxy(); |
| 433 VisitVariableLoad(proxy->var()); | 566 VisitVariableLoad(proxy->var()); |
| 434 builder().StoreAccumulatorInRegister(callee); | 567 builder()->StoreAccumulatorInRegister(callee); |
| 435 break; | 568 break; |
| 436 } | 569 } |
| 437 case Call::LOOKUP_SLOT_CALL: | 570 case Call::LOOKUP_SLOT_CALL: |
| 438 case Call::SUPER_CALL: | 571 case Call::SUPER_CALL: |
| 439 case Call::POSSIBLY_EVAL_CALL: | 572 case Call::POSSIBLY_EVAL_CALL: |
| 440 case Call::OTHER_CALL: | 573 case Call::OTHER_CALL: |
| 441 UNIMPLEMENTED(); | 574 UNIMPLEMENTED(); |
| 442 } | 575 } |
| 443 | 576 |
| 444 // Evaluate all arguments to the function call and store in sequential | 577 // Evaluate all arguments to the function call and store in sequential |
| 445 // registers. | 578 // registers. |
| 446 ZoneList<Expression*>* args = expr->arguments(); | 579 ZoneList<Expression*>* args = expr->arguments(); |
| 447 for (int i = 0; i < args->length(); ++i) { | 580 for (int i = 0; i < args->length(); ++i) { |
| 448 Visit(args->at(i)); | 581 Visit(args->at(i)); |
| 449 Register arg = temporary_register_scope.NewRegister(); | 582 Register arg = temporary_register_scope.NewRegister(); |
| 450 DCHECK(arg.index() - i == receiver.index() + 1); | 583 DCHECK(arg.index() - i == receiver.index() + 1); |
| 451 builder().StoreAccumulatorInRegister(arg); | 584 builder()->StoreAccumulatorInRegister(arg); |
| 452 } | 585 } |
| 453 | 586 |
| 454 // TODO(rmcilroy): Deal with possible direct eval here? | 587 // TODO(rmcilroy): Deal with possible direct eval here? |
| 455 // TODO(rmcilroy): Use CallIC to allow call type feedback. | 588 // TODO(rmcilroy): Use CallIC to allow call type feedback. |
| 456 builder().Call(callee, receiver, args->length()); | 589 builder()->Call(callee, receiver, args->length()); |
| 457 } | 590 } |
| 458 | 591 |
| 459 | 592 |
| 460 void BytecodeGenerator::VisitCallNew(CallNew* expr) { UNIMPLEMENTED(); } | 593 void BytecodeGenerator::VisitCallNew(CallNew* expr) { UNIMPLEMENTED(); } |
| 461 | 594 |
| 462 | 595 |
| 463 void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) { UNIMPLEMENTED(); } | 596 void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) { UNIMPLEMENTED(); } |
| 464 | 597 |
| 465 | 598 |
| 466 void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 599 void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 489 | 622 |
| 490 void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) { | 623 void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
| 491 Token::Value op = expr->op(); | 624 Token::Value op = expr->op(); |
| 492 Expression* left = expr->left(); | 625 Expression* left = expr->left(); |
| 493 Expression* right = expr->right(); | 626 Expression* right = expr->right(); |
| 494 | 627 |
| 495 TemporaryRegisterScope temporary_register_scope(&builder_); | 628 TemporaryRegisterScope temporary_register_scope(&builder_); |
| 496 Register temporary = temporary_register_scope.NewRegister(); | 629 Register temporary = temporary_register_scope.NewRegister(); |
| 497 | 630 |
| 498 Visit(left); | 631 Visit(left); |
| 499 builder().StoreAccumulatorInRegister(temporary); | 632 builder()->StoreAccumulatorInRegister(temporary); |
| 500 Visit(right); | 633 Visit(right); |
| 501 builder().CompareOperation(op, temporary, language_mode()); | 634 builder()->CompareOperation(op, temporary, language_mode()); |
| 502 } | 635 } |
| 503 | 636 |
| 504 | 637 |
| 505 void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); } | 638 void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); } |
| 506 | 639 |
| 507 | 640 |
| 508 void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) { | 641 void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) { |
| 509 UNREACHABLE(); | 642 UNREACHABLE(); |
| 510 } | 643 } |
| 511 | 644 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 528 | 661 |
| 529 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* binop) { | 662 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* binop) { |
| 530 Token::Value op = binop->op(); | 663 Token::Value op = binop->op(); |
| 531 Expression* left = binop->left(); | 664 Expression* left = binop->left(); |
| 532 Expression* right = binop->right(); | 665 Expression* right = binop->right(); |
| 533 | 666 |
| 534 TemporaryRegisterScope temporary_register_scope(&builder_); | 667 TemporaryRegisterScope temporary_register_scope(&builder_); |
| 535 Register temporary = temporary_register_scope.NewRegister(); | 668 Register temporary = temporary_register_scope.NewRegister(); |
| 536 | 669 |
| 537 Visit(left); | 670 Visit(left); |
| 538 builder().StoreAccumulatorInRegister(temporary); | 671 builder()->StoreAccumulatorInRegister(temporary); |
| 539 Visit(right); | 672 Visit(right); |
| 540 builder().BinaryOperation(op, temporary); | 673 builder()->BinaryOperation(op, temporary); |
| 541 } | 674 } |
| 542 | 675 |
| 543 | 676 |
| 544 LanguageMode BytecodeGenerator::language_mode() const { | 677 LanguageMode BytecodeGenerator::language_mode() const { |
| 545 return info()->language_mode(); | 678 return info()->language_mode(); |
| 546 } | 679 } |
| 547 | 680 |
| 548 | 681 |
| 549 int BytecodeGenerator::feedback_index(FeedbackVectorICSlot slot) const { | 682 int BytecodeGenerator::feedback_index(FeedbackVectorICSlot slot) const { |
| 550 return info()->feedback_vector()->GetIndex(slot); | 683 return info()->feedback_vector()->GetIndex(slot); |
| 551 } | 684 } |
| 552 | 685 |
| 553 } // namespace interpreter | 686 } // namespace interpreter |
| 554 } // namespace internal | 687 } // namespace internal |
| 555 } // namespace v8 | 688 } // namespace v8 |
| OLD | NEW |