Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/interpreter/bytecode-generator.h" | 5 #include "src/interpreter/bytecode-generator.h" |
| 6 | 6 |
| 7 #include "src/compiler.h" | 7 #include "src/compiler.h" |
| 8 #include "src/interpreter/control-flow-builders.h" | 8 #include "src/interpreter/control-flow-builders.h" |
| 9 #include "src/objects.h" | 9 #include "src/objects.h" |
| 10 #include "src/parser.h" | 10 #include "src/parser.h" |
| (...skipping 595 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 606 } else { | 606 } else { |
| 607 builder()->Jump(&body_label); | 607 builder()->Jump(&body_label); |
| 608 } | 608 } |
| 609 builder()->Bind(&done_label); | 609 builder()->Bind(&done_label); |
| 610 | 610 |
| 611 loop_builder.SetBreakTarget(done_label); | 611 loop_builder.SetBreakTarget(done_label); |
| 612 loop_builder.SetContinueTarget(next_label); | 612 loop_builder.SetContinueTarget(next_label); |
| 613 } | 613 } |
| 614 | 614 |
| 615 | 615 |
| 616 void BytecodeGenerator::VisitForInAssignment(Expression* expr, | |
| 617 FeedbackVectorSlot slot) { | |
| 618 DCHECK(expr->IsValidReferenceExpression()); | |
| 619 | |
| 620 // Evaluate assignment starting with the value to be stored in the | |
| 621 // accumulator. | |
| 622 Property* property = expr->AsProperty(); | |
| 623 LhsKind assign_type = Property::GetAssignType(property); | |
| 624 switch (assign_type) { | |
| 625 case VARIABLE: { | |
| 626 Variable* variable = expr->AsVariableProxy()->var(); | |
| 627 VisitVariableAssignment(variable, slot); | |
| 628 break; | |
| 629 } | |
| 630 case NAMED_PROPERTY: { | |
| 631 TemporaryRegisterScope temporary_register_scope(builder()); | |
| 632 Register value = temporary_register_scope.NewRegister(); | |
| 633 builder()->StoreAccumulatorInRegister(value); | |
| 634 Register object = VisitForRegisterValue(property->obj()); | |
| 635 size_t name_index = builder()->GetConstantPoolEntry( | |
| 636 property->key()->AsLiteral()->AsPropertyName()); | |
| 637 builder()->StoreNamedProperty(object, name_index, feedback_index(slot), | |
| 638 language_mode()); | |
| 639 break; | |
| 640 } | |
| 641 case KEYED_PROPERTY: { | |
| 642 TemporaryRegisterScope temporary_register_scope(builder()); | |
| 643 Register value = temporary_register_scope.NewRegister(); | |
| 644 builder()->StoreAccumulatorInRegister(value); | |
| 645 Register object = VisitForRegisterValue(property->obj()); | |
| 646 Register key = VisitForRegisterValue(property->key()); | |
| 647 builder()->LoadAccumulatorWithRegister(value); | |
| 648 builder()->StoreKeyedProperty(object, key, feedback_index(slot), | |
| 649 language_mode()); | |
| 650 break; | |
| 651 } | |
| 652 case NAMED_SUPER_PROPERTY: | |
| 653 case KEYED_SUPER_PROPERTY: | |
| 654 UNIMPLEMENTED(); | |
| 655 } | |
| 656 } | |
| 657 | |
| 658 | |
| 616 void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) { | 659 void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) { |
| 617 UNIMPLEMENTED(); | 660 // TODO(oth): For now we need a parent scope for paths that end up |
| 661 // in VisitLiteral which can allocate in the parent scope. A future | |
| 662 // CL in preparation will a StatementResultScope that will remove | |
|
rmcilroy
2015/10/28 13:46:22
/s/will a Statement.../will add a Statement.../
oth
2015/10/28 22:50:40
Done.
| |
| 663 // the need for this EffectResultScope. | |
| 664 EffectResultScope result_scope(this); | |
| 665 | |
| 666 if (stmt->subject()->IsNullLiteral() || | |
| 667 stmt->subject()->IsUndefinedLiteral(isolate())) { | |
| 668 // ForIn generates lots of code, skip if it wouldn't produce any effects. | |
| 669 return; | |
| 670 } | |
| 671 | |
| 672 LoopBuilder loop_builder(builder()); | |
| 673 ControlScopeForIteration control_scope(this, stmt, &loop_builder); | |
| 674 | |
| 675 // Prepare the state for executing ForIn. | |
| 676 builder()->EnterBlock(); | |
| 677 VisitForAccumulatorValue(stmt->subject()); | |
| 678 loop_builder.BreakIfUndefined(); | |
| 679 loop_builder.BreakIfNull(); | |
| 680 | |
| 681 builder()->CastAccumulatorToJSObject(); | |
| 682 Register receiver = execution_result()->NewRegister(); | |
| 683 builder()->StoreAccumulatorInRegister(receiver); | |
| 684 builder()->CallRuntime(Runtime::kGetPropertyNamesFast, receiver, 1); | |
| 685 builder()->ForInPrepare(receiver); | |
| 686 Register for_in_state = execution_result()->NewRegister(); | |
|
rmcilroy
2015/10/28 13:46:22
nit - I would put Register declarations at the top
oth
2015/10/28 22:50:40
Done.
| |
| 687 builder() | |
| 688 ->StoreAccumulatorInRegister(for_in_state) | |
| 689 .LoadUndefined() | |
| 690 .CompareOperation(Token::Value::EQ_STRICT, for_in_state, | |
| 691 language_mode_strength()); | |
|
rmcilroy
2015/10/28 13:46:22
Can you use BreakIfUndefined here instead?
oth
2015/10/28 22:50:40
Done.
| |
| 692 loop_builder.BreakIfTrue(); | |
| 693 | |
| 694 // The loop. | |
| 695 BytecodeLabel condition_label, break_label, continue_label; | |
| 696 Register index = receiver; // re-using register as receiver no longer used. | |
|
rmcilroy
2015/10/28 13:46:22
nit - /s/re/Re
oth
2015/10/28 22:50:40
Done.
| |
| 697 builder()->LoadLiteral(Smi::FromInt(0)); | |
| 698 | |
| 699 // Check loop termination (accumulator holds index). | |
| 700 builder() | |
| 701 ->Bind(&condition_label) | |
| 702 .StoreAccumulatorInRegister(index) | |
| 703 .ForInDone(for_in_state); | |
| 704 loop_builder.BreakIfTrue(); | |
| 705 | |
| 706 // Get the next item. | |
| 707 builder()->LoadAccumulatorWithRegister(index).ForInNext(for_in_state); | |
|
rmcilroy
2015/10/28 13:46:22
nit - could you require ForInNext to take a regist
oth
2015/10/28 22:50:40
Done.
| |
| 708 | |
| 709 // Start again if the item, currently in the accumulator, is undefined. | |
| 710 loop_builder.ContinueIfUndefined(); | |
| 711 | |
| 712 // Store the value in the each variable. | |
| 713 VisitForInAssignment(stmt->each(), stmt->EachFeedbackSlot()); | |
| 714 // NB the user's loop variable will be assigned the value of each so | |
| 715 // even an empty body will have this assignment. | |
| 716 Visit(stmt->body()); | |
|
rmcilroy
2015/10/28 13:46:22
VisitForEffect?
oth
2015/10/28 22:50:40
stmt->body() is a statement rather than expression
rmcilroy
2015/10/29 10:53:45
Acknowledged.
| |
| 717 | |
| 718 // Increment the index and start loop again. | |
| 719 builder() | |
| 720 ->Bind(&continue_label) | |
| 721 .LoadAccumulatorWithRegister(index) | |
| 722 .CountOperation(Token::Value::ADD, language_mode_strength()) | |
| 723 .Jump(&condition_label); | |
| 724 | |
| 725 // End of loop | |
| 726 builder()->Bind(&break_label).LeaveBlock(); | |
| 727 | |
| 728 loop_builder.SetBreakTarget(break_label); | |
| 729 loop_builder.SetContinueTarget(continue_label); | |
| 618 } | 730 } |
| 619 | 731 |
| 620 | 732 |
| 621 void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { | 733 void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { |
| 622 UNIMPLEMENTED(); | 734 UNIMPLEMENTED(); |
| 623 } | 735 } |
| 624 | 736 |
| 625 | 737 |
| 626 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { | 738 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { |
| 627 if (FLAG_ignition_fake_try_catch) { | 739 if (FLAG_ignition_fake_try_catch) { |
| (...skipping 1319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1947 } | 2059 } |
| 1948 | 2060 |
| 1949 | 2061 |
| 1950 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 2062 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
| 1951 return info()->feedback_vector()->GetIndex(slot); | 2063 return info()->feedback_vector()->GetIndex(slot); |
| 1952 } | 2064 } |
| 1953 | 2065 |
| 1954 } // namespace interpreter | 2066 } // namespace interpreter |
| 1955 } // namespace internal | 2067 } // namespace internal |
| 1956 } // namespace v8 | 2068 } // namespace v8 |
| OLD | NEW |