| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 74 } | 74 } |
| 75 } | 75 } |
| 76 | 76 |
| 77 bool function_in_register = true; | 77 bool function_in_register = true; |
| 78 | 78 |
| 79 // Possibly allocate a local context. | 79 // Possibly allocate a local context. |
| 80 if (scope()->num_heap_slots() > 0) { | 80 if (scope()->num_heap_slots() > 0) { |
| 81 Comment cmnt(masm_, "[ Allocate local context"); | 81 Comment cmnt(masm_, "[ Allocate local context"); |
| 82 // Argument to NewContext is the function, which is still in rdi. | 82 // Argument to NewContext is the function, which is still in rdi. |
| 83 __ push(rdi); | 83 __ push(rdi); |
| 84 __ CallRuntime(Runtime::kNewContext, 1); | 84 EmitCallRuntime(Runtime::kNewContext, 1); |
| 85 function_in_register = false; | 85 function_in_register = false; |
| 86 // Context is returned in both rax and rsi. It replaces the context | 86 // Context is returned in both rax and rsi. It replaces the context |
| 87 // passed to us. It's saved in the stack and kept live in rsi. | 87 // passed to us. It's saved in the stack and kept live in rsi. |
| 88 __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi); | 88 __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi); |
| 89 | 89 |
| 90 // Copy any necessary parameters into the context. | 90 // Copy any necessary parameters into the context. |
| 91 int num_parameters = scope()->num_parameters(); | 91 int num_parameters = scope()->num_parameters(); |
| 92 for (int i = 0; i < num_parameters; i++) { | 92 for (int i = 0; i < num_parameters; i++) { |
| 93 Slot* slot = scope()->parameter(i)->slot(); | 93 Slot* slot = scope()->parameter(i)->slot(); |
| 94 if (slot != NULL && slot->type() == Slot::CONTEXT) { | 94 if (slot != NULL && slot->type() == Slot::CONTEXT) { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 147 { Comment cmnt(masm_, "[ Stack check"); | 147 { Comment cmnt(masm_, "[ Stack check"); |
| 148 Label ok; | 148 Label ok; |
| 149 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); | 149 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); |
| 150 __ j(above_equal, &ok); | 150 __ j(above_equal, &ok); |
| 151 StackCheckStub stub; | 151 StackCheckStub stub; |
| 152 __ CallStub(&stub); | 152 __ CallStub(&stub); |
| 153 __ bind(&ok); | 153 __ bind(&ok); |
| 154 } | 154 } |
| 155 | 155 |
| 156 if (FLAG_trace) { | 156 if (FLAG_trace) { |
| 157 __ CallRuntime(Runtime::kTraceEnter, 0); | 157 EmitCallRuntime(Runtime::kTraceEnter, 0); |
| 158 } | 158 } |
| 159 | 159 |
| 160 { Comment cmnt(masm_, "[ Body"); | 160 { Comment cmnt(masm_, "[ Body"); |
| 161 ASSERT(loop_depth() == 0); | 161 ASSERT(loop_depth() == 0); |
| 162 VisitStatements(function()->body()); | 162 VisitStatements(function()->body()); |
| 163 ASSERT(loop_depth() == 0); | 163 ASSERT(loop_depth() == 0); |
| 164 } | 164 } |
| 165 | 165 |
| 166 { Comment cmnt(masm_, "[ return <undefined>;"); | 166 { Comment cmnt(masm_, "[ return <undefined>;"); |
| 167 // Emit a 'return undefined' in case control fell off the end of the body. | 167 // Emit a 'return undefined' in case control fell off the end of the body. |
| 168 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 168 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); |
| 169 EmitReturnSequence(function()->end_position()); | 169 EmitReturnSequence(function()->end_position()); |
| 170 } | 170 } |
| 171 } | 171 } |
| 172 | 172 |
| 173 | 173 |
| 174 void FullCodeGenerator::EmitReturnSequence(int position) { | 174 void FullCodeGenerator::EmitReturnSequence(int position) { |
| 175 Comment cmnt(masm_, "[ Return sequence"); | 175 Comment cmnt(masm_, "[ Return sequence"); |
| 176 if (return_label_.is_bound()) { | 176 if (return_label_.is_bound()) { |
| 177 __ jmp(&return_label_); | 177 __ jmp(&return_label_); |
| 178 } else { | 178 } else { |
| 179 __ bind(&return_label_); | 179 __ bind(&return_label_); |
| 180 if (FLAG_trace) { | 180 if (FLAG_trace) { |
| 181 __ push(rax); | 181 __ push(rax); |
| 182 __ CallRuntime(Runtime::kTraceExit, 1); | 182 EmitCallRuntime(Runtime::kTraceExit, 1); |
| 183 } | 183 } |
| 184 #ifdef DEBUG | 184 #ifdef DEBUG |
| 185 // Add a label for checking the size of the code used for returning. | 185 // Add a label for checking the size of the code used for returning. |
| 186 Label check_exit_codesize; | 186 Label check_exit_codesize; |
| 187 masm_->bind(&check_exit_codesize); | 187 masm_->bind(&check_exit_codesize); |
| 188 #endif | 188 #endif |
| 189 CodeGenerator::RecordPositions(masm_, position); | 189 CodeGenerator::RecordPositions(masm_, position); |
| 190 __ RecordJSReturn(); | 190 __ RecordJSReturn(); |
| 191 // Do not use the leave instruction here because it is too short to | 191 // Do not use the leave instruction here because it is too short to |
| 192 // patch with the code required by the debugger. | 192 // patch with the code required by the debugger. |
| (...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 726 // Note: For variables we must not push an initial value (such as | 726 // Note: For variables we must not push an initial value (such as |
| 727 // 'undefined') because we may have a (legal) redeclaration and we | 727 // 'undefined') because we may have a (legal) redeclaration and we |
| 728 // must not destroy the current value. | 728 // must not destroy the current value. |
| 729 if (decl->mode() == Variable::CONST) { | 729 if (decl->mode() == Variable::CONST) { |
| 730 __ PushRoot(Heap::kTheHoleValueRootIndex); | 730 __ PushRoot(Heap::kTheHoleValueRootIndex); |
| 731 } else if (decl->fun() != NULL) { | 731 } else if (decl->fun() != NULL) { |
| 732 VisitForValue(decl->fun(), kStack); | 732 VisitForValue(decl->fun(), kStack); |
| 733 } else { | 733 } else { |
| 734 __ Push(Smi::FromInt(0)); // no initial value! | 734 __ Push(Smi::FromInt(0)); // no initial value! |
| 735 } | 735 } |
| 736 __ CallRuntime(Runtime::kDeclareContextSlot, 4); | 736 EmitCallRuntime(Runtime::kDeclareContextSlot, 4); |
| 737 break; | 737 break; |
| 738 } | 738 } |
| 739 } | 739 } |
| 740 | 740 |
| 741 } else if (prop != NULL) { | 741 } else if (prop != NULL) { |
| 742 if (decl->fun() != NULL || decl->mode() == Variable::CONST) { | 742 if (decl->fun() != NULL || decl->mode() == Variable::CONST) { |
| 743 // We are declaring a function or constant that rewrites to a | 743 // We are declaring a function or constant that rewrites to a |
| 744 // property. Use (keyed) IC to set the initial value. | 744 // property. Use (keyed) IC to set the initial value. |
| 745 VisitForValue(prop->obj(), kStack); | 745 VisitForValue(prop->obj(), kStack); |
| 746 VisitForValue(prop->key(), kStack); | 746 VisitForValue(prop->key(), kStack); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 763 } | 763 } |
| 764 } | 764 } |
| 765 } | 765 } |
| 766 | 766 |
| 767 | 767 |
| 768 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 768 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
| 769 // Call the runtime to declare the globals. | 769 // Call the runtime to declare the globals. |
| 770 __ push(rsi); // The context is the first argument. | 770 __ push(rsi); // The context is the first argument. |
| 771 __ Push(pairs); | 771 __ Push(pairs); |
| 772 __ Push(Smi::FromInt(is_eval() ? 1 : 0)); | 772 __ Push(Smi::FromInt(is_eval() ? 1 : 0)); |
| 773 __ CallRuntime(Runtime::kDeclareGlobals, 3); | 773 EmitCallRuntime(Runtime::kDeclareGlobals, 3); |
| 774 // Return value is ignored. | 774 // Return value is ignored. |
| 775 } | 775 } |
| 776 | 776 |
| 777 | 777 |
| 778 void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { | 778 void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { |
| 779 Comment cmnt(masm_, "[ FunctionLiteral"); | 779 Comment cmnt(masm_, "[ FunctionLiteral"); |
| 780 | 780 |
| 781 // Build the function boilerplate and instantiate it. | 781 // Build the function boilerplate and instantiate it. |
| 782 Handle<JSFunction> boilerplate = | 782 Handle<JSFunction> boilerplate = |
| 783 Compiler::BuildBoilerplate(expr, script(), this); | 783 Compiler::BuildBoilerplate(expr, script(), this); |
| 784 if (HasStackOverflow()) return; | 784 if (HasStackOverflow()) return; |
| 785 | 785 |
| 786 ASSERT(boilerplate->IsBoilerplate()); | 786 ASSERT(boilerplate->IsBoilerplate()); |
| 787 | 787 |
| 788 // Create a new closure. | 788 // Create a new closure. |
| 789 __ push(rsi); | 789 __ push(rsi); |
| 790 __ Push(boilerplate); | 790 __ Push(boilerplate); |
| 791 __ CallRuntime(Runtime::kNewClosure, 2); | 791 EmitCallRuntime(Runtime::kNewClosure, 2); |
| 792 Apply(context_, rax); | 792 Apply(context_, rax); |
| 793 } | 793 } |
| 794 | 794 |
| 795 | 795 |
| 796 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { | 796 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
| 797 Comment cmnt(masm_, "[ VariableProxy"); | 797 Comment cmnt(masm_, "[ VariableProxy"); |
| 798 EmitVariableLoad(expr->var(), context_); | 798 EmitVariableLoad(expr->var(), context_); |
| 799 } | 799 } |
| 800 | 800 |
| 801 | 801 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 818 // A test rax instruction following the call is used by the IC to | 818 // A test rax instruction following the call is used by the IC to |
| 819 // indicate that the inobject property case was inlined. Ensure there | 819 // indicate that the inobject property case was inlined. Ensure there |
| 820 // is no test rax instruction here. | 820 // is no test rax instruction here. |
| 821 __ nop(); | 821 __ nop(); |
| 822 DropAndApply(1, context, rax); | 822 DropAndApply(1, context, rax); |
| 823 | 823 |
| 824 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { | 824 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { |
| 825 Comment cmnt(masm_, "Lookup slot"); | 825 Comment cmnt(masm_, "Lookup slot"); |
| 826 __ push(rsi); // Context. | 826 __ push(rsi); // Context. |
| 827 __ Push(var->name()); | 827 __ Push(var->name()); |
| 828 __ CallRuntime(Runtime::kLoadContextSlot, 2); | 828 EmitCallRuntime(Runtime::kLoadContextSlot, 2); |
| 829 Apply(context, rax); | 829 Apply(context, rax); |
| 830 | 830 |
| 831 } else if (slot != NULL) { | 831 } else if (slot != NULL) { |
| 832 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) | 832 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) |
| 833 ? "Context slot" | 833 ? "Context slot" |
| 834 : "Stack slot"); | 834 : "Stack slot"); |
| 835 Apply(context, slot); | 835 Apply(context, slot); |
| 836 | 836 |
| 837 } else { | 837 } else { |
| 838 Comment cmnt(masm_, "Rewritten parameter"); | 838 Comment cmnt(masm_, "Rewritten parameter"); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 882 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; | 882 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; |
| 883 __ movq(rax, FieldOperand(rbx, literal_offset)); | 883 __ movq(rax, FieldOperand(rbx, literal_offset)); |
| 884 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); | 884 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); |
| 885 __ j(not_equal, &done); | 885 __ j(not_equal, &done); |
| 886 // Create regexp literal using runtime function | 886 // Create regexp literal using runtime function |
| 887 // Result will be in rax. | 887 // Result will be in rax. |
| 888 __ push(rbx); | 888 __ push(rbx); |
| 889 __ Push(Smi::FromInt(expr->literal_index())); | 889 __ Push(Smi::FromInt(expr->literal_index())); |
| 890 __ Push(expr->pattern()); | 890 __ Push(expr->pattern()); |
| 891 __ Push(expr->flags()); | 891 __ Push(expr->flags()); |
| 892 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); | 892 EmitCallRuntime(Runtime::kMaterializeRegExpLiteral, 4); |
| 893 __ bind(&done); | 893 __ bind(&done); |
| 894 Apply(context_, rax); | 894 Apply(context_, rax); |
| 895 } | 895 } |
| 896 | 896 |
| 897 | 897 |
| 898 void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { | 898 void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
| 899 Comment cmnt(masm_, "[ ObjectLiteral"); | 899 Comment cmnt(masm_, "[ ObjectLiteral"); |
| 900 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 900 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
| 901 __ push(FieldOperand(rdi, JSFunction::kLiteralsOffset)); | 901 __ push(FieldOperand(rdi, JSFunction::kLiteralsOffset)); |
| 902 __ Push(Smi::FromInt(expr->literal_index())); | 902 __ Push(Smi::FromInt(expr->literal_index())); |
| 903 __ Push(expr->constant_properties()); | 903 __ Push(expr->constant_properties()); |
| 904 if (expr->depth() > 1) { | 904 if (expr->depth() > 1) { |
| 905 __ CallRuntime(Runtime::kCreateObjectLiteral, 3); | 905 EmitCallRuntime(Runtime::kCreateObjectLiteral, 3); |
| 906 } else { | 906 } else { |
| 907 __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 3); | 907 EmitCallRuntime(Runtime::kCreateObjectLiteralShallow, 3); |
| 908 } | 908 } |
| 909 | 909 |
| 910 // If result_saved is true the result is on top of the stack. If | 910 // If result_saved is true the result is on top of the stack. If |
| 911 // result_saved is false the result is in rax. | 911 // result_saved is false the result is in rax. |
| 912 bool result_saved = false; | 912 bool result_saved = false; |
| 913 | 913 |
| 914 for (int i = 0; i < expr->properties()->length(); i++) { | 914 for (int i = 0; i < expr->properties()->length(); i++) { |
| 915 ObjectLiteral::Property* property = expr->properties()->at(i); | 915 ObjectLiteral::Property* property = expr->properties()->at(i); |
| 916 if (property->IsCompileTimeValue()) continue; | 916 if (property->IsCompileTimeValue()) continue; |
| 917 | 917 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 935 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 935 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 936 __ call(ic, RelocInfo::CODE_TARGET); | 936 __ call(ic, RelocInfo::CODE_TARGET); |
| 937 __ nop(); | 937 __ nop(); |
| 938 break; | 938 break; |
| 939 } | 939 } |
| 940 // Fall through. | 940 // Fall through. |
| 941 case ObjectLiteral::Property::PROTOTYPE: | 941 case ObjectLiteral::Property::PROTOTYPE: |
| 942 __ push(Operand(rsp, 0)); // Duplicate receiver. | 942 __ push(Operand(rsp, 0)); // Duplicate receiver. |
| 943 VisitForValue(key, kStack); | 943 VisitForValue(key, kStack); |
| 944 VisitForValue(value, kStack); | 944 VisitForValue(value, kStack); |
| 945 __ CallRuntime(Runtime::kSetProperty, 3); | 945 EmitCallRuntime(Runtime::kSetProperty, 3); |
| 946 break; | 946 break; |
| 947 case ObjectLiteral::Property::SETTER: | 947 case ObjectLiteral::Property::SETTER: |
| 948 case ObjectLiteral::Property::GETTER: | 948 case ObjectLiteral::Property::GETTER: |
| 949 __ push(Operand(rsp, 0)); // Duplicate receiver. | 949 __ push(Operand(rsp, 0)); // Duplicate receiver. |
| 950 VisitForValue(key, kStack); | 950 VisitForValue(key, kStack); |
| 951 __ Push(property->kind() == ObjectLiteral::Property::SETTER ? | 951 __ Push(property->kind() == ObjectLiteral::Property::SETTER ? |
| 952 Smi::FromInt(1) : | 952 Smi::FromInt(1) : |
| 953 Smi::FromInt(0)); | 953 Smi::FromInt(0)); |
| 954 VisitForValue(value, kStack); | 954 VisitForValue(value, kStack); |
| 955 __ CallRuntime(Runtime::kDefineAccessor, 4); | 955 EmitCallRuntime(Runtime::kDefineAccessor, 4); |
| 956 break; | 956 break; |
| 957 } | 957 } |
| 958 } | 958 } |
| 959 | 959 |
| 960 if (result_saved) { | 960 if (result_saved) { |
| 961 ApplyTOS(context_); | 961 ApplyTOS(context_); |
| 962 } else { | 962 } else { |
| 963 Apply(context_, rax); | 963 Apply(context_, rax); |
| 964 } | 964 } |
| 965 } | 965 } |
| 966 | 966 |
| 967 | 967 |
| 968 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 968 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
| 969 Comment cmnt(masm_, "[ ArrayLiteral"); | 969 Comment cmnt(masm_, "[ ArrayLiteral"); |
| 970 __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 970 __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
| 971 __ push(FieldOperand(rbx, JSFunction::kLiteralsOffset)); | 971 __ push(FieldOperand(rbx, JSFunction::kLiteralsOffset)); |
| 972 __ Push(Smi::FromInt(expr->literal_index())); | 972 __ Push(Smi::FromInt(expr->literal_index())); |
| 973 __ Push(expr->constant_elements()); | 973 __ Push(expr->constant_elements()); |
| 974 if (expr->depth() > 1) { | 974 if (expr->depth() > 1) { |
| 975 __ CallRuntime(Runtime::kCreateArrayLiteral, 3); | 975 EmitCallRuntime(Runtime::kCreateArrayLiteral, 3); |
| 976 } else { | 976 } else { |
| 977 __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); | 977 EmitCallRuntime(Runtime::kCreateArrayLiteralShallow, 3); |
| 978 } | 978 } |
| 979 | 979 |
| 980 bool result_saved = false; // Is the result saved to the stack? | 980 bool result_saved = false; // Is the result saved to the stack? |
| 981 | 981 |
| 982 // Emit code to evaluate all the non-constant subexpressions and to store | 982 // Emit code to evaluate all the non-constant subexpressions and to store |
| 983 // them into the newly cloned array. | 983 // them into the newly cloned array. |
| 984 ZoneList<Expression*>* subexprs = expr->values(); | 984 ZoneList<Expression*>* subexprs = expr->values(); |
| 985 for (int i = 0, len = subexprs->length(); i < len; i++) { | 985 for (int i = 0, len = subexprs->length(); i < len; i++) { |
| 986 Expression* subexpr = subexprs->at(i); | 986 Expression* subexpr = subexprs->at(i); |
| 987 // If the subexpression is a literal or a simple materialized literal it | 987 // If the subexpression is a literal or a simple materialized literal it |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1146 __ Move(rcx, var->name()); | 1146 __ Move(rcx, var->name()); |
| 1147 __ movq(rdx, CodeGenerator::GlobalObject()); | 1147 __ movq(rdx, CodeGenerator::GlobalObject()); |
| 1148 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 1148 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 1149 __ Call(ic, RelocInfo::CODE_TARGET); | 1149 __ Call(ic, RelocInfo::CODE_TARGET); |
| 1150 Apply(context, rax); | 1150 Apply(context, rax); |
| 1151 | 1151 |
| 1152 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { | 1152 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { |
| 1153 __ push(result_register()); // Value. | 1153 __ push(result_register()); // Value. |
| 1154 __ push(rsi); // Context. | 1154 __ push(rsi); // Context. |
| 1155 __ Push(var->name()); | 1155 __ Push(var->name()); |
| 1156 __ CallRuntime(Runtime::kStoreContextSlot, 3); | 1156 EmitCallRuntime(Runtime::kStoreContextSlot, 3); |
| 1157 Apply(context, rax); | 1157 Apply(context, rax); |
| 1158 | 1158 |
| 1159 } else if (var->slot() != NULL) { | 1159 } else if (var->slot() != NULL) { |
| 1160 switch (slot->type()) { | 1160 switch (slot->type()) { |
| 1161 case Slot::LOCAL: | 1161 case Slot::LOCAL: |
| 1162 case Slot::PARAMETER: | 1162 case Slot::PARAMETER: |
| 1163 __ movq(Operand(rbp, SlotOffset(slot)), result_register()); | 1163 __ movq(Operand(rbp, SlotOffset(slot)), result_register()); |
| 1164 break; | 1164 break; |
| 1165 | 1165 |
| 1166 case Slot::CONTEXT: { | 1166 case Slot::CONTEXT: { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1193 Property* prop = expr->target()->AsProperty(); | 1193 Property* prop = expr->target()->AsProperty(); |
| 1194 ASSERT(prop != NULL); | 1194 ASSERT(prop != NULL); |
| 1195 ASSERT(prop->key()->AsLiteral() != NULL); | 1195 ASSERT(prop->key()->AsLiteral() != NULL); |
| 1196 | 1196 |
| 1197 // If the assignment starts a block of assignments to the same object, | 1197 // If the assignment starts a block of assignments to the same object, |
| 1198 // change to slow case to avoid the quadratic behavior of repeatedly | 1198 // change to slow case to avoid the quadratic behavior of repeatedly |
| 1199 // adding fast properties. | 1199 // adding fast properties. |
| 1200 if (expr->starts_initialization_block()) { | 1200 if (expr->starts_initialization_block()) { |
| 1201 __ push(result_register()); | 1201 __ push(result_register()); |
| 1202 __ push(Operand(rsp, kPointerSize)); // Receiver is now under value. | 1202 __ push(Operand(rsp, kPointerSize)); // Receiver is now under value. |
| 1203 __ CallRuntime(Runtime::kToSlowProperties, 1); | 1203 EmitCallRuntime(Runtime::kToSlowProperties, 1); |
| 1204 __ pop(result_register()); | 1204 __ pop(result_register()); |
| 1205 } | 1205 } |
| 1206 | 1206 |
| 1207 // Record source code position before IC call. | 1207 // Record source code position before IC call. |
| 1208 SetSourcePosition(expr->position()); | 1208 SetSourcePosition(expr->position()); |
| 1209 __ Move(rcx, prop->key()->AsLiteral()->handle()); | 1209 __ Move(rcx, prop->key()->AsLiteral()->handle()); |
| 1210 if (expr->ends_initialization_block()) { | 1210 if (expr->ends_initialization_block()) { |
| 1211 __ movq(rdx, Operand(rsp, 0)); | 1211 __ movq(rdx, Operand(rsp, 0)); |
| 1212 } else { | 1212 } else { |
| 1213 __ pop(rdx); | 1213 __ pop(rdx); |
| 1214 } | 1214 } |
| 1215 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 1215 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 1216 __ Call(ic, RelocInfo::CODE_TARGET); | 1216 __ Call(ic, RelocInfo::CODE_TARGET); |
| 1217 __ nop(); | 1217 __ nop(); |
| 1218 | 1218 |
| 1219 // If the assignment ends an initialization block, revert to fast case. | 1219 // If the assignment ends an initialization block, revert to fast case. |
| 1220 if (expr->ends_initialization_block()) { | 1220 if (expr->ends_initialization_block()) { |
| 1221 __ push(rax); // Result of assignment, saved even if not needed. | 1221 __ push(rax); // Result of assignment, saved even if not needed. |
| 1222 __ push(Operand(rsp, kPointerSize)); // Receiver is under value. | 1222 __ push(Operand(rsp, kPointerSize)); // Receiver is under value. |
| 1223 __ CallRuntime(Runtime::kToFastProperties, 1); | 1223 EmitCallRuntime(Runtime::kToFastProperties, 1); |
| 1224 __ pop(rax); | 1224 __ pop(rax); |
| 1225 DropAndApply(1, context_, rax); | 1225 DropAndApply(1, context_, rax); |
| 1226 } else { | 1226 } else { |
| 1227 Apply(context_, rax); | 1227 Apply(context_, rax); |
| 1228 } | 1228 } |
| 1229 } | 1229 } |
| 1230 | 1230 |
| 1231 | 1231 |
| 1232 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 1232 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
| 1233 // Assignment to a property, using a keyed store IC. | 1233 // Assignment to a property, using a keyed store IC. |
| 1234 | 1234 |
| 1235 // If the assignment starts a block of assignments to the same object, | 1235 // If the assignment starts a block of assignments to the same object, |
| 1236 // change to slow case to avoid the quadratic behavior of repeatedly | 1236 // change to slow case to avoid the quadratic behavior of repeatedly |
| 1237 // adding fast properties. | 1237 // adding fast properties. |
| 1238 if (expr->starts_initialization_block()) { | 1238 if (expr->starts_initialization_block()) { |
| 1239 __ push(result_register()); | 1239 __ push(result_register()); |
| 1240 // Receiver is now under the key and value. | 1240 // Receiver is now under the key and value. |
| 1241 __ push(Operand(rsp, 2 * kPointerSize)); | 1241 __ push(Operand(rsp, 2 * kPointerSize)); |
| 1242 __ CallRuntime(Runtime::kToSlowProperties, 1); | 1242 EmitCallRuntime(Runtime::kToSlowProperties, 1); |
| 1243 __ pop(result_register()); | 1243 __ pop(result_register()); |
| 1244 } | 1244 } |
| 1245 | 1245 |
| 1246 // Record source code position before IC call. | 1246 // Record source code position before IC call. |
| 1247 SetSourcePosition(expr->position()); | 1247 SetSourcePosition(expr->position()); |
| 1248 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 1248 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
| 1249 __ Call(ic, RelocInfo::CODE_TARGET); | 1249 __ Call(ic, RelocInfo::CODE_TARGET); |
| 1250 // This nop signals to the IC that there is no inlined code at the call | 1250 // This nop signals to the IC that there is no inlined code at the call |
| 1251 // site for it to patch. | 1251 // site for it to patch. |
| 1252 __ nop(); | 1252 __ nop(); |
| 1253 | 1253 |
| 1254 // If the assignment ends an initialization block, revert to fast case. | 1254 // If the assignment ends an initialization block, revert to fast case. |
| 1255 if (expr->ends_initialization_block()) { | 1255 if (expr->ends_initialization_block()) { |
| 1256 __ push(rax); // Result of assignment, saved even if not needed. | 1256 __ push(rax); // Result of assignment, saved even if not needed. |
| 1257 // Receiver is under the key and value. | 1257 // Receiver is under the key and value. |
| 1258 __ push(Operand(rsp, 2 * kPointerSize)); | 1258 __ push(Operand(rsp, 2 * kPointerSize)); |
| 1259 __ CallRuntime(Runtime::kToFastProperties, 1); | 1259 EmitCallRuntime(Runtime::kToFastProperties, 1); |
| 1260 __ pop(rax); | 1260 __ pop(rax); |
| 1261 } | 1261 } |
| 1262 | 1262 |
| 1263 // Receiver and key are still on stack. | 1263 // Receiver and key are still on stack. |
| 1264 DropAndApply(2, context_, rax); | 1264 DropAndApply(2, context_, rax); |
| 1265 } | 1265 } |
| 1266 | 1266 |
| 1267 | 1267 |
| 1268 void FullCodeGenerator::VisitProperty(Property* expr) { | 1268 void FullCodeGenerator::VisitProperty(Property* expr) { |
| 1269 Comment cmnt(masm_, "[ Property"); | 1269 Comment cmnt(masm_, "[ Property"); |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1451 | 1451 |
| 1452 if (expr->is_jsruntime()) { | 1452 if (expr->is_jsruntime()) { |
| 1453 // Call the JS runtime function using a call IC. | 1453 // Call the JS runtime function using a call IC. |
| 1454 __ Move(rcx, expr->name()); | 1454 __ Move(rcx, expr->name()); |
| 1455 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 1455 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
| 1456 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); | 1456 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); |
| 1457 __ call(ic, RelocInfo::CODE_TARGET); | 1457 __ call(ic, RelocInfo::CODE_TARGET); |
| 1458 // Restore context register. | 1458 // Restore context register. |
| 1459 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 1459 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 1460 } else { | 1460 } else { |
| 1461 __ CallRuntime(expr->function(), arg_count); | 1461 EmitCallRuntime(expr->function(), arg_count); |
| 1462 } | 1462 } |
| 1463 Apply(context_, rax); | 1463 Apply(context_, rax); |
| 1464 } | 1464 } |
| 1465 | 1465 |
| 1466 | 1466 |
| 1467 void FullCodeGenerator::EmitCallRuntime(Runtime::FunctionId id, int arg_count) { |
| 1468 EmitCallRuntime(Runtime::FunctionForId(id), arg_count); |
| 1469 } |
| 1470 |
| 1471 |
| 1472 void FullCodeGenerator::EmitCallRuntime(Runtime::Function* f, int arg_count) { |
| 1473 if (Runtime::DIRECT_CALL_NOT_FAILS == f->calling_convention) { |
| 1474 if (arg_count > kCArgRegsCount) { |
| 1475 __ IllegalOperation(arg_count); |
| 1476 __ Drop(arg_count); |
| 1477 return; |
| 1478 } |
| 1479 for (int i = arg_count - 1; i >= 0; i--) { |
| 1480 __ pop(kCArgRegs[i]); |
| 1481 } |
| 1482 } |
| 1483 |
| 1484 __ CallRuntime(f, arg_count); |
| 1485 |
| 1486 if (Runtime::DIRECT_CALL_NOT_FAILS == f->calling_convention) { |
| 1487 // Restore context register. |
| 1488 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 1489 } |
| 1490 } |
| 1491 |
| 1492 |
| 1467 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 1493 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
| 1468 switch (expr->op()) { | 1494 switch (expr->op()) { |
| 1469 case Token::VOID: { | 1495 case Token::VOID: { |
| 1470 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); | 1496 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); |
| 1471 VisitForEffect(expr->expression()); | 1497 VisitForEffect(expr->expression()); |
| 1472 switch (context_) { | 1498 switch (context_) { |
| 1473 case Expression::kUninitialized: | 1499 case Expression::kUninitialized: |
| 1474 UNREACHABLE(); | 1500 UNREACHABLE(); |
| 1475 break; | 1501 break; |
| 1476 case Expression::kEffect: | 1502 case Expression::kEffect: |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1549 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 1575 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
| 1550 // Use a regular load, not a contextual load, to avoid a reference | 1576 // Use a regular load, not a contextual load, to avoid a reference |
| 1551 // error. | 1577 // error. |
| 1552 __ Call(ic, RelocInfo::CODE_TARGET); | 1578 __ Call(ic, RelocInfo::CODE_TARGET); |
| 1553 __ movq(Operand(rsp, 0), rax); | 1579 __ movq(Operand(rsp, 0), rax); |
| 1554 } else if (proxy != NULL && | 1580 } else if (proxy != NULL && |
| 1555 proxy->var()->slot() != NULL && | 1581 proxy->var()->slot() != NULL && |
| 1556 proxy->var()->slot()->type() == Slot::LOOKUP) { | 1582 proxy->var()->slot()->type() == Slot::LOOKUP) { |
| 1557 __ push(rsi); | 1583 __ push(rsi); |
| 1558 __ Push(proxy->name()); | 1584 __ Push(proxy->name()); |
| 1559 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); | 1585 EmitCallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); |
| 1560 __ push(rax); | 1586 __ push(rax); |
| 1561 } else { | 1587 } else { |
| 1562 // This expression cannot throw a reference error at the top level. | 1588 // This expression cannot throw a reference error at the top level. |
| 1563 VisitForValue(expr->expression(), kStack); | 1589 VisitForValue(expr->expression(), kStack); |
| 1564 } | 1590 } |
| 1565 | 1591 |
| 1566 __ CallRuntime(Runtime::kTypeof, 1); | 1592 EmitCallRuntime(Runtime::kTypeof, 1); |
| 1567 Apply(context_, rax); | 1593 Apply(context_, rax); |
| 1568 break; | 1594 break; |
| 1569 } | 1595 } |
| 1570 | 1596 |
| 1571 case Token::ADD: { | 1597 case Token::ADD: { |
| 1572 Comment cmt(masm_, "[ UnaryOperation (ADD)"); | 1598 Comment cmt(masm_, "[ UnaryOperation (ADD)"); |
| 1573 VisitForValue(expr->expression(), kAccumulator); | 1599 VisitForValue(expr->expression(), kAccumulator); |
| 1574 Label no_conversion; | 1600 Label no_conversion; |
| 1575 Condition is_smi = masm_->CheckSmi(result_register()); | 1601 Condition is_smi = masm_->CheckSmi(result_register()); |
| 1576 __ j(is_smi, &no_conversion); | 1602 __ j(is_smi, &no_conversion); |
| (...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1982 __ movq(Operand(rsp, 0), rdx); | 2008 __ movq(Operand(rsp, 0), rdx); |
| 1983 // And return. | 2009 // And return. |
| 1984 __ ret(0); | 2010 __ ret(0); |
| 1985 } | 2011 } |
| 1986 | 2012 |
| 1987 | 2013 |
| 1988 #undef __ | 2014 #undef __ |
| 1989 | 2015 |
| 1990 | 2016 |
| 1991 } } // namespace v8::internal | 2017 } } // namespace v8::internal |
| OLD | NEW |