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