| 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 |