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 add a StatementResultScope that will |
| 663 // remove 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 Register receiver = execution_result()->NewRegister(); |
| 682 builder()->CastAccumulatorToJSObject(); |
| 683 builder()->StoreAccumulatorInRegister(receiver); |
| 684 builder()->CallRuntime(Runtime::kGetPropertyNamesFast, receiver, 1); |
| 685 builder()->ForInPrepare(receiver); |
| 686 loop_builder.BreakIfUndefined(); |
| 687 |
| 688 Register for_in_state = execution_result()->NewRegister(); |
| 689 builder()->StoreAccumulatorInRegister(for_in_state); |
| 690 |
| 691 // The loop. |
| 692 BytecodeLabel condition_label, break_label, continue_label; |
| 693 Register index = receiver; // Re-using register as receiver no longer used. |
| 694 builder()->LoadLiteral(Smi::FromInt(0)); |
| 695 |
| 696 // Check loop termination (accumulator holds index). |
| 697 builder() |
| 698 ->Bind(&condition_label) |
| 699 .StoreAccumulatorInRegister(index) |
| 700 .ForInDone(for_in_state); |
| 701 loop_builder.BreakIfTrue(); |
| 702 |
| 703 // Get the next item. |
| 704 builder()->ForInNext(for_in_state, index); |
| 705 |
| 706 // Start again if the item, currently in the accumulator, is undefined. |
| 707 loop_builder.ContinueIfUndefined(); |
| 708 |
| 709 // Store the value in the each variable. |
| 710 VisitForInAssignment(stmt->each(), stmt->EachFeedbackSlot()); |
| 711 // NB the user's loop variable will be assigned the value of each so |
| 712 // even an empty body will have this assignment. |
| 713 Visit(stmt->body()); |
| 714 |
| 715 // Increment the index and start loop again. |
| 716 builder() |
| 717 ->Bind(&continue_label) |
| 718 .LoadAccumulatorWithRegister(index) |
| 719 .CountOperation(Token::Value::ADD, language_mode_strength()) |
| 720 .Jump(&condition_label); |
| 721 |
| 722 // End of loop |
| 723 builder()->Bind(&break_label).LeaveBlock(); |
| 724 |
| 725 loop_builder.SetBreakTarget(break_label); |
| 726 loop_builder.SetContinueTarget(continue_label); |
618 } | 727 } |
619 | 728 |
620 | 729 |
621 void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { | 730 void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { |
622 UNIMPLEMENTED(); | 731 UNIMPLEMENTED(); |
623 } | 732 } |
624 | 733 |
625 | 734 |
626 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { | 735 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { |
627 if (FLAG_ignition_fake_try_catch) { | 736 if (FLAG_ignition_fake_try_catch) { |
(...skipping 1319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1947 } | 2056 } |
1948 | 2057 |
1949 | 2058 |
1950 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 2059 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
1951 return info()->feedback_vector()->GetIndex(slot); | 2060 return info()->feedback_vector()->GetIndex(slot); |
1952 } | 2061 } |
1953 | 2062 |
1954 } // namespace interpreter | 2063 } // namespace interpreter |
1955 } // namespace internal | 2064 } // namespace internal |
1956 } // namespace v8 | 2065 } // namespace v8 |
OLD | NEW |