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

Side by Side Diff: src/x64/codegen-x64.cc

Issue 140068: Implement code generation for conditional expressions and regexp... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years, 6 months 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | src/x64/frames-x64.cc » ('j') | src/x64/ic-x64.cc » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2009 the V8 project authors. All rights reserved. 1 // Copyright 2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 "\n" 158 "\n"
159 " function test_local_variables(x, y){" 159 " function test_local_variables(x, y){"
160 " var w; y = x; x = w; w = y; y = x; return w;" 160 " var w; y = x; x = w; w = y; y = x; return w;"
161 " };" 161 " };"
162 " test_local_variables(2,3);" 162 " test_local_variables(2,3);"
163 " function test_nesting_calls(x, y, zee){return zee;};" 163 " function test_nesting_calls(x, y, zee){return zee;};"
164 " test_local_variables(" 164 " test_local_variables("
165 " test_nesting_calls(test_local_variables(1,3), 42, 47)," 165 " test_nesting_calls(test_local_variables(1,3), 42, 47),"
166 " test_local_variables(-25.3, 2));" 166 " test_local_variables(-25.3, 2));"
167 " // return test_recursion_with_base(0, 0, 0, 47);\n" 167 " // return test_recursion_with_base(0, 0, 0, 47);\n"
168 " var o = { x: 42 };" 168 " var x_value = 42;"
169 " var o = { x: x_value };"
169 " var a = [ 1, 2, 3 ];" 170 " var a = [ 1, 2, 3 ];"
171 " var x = true ? 42 : 32;"
170 " return test_if_then_else(0, 46, 47);" 172 " return test_if_then_else(0, 46, 47);"
171 "})()")), 173 "})()")),
172 Factory::NewStringFromAscii(CStrVector("CodeGeneratorTestScript")), 174 Factory::NewStringFromAscii(CStrVector("CodeGeneratorTestScript")),
173 0, 175 0,
174 0, 176 0,
175 NULL, 177 NULL,
176 NULL); 178 NULL);
177 179
178 Code* code_object = test_function->code(); // Local for debugging ease. 180 Code* code_object = test_function->code(); // Local for debugging ease.
179 USE(code_object); 181 USE(code_object);
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after
465 Comment cmnt(masm_, "[ ExpressionStatement"); 467 Comment cmnt(masm_, "[ ExpressionStatement");
466 CodeForStatementPosition(node); 468 CodeForStatementPosition(node);
467 Expression* expression = node->expression(); 469 Expression* expression = node->expression();
468 expression->MarkAsStatement(); 470 expression->MarkAsStatement();
469 Load(expression); 471 Load(expression);
470 // Remove the lingering expression result from the top of stack. 472 // Remove the lingering expression result from the top of stack.
471 frame_->Drop(); 473 frame_->Drop();
472 } 474 }
473 475
474 476
475 void CodeGenerator::VisitEmptyStatement(EmptyStatement* a) { 477 void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) {
476 UNIMPLEMENTED(); 478 ASSERT(!in_spilled_code());
479 Comment cmnt(masm_, "// EmptyStatement");
480 CodeForStatementPosition(node);
481 // nothing to do
477 } 482 }
478 483
479 484
480 void CodeGenerator::VisitIfStatement(IfStatement* node) { 485 void CodeGenerator::VisitIfStatement(IfStatement* node) {
481 ASSERT(!in_spilled_code()); 486 ASSERT(!in_spilled_code());
482 Comment cmnt(masm_, "[ IfStatement"); 487 Comment cmnt(masm_, "[ IfStatement");
483 // Generate different code depending on which parts of the if statement 488 // Generate different code depending on which parts of the if statement
484 // are present or not. 489 // are present or not.
485 bool has_then_stm = node->HasThenStatement(); 490 bool has_then_stm = node->HasThenStatement();
486 bool has_else_stm = node->HasElseStatement(); 491 bool has_else_stm = node->HasElseStatement();
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
669 } 674 }
670 675
671 676
672 void CodeGenerator::VisitFunctionBoilerplateLiteral( 677 void CodeGenerator::VisitFunctionBoilerplateLiteral(
673 FunctionBoilerplateLiteral* node) { 678 FunctionBoilerplateLiteral* node) {
674 Comment cmnt(masm_, "[ FunctionBoilerplateLiteral"); 679 Comment cmnt(masm_, "[ FunctionBoilerplateLiteral");
675 InstantiateBoilerplate(node->boilerplate()); 680 InstantiateBoilerplate(node->boilerplate());
676 } 681 }
677 682
678 683
679 void CodeGenerator::VisitConditional(Conditional* a) { 684 void CodeGenerator::VisitConditional(Conditional* node) {
680 UNIMPLEMENTED(); 685 Comment cmnt(masm_, "[ Conditional");
686 JumpTarget then;
687 JumpTarget else_;
688 JumpTarget exit;
689 ControlDestination dest(&then, &else_, true);
690 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true);
691
692 if (dest.false_was_fall_through()) {
693 // The else target was bound, so we compile the else part first.
694 Load(node->else_expression(), typeof_state());
695
696 if (then.is_linked()) {
697 exit.Jump();
698 then.Bind();
699 Load(node->then_expression(), typeof_state());
700 }
701 } else {
702 // The then target was bound, so we compile the then part first.
703 Load(node->then_expression(), typeof_state());
704
705 if (else_.is_linked()) {
706 exit.Jump();
707 else_.Bind();
708 Load(node->else_expression(), typeof_state());
709 }
710 }
711
712 exit.Bind();
681 } 713 }
682 714
715
683 void CodeGenerator::VisitSlot(Slot* node) { 716 void CodeGenerator::VisitSlot(Slot* node) {
684 Comment cmnt(masm_, "[ Slot"); 717 Comment cmnt(masm_, "[ Slot");
685 LoadFromSlot(node, typeof_state()); 718 LoadFromSlot(node, typeof_state());
686 } 719 }
687 720
688 721
689 void CodeGenerator::VisitVariableProxy(VariableProxy* node) { 722 void CodeGenerator::VisitVariableProxy(VariableProxy* node) {
690 Comment cmnt(masm_, "[ VariableProxy"); 723 Comment cmnt(masm_, "[ VariableProxy");
691 Variable* var = node->var(); 724 Variable* var = node->var();
692 Expression* expr = var->rewrite(); 725 Expression* expr = var->rewrite();
693 if (expr != NULL) { 726 if (expr != NULL) {
694 Visit(expr); 727 Visit(expr);
695 } else { 728 } else {
696 ASSERT(var->is_global()); 729 ASSERT(var->is_global());
697 Reference ref(this, node); 730 Reference ref(this, node);
698 ref.GetValue(typeof_state()); 731 ref.GetValue(typeof_state());
699 } 732 }
700 } 733 }
701 734
702 735
703 void CodeGenerator::VisitLiteral(Literal* node) { 736 void CodeGenerator::VisitLiteral(Literal* node) {
704 Comment cmnt(masm_, "[ Literal"); 737 Comment cmnt(masm_, "[ Literal");
705 frame_->Push(node->handle()); 738 frame_->Push(node->handle());
706 } 739 }
707 740
708 741
709 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* a) { 742 // Materialize the regexp literal 'node' in the literals array
710 UNIMPLEMENTED(); 743 // 'literals' of the function. Leave the regexp boilerplate in
744 // 'boilerplate'.
745 class DeferredRegExpLiteral: public DeferredCode {
746 public:
747 DeferredRegExpLiteral(Register boilerplate,
748 Register literals,
749 RegExpLiteral* node)
750 : boilerplate_(boilerplate), literals_(literals), node_(node) {
751 set_comment("[ DeferredRegExpLiteral");
752 }
753
754 void Generate();
755
756 private:
757 Register boilerplate_;
758 Register literals_;
759 RegExpLiteral* node_;
760 };
761
762
763 void DeferredRegExpLiteral::Generate() {
764 // Since the entry is undefined we call the runtime system to
765 // compute the literal.
766 // Literal array (0).
767 __ push(literals_);
768 // Literal index (1).
769 __ push(Immediate(Smi::FromInt(node_->literal_index())));
770 // RegExp pattern (2).
771 __ Push(node_->pattern());
772 // RegExp flags (3).
773 __ Push(node_->flags());
774 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
775 if (!boilerplate_.is(rax)) __ movq(boilerplate_, rax);
776 }
777
778
779 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) {
780 Comment cmnt(masm_, "[ RegExp Literal");
781
782 // Retrieve the literals array and check the allocated entry. Begin
783 // with a writable copy of the function of this activation in a
784 // register.
785 frame_->PushFunction();
786 Result literals = frame_->Pop();
787 literals.ToRegister();
788 frame_->Spill(literals.reg());
789
790 // Load the literals array of the function.
791 __ movq(literals.reg(),
792 FieldOperand(literals.reg(), JSFunction::kLiteralsOffset));
793
794 // Load the literal at the ast saved index.
795 Result boilerplate = allocator_->Allocate();
796 ASSERT(boilerplate.is_valid());
797 int literal_offset =
798 FixedArray::kHeaderSize + node->literal_index() * kPointerSize;
799 __ movq(boilerplate.reg(), FieldOperand(literals.reg(), literal_offset));
800
801 // Check whether we need to materialize the RegExp object. If so,
802 // jump to the deferred code passing the literals array.
803 DeferredRegExpLiteral* deferred =
804 new DeferredRegExpLiteral(boilerplate.reg(), literals.reg(), node);
805 __ Cmp(boilerplate.reg(), Factory::undefined_value());
806 deferred->Branch(equal);
807 deferred->BindExit();
808 literals.Unuse();
809
810 // Push the boilerplate object.
811 frame_->Push(&boilerplate);
711 } 812 }
712 813
713 814
714 // Materialize the object literal 'node' in the literals array 815 // Materialize the object literal 'node' in the literals array
715 // 'literals' of the function. Leave the object boilerplate in 816 // 'literals' of the function. Leave the object boilerplate in
716 // 'boilerplate'. 817 // 'boilerplate'.
717 class DeferredObjectLiteral: public DeferredCode { 818 class DeferredObjectLiteral: public DeferredCode {
718 public: 819 public:
719 DeferredObjectLiteral(Register boilerplate, 820 DeferredObjectLiteral(Register boilerplate,
720 Register literals, 821 Register literals,
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
790 891
791 for (int i = 0; i < node->properties()->length(); i++) { 892 for (int i = 0; i < node->properties()->length(); i++) {
792 ObjectLiteral::Property* property = node->properties()->at(i); 893 ObjectLiteral::Property* property = node->properties()->at(i);
793 switch (property->kind()) { 894 switch (property->kind()) {
794 case ObjectLiteral::Property::CONSTANT: 895 case ObjectLiteral::Property::CONSTANT:
795 break; 896 break;
796 case ObjectLiteral::Property::MATERIALIZED_LITERAL: 897 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
797 if (CompileTimeValue::IsCompileTimeValue(property->value())) break; 898 if (CompileTimeValue::IsCompileTimeValue(property->value())) break;
798 // else fall through. 899 // else fall through.
799 case ObjectLiteral::Property::COMPUTED: { 900 case ObjectLiteral::Property::COMPUTED: {
800 // TODO(X64): Implement setting of computed values in object literals. 901 Handle<Object> key(property->key()->handle());
801 UNIMPLEMENTED(); 902 if (key->IsSymbol()) {
903 // Duplicate the object as the IC receiver.
904 frame_->Dup();
905 Load(property->value());
906 frame_->Push(key);
907 Result ignored = frame_->CallStoreIC();
908 // Drop the duplicated receiver and ignore the result.
909 frame_->Drop();
910 break;
911 }
912 // Fall through
802 } 913 }
803 case ObjectLiteral::Property::PROTOTYPE: { 914 case ObjectLiteral::Property::PROTOTYPE: {
804 // Duplicate the object as an argument to the runtime call. 915 // Duplicate the object as an argument to the runtime call.
805 frame_->Dup(); 916 frame_->Dup();
806 Load(property->key()); 917 Load(property->key());
807 Load(property->value()); 918 Load(property->value());
808 Result ignored = frame_->CallRuntime(Runtime::kSetProperty, 3); 919 Result ignored = frame_->CallRuntime(Runtime::kSetProperty, 3);
809 // Ignore the result. 920 // Ignore the result.
810 break; 921 break;
811 } 922 }
(...skipping 1070 matching lines...) Expand 10 before | Expand all | Expand 10 after
1882 // expressions. 1993 // expressions.
1883 // 1994 //
1884 // Note: We will reach here even with slot->var()->mode() == 1995 // Note: We will reach here even with slot->var()->mode() ==
1885 // Variable::CONST because of const declarations which will initialize 1996 // Variable::CONST because of const declarations which will initialize
1886 // consts to 'the hole' value and by doing so, end up calling this code. 1997 // consts to 'the hole' value and by doing so, end up calling this code.
1887 if (slot->type() == Slot::PARAMETER) { 1998 if (slot->type() == Slot::PARAMETER) {
1888 frame_->StoreToParameterAt(slot->index()); 1999 frame_->StoreToParameterAt(slot->index());
1889 } else if (slot->type() == Slot::LOCAL) { 2000 } else if (slot->type() == Slot::LOCAL) {
1890 frame_->StoreToLocalAt(slot->index()); 2001 frame_->StoreToLocalAt(slot->index());
1891 } else { 2002 } else {
2003 // The other slot types (LOOKUP and GLOBAL) cannot reach here.
2004 //
2005 // The use of SlotOperand below is safe for an unspilled frame
2006 // because the slot is a context slot.
1892 ASSERT(slot->type() == Slot::CONTEXT); 2007 ASSERT(slot->type() == Slot::CONTEXT);
1893 frame_->Dup(); 2008 frame_->Dup();
1894 Result value = frame_->Pop(); 2009 Result value = frame_->Pop();
1895 value.ToRegister(); 2010 value.ToRegister();
1896 Result start = allocator_->Allocate(); 2011 Result start = allocator_->Allocate();
1897 ASSERT(start.is_valid()); 2012 ASSERT(start.is_valid());
1898 __ movq(SlotOperand(slot, start.reg()), value.reg()); 2013 __ movq(SlotOperand(slot, start.reg()), value.reg());
1899 // RecordWrite may destroy the value registers. 2014 // RecordWrite may destroy the value registers.
1900 // 2015 //
1901 // TODO(204): Avoid actually spilling when the value is not 2016 // TODO(204): Avoid actually spilling when the value is not
(...skipping 906 matching lines...) Expand 10 before | Expand all | Expand 10 after
2808 __ addq(rsp, Immediate(2 * kPointerSize)); // remove markers 2923 __ addq(rsp, Immediate(2 * kPointerSize)); // remove markers
2809 2924
2810 // Restore frame pointer and return. 2925 // Restore frame pointer and return.
2811 __ pop(rbp); 2926 __ pop(rbp);
2812 __ ret(0); 2927 __ ret(0);
2813 } 2928 }
2814 2929
2815 #undef __ 2930 #undef __
2816 2931
2817 } } // namespace v8::internal 2932 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | src/x64/frames-x64.cc » ('j') | src/x64/ic-x64.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698