Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(81)

Side by Side Diff: src/interpreter/bytecode-generator.cc

Issue 1422033002: [Interpreter] Add support for for..in. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Update comments. Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698