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 |