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

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

Issue 598072: Direct call C++ functions (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 10 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
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« src/runtime.h ('K') | « src/x64/codegen-x64.cc ('k') | src/x64/ic-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698