OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |