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

Side by Side Diff: src/ia32/builtins-ia32.cc

Issue 913073003: [es6] implement Reflect.apply() & Reflect.construct() (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix arm Created 5 years, 9 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
« no previous file with comments | « src/harmony-reflect.js ('k') | src/macros.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #if V8_TARGET_ARCH_IA32 7 #if V8_TARGET_ARCH_IA32
8 8
9 #include "src/code-factory.h" 9 #include "src/code-factory.h"
10 #include "src/codegen.h" 10 #include "src/codegen.h"
(...skipping 972 matching lines...) Expand 10 before | Expand all | Expand 10 after
983 __ SmiUntag(ebx); 983 __ SmiUntag(ebx);
984 __ cmp(eax, ebx); 984 __ cmp(eax, ebx);
985 __ j(not_equal, 985 __ j(not_equal,
986 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline()); 986 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline());
987 987
988 ParameterCount expected(0); 988 ParameterCount expected(0);
989 __ InvokeCode(edx, expected, expected, JUMP_FUNCTION, NullCallWrapper()); 989 __ InvokeCode(edx, expected, expected, JUMP_FUNCTION, NullCallWrapper());
990 } 990 }
991 991
992 992
993 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { 993 static void Generate_CheckStackOverflow(MacroAssembler* masm,
994 static const int kArgumentsOffset = 2 * kPointerSize; 994 const int calleeOffset) {
995 static const int kReceiverOffset = 3 * kPointerSize; 995 // eax : the number of items to be pushed to the stack
996 static const int kFunctionOffset = 4 * kPointerSize; 996 //
997 // Check the stack for overflow. We are not trying to catch
998 // interruptions (e.g. debug break and preemption) here, so the "real stack
999 // limit" is checked.
1000 Label okay;
1001 ExternalReference real_stack_limit =
1002 ExternalReference::address_of_real_stack_limit(masm->isolate());
1003 __ mov(edi, Operand::StaticVariable(real_stack_limit));
1004 // Make ecx the space we have left. The stack might already be overflowed
1005 // here which will cause ecx to become negative.
1006 __ mov(ecx, esp);
1007 __ sub(ecx, edi);
1008 // Make edx the space we need for the array when it is unrolled onto the
1009 // stack.
1010 __ mov(edx, eax);
1011 __ shl(edx, kPointerSizeLog2 - kSmiTagSize);
1012 // Check if the arguments will overflow the stack.
1013 __ cmp(ecx, edx);
1014 __ j(greater, &okay); // Signed comparison.
1015
1016 // Out of stack space.
1017 __ push(Operand(ebp, calleeOffset)); // push this
1018 __ push(eax);
1019 __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
1020
1021 __ bind(&okay);
1022 }
1023
1024
1025 static void Generate_PushAppliedArguments(MacroAssembler* masm,
1026 const int argumentsOffset,
1027 const int indexOffset,
1028 const int limitOffset) {
1029 // Copy all arguments from the array to the stack.
1030 Label entry, loop;
1031 Register receiver = LoadDescriptor::ReceiverRegister();
1032 Register key = LoadDescriptor::NameRegister();
1033 __ mov(key, Operand(ebp, indexOffset));
1034 __ jmp(&entry);
1035 __ bind(&loop);
1036 __ mov(receiver, Operand(ebp, argumentsOffset)); // load arguments
1037
1038 if (FLAG_vector_ics) {
1039 // TODO(mvstanton): Vector-based ics need additional infrastructure to
1040 // be embedded here. For now, just call the runtime.
1041 __ push(receiver);
1042 __ push(key);
1043 __ CallRuntime(Runtime::kGetProperty, 2);
1044 } else {
1045 // Use inline caching to speed up access to arguments.
1046 Handle<Code> ic = CodeFactory::KeyedLoadIC(masm->isolate()).code();
1047 __ call(ic, RelocInfo::CODE_TARGET);
1048 // It is important that we do not have a test instruction after the
1049 // call. A test instruction after the call is used to indicate that
1050 // we have generated an inline version of the keyed load. In this
1051 // case, we know that we are not generating a test instruction next.
1052 }
1053
1054 // Push the nth argument.
1055 __ push(eax);
1056
1057 // Update the index on the stack and in register key.
1058 __ mov(key, Operand(ebp, indexOffset));
1059 __ add(key, Immediate(1 << kSmiTagSize));
1060 __ mov(Operand(ebp, indexOffset), key);
1061
1062 __ bind(&entry);
1063 __ cmp(key, Operand(ebp, limitOffset));
1064 __ j(not_equal, &loop);
1065
1066 // On exit, the pushed arguments count is in eax, untagged
1067 __ Move(eax, key);
1068 __ SmiUntag(eax);
1069 }
1070
1071
1072 // Used by FunctionApply and ReflectApply
1073 static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
1074 const int kFormalParameters = targetIsArgument ? 3 : 2;
1075 const int kStackSize = kFormalParameters + 1;
1076
1077 // Stack at entry:
1078 // esp : return address
1079 // esp[4] : arguments
1080 // esp[8] : receiver ("this")
1081 // esp[12] : function
997 { 1082 {
998 FrameScope frame_scope(masm, StackFrame::INTERNAL); 1083 FrameScope frame_scope(masm, StackFrame::INTERNAL);
1084 // Stack frame:
1085 // ebp : Old base pointer
1086 // ebp[4] : return address
1087 // ebp[8] : function arguments
1088 // ebp[12] : receiver
1089 // ebp[16] : function
1090 static const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize;
1091 static const int kReceiverOffset = kArgumentsOffset + kPointerSize;
1092 static const int kFunctionOffset = kReceiverOffset + kPointerSize;
999 1093
1000 __ push(Operand(ebp, kFunctionOffset)); // push this 1094 __ push(Operand(ebp, kFunctionOffset)); // push this
1001 __ push(Operand(ebp, kArgumentsOffset)); // push arguments 1095 __ push(Operand(ebp, kArgumentsOffset)); // push arguments
1002 __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); 1096 if (targetIsArgument) {
1097 __ InvokeBuiltin(Builtins::REFLECT_APPLY_PREPARE, CALL_FUNCTION);
1098 } else {
1099 __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION);
1100 }
1003 1101
1004 // Check the stack for overflow. We are not trying to catch 1102 Generate_CheckStackOverflow(masm, kFunctionOffset);
1005 // interruptions (e.g. debug break and preemption) here, so the "real stack
1006 // limit" is checked.
1007 Label okay;
1008 ExternalReference real_stack_limit =
1009 ExternalReference::address_of_real_stack_limit(masm->isolate());
1010 __ mov(edi, Operand::StaticVariable(real_stack_limit));
1011 // Make ecx the space we have left. The stack might already be overflowed
1012 // here which will cause ecx to become negative.
1013 __ mov(ecx, esp);
1014 __ sub(ecx, edi);
1015 // Make edx the space we need for the array when it is unrolled onto the
1016 // stack.
1017 __ mov(edx, eax);
1018 __ shl(edx, kPointerSizeLog2 - kSmiTagSize);
1019 // Check if the arguments will overflow the stack.
1020 __ cmp(ecx, edx);
1021 __ j(greater, &okay); // Signed comparison.
1022
1023 // Out of stack space.
1024 __ push(Operand(ebp, 4 * kPointerSize)); // push this
1025 __ push(eax);
1026 __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
1027 __ bind(&okay);
1028 // End of stack check.
1029 1103
1030 // Push current index and limit. 1104 // Push current index and limit.
1031 const int kLimitOffset = 1105 const int kLimitOffset =
1032 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize; 1106 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize;
1033 const int kIndexOffset = kLimitOffset - 1 * kPointerSize; 1107 const int kIndexOffset = kLimitOffset - 1 * kPointerSize;
1034 __ push(eax); // limit 1108 __ push(eax); // limit
1035 __ push(Immediate(0)); // index 1109 __ push(Immediate(0)); // index
1036 1110
1037 // Get the receiver. 1111 // Get the receiver.
1038 __ mov(ebx, Operand(ebp, kReceiverOffset)); 1112 __ mov(ebx, Operand(ebp, kReceiverOffset));
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1081 1155
1082 __ bind(&use_global_proxy); 1156 __ bind(&use_global_proxy);
1083 __ mov(ebx, 1157 __ mov(ebx,
1084 Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); 1158 Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
1085 __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalProxyOffset)); 1159 __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalProxyOffset));
1086 1160
1087 // Push the receiver. 1161 // Push the receiver.
1088 __ bind(&push_receiver); 1162 __ bind(&push_receiver);
1089 __ push(ebx); 1163 __ push(ebx);
1090 1164
1091 // Copy all arguments from the array to the stack. 1165 // Loop over the arguments array, pushing each value to the stack
1092 Label entry, loop; 1166 Generate_PushAppliedArguments(
1093 Register receiver = LoadDescriptor::ReceiverRegister(); 1167 masm, kArgumentsOffset, kIndexOffset, kLimitOffset);
1094 Register key = LoadDescriptor::NameRegister();
1095 __ mov(key, Operand(ebp, kIndexOffset));
1096 __ jmp(&entry);
1097 __ bind(&loop);
1098 __ mov(receiver, Operand(ebp, kArgumentsOffset)); // load arguments
1099
1100 if (FLAG_vector_ics) {
1101 // TODO(mvstanton): Vector-based ics need additional infrastructure to
1102 // be embedded here. For now, just call the runtime.
1103 __ push(receiver);
1104 __ push(key);
1105 __ CallRuntime(Runtime::kGetProperty, 2);
1106 } else {
1107 // Use inline caching to speed up access to arguments.
1108 Handle<Code> ic = CodeFactory::KeyedLoadIC(masm->isolate()).code();
1109 __ call(ic, RelocInfo::CODE_TARGET);
1110 // It is important that we do not have a test instruction after the
1111 // call. A test instruction after the call is used to indicate that
1112 // we have generated an inline version of the keyed load. In this
1113 // case, we know that we are not generating a test instruction next.
1114 }
1115
1116 // Push the nth argument.
1117 __ push(eax);
1118
1119 // Update the index on the stack and in register key.
1120 __ mov(key, Operand(ebp, kIndexOffset));
1121 __ add(key, Immediate(1 << kSmiTagSize));
1122 __ mov(Operand(ebp, kIndexOffset), key);
1123
1124 __ bind(&entry);
1125 __ cmp(key, Operand(ebp, kLimitOffset));
1126 __ j(not_equal, &loop);
1127 1168
1128 // Call the function. 1169 // Call the function.
1129 Label call_proxy; 1170 Label call_proxy;
1130 ParameterCount actual(eax); 1171 ParameterCount actual(eax);
1131 __ Move(eax, key);
1132 __ SmiUntag(eax);
1133 __ mov(edi, Operand(ebp, kFunctionOffset)); 1172 __ mov(edi, Operand(ebp, kFunctionOffset));
1134 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); 1173 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
1135 __ j(not_equal, &call_proxy); 1174 __ j(not_equal, &call_proxy);
1136 __ InvokeFunction(edi, actual, CALL_FUNCTION, NullCallWrapper()); 1175 __ InvokeFunction(edi, actual, CALL_FUNCTION, NullCallWrapper());
1137 1176
1138 frame_scope.GenerateLeaveFrame(); 1177 frame_scope.GenerateLeaveFrame();
1139 __ ret(3 * kPointerSize); // remove this, receiver, and arguments 1178 __ ret(kStackSize * kPointerSize); // remove this, receiver, and arguments
1140 1179
1141 // Call the function proxy. 1180 // Call the function proxy.
1142 __ bind(&call_proxy); 1181 __ bind(&call_proxy);
1143 __ push(edi); // add function proxy as last argument 1182 __ push(edi); // add function proxy as last argument
1144 __ inc(eax); 1183 __ inc(eax);
1145 __ Move(ebx, Immediate(0)); 1184 __ Move(ebx, Immediate(0));
1146 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY); 1185 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY);
1147 __ call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 1186 __ call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1148 RelocInfo::CODE_TARGET); 1187 RelocInfo::CODE_TARGET);
1149 1188
1150 // Leave internal frame. 1189 // Leave internal frame.
1151 } 1190 }
1152 __ ret(3 * kPointerSize); // remove this, receiver, and arguments 1191 __ ret(kStackSize * kPointerSize); // remove this, receiver, and arguments
1153 } 1192 }
1154 1193
1155 1194
1195 // Used by ReflectConstruct
1196 static void Generate_ConstructHelper(MacroAssembler* masm) {
1197 const int kFormalParameters = 3;
1198 const int kStackSize = kFormalParameters + 1;
1199
1200 // Stack at entry:
1201 // esp : return address
1202 // esp[4] : original constructor (new.target)
1203 // esp[8] : arguments
1204 // esp[16] : constructor
1205 {
1206 FrameScope frame_scope(masm, StackFrame::INTERNAL);
1207 // Stack frame:
1208 // ebp : Old base pointer
1209 // ebp[4] : return address
1210 // ebp[8] : original constructor (new.target)
1211 // ebp[12] : arguments
1212 // ebp[16] : constructor
1213 static const int kNewTargetOffset = kFPOnStackSize + kPCOnStackSize;
1214 static const int kArgumentsOffset = kNewTargetOffset + kPointerSize;
1215 static const int kFunctionOffset = kArgumentsOffset + kPointerSize;
1216
1217 // If newTarget is not supplied, set it to constructor
1218 Label validate_arguments;
1219 __ mov(eax, Operand(ebp, kNewTargetOffset));
1220 __ CompareRoot(eax, Heap::kUndefinedValueRootIndex);
1221 __ j(not_equal, &validate_arguments, Label::kNear);
1222 __ mov(eax, Operand(ebp, kFunctionOffset));
1223 __ mov(Operand(ebp, kNewTargetOffset), eax);
1224
1225 // Validate arguments
1226 __ bind(&validate_arguments);
1227 __ push(Operand(ebp, kFunctionOffset));
1228 __ push(Operand(ebp, kArgumentsOffset));
1229 __ push(Operand(ebp, kNewTargetOffset));
1230 __ InvokeBuiltin(Builtins::REFLECT_CONSTRUCT_PREPARE, CALL_FUNCTION);
1231
1232 Generate_CheckStackOverflow(masm, kFunctionOffset);
1233
1234 // Push current index and limit.
1235 const int kLimitOffset =
1236 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize;
1237 const int kIndexOffset = kLimitOffset - 1 * kPointerSize;
1238 __ Push(eax); // limit
1239 __ push(Immediate(0)); // index
1240 // Push newTarget and callee functions
1241 __ push(Operand(ebp, kNewTargetOffset));
1242 __ push(Operand(ebp, kFunctionOffset));
1243
1244 // Loop over the arguments array, pushing each value to the stack
1245 Generate_PushAppliedArguments(
1246 masm, kArgumentsOffset, kIndexOffset, kLimitOffset);
1247
1248 // Use undefined feedback vector
1249 __ LoadRoot(ebx, Heap::kUndefinedValueRootIndex);
1250 __ mov(edi, Operand(ebp, kFunctionOffset));
1251
1252 // Call the function.
1253 CallConstructStub stub(masm->isolate(), SUPER_CONSTRUCTOR_CALL);
1254 __ call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
1255
1256 __ Drop(1);
1257
1258 // Leave internal frame.
1259 }
1260 // remove this, target, arguments, and newTarget
1261 __ ret(kStackSize * kPointerSize);
1262 }
1263
1264
1265 void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
1266 Generate_ApplyHelper(masm, false);
1267 }
1268
1269
1270 void Builtins::Generate_ReflectApply(MacroAssembler* masm) {
1271 Generate_ApplyHelper(masm, true);
1272 }
1273
1274
1275 void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
1276 Generate_ConstructHelper(masm);
1277 }
1278
1279
1156 void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) { 1280 void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) {
1157 // ----------- S t a t e ------------- 1281 // ----------- S t a t e -------------
1158 // -- eax : argc 1282 // -- eax : argc
1159 // -- esp[0] : return address 1283 // -- esp[0] : return address
1160 // -- esp[4] : last argument 1284 // -- esp[4] : last argument
1161 // ----------------------------------- 1285 // -----------------------------------
1162 Label generic_array_code; 1286 Label generic_array_code;
1163 1287
1164 // Get the InternalArray function. 1288 // Get the InternalArray function.
1165 __ LoadGlobalFunction(Context::INTERNAL_ARRAY_FUNCTION_INDEX, edi); 1289 __ LoadGlobalFunction(Context::INTERNAL_ARRAY_FUNCTION_INDEX, edi);
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after
1549 1673
1550 __ bind(&ok); 1674 __ bind(&ok);
1551 __ ret(0); 1675 __ ret(0);
1552 } 1676 }
1553 1677
1554 #undef __ 1678 #undef __
1555 } 1679 }
1556 } // namespace v8::internal 1680 } // namespace v8::internal
1557 1681
1558 #endif // V8_TARGET_ARCH_IA32 1682 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/harmony-reflect.js ('k') | src/macros.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698