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); | |
rmcilroy
2015/10/01 09:18:56
Do we expect to reach the end of the loop not havi
oth
2015/10/01 11:43:02
Done.
| |
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()) { |
rmcilroy
2015/10/01 09:18:55
Can we just have this around the else statement -
oth
2015/10/01 11:43:02
Done.
| |
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 control_scope(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 control_scope(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 control_scope(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); | |
rmcilroy
2015/10/01 09:18:55
nit - put this in the if (stmt->cond())
oth
2015/10/01 11:43:02
Done.
| |
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 |