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/interpreter/control-flow-builders.h" |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
82 Statement* statement) { | 82 Statement* statement) { |
83 ControlScope* current = this; | 83 ControlScope* current = this; |
84 do { | 84 do { |
85 if (current->Execute(command, statement)) return; | 85 if (current->Execute(command, statement)) return; |
86 current = current->outer(); | 86 current = current->outer(); |
87 } while (current != nullptr); | 87 } while (current != nullptr); |
88 UNREACHABLE(); | 88 UNREACHABLE(); |
89 } | 89 } |
90 | 90 |
91 | 91 |
92 // Scoped base class for determining where the result of an expression | |
93 // is stored. | |
94 class BytecodeGenerator::ExpressionResultScope { | |
95 public: | |
96 explicit ExpressionResultScope(BytecodeGenerator* generator) | |
97 : generator_(generator), | |
98 outer_(generator->result_scope()), | |
99 result_identified_(false) { | |
100 generator_->set_result_scope(this); | |
101 } | |
102 | |
103 virtual ~ExpressionResultScope() { | |
104 generator_->set_result_scope(outer_); | |
105 DCHECK_EQ(result_identified(), true); | |
106 } | |
107 | |
108 virtual void SetResultInAccumulator() = 0; | |
109 virtual void SetResultInRegister(Register reg) = 0; | |
110 | |
111 BytecodeGenerator* generator() const { return generator_; } | |
112 BytecodeArrayBuilder* builder() const { return generator()->builder(); } | |
113 | |
114 protected: | |
115 void set_result_identified() { | |
116 DCHECK(!result_identified()); | |
117 result_identified_ = true; | |
118 } | |
119 bool result_identified() const { return result_identified_; } | |
120 | |
121 private: | |
122 BytecodeGenerator* generator_; | |
123 ExpressionResultScope* outer_; | |
124 bool result_identified_; | |
125 DISALLOW_COPY_AND_ASSIGN(ExpressionResultScope); | |
126 }; | |
127 | |
128 | |
129 // Scoped class used when the result of the current expression to be | |
130 // evaluated should go into the interpreter's accumulator register. | |
131 class BytecodeGenerator::AccumulatorResultScope final | |
132 : public ExpressionResultScope { | |
133 public: | |
134 explicit AccumulatorResultScope(BytecodeGenerator* generator) | |
135 : ExpressionResultScope(generator) {} | |
136 virtual void SetResultInAccumulator() { | |
137 if (!result_identified()) { | |
138 // TODO(oth): REVIEW. | |
139 set_result_identified(); | |
140 } | |
141 } | |
142 virtual void SetResultInRegister(Register reg) { | |
143 builder()->LoadAccumulatorWithRegister(reg); | |
144 set_result_identified(); | |
145 } | |
146 }; | |
147 | |
148 | |
149 // Scoped class used when the result of the current expression is not | |
150 // expected to produce a result. | |
151 class BytecodeGenerator::EffectResultScope final | |
152 : public ExpressionResultScope { | |
153 public: | |
154 explicit EffectResultScope(BytecodeGenerator* generator) | |
155 : ExpressionResultScope(generator) { set_result_identified(); } | |
156 virtual void SetResultInAccumulator() {} | |
157 virtual void SetResultInRegister(Register reg) {} | |
158 }; | |
159 | |
160 | |
161 // Scoped class used when the result of the current expression to be | |
162 // evaluated should go into an interpreter register. | |
163 class BytecodeGenerator::RegisterResultScope final | |
164 : public ExpressionResultScope { | |
165 public: | |
166 explicit RegisterResultScope(BytecodeGenerator* generator, | |
167 TemporaryRegisterScope* register_scope) | |
168 : ExpressionResultScope(generator), register_scope_(register_scope) { | |
169 DCHECK(generator->ResultRegisterIsEmpty()); | |
170 } | |
171 ~RegisterResultScope() { DCHECK(generator()->ResultRegisterIsEmpty()); } | |
172 | |
173 virtual void SetResultInAccumulator() { | |
174 Register allocated = register_scope_->NewRegister(); | |
175 builder()->StoreAccumulatorInRegister(allocated); | |
176 generator()->SetResultRegister(allocated); | |
177 set_result_identified(); | |
178 } | |
179 | |
180 virtual void SetResultInRegister(Register reg) { | |
181 generator()->SetResultRegister(reg); | |
182 set_result_identified(); | |
183 } | |
184 | |
185 private: | |
186 TemporaryRegisterScope* register_scope_; | |
187 }; | |
188 | |
189 | |
92 BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone) | 190 BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone) |
93 : builder_(isolate, zone), | 191 : builder_(isolate, zone), |
94 info_(nullptr), | 192 info_(nullptr), |
95 scope_(nullptr), | 193 scope_(nullptr), |
96 globals_(0, zone), | 194 globals_(0, zone), |
97 control_scope_(nullptr), | 195 control_scope_(nullptr), |
98 current_context_(Register::function_context()) { | 196 current_context_(Register::function_context()), |
197 result_scope_(nullptr), | |
198 result_register_(Nothing<Register>()) { | |
99 InitializeAstVisitor(isolate, zone); | 199 InitializeAstVisitor(isolate, zone); |
100 } | 200 } |
101 | 201 |
102 | 202 |
103 BytecodeGenerator::~BytecodeGenerator() {} | 203 BytecodeGenerator::~BytecodeGenerator() {} |
104 | 204 |
105 | 205 |
106 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) { | 206 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) { |
107 set_info(info); | 207 set_info(info); |
108 set_scope(info->scope()); | 208 set_scope(info->scope()); |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
228 builder()->LoadLiteral(Smi::FromInt(encoded_flags)); | 328 builder()->LoadLiteral(Smi::FromInt(encoded_flags)); |
229 builder()->StoreAccumulatorInRegister(flags); | 329 builder()->StoreAccumulatorInRegister(flags); |
230 DCHECK(flags.index() == pairs.index() + 1); | 330 DCHECK(flags.index() == pairs.index() + 1); |
231 | 331 |
232 builder()->CallRuntime(Runtime::kDeclareGlobals, pairs, 2); | 332 builder()->CallRuntime(Runtime::kDeclareGlobals, pairs, 2); |
233 globals()->clear(); | 333 globals()->clear(); |
234 } | 334 } |
235 | 335 |
236 | 336 |
237 void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { | 337 void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { |
238 Visit(stmt->expression()); | 338 VisitForAccumulatorValue(stmt->expression()); |
239 } | 339 } |
240 | 340 |
241 | 341 |
242 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { | 342 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { |
243 // TODO(oth): For control-flow it could be useful to signal empty paths here. | 343 // TODO(oth): For control-flow it could be useful to signal empty paths here. |
244 } | 344 } |
245 | 345 |
246 | 346 |
247 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) { | 347 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) { |
248 // TODO(oth): Spot easy cases where there code would not need to | 348 // TODO(oth): Spot easy cases where there code would not need to |
249 // emit the then block or the else block, e.g. condition is | 349 // emit the then block or the else block, e.g. condition is |
250 // obviously true/1/false/0. | 350 // obviously true/1/false/0. |
251 | 351 |
252 BytecodeLabel else_label, end_label; | 352 BytecodeLabel else_label, end_label; |
253 | 353 |
254 Visit(stmt->condition()); | 354 VisitForAccumulatorValue(stmt->condition()); |
255 builder()->CastAccumulatorToBoolean(); | 355 builder()->CastAccumulatorToBoolean(); |
256 builder()->JumpIfFalse(&else_label); | 356 builder()->JumpIfFalse(&else_label); |
257 Visit(stmt->then_statement()); | 357 Visit(stmt->then_statement()); |
258 if (stmt->HasElseStatement()) { | 358 if (stmt->HasElseStatement()) { |
259 builder()->Jump(&end_label); | 359 builder()->Jump(&end_label); |
260 builder()->Bind(&else_label); | 360 builder()->Bind(&else_label); |
261 Visit(stmt->else_statement()); | 361 Visit(stmt->else_statement()); |
262 } else { | 362 } else { |
263 builder()->Bind(&else_label); | 363 builder()->Bind(&else_label); |
264 } | 364 } |
(...skipping 11 matching lines...) Expand all Loading... | |
276 control_scope()->Continue(stmt->target()); | 376 control_scope()->Continue(stmt->target()); |
277 } | 377 } |
278 | 378 |
279 | 379 |
280 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) { | 380 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) { |
281 control_scope()->Break(stmt->target()); | 381 control_scope()->Break(stmt->target()); |
282 } | 382 } |
283 | 383 |
284 | 384 |
285 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { | 385 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { |
286 Visit(stmt->expression()); | 386 VisitForAccumulatorValue(stmt->expression()); |
287 builder()->Return(); | 387 builder()->Return(); |
288 } | 388 } |
289 | 389 |
290 | 390 |
291 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) { | 391 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) { |
292 UNIMPLEMENTED(); | 392 UNIMPLEMENTED(); |
293 } | 393 } |
294 | 394 |
295 | 395 |
296 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { | 396 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { |
297 UNIMPLEMENTED(); | 397 UNIMPLEMENTED(); |
298 } | 398 } |
299 | 399 |
300 | 400 |
301 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { UNIMPLEMENTED(); } | 401 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { UNIMPLEMENTED(); } |
302 | 402 |
303 | 403 |
304 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { | 404 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { |
305 LoopBuilder loop_builder(builder()); | 405 LoopBuilder loop_builder(builder()); |
306 ControlScopeForIteration control_scope(this, stmt, &loop_builder); | 406 ControlScopeForIteration control_scope(this, stmt, &loop_builder); |
307 | 407 |
308 BytecodeLabel body_label, condition_label, done_label; | 408 BytecodeLabel body_label, condition_label, done_label; |
309 builder()->Bind(&body_label); | 409 builder()->Bind(&body_label); |
310 Visit(stmt->body()); | 410 Visit(stmt->body()); |
311 builder()->Bind(&condition_label); | 411 builder()->Bind(&condition_label); |
312 Visit(stmt->cond()); | 412 VisitForAccumulatorValue(stmt->cond()); |
313 builder()->JumpIfTrue(&body_label); | 413 builder()->JumpIfTrue(&body_label); |
314 builder()->Bind(&done_label); | 414 builder()->Bind(&done_label); |
315 | 415 |
316 loop_builder.SetBreakTarget(done_label); | 416 loop_builder.SetBreakTarget(done_label); |
317 loop_builder.SetContinueTarget(condition_label); | 417 loop_builder.SetContinueTarget(condition_label); |
318 } | 418 } |
319 | 419 |
320 | 420 |
321 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) { | 421 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) { |
322 LoopBuilder loop_builder(builder()); | 422 LoopBuilder loop_builder(builder()); |
323 ControlScopeForIteration control_scope(this, stmt, &loop_builder); | 423 ControlScopeForIteration control_scope(this, stmt, &loop_builder); |
324 | 424 |
325 BytecodeLabel body_label, condition_label, done_label; | 425 BytecodeLabel body_label, condition_label, done_label; |
326 builder()->Jump(&condition_label); | 426 builder()->Jump(&condition_label); |
327 builder()->Bind(&body_label); | 427 builder()->Bind(&body_label); |
328 Visit(stmt->body()); | 428 Visit(stmt->body()); |
329 builder()->Bind(&condition_label); | 429 builder()->Bind(&condition_label); |
330 Visit(stmt->cond()); | 430 VisitForAccumulatorValue(stmt->cond()); |
331 builder()->JumpIfTrue(&body_label); | 431 builder()->JumpIfTrue(&body_label); |
332 builder()->Bind(&done_label); | 432 builder()->Bind(&done_label); |
333 | 433 |
334 loop_builder.SetBreakTarget(done_label); | 434 loop_builder.SetBreakTarget(done_label); |
335 loop_builder.SetContinueTarget(condition_label); | 435 loop_builder.SetContinueTarget(condition_label); |
336 } | 436 } |
337 | 437 |
338 | 438 |
339 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { | 439 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { |
340 LoopBuilder loop_builder(builder()); | 440 LoopBuilder loop_builder(builder()); |
341 ControlScopeForIteration control_scope(this, stmt, &loop_builder); | 441 ControlScopeForIteration control_scope(this, stmt, &loop_builder); |
342 | 442 |
343 if (stmt->init() != nullptr) { | 443 if (stmt->init() != nullptr) { |
344 Visit(stmt->init()); | 444 Visit(stmt->init()); |
345 } | 445 } |
346 | 446 |
347 BytecodeLabel body_label, condition_label, next_label, done_label; | 447 BytecodeLabel body_label, condition_label, next_label, done_label; |
348 if (stmt->cond() != nullptr) { | 448 if (stmt->cond() != nullptr) { |
349 builder()->Jump(&condition_label); | 449 builder()->Jump(&condition_label); |
350 } | 450 } |
351 builder()->Bind(&body_label); | 451 builder()->Bind(&body_label); |
352 Visit(stmt->body()); | 452 Visit(stmt->body()); |
353 builder()->Bind(&next_label); | 453 builder()->Bind(&next_label); |
354 if (stmt->next() != nullptr) { | 454 if (stmt->next() != nullptr) { |
355 Visit(stmt->next()); | 455 Visit(stmt->next()); |
356 } | 456 } |
357 if (stmt->cond()) { | 457 if (stmt->cond()) { |
358 builder()->Bind(&condition_label); | 458 builder()->Bind(&condition_label); |
359 Visit(stmt->cond()); | 459 VisitForAccumulatorValue(stmt->cond()); |
360 builder()->JumpIfTrue(&body_label); | 460 builder()->JumpIfTrue(&body_label); |
361 } else { | 461 } else { |
362 builder()->Jump(&body_label); | 462 builder()->Jump(&body_label); |
363 } | 463 } |
364 builder()->Bind(&done_label); | 464 builder()->Bind(&done_label); |
365 | 465 |
366 loop_builder.SetBreakTarget(done_label); | 466 loop_builder.SetBreakTarget(done_label); |
367 loop_builder.SetContinueTarget(next_label); | 467 loop_builder.SetContinueTarget(next_label); |
368 } | 468 } |
369 | 469 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
422 builder()->LoadTrue(); | 522 builder()->LoadTrue(); |
423 } else if (value->IsFalse()) { | 523 } else if (value->IsFalse()) { |
424 builder()->LoadFalse(); | 524 builder()->LoadFalse(); |
425 } else if (value->IsNull()) { | 525 } else if (value->IsNull()) { |
426 builder()->LoadNull(); | 526 builder()->LoadNull(); |
427 } else if (value->IsTheHole()) { | 527 } else if (value->IsTheHole()) { |
428 builder()->LoadTheHole(); | 528 builder()->LoadTheHole(); |
429 } else { | 529 } else { |
430 builder()->LoadLiteral(value); | 530 builder()->LoadLiteral(value); |
431 } | 531 } |
532 result_scope()->SetResultInAccumulator(); | |
432 } | 533 } |
433 | 534 |
434 | 535 |
435 void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 536 void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
436 UNIMPLEMENTED(); | 537 UNIMPLEMENTED(); |
437 } | 538 } |
438 | 539 |
439 | 540 |
440 void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { | 541 void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
441 UNIMPLEMENTED(); | 542 UNIMPLEMENTED(); |
442 } | 543 } |
443 | 544 |
444 | 545 |
445 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 546 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
446 UNIMPLEMENTED(); | 547 UNIMPLEMENTED(); |
447 } | 548 } |
448 | 549 |
449 | 550 |
450 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { | 551 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { |
451 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); | 552 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); |
452 } | 553 } |
453 | 554 |
454 | 555 |
455 void BytecodeGenerator::VisitVariableLoad(Variable* variable, | 556 void BytecodeGenerator::VisitVariableLoad(Variable* variable, |
456 FeedbackVectorSlot slot) { | 557 FeedbackVectorSlot slot) { |
457 switch (variable->location()) { | 558 switch (variable->location()) { |
458 case VariableLocation::LOCAL: { | 559 case VariableLocation::LOCAL: { |
459 Register source(variable->index()); | 560 result_scope()->SetResultInRegister(Register(variable->index())); |
460 builder()->LoadAccumulatorWithRegister(source); | |
461 break; | 561 break; |
462 } | 562 } |
463 case VariableLocation::PARAMETER: { | 563 case VariableLocation::PARAMETER: { |
464 // The parameter indices are shifted by 1 (receiver is variable | 564 // The parameter indices are shifted by 1 (receiver is variable |
465 // index -1 but is parameter index 0 in BytecodeArrayBuilder). | 565 // index -1 but is parameter index 0 in BytecodeArrayBuilder). |
466 Register source(builder()->Parameter(variable->index() + 1)); | 566 result_scope()->SetResultInRegister( |
467 builder()->LoadAccumulatorWithRegister(source); | 567 builder()->Parameter(variable->index() + 1)); |
468 break; | 568 break; |
469 } | 569 } |
470 case VariableLocation::GLOBAL: { | 570 case VariableLocation::GLOBAL: { |
471 // Global var, const, or let variable. | 571 // Global var, const, or let variable. |
472 // TODO(rmcilroy): If context chain depth is short enough, do this using | 572 // TODO(rmcilroy): If context chain depth is short enough, do this using |
473 // a generic version of LoadGlobalViaContextStub rather than calling the | 573 // a generic version of LoadGlobalViaContextStub rather than calling the |
474 // runtime. | 574 // runtime. |
475 DCHECK(variable->IsStaticGlobalObjectProperty()); | 575 DCHECK(variable->IsStaticGlobalObjectProperty()); |
476 builder()->LoadGlobal(variable->index()); | 576 builder()->LoadGlobal(variable->index()); |
577 result_scope()->SetResultInAccumulator(); | |
477 break; | 578 break; |
478 } | 579 } |
479 case VariableLocation::UNALLOCATED: { | 580 case VariableLocation::UNALLOCATED: { |
480 TemporaryRegisterScope temporary_register_scope(&builder_); | 581 TemporaryRegisterScope temporary_register_scope(&builder_); |
481 Register obj = temporary_register_scope.NewRegister(); | 582 Register obj = temporary_register_scope.NewRegister(); |
482 builder()->LoadContextSlot(current_context(), | 583 builder()->LoadContextSlot(current_context(), |
483 Context::GLOBAL_OBJECT_INDEX); | 584 Context::GLOBAL_OBJECT_INDEX); |
484 builder()->StoreAccumulatorInRegister(obj); | 585 builder()->StoreAccumulatorInRegister(obj); |
485 builder()->LoadLiteral(variable->name()); | 586 builder()->LoadLiteral(variable->name()); |
486 builder()->LoadNamedProperty(obj, feedback_index(slot), language_mode()); | 587 builder()->LoadNamedProperty(obj, feedback_index(slot), language_mode()); |
588 result_scope()->SetResultInAccumulator(); | |
487 break; | 589 break; |
488 } | 590 } |
489 case VariableLocation::CONTEXT: | 591 case VariableLocation::CONTEXT: |
490 case VariableLocation::LOOKUP: | 592 case VariableLocation::LOOKUP: |
593 default: | |
rmcilroy
2015/10/09 13:02:56
Is this required? I'd prefer to avoid default: if
oth
2015/10/09 13:27:39
Acknowledged.
| |
491 UNIMPLEMENTED(); | 594 UNIMPLEMENTED(); |
492 } | 595 } |
493 } | 596 } |
494 | 597 |
495 | 598 |
496 void BytecodeGenerator::VisitVariableAssignment(Variable* variable, | 599 void BytecodeGenerator::VisitVariableAssignment(Variable* variable, |
497 FeedbackVectorSlot slot) { | 600 FeedbackVectorSlot slot) { |
498 switch (variable->location()) { | 601 switch (variable->location()) { |
499 case VariableLocation::LOCAL: { | 602 case VariableLocation::LOCAL: { |
500 // TODO(rmcilroy): support const mode initialization. | 603 // TODO(rmcilroy): support const mode initialization. |
(...skipping 30 matching lines...) Expand all Loading... | |
531 builder()->StoreAccumulatorInRegister(obj); | 634 builder()->StoreAccumulatorInRegister(obj); |
532 builder()->LoadLiteral(variable->name()); | 635 builder()->LoadLiteral(variable->name()); |
533 builder()->StoreAccumulatorInRegister(name); | 636 builder()->StoreAccumulatorInRegister(name); |
534 builder()->LoadAccumulatorWithRegister(value); | 637 builder()->LoadAccumulatorWithRegister(value); |
535 builder()->StoreNamedProperty(obj, name, feedback_index(slot), | 638 builder()->StoreNamedProperty(obj, name, feedback_index(slot), |
536 language_mode()); | 639 language_mode()); |
537 break; | 640 break; |
538 } | 641 } |
539 case VariableLocation::CONTEXT: | 642 case VariableLocation::CONTEXT: |
540 case VariableLocation::LOOKUP: | 643 case VariableLocation::LOOKUP: |
644 default: | |
541 UNIMPLEMENTED(); | 645 UNIMPLEMENTED(); |
542 } | 646 } |
543 } | 647 } |
544 | 648 |
545 | 649 |
546 void BytecodeGenerator::VisitAssignment(Assignment* expr) { | 650 void BytecodeGenerator::VisitAssignment(Assignment* expr) { |
547 DCHECK(expr->target()->IsValidReferenceExpression()); | 651 DCHECK(expr->target()->IsValidReferenceExpression()); |
548 TemporaryRegisterScope temporary_register_scope(&builder_); | 652 TemporaryRegisterScope temporary_register_scope(builder()); |
549 Register object, key; | 653 Register object, key; |
550 | 654 |
551 // Left-hand side can only be a property, a global or a variable slot. | 655 // Left-hand side can only be a property, a global or a variable slot. |
552 Property* property = expr->target()->AsProperty(); | 656 Property* property = expr->target()->AsProperty(); |
553 LhsKind assign_type = Property::GetAssignType(property); | 657 LhsKind assign_type = Property::GetAssignType(property); |
554 | 658 |
555 // Evaluate LHS expression. | 659 // Evaluate LHS expression. |
556 switch (assign_type) { | 660 switch (assign_type) { |
557 case VARIABLE: | 661 case VARIABLE: |
558 // Nothing to do to evaluate variable assignment LHS. | 662 // Nothing to do to evaluate variable assignment LHS. |
559 break; | 663 break; |
560 case NAMED_PROPERTY: | 664 case NAMED_PROPERTY: |
561 object = temporary_register_scope.NewRegister(); | 665 object = |
666 VisitForRegisterValue(property->obj(), &temporary_register_scope); | |
667 builder()->LoadLiteral(property->key()->AsLiteral()->AsPropertyName()); | |
562 key = temporary_register_scope.NewRegister(); | 668 key = temporary_register_scope.NewRegister(); |
563 Visit(property->obj()); | |
564 builder()->StoreAccumulatorInRegister(object); | |
565 builder()->LoadLiteral(property->key()->AsLiteral()->AsPropertyName()); | |
566 builder()->StoreAccumulatorInRegister(key); | 669 builder()->StoreAccumulatorInRegister(key); |
567 break; | 670 break; |
568 case KEYED_PROPERTY: | 671 case KEYED_PROPERTY: |
569 object = temporary_register_scope.NewRegister(); | 672 object = |
570 key = temporary_register_scope.NewRegister(); | 673 VisitForRegisterValue(property->obj(), &temporary_register_scope); |
571 Visit(property->obj()); | 674 key = VisitForRegisterValue(property->key(), &temporary_register_scope); |
572 builder()->StoreAccumulatorInRegister(object); | |
573 Visit(property->key()); | |
574 builder()->StoreAccumulatorInRegister(key); | |
575 break; | 675 break; |
576 case NAMED_SUPER_PROPERTY: | 676 case NAMED_SUPER_PROPERTY: |
577 case KEYED_SUPER_PROPERTY: | 677 case KEYED_SUPER_PROPERTY: |
678 default: | |
578 UNIMPLEMENTED(); | 679 UNIMPLEMENTED(); |
579 } | 680 } |
580 | 681 |
581 // Evaluate the value and potentially handle compound assignments by loading | 682 // Evaluate the value and potentially handle compound assignments by loading |
582 // the left-hand side value and performing a binary operation. | 683 // the left-hand side value and performing a binary operation. |
583 if (expr->is_compound()) { | 684 if (expr->is_compound()) { |
584 UNIMPLEMENTED(); | 685 UNIMPLEMENTED(); |
585 } else { | 686 } else { |
586 Visit(expr->value()); | 687 VisitForAccumulatorValue(expr->value()); |
688 result_scope()->SetResultInAccumulator(); | |
587 } | 689 } |
588 | 690 |
589 // Store the value. | 691 // Store the value. |
590 FeedbackVectorSlot slot = expr->AssignmentSlot(); | 692 FeedbackVectorSlot slot = expr->AssignmentSlot(); |
591 switch (assign_type) { | 693 switch (assign_type) { |
592 case VARIABLE: { | 694 case VARIABLE: { |
593 Variable* variable = expr->target()->AsVariableProxy()->var(); | 695 Variable* variable = expr->target()->AsVariableProxy()->var(); |
594 VisitVariableAssignment(variable, slot); | 696 VisitVariableAssignment(variable, slot); |
595 break; | 697 break; |
596 } | 698 } |
(...skipping 20 matching lines...) Expand all Loading... | |
617 | 719 |
618 void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) { | 720 void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) { |
619 LhsKind property_kind = Property::GetAssignType(expr); | 721 LhsKind property_kind = Property::GetAssignType(expr); |
620 FeedbackVectorSlot slot = expr->PropertyFeedbackSlot(); | 722 FeedbackVectorSlot slot = expr->PropertyFeedbackSlot(); |
621 switch (property_kind) { | 723 switch (property_kind) { |
622 case VARIABLE: | 724 case VARIABLE: |
623 UNREACHABLE(); | 725 UNREACHABLE(); |
624 case NAMED_PROPERTY: { | 726 case NAMED_PROPERTY: { |
625 builder()->LoadLiteral(expr->key()->AsLiteral()->AsPropertyName()); | 727 builder()->LoadLiteral(expr->key()->AsLiteral()->AsPropertyName()); |
626 builder()->LoadNamedProperty(obj, feedback_index(slot), language_mode()); | 728 builder()->LoadNamedProperty(obj, feedback_index(slot), language_mode()); |
729 result_scope()->SetResultInAccumulator(); | |
627 break; | 730 break; |
628 } | 731 } |
629 case KEYED_PROPERTY: { | 732 case KEYED_PROPERTY: { |
630 Visit(expr->key()); | 733 VisitForAccumulatorValue(expr->key()); |
631 builder()->LoadKeyedProperty(obj, feedback_index(slot), language_mode()); | 734 builder()->LoadKeyedProperty(obj, feedback_index(slot), language_mode()); |
735 result_scope()->SetResultInAccumulator(); | |
632 break; | 736 break; |
633 } | 737 } |
634 case NAMED_SUPER_PROPERTY: | 738 case NAMED_SUPER_PROPERTY: |
635 case KEYED_SUPER_PROPERTY: | 739 case KEYED_SUPER_PROPERTY: |
636 UNIMPLEMENTED(); | 740 UNIMPLEMENTED(); |
637 } | 741 } |
638 } | 742 } |
639 | 743 |
640 | 744 |
641 void BytecodeGenerator::VisitProperty(Property* expr) { | 745 void BytecodeGenerator::VisitProperty(Property* expr) { |
642 TemporaryRegisterScope temporary_register_scope(&builder_); | 746 TemporaryRegisterScope temporary_register_scope(builder()); |
643 Register obj = temporary_register_scope.NewRegister(); | 747 Register obj = VisitForRegisterValue(expr->obj(), &temporary_register_scope); |
644 Visit(expr->obj()); | |
645 builder()->StoreAccumulatorInRegister(obj); | |
646 VisitPropertyLoad(obj, expr); | 748 VisitPropertyLoad(obj, expr); |
647 } | 749 } |
648 | 750 |
649 | 751 |
650 void BytecodeGenerator::VisitCall(Call* expr) { | 752 void BytecodeGenerator::VisitCall(Call* expr) { |
651 Expression* callee_expr = expr->expression(); | 753 Expression* callee_expr = expr->expression(); |
652 Call::CallType call_type = expr->GetCallType(isolate()); | 754 Call::CallType call_type = expr->GetCallType(isolate()); |
653 | 755 |
654 // Prepare the callee and the receiver to the function call. This depends on | 756 // Prepare the callee and the receiver to the function call. This depends on |
655 // the semantics of the underlying call type. | 757 // the semantics of the underlying call type. |
656 TemporaryRegisterScope temporary_register_scope(&builder_); | 758 TemporaryRegisterScope temporary_register_scope(builder()); |
657 Register callee = temporary_register_scope.NewRegister(); | 759 Register callee = temporary_register_scope.NewRegister(); |
760 | |
761 // The receiver and arguments need to allocated consecutively for | |
762 // Call(). Future optimizations could avoid this there are no | |
763 // arguments or the receiver and arguments are already consecutive. | |
658 Register receiver = temporary_register_scope.NewRegister(); | 764 Register receiver = temporary_register_scope.NewRegister(); |
659 | 765 |
660 switch (call_type) { | 766 switch (call_type) { |
661 case Call::PROPERTY_CALL: { | 767 case Call::PROPERTY_CALL: { |
662 Property* property = callee_expr->AsProperty(); | 768 Property* property = callee_expr->AsProperty(); |
663 if (property->IsSuperAccess()) { | 769 if (property->IsSuperAccess()) { |
664 UNIMPLEMENTED(); | 770 UNIMPLEMENTED(); |
665 } | 771 } |
666 Visit(property->obj()); | 772 VisitForAccumulatorValue(property->obj()); |
667 builder()->StoreAccumulatorInRegister(receiver); | 773 builder()->StoreAccumulatorInRegister(receiver); |
668 // Perform a property load of the callee. | 774 // Perform a property load of the callee. |
669 VisitPropertyLoad(receiver, property); | 775 VisitPropertyLoad(receiver, property); |
670 builder()->StoreAccumulatorInRegister(callee); | 776 builder()->StoreAccumulatorInRegister(callee); |
671 break; | 777 break; |
672 } | 778 } |
673 case Call::GLOBAL_CALL: { | 779 case Call::GLOBAL_CALL: { |
674 // Receiver is undefined for global calls. | 780 // Receiver is undefined for global calls. |
675 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); | 781 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); |
676 // Load callee as a global variable. | 782 // Load callee as a global variable. |
677 VariableProxy* proxy = callee_expr->AsVariableProxy(); | 783 VariableProxy* proxy = callee_expr->AsVariableProxy(); |
678 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); | 784 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); |
679 builder()->StoreAccumulatorInRegister(callee); | 785 builder()->StoreAccumulatorInRegister(callee); |
680 break; | 786 break; |
681 } | 787 } |
682 case Call::LOOKUP_SLOT_CALL: | 788 case Call::LOOKUP_SLOT_CALL: |
683 case Call::SUPER_CALL: | 789 case Call::SUPER_CALL: |
684 case Call::POSSIBLY_EVAL_CALL: | 790 case Call::POSSIBLY_EVAL_CALL: |
685 case Call::OTHER_CALL: | 791 case Call::OTHER_CALL: |
686 UNIMPLEMENTED(); | 792 UNIMPLEMENTED(); |
687 } | 793 } |
688 | 794 |
689 // Evaluate all arguments to the function call and store in sequential | 795 // Evaluate all arguments to the function call and store in sequential |
690 // registers. | 796 // registers. |
691 ZoneList<Expression*>* args = expr->arguments(); | 797 ZoneList<Expression*>* args = expr->arguments(); |
692 for (int i = 0; i < args->length(); ++i) { | 798 for (int i = 0; i < args->length(); ++i) { |
693 Visit(args->at(i)); | 799 VisitForAccumulatorValue(args->at(i)); |
694 Register arg = temporary_register_scope.NewRegister(); | 800 Register arg = temporary_register_scope.NewRegister(); |
695 DCHECK(arg.index() - i == receiver.index() + 1); | 801 DCHECK(arg.index() - i == receiver.index() + 1); |
696 builder()->StoreAccumulatorInRegister(arg); | 802 builder()->StoreAccumulatorInRegister(arg); |
697 } | 803 } |
698 | 804 |
699 // TODO(rmcilroy): Deal with possible direct eval here? | 805 // TODO(rmcilroy): Deal with possible direct eval here? |
700 // TODO(rmcilroy): Use CallIC to allow call type feedback. | 806 // TODO(rmcilroy): Use CallIC to allow call type feedback. |
701 builder()->Call(callee, receiver, args->length()); | 807 builder()->Call(callee, receiver, args->length()); |
808 result_scope()->SetResultInAccumulator(); | |
702 } | 809 } |
703 | 810 |
704 | 811 |
705 void BytecodeGenerator::VisitCallNew(CallNew* expr) { UNIMPLEMENTED(); } | 812 void BytecodeGenerator::VisitCallNew(CallNew* expr) { UNIMPLEMENTED(); } |
706 | 813 |
707 | 814 |
708 void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 815 void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
709 if (expr->is_jsruntime()) { | 816 if (expr->is_jsruntime()) { |
710 UNIMPLEMENTED(); | 817 UNIMPLEMENTED(); |
711 } | 818 } |
712 | 819 |
713 // Evaluate all arguments to the runtime call. | 820 // Evaluate all arguments to the runtime call. |
714 ZoneList<Expression*>* args = expr->arguments(); | 821 ZoneList<Expression*>* args = expr->arguments(); |
715 TemporaryRegisterScope temporary_register_scope(&builder_); | 822 TemporaryRegisterScope temporary_register_scope(builder()); |
716 // Ensure we always have a valid first_arg register even if there are no | 823 // Ensure we always have a valid first_arg register even if there are no |
717 // arguments to pass. | 824 // arguments to pass. |
718 Register first_arg = temporary_register_scope.NewRegister(); | 825 Register first_arg = temporary_register_scope.NewRegister(); |
719 for (int i = 0; i < args->length(); ++i) { | 826 for (int i = 0; i < args->length(); ++i) { |
720 Register arg = | 827 Register arg = |
721 (i == 0) ? first_arg : temporary_register_scope.NewRegister(); | 828 (i == 0) ? first_arg : temporary_register_scope.NewRegister(); |
722 Visit(args->at(i)); | 829 VisitForAccumulatorValue(args->at(i)); |
723 DCHECK_EQ(arg.index() - i, first_arg.index()); | 830 DCHECK_EQ(arg.index() - i, first_arg.index()); |
724 builder()->StoreAccumulatorInRegister(arg); | 831 builder()->StoreAccumulatorInRegister(arg); |
725 } | 832 } |
726 | 833 |
727 // TODO(rmcilroy): support multiple return values. | 834 // TODO(rmcilroy): support multiple return values. |
728 DCHECK_LE(expr->function()->result_size, 1); | 835 DCHECK_LE(expr->function()->result_size, 1); |
729 Runtime::FunctionId function_id = expr->function()->function_id; | 836 Runtime::FunctionId function_id = expr->function()->function_id; |
730 builder()->CallRuntime(function_id, first_arg, args->length()); | 837 builder()->CallRuntime(function_id, first_arg, args->length()); |
838 result_scope()->SetResultInAccumulator(); | |
731 } | 839 } |
732 | 840 |
733 | 841 |
734 void BytecodeGenerator::VisitVoid(UnaryOperation* expr) { | 842 void BytecodeGenerator::VisitVoid(UnaryOperation* expr) { |
735 Visit(expr->expression()); | 843 VisitForEffect(expr->expression()); |
736 builder()->LoadUndefined(); | 844 builder()->LoadUndefined(); |
845 result_scope()->SetResultInAccumulator(); | |
737 } | 846 } |
738 | 847 |
739 | 848 |
740 void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) { | 849 void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) { |
741 Visit(expr->expression()); | 850 VisitForAccumulatorValue(expr->expression()); |
742 builder()->TypeOf(); | 851 builder()->TypeOf(); |
852 result_scope()->SetResultInAccumulator(); | |
743 } | 853 } |
744 | 854 |
745 | 855 |
746 void BytecodeGenerator::VisitNot(UnaryOperation* expr) { | 856 void BytecodeGenerator::VisitNot(UnaryOperation* expr) { |
747 Visit(expr->expression()); | 857 VisitForAccumulatorValue(expr->expression()); |
748 builder()->LogicalNot(); | 858 builder()->LogicalNot(); |
859 result_scope()->SetResultInAccumulator(); | |
749 } | 860 } |
750 | 861 |
751 | 862 |
752 void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 863 void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
753 switch (expr->op()) { | 864 switch (expr->op()) { |
754 case Token::Value::NOT: | 865 case Token::Value::NOT: |
755 VisitNot(expr); | 866 VisitNot(expr); |
756 break; | 867 break; |
757 case Token::Value::TYPEOF: | 868 case Token::Value::TYPEOF: |
758 VisitTypeOf(expr); | 869 VisitTypeOf(expr); |
(...skipping 23 matching lines...) Expand all Loading... | |
782 UNIMPLEMENTED(); | 893 UNIMPLEMENTED(); |
783 break; | 894 break; |
784 default: | 895 default: |
785 VisitArithmeticExpression(binop); | 896 VisitArithmeticExpression(binop); |
786 break; | 897 break; |
787 } | 898 } |
788 } | 899 } |
789 | 900 |
790 | 901 |
791 void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) { | 902 void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
792 Token::Value op = expr->op(); | 903 TemporaryRegisterScope temporary_register_scope(builder()); |
793 Expression* left = expr->left(); | 904 Register lhs = VisitForRegisterValue(expr->left(), &temporary_register_scope); |
794 Expression* right = expr->right(); | 905 VisitForAccumulatorValue(expr->right()); |
795 | 906 builder()->CompareOperation(expr->op(), lhs, language_mode_strength()); |
796 TemporaryRegisterScope temporary_register_scope(&builder_); | 907 result_scope()->SetResultInAccumulator(); |
797 Register temporary = temporary_register_scope.NewRegister(); | |
798 | |
799 Visit(left); | |
800 builder()->StoreAccumulatorInRegister(temporary); | |
801 Visit(right); | |
802 builder()->CompareOperation(op, temporary, language_mode_strength()); | |
803 } | 908 } |
804 | 909 |
805 | 910 |
806 void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); } | 911 void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); } |
807 | 912 |
808 | 913 |
809 void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) { | 914 void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) { |
810 UNREACHABLE(); | 915 UNREACHABLE(); |
811 } | 916 } |
812 | 917 |
813 | 918 |
814 void BytecodeGenerator::VisitThisFunction(ThisFunction* expr) { | 919 void BytecodeGenerator::VisitThisFunction(ThisFunction* expr) { |
815 UNIMPLEMENTED(); | 920 UNIMPLEMENTED(); |
816 } | 921 } |
817 | 922 |
818 | 923 |
819 void BytecodeGenerator::VisitSuperCallReference(SuperCallReference* expr) { | 924 void BytecodeGenerator::VisitSuperCallReference(SuperCallReference* expr) { |
820 UNIMPLEMENTED(); | 925 UNIMPLEMENTED(); |
821 } | 926 } |
822 | 927 |
823 | 928 |
824 void BytecodeGenerator::VisitSuperPropertyReference( | 929 void BytecodeGenerator::VisitSuperPropertyReference( |
825 SuperPropertyReference* expr) { | 930 SuperPropertyReference* expr) { |
826 UNIMPLEMENTED(); | 931 UNIMPLEMENTED(); |
827 } | 932 } |
828 | 933 |
829 | 934 |
830 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* binop) { | 935 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* binop) { |
831 Token::Value op = binop->op(); | 936 TemporaryRegisterScope temporary_register_scope(builder()); |
832 Expression* left = binop->left(); | 937 Register lhs = |
833 Expression* right = binop->right(); | 938 VisitForRegisterValue(binop->left(), &temporary_register_scope); |
834 | 939 VisitForAccumulatorValue(binop->right()); |
835 TemporaryRegisterScope temporary_register_scope(&builder_); | 940 builder()->BinaryOperation(binop->op(), lhs, language_mode_strength()); |
836 Register temporary = temporary_register_scope.NewRegister(); | 941 result_scope()->SetResultInAccumulator(); |
837 | |
838 Visit(left); | |
839 builder()->StoreAccumulatorInRegister(temporary); | |
840 Visit(right); | |
841 builder()->BinaryOperation(op, temporary, language_mode_strength()); | |
842 } | 942 } |
843 | 943 |
844 | 944 |
945 void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) { | |
946 AccumulatorResultScope accumulator_scope(this); | |
947 Visit(expr); | |
948 } | |
949 | |
950 | |
951 void BytecodeGenerator::VisitForEffect(Expression* node) { | |
952 EffectResultScope effect_scope(this); | |
953 Visit(node); | |
954 } | |
955 | |
956 Register BytecodeGenerator::VisitForRegisterValue( | |
957 Expression* expr, TemporaryRegisterScope* temporary_register_scope) { | |
958 RegisterResultScope register_scope(this, temporary_register_scope); | |
959 Visit(expr); | |
960 return GetResultRegister(); | |
961 } | |
962 | |
963 | |
964 void BytecodeGenerator::SetResultRegister(Register reg) { | |
965 DCHECK(result_register_.IsNothing()); | |
966 result_register_ = Just<Register>(reg); | |
967 } | |
968 | |
969 | |
970 Register BytecodeGenerator::GetResultRegister() { | |
971 Register reg = result_register_.FromJust(); | |
972 result_register_ = Nothing<Register>(); | |
973 return reg; | |
974 } | |
975 | |
976 | |
977 bool BytecodeGenerator::ResultRegisterIsEmpty() const { | |
978 return result_register_.IsNothing(); | |
979 } | |
980 | |
845 LanguageMode BytecodeGenerator::language_mode() const { | 981 LanguageMode BytecodeGenerator::language_mode() const { |
846 return info()->language_mode(); | 982 return info()->language_mode(); |
847 } | 983 } |
848 | 984 |
849 | 985 |
850 Strength BytecodeGenerator::language_mode_strength() const { | 986 Strength BytecodeGenerator::language_mode_strength() const { |
851 return strength(language_mode()); | 987 return strength(language_mode()); |
852 } | 988 } |
853 | 989 |
854 | 990 |
855 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 991 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
856 return info()->feedback_vector()->GetIndex(slot); | 992 return info()->feedback_vector()->GetIndex(slot); |
857 } | 993 } |
858 | 994 |
859 | 995 |
860 Register BytecodeGenerator::current_context() const { return current_context_; } | 996 Register BytecodeGenerator::current_context() const { return current_context_; } |
861 | 997 |
862 } // namespace interpreter | 998 } // namespace interpreter |
863 } // namespace internal | 999 } // namespace internal |
864 } // namespace v8 | 1000 } // namespace v8 |
OLD | NEW |