| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 159 void KeyedLoadFieldStub::InitializeInterfaceDescriptor( | 159 void KeyedLoadFieldStub::InitializeInterfaceDescriptor( |
| 160 Isolate* isolate, | 160 Isolate* isolate, |
| 161 CodeStubInterfaceDescriptor* descriptor) { | 161 CodeStubInterfaceDescriptor* descriptor) { |
| 162 static Register registers[] = { rdx }; | 162 static Register registers[] = { rdx }; |
| 163 descriptor->register_param_count_ = 1; | 163 descriptor->register_param_count_ = 1; |
| 164 descriptor->register_params_ = registers; | 164 descriptor->register_params_ = registers; |
| 165 descriptor->deoptimization_handler_ = NULL; | 165 descriptor->deoptimization_handler_ = NULL; |
| 166 } | 166 } |
| 167 | 167 |
| 168 | 168 |
| 169 void StringLengthStub::InitializeInterfaceDescriptor( |
| 170 Isolate* isolate, |
| 171 CodeStubInterfaceDescriptor* descriptor) { |
| 172 static Register registers[] = { rax, rcx }; |
| 173 descriptor->register_param_count_ = 2; |
| 174 descriptor->register_params_ = registers; |
| 175 descriptor->deoptimization_handler_ = NULL; |
| 176 } |
| 177 |
| 178 |
| 179 void KeyedStringLengthStub::InitializeInterfaceDescriptor( |
| 180 Isolate* isolate, |
| 181 CodeStubInterfaceDescriptor* descriptor) { |
| 182 static Register registers[] = { rdx, rax }; |
| 183 descriptor->register_param_count_ = 2; |
| 184 descriptor->register_params_ = registers; |
| 185 descriptor->deoptimization_handler_ = NULL; |
| 186 } |
| 187 |
| 188 |
| 169 void KeyedStoreFastElementStub::InitializeInterfaceDescriptor( | 189 void KeyedStoreFastElementStub::InitializeInterfaceDescriptor( |
| 170 Isolate* isolate, | 190 Isolate* isolate, |
| 171 CodeStubInterfaceDescriptor* descriptor) { | 191 CodeStubInterfaceDescriptor* descriptor) { |
| 172 static Register registers[] = { rdx, rcx, rax }; | 192 static Register registers[] = { rdx, rcx, rax }; |
| 173 descriptor->register_param_count_ = 3; | 193 descriptor->register_param_count_ = 3; |
| 174 descriptor->register_params_ = registers; | 194 descriptor->register_params_ = registers; |
| 175 descriptor->deoptimization_handler_ = | 195 descriptor->deoptimization_handler_ = |
| 176 FUNCTION_ADDR(KeyedStoreIC_MissFromStubFailure); | 196 FUNCTION_ADDR(KeyedStoreIC_MissFromStubFailure); |
| 177 } | 197 } |
| 178 | 198 |
| (...skipping 727 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 906 receiver = rax; | 926 receiver = rax; |
| 907 } | 927 } |
| 908 | 928 |
| 909 StubCompiler::GenerateLoadFunctionPrototype(masm, receiver, r8, r9, &miss); | 929 StubCompiler::GenerateLoadFunctionPrototype(masm, receiver, r8, r9, &miss); |
| 910 __ bind(&miss); | 930 __ bind(&miss); |
| 911 StubCompiler::TailCallBuiltin( | 931 StubCompiler::TailCallBuiltin( |
| 912 masm, BaseLoadStoreStubCompiler::MissBuiltin(kind())); | 932 masm, BaseLoadStoreStubCompiler::MissBuiltin(kind())); |
| 913 } | 933 } |
| 914 | 934 |
| 915 | 935 |
| 916 void StringLengthStub::Generate(MacroAssembler* masm) { | |
| 917 Label miss; | |
| 918 Register receiver; | |
| 919 if (kind() == Code::KEYED_LOAD_IC) { | |
| 920 // ----------- S t a t e ------------- | |
| 921 // -- rax : key | |
| 922 // -- rdx : receiver | |
| 923 // -- rsp[0] : return address | |
| 924 // ----------------------------------- | |
| 925 __ Cmp(rax, masm->isolate()->factory()->length_string()); | |
| 926 __ j(not_equal, &miss); | |
| 927 receiver = rdx; | |
| 928 } else { | |
| 929 ASSERT(kind() == Code::LOAD_IC); | |
| 930 // ----------- S t a t e ------------- | |
| 931 // -- rax : receiver | |
| 932 // -- rcx : name | |
| 933 // -- rsp[0] : return address | |
| 934 // ----------------------------------- | |
| 935 receiver = rax; | |
| 936 } | |
| 937 | |
| 938 StubCompiler::GenerateLoadStringLength(masm, receiver, r8, r9, &miss); | |
| 939 __ bind(&miss); | |
| 940 StubCompiler::TailCallBuiltin( | |
| 941 masm, BaseLoadStoreStubCompiler::MissBuiltin(kind())); | |
| 942 } | |
| 943 | |
| 944 | |
| 945 void StoreArrayLengthStub::Generate(MacroAssembler* masm) { | 936 void StoreArrayLengthStub::Generate(MacroAssembler* masm) { |
| 946 // ----------- S t a t e ------------- | 937 // ----------- S t a t e ------------- |
| 947 // -- rax : value | 938 // -- rax : value |
| 948 // -- rcx : key | 939 // -- rcx : key |
| 949 // -- rdx : receiver | 940 // -- rdx : receiver |
| 950 // -- rsp[0] : return address | 941 // -- rsp[0] : return address |
| 951 // ----------------------------------- | 942 // ----------------------------------- |
| 952 // | 943 // |
| 953 // This accepts as a receiver anything JSArray::SetElementsLength accepts | 944 // This accepts as a receiver anything JSArray::SetElementsLength accepts |
| 954 // (currently anything except for external arrays which means anything with | 945 // (currently anything except for external arrays which means anything with |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1055 // Slow-case: Handle non-smi or out-of-bounds access to arguments | 1046 // Slow-case: Handle non-smi or out-of-bounds access to arguments |
| 1056 // by calling the runtime system. | 1047 // by calling the runtime system. |
| 1057 __ bind(&slow); | 1048 __ bind(&slow); |
| 1058 __ PopReturnAddressTo(rbx); | 1049 __ PopReturnAddressTo(rbx); |
| 1059 __ push(rdx); | 1050 __ push(rdx); |
| 1060 __ PushReturnAddressFrom(rbx); | 1051 __ PushReturnAddressFrom(rbx); |
| 1061 __ TailCallRuntime(Runtime::kGetArgumentsProperty, 1, 1); | 1052 __ TailCallRuntime(Runtime::kGetArgumentsProperty, 1, 1); |
| 1062 } | 1053 } |
| 1063 | 1054 |
| 1064 | 1055 |
| 1065 void ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) { | 1056 void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) { |
| 1066 // Stack layout: | 1057 // Stack layout: |
| 1067 // rsp[0] : return address | 1058 // rsp[0] : return address |
| 1068 // rsp[8] : number of parameters (tagged) | 1059 // rsp[8] : number of parameters (tagged) |
| 1069 // rsp[16] : receiver displacement | 1060 // rsp[16] : receiver displacement |
| 1070 // rsp[24] : function | 1061 // rsp[24] : function |
| 1071 // Registers used over the whole function: | 1062 // Registers used over the whole function: |
| 1072 // rbx: the mapped parameter count (untagged) | 1063 // rbx: the mapped parameter count (untagged) |
| 1073 // rax: the allocated object (tagged). | 1064 // rax: the allocated object (tagged). |
| 1074 | 1065 |
| 1075 Factory* factory = masm->isolate()->factory(); | 1066 Factory* factory = masm->isolate()->factory(); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1116 __ xor_(r8, r8); | 1107 __ xor_(r8, r8); |
| 1117 __ testq(rbx, rbx); | 1108 __ testq(rbx, rbx); |
| 1118 __ j(zero, &no_parameter_map, Label::kNear); | 1109 __ j(zero, &no_parameter_map, Label::kNear); |
| 1119 __ lea(r8, Operand(rbx, times_pointer_size, kParameterMapHeaderSize)); | 1110 __ lea(r8, Operand(rbx, times_pointer_size, kParameterMapHeaderSize)); |
| 1120 __ bind(&no_parameter_map); | 1111 __ bind(&no_parameter_map); |
| 1121 | 1112 |
| 1122 // 2. Backing store. | 1113 // 2. Backing store. |
| 1123 __ lea(r8, Operand(r8, rcx, times_pointer_size, FixedArray::kHeaderSize)); | 1114 __ lea(r8, Operand(r8, rcx, times_pointer_size, FixedArray::kHeaderSize)); |
| 1124 | 1115 |
| 1125 // 3. Arguments object. | 1116 // 3. Arguments object. |
| 1126 __ addq(r8, Immediate(Heap::kArgumentsObjectSize)); | 1117 __ addq(r8, Immediate(Heap::kSloppyArgumentsObjectSize)); |
| 1127 | 1118 |
| 1128 // Do the allocation of all three objects in one go. | 1119 // Do the allocation of all three objects in one go. |
| 1129 __ Allocate(r8, rax, rdx, rdi, &runtime, TAG_OBJECT); | 1120 __ Allocate(r8, rax, rdx, rdi, &runtime, TAG_OBJECT); |
| 1130 | 1121 |
| 1131 // rax = address of new object(s) (tagged) | 1122 // rax = address of new object(s) (tagged) |
| 1132 // rcx = argument count (untagged) | 1123 // rcx = argument count (untagged) |
| 1133 // Get the arguments boilerplate from the current native context into rdi. | 1124 // Get the arguments boilerplate from the current native context into rdi. |
| 1134 Label has_mapped_parameters, copy; | 1125 Label has_mapped_parameters, copy; |
| 1135 __ movp(rdi, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | 1126 __ movp(rdi, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
| 1136 __ movp(rdi, FieldOperand(rdi, GlobalObject::kNativeContextOffset)); | 1127 __ movp(rdi, FieldOperand(rdi, GlobalObject::kNativeContextOffset)); |
| 1137 __ testq(rbx, rbx); | 1128 __ testq(rbx, rbx); |
| 1138 __ j(not_zero, &has_mapped_parameters, Label::kNear); | 1129 __ j(not_zero, &has_mapped_parameters, Label::kNear); |
| 1139 | 1130 |
| 1140 const int kIndex = Context::ARGUMENTS_BOILERPLATE_INDEX; | 1131 const int kIndex = Context::SLOPPY_ARGUMENTS_BOILERPLATE_INDEX; |
| 1141 __ movp(rdi, Operand(rdi, Context::SlotOffset(kIndex))); | 1132 __ movp(rdi, Operand(rdi, Context::SlotOffset(kIndex))); |
| 1142 __ jmp(©, Label::kNear); | 1133 __ jmp(©, Label::kNear); |
| 1143 | 1134 |
| 1144 const int kAliasedIndex = Context::ALIASED_ARGUMENTS_BOILERPLATE_INDEX; | 1135 const int kAliasedIndex = Context::ALIASED_ARGUMENTS_BOILERPLATE_INDEX; |
| 1145 __ bind(&has_mapped_parameters); | 1136 __ bind(&has_mapped_parameters); |
| 1146 __ movp(rdi, Operand(rdi, Context::SlotOffset(kAliasedIndex))); | 1137 __ movp(rdi, Operand(rdi, Context::SlotOffset(kAliasedIndex))); |
| 1147 __ bind(©); | 1138 __ bind(©); |
| 1148 | 1139 |
| 1149 // rax = address of new object (tagged) | 1140 // rax = address of new object (tagged) |
| 1150 // rbx = mapped parameter count (untagged) | 1141 // rbx = mapped parameter count (untagged) |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1167 // Note: rcx is tagged from here on. | 1158 // Note: rcx is tagged from here on. |
| 1168 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); | 1159 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); |
| 1169 __ Integer32ToSmi(rcx, rcx); | 1160 __ Integer32ToSmi(rcx, rcx); |
| 1170 __ movp(FieldOperand(rax, JSObject::kHeaderSize + | 1161 __ movp(FieldOperand(rax, JSObject::kHeaderSize + |
| 1171 Heap::kArgumentsLengthIndex * kPointerSize), | 1162 Heap::kArgumentsLengthIndex * kPointerSize), |
| 1172 rcx); | 1163 rcx); |
| 1173 | 1164 |
| 1174 // Set up the elements pointer in the allocated arguments object. | 1165 // Set up the elements pointer in the allocated arguments object. |
| 1175 // If we allocated a parameter map, edi will point there, otherwise to the | 1166 // If we allocated a parameter map, edi will point there, otherwise to the |
| 1176 // backing store. | 1167 // backing store. |
| 1177 __ lea(rdi, Operand(rax, Heap::kArgumentsObjectSize)); | 1168 __ lea(rdi, Operand(rax, Heap::kSloppyArgumentsObjectSize)); |
| 1178 __ movp(FieldOperand(rax, JSObject::kElementsOffset), rdi); | 1169 __ movp(FieldOperand(rax, JSObject::kElementsOffset), rdi); |
| 1179 | 1170 |
| 1180 // rax = address of new object (tagged) | 1171 // rax = address of new object (tagged) |
| 1181 // rbx = mapped parameter count (untagged) | 1172 // rbx = mapped parameter count (untagged) |
| 1182 // rcx = argument count (tagged) | 1173 // rcx = argument count (tagged) |
| 1183 // rdi = address of parameter map or backing store (tagged) | 1174 // rdi = address of parameter map or backing store (tagged) |
| 1184 | 1175 |
| 1185 // Initialize parameter map. If there are no mapped arguments, we're done. | 1176 // Initialize parameter map. If there are no mapped arguments, we're done. |
| 1186 Label skip_parameter_map; | 1177 Label skip_parameter_map; |
| 1187 __ testq(rbx, rbx); | 1178 __ testq(rbx, rbx); |
| 1188 __ j(zero, &skip_parameter_map); | 1179 __ j(zero, &skip_parameter_map); |
| 1189 | 1180 |
| 1190 __ LoadRoot(kScratchRegister, Heap::kNonStrictArgumentsElementsMapRootIndex); | 1181 __ LoadRoot(kScratchRegister, Heap::kSloppyArgumentsElementsMapRootIndex); |
| 1191 // rbx contains the untagged argument count. Add 2 and tag to write. | 1182 // rbx contains the untagged argument count. Add 2 and tag to write. |
| 1192 __ movp(FieldOperand(rdi, FixedArray::kMapOffset), kScratchRegister); | 1183 __ movp(FieldOperand(rdi, FixedArray::kMapOffset), kScratchRegister); |
| 1193 __ Integer64PlusConstantToSmi(r9, rbx, 2); | 1184 __ Integer64PlusConstantToSmi(r9, rbx, 2); |
| 1194 __ movp(FieldOperand(rdi, FixedArray::kLengthOffset), r9); | 1185 __ movp(FieldOperand(rdi, FixedArray::kLengthOffset), r9); |
| 1195 __ movp(FieldOperand(rdi, FixedArray::kHeaderSize + 0 * kPointerSize), rsi); | 1186 __ movp(FieldOperand(rdi, FixedArray::kHeaderSize + 0 * kPointerSize), rsi); |
| 1196 __ lea(r9, Operand(rdi, rbx, times_pointer_size, kParameterMapHeaderSize)); | 1187 __ lea(r9, Operand(rdi, rbx, times_pointer_size, kParameterMapHeaderSize)); |
| 1197 __ movp(FieldOperand(rdi, FixedArray::kHeaderSize + 1 * kPointerSize), r9); | 1188 __ movp(FieldOperand(rdi, FixedArray::kHeaderSize + 1 * kPointerSize), r9); |
| 1198 | 1189 |
| 1199 // Copy the parameter slots and the holes in the arguments. | 1190 // Copy the parameter slots and the holes in the arguments. |
| 1200 // We need to fill in mapped_parameter_count slots. They index the context, | 1191 // We need to fill in mapped_parameter_count slots. They index the context, |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1273 | 1264 |
| 1274 // Do the runtime call to allocate the arguments object. | 1265 // Do the runtime call to allocate the arguments object. |
| 1275 // rcx = argument count (untagged) | 1266 // rcx = argument count (untagged) |
| 1276 __ bind(&runtime); | 1267 __ bind(&runtime); |
| 1277 __ Integer32ToSmi(rcx, rcx); | 1268 __ Integer32ToSmi(rcx, rcx); |
| 1278 __ movp(args.GetArgumentOperand(2), rcx); // Patch argument count. | 1269 __ movp(args.GetArgumentOperand(2), rcx); // Patch argument count. |
| 1279 __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1); | 1270 __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1); |
| 1280 } | 1271 } |
| 1281 | 1272 |
| 1282 | 1273 |
| 1283 void ArgumentsAccessStub::GenerateNewNonStrictSlow(MacroAssembler* masm) { | 1274 void ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) { |
| 1284 // rsp[0] : return address | 1275 // rsp[0] : return address |
| 1285 // rsp[8] : number of parameters | 1276 // rsp[8] : number of parameters |
| 1286 // rsp[16] : receiver displacement | 1277 // rsp[16] : receiver displacement |
| 1287 // rsp[24] : function | 1278 // rsp[24] : function |
| 1288 | 1279 |
| 1289 // Check if the calling frame is an arguments adaptor frame. | 1280 // Check if the calling frame is an arguments adaptor frame. |
| 1290 Label runtime; | 1281 Label runtime; |
| 1291 __ movp(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); | 1282 __ movp(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); |
| 1292 __ movp(rcx, Operand(rdx, StandardFrameConstants::kContextOffset)); | 1283 __ movp(rcx, Operand(rdx, StandardFrameConstants::kContextOffset)); |
| 1293 __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); | 1284 __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1336 __ movp(args.GetArgumentOperand(1), rdx); | 1327 __ movp(args.GetArgumentOperand(1), rdx); |
| 1337 | 1328 |
| 1338 // Try the new space allocation. Start out with computing the size of | 1329 // Try the new space allocation. Start out with computing the size of |
| 1339 // the arguments object and the elements array. | 1330 // the arguments object and the elements array. |
| 1340 Label add_arguments_object; | 1331 Label add_arguments_object; |
| 1341 __ bind(&try_allocate); | 1332 __ bind(&try_allocate); |
| 1342 __ testq(rcx, rcx); | 1333 __ testq(rcx, rcx); |
| 1343 __ j(zero, &add_arguments_object, Label::kNear); | 1334 __ j(zero, &add_arguments_object, Label::kNear); |
| 1344 __ lea(rcx, Operand(rcx, times_pointer_size, FixedArray::kHeaderSize)); | 1335 __ lea(rcx, Operand(rcx, times_pointer_size, FixedArray::kHeaderSize)); |
| 1345 __ bind(&add_arguments_object); | 1336 __ bind(&add_arguments_object); |
| 1346 __ addq(rcx, Immediate(Heap::kArgumentsObjectSizeStrict)); | 1337 __ addq(rcx, Immediate(Heap::kStrictArgumentsObjectSize)); |
| 1347 | 1338 |
| 1348 // Do the allocation of both objects in one go. | 1339 // Do the allocation of both objects in one go. |
| 1349 __ Allocate(rcx, rax, rdx, rbx, &runtime, TAG_OBJECT); | 1340 __ Allocate(rcx, rax, rdx, rbx, &runtime, TAG_OBJECT); |
| 1350 | 1341 |
| 1351 // Get the arguments boilerplate from the current native context. | 1342 // Get the arguments boilerplate from the current native context. |
| 1352 __ movp(rdi, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | 1343 __ movp(rdi, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
| 1353 __ movp(rdi, FieldOperand(rdi, GlobalObject::kNativeContextOffset)); | 1344 __ movp(rdi, FieldOperand(rdi, GlobalObject::kNativeContextOffset)); |
| 1354 const int offset = | 1345 const int offset = |
| 1355 Context::SlotOffset(Context::STRICT_MODE_ARGUMENTS_BOILERPLATE_INDEX); | 1346 Context::SlotOffset(Context::STRICT_ARGUMENTS_BOILERPLATE_INDEX); |
| 1356 __ movp(rdi, Operand(rdi, offset)); | 1347 __ movp(rdi, Operand(rdi, offset)); |
| 1357 | 1348 |
| 1358 // Copy the JS object part. | 1349 // Copy the JS object part. |
| 1359 for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) { | 1350 for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) { |
| 1360 __ movp(rbx, FieldOperand(rdi, i)); | 1351 __ movp(rbx, FieldOperand(rdi, i)); |
| 1361 __ movp(FieldOperand(rax, i), rbx); | 1352 __ movp(FieldOperand(rax, i), rbx); |
| 1362 } | 1353 } |
| 1363 | 1354 |
| 1364 // Get the length (smi tagged) and set that as an in-object property too. | 1355 // Get the length (smi tagged) and set that as an in-object property too. |
| 1365 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); | 1356 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); |
| 1366 __ movp(rcx, args.GetArgumentOperand(2)); | 1357 __ movp(rcx, args.GetArgumentOperand(2)); |
| 1367 __ movp(FieldOperand(rax, JSObject::kHeaderSize + | 1358 __ movp(FieldOperand(rax, JSObject::kHeaderSize + |
| 1368 Heap::kArgumentsLengthIndex * kPointerSize), | 1359 Heap::kArgumentsLengthIndex * kPointerSize), |
| 1369 rcx); | 1360 rcx); |
| 1370 | 1361 |
| 1371 // If there are no actual arguments, we're done. | 1362 // If there are no actual arguments, we're done. |
| 1372 Label done; | 1363 Label done; |
| 1373 __ testq(rcx, rcx); | 1364 __ testq(rcx, rcx); |
| 1374 __ j(zero, &done); | 1365 __ j(zero, &done); |
| 1375 | 1366 |
| 1376 // Get the parameters pointer from the stack. | 1367 // Get the parameters pointer from the stack. |
| 1377 __ movp(rdx, args.GetArgumentOperand(1)); | 1368 __ movp(rdx, args.GetArgumentOperand(1)); |
| 1378 | 1369 |
| 1379 // Set up the elements pointer in the allocated arguments object and | 1370 // Set up the elements pointer in the allocated arguments object and |
| 1380 // initialize the header in the elements fixed array. | 1371 // initialize the header in the elements fixed array. |
| 1381 __ lea(rdi, Operand(rax, Heap::kArgumentsObjectSizeStrict)); | 1372 __ lea(rdi, Operand(rax, Heap::kStrictArgumentsObjectSize)); |
| 1382 __ movp(FieldOperand(rax, JSObject::kElementsOffset), rdi); | 1373 __ movp(FieldOperand(rax, JSObject::kElementsOffset), rdi); |
| 1383 __ LoadRoot(kScratchRegister, Heap::kFixedArrayMapRootIndex); | 1374 __ LoadRoot(kScratchRegister, Heap::kFixedArrayMapRootIndex); |
| 1384 __ movp(FieldOperand(rdi, FixedArray::kMapOffset), kScratchRegister); | 1375 __ movp(FieldOperand(rdi, FixedArray::kMapOffset), kScratchRegister); |
| 1385 | 1376 |
| 1386 | 1377 |
| 1387 __ movp(FieldOperand(rdi, FixedArray::kLengthOffset), rcx); | 1378 __ movp(FieldOperand(rdi, FixedArray::kLengthOffset), rcx); |
| 1388 // Untag the length for the loop below. | 1379 // Untag the length for the loop below. |
| 1389 __ SmiToInteger64(rcx, rcx); | 1380 __ SmiToInteger64(rcx, rcx); |
| 1390 | 1381 |
| 1391 // Copy the fixed array slots. | 1382 // Copy the fixed array slots. |
| (...skipping 868 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2260 | 2251 |
| 2261 __ bind(&done); | 2252 __ bind(&done); |
| 2262 __ Integer32ToSmi(rdx, rdx); | 2253 __ Integer32ToSmi(rdx, rdx); |
| 2263 | 2254 |
| 2264 __ bind(&done_no_smi_convert); | 2255 __ bind(&done_no_smi_convert); |
| 2265 } | 2256 } |
| 2266 | 2257 |
| 2267 | 2258 |
| 2268 void CallFunctionStub::Generate(MacroAssembler* masm) { | 2259 void CallFunctionStub::Generate(MacroAssembler* masm) { |
| 2269 // rbx : feedback vector | 2260 // rbx : feedback vector |
| 2270 // rdx : (only if rbx is not undefined) slot in feedback vector (Smi) | 2261 // rdx : (only if rbx is not the megamorphic symbol) slot in feedback |
| 2262 // vector (Smi) |
| 2271 // rdi : the function to call | 2263 // rdi : the function to call |
| 2272 Isolate* isolate = masm->isolate(); | 2264 Isolate* isolate = masm->isolate(); |
| 2273 Label slow, non_function, wrap, cont; | 2265 Label slow, non_function, wrap, cont; |
| 2274 StackArgumentsAccessor args(rsp, argc_); | 2266 StackArgumentsAccessor args(rsp, argc_); |
| 2275 | 2267 |
| 2276 if (NeedsChecks()) { | 2268 if (NeedsChecks()) { |
| 2277 // Check that the function really is a JavaScript function. | 2269 // Check that the function really is a JavaScript function. |
| 2278 __ JumpIfSmi(rdi, &non_function); | 2270 __ JumpIfSmi(rdi, &non_function); |
| 2279 | 2271 |
| 2280 // Goto slow case if we do not have a function. | 2272 // Goto slow case if we do not have a function. |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2320 __ bind(&cont); | 2312 __ bind(&cont); |
| 2321 } | 2313 } |
| 2322 __ InvokeFunction(rdi, actual, JUMP_FUNCTION, NullCallWrapper()); | 2314 __ InvokeFunction(rdi, actual, JUMP_FUNCTION, NullCallWrapper()); |
| 2323 | 2315 |
| 2324 if (NeedsChecks()) { | 2316 if (NeedsChecks()) { |
| 2325 // Slow-case: Non-function called. | 2317 // Slow-case: Non-function called. |
| 2326 __ bind(&slow); | 2318 __ bind(&slow); |
| 2327 if (RecordCallTarget()) { | 2319 if (RecordCallTarget()) { |
| 2328 // If there is a call target cache, mark it megamorphic in the | 2320 // If there is a call target cache, mark it megamorphic in the |
| 2329 // non-function case. MegamorphicSentinel is an immortal immovable | 2321 // non-function case. MegamorphicSentinel is an immortal immovable |
| 2330 // object (undefined) so no write barrier is needed. | 2322 // object (megamorphic symbol) so no write barrier is needed. |
| 2331 __ SmiToInteger32(rdx, rdx); | 2323 __ SmiToInteger32(rdx, rdx); |
| 2332 __ Move(FieldOperand(rbx, rdx, times_pointer_size, | 2324 __ Move(FieldOperand(rbx, rdx, times_pointer_size, |
| 2333 FixedArray::kHeaderSize), | 2325 FixedArray::kHeaderSize), |
| 2334 TypeFeedbackInfo::MegamorphicSentinel(isolate)); | 2326 TypeFeedbackInfo::MegamorphicSentinel(isolate)); |
| 2335 __ Integer32ToSmi(rdx, rdx); | 2327 __ Integer32ToSmi(rdx, rdx); |
| 2336 } | 2328 } |
| 2337 // Check for function proxy. | 2329 // Check for function proxy. |
| 2338 __ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE); | 2330 __ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE); |
| 2339 __ j(not_equal, &non_function); | 2331 __ j(not_equal, &non_function); |
| 2340 __ PopReturnAddressTo(rcx); | 2332 __ PopReturnAddressTo(rcx); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2372 } | 2364 } |
| 2373 __ movp(args.GetReceiverOperand(), rax); | 2365 __ movp(args.GetReceiverOperand(), rax); |
| 2374 __ jmp(&cont); | 2366 __ jmp(&cont); |
| 2375 } | 2367 } |
| 2376 } | 2368 } |
| 2377 | 2369 |
| 2378 | 2370 |
| 2379 void CallConstructStub::Generate(MacroAssembler* masm) { | 2371 void CallConstructStub::Generate(MacroAssembler* masm) { |
| 2380 // rax : number of arguments | 2372 // rax : number of arguments |
| 2381 // rbx : feedback vector | 2373 // rbx : feedback vector |
| 2382 // rdx : (only if rbx is not undefined) slot in feedback vector (Smi) | 2374 // rdx : (only if rbx is not the megamorphic symbol) slot in feedback |
| 2375 // vector (Smi) |
| 2383 // rdi : constructor function | 2376 // rdi : constructor function |
| 2384 Label slow, non_function_call; | 2377 Label slow, non_function_call; |
| 2385 | 2378 |
| 2386 // Check that function is not a smi. | 2379 // Check that function is not a smi. |
| 2387 __ JumpIfSmi(rdi, &non_function_call); | 2380 __ JumpIfSmi(rdi, &non_function_call); |
| 2388 // Check that function is a JSFunction. | 2381 // Check that function is a JSFunction. |
| 2389 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); | 2382 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); |
| 2390 __ j(not_equal, &slow); | 2383 __ j(not_equal, &slow); |
| 2391 | 2384 |
| 2392 if (RecordCallTarget()) { | 2385 if (RecordCallTarget()) { |
| (...skipping 2137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4530 __ CheckPageFlag(regs_.object(), | 4523 __ CheckPageFlag(regs_.object(), |
| 4531 regs_.scratch0(), | 4524 regs_.scratch0(), |
| 4532 1 << MemoryChunk::SCAN_ON_SCAVENGE, | 4525 1 << MemoryChunk::SCAN_ON_SCAVENGE, |
| 4533 not_zero, | 4526 not_zero, |
| 4534 &dont_need_remembered_set); | 4527 &dont_need_remembered_set); |
| 4535 | 4528 |
| 4536 // First notify the incremental marker if necessary, then update the | 4529 // First notify the incremental marker if necessary, then update the |
| 4537 // remembered set. | 4530 // remembered set. |
| 4538 CheckNeedsToInformIncrementalMarker( | 4531 CheckNeedsToInformIncrementalMarker( |
| 4539 masm, kUpdateRememberedSetOnNoNeedToInformIncrementalMarker, mode); | 4532 masm, kUpdateRememberedSetOnNoNeedToInformIncrementalMarker, mode); |
| 4540 InformIncrementalMarker(masm, mode); | 4533 InformIncrementalMarker(masm); |
| 4541 regs_.Restore(masm); | 4534 regs_.Restore(masm); |
| 4542 __ RememberedSetHelper(object_, | 4535 __ RememberedSetHelper(object_, |
| 4543 address_, | 4536 address_, |
| 4544 value_, | 4537 value_, |
| 4545 save_fp_regs_mode_, | 4538 save_fp_regs_mode_, |
| 4546 MacroAssembler::kReturnAtEnd); | 4539 MacroAssembler::kReturnAtEnd); |
| 4547 | 4540 |
| 4548 __ bind(&dont_need_remembered_set); | 4541 __ bind(&dont_need_remembered_set); |
| 4549 } | 4542 } |
| 4550 | 4543 |
| 4551 CheckNeedsToInformIncrementalMarker( | 4544 CheckNeedsToInformIncrementalMarker( |
| 4552 masm, kReturnOnNoNeedToInformIncrementalMarker, mode); | 4545 masm, kReturnOnNoNeedToInformIncrementalMarker, mode); |
| 4553 InformIncrementalMarker(masm, mode); | 4546 InformIncrementalMarker(masm); |
| 4554 regs_.Restore(masm); | 4547 regs_.Restore(masm); |
| 4555 __ ret(0); | 4548 __ ret(0); |
| 4556 } | 4549 } |
| 4557 | 4550 |
| 4558 | 4551 |
| 4559 void RecordWriteStub::InformIncrementalMarker(MacroAssembler* masm, Mode mode) { | 4552 void RecordWriteStub::InformIncrementalMarker(MacroAssembler* masm) { |
| 4560 regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode_); | 4553 regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode_); |
| 4561 Register address = | 4554 Register address = |
| 4562 arg_reg_1.is(regs_.address()) ? kScratchRegister : regs_.address(); | 4555 arg_reg_1.is(regs_.address()) ? kScratchRegister : regs_.address(); |
| 4563 ASSERT(!address.is(regs_.object())); | 4556 ASSERT(!address.is(regs_.object())); |
| 4564 ASSERT(!address.is(arg_reg_1)); | 4557 ASSERT(!address.is(arg_reg_1)); |
| 4565 __ Move(address, regs_.address()); | 4558 __ Move(address, regs_.address()); |
| 4566 __ Move(arg_reg_1, regs_.object()); | 4559 __ Move(arg_reg_1, regs_.object()); |
| 4567 // TODO(gc) Can we just set address arg2 in the beginning? | 4560 // TODO(gc) Can we just set address arg2 in the beginning? |
| 4568 __ Move(arg_reg_2, address); | 4561 __ Move(arg_reg_2, address); |
| 4569 __ LoadAddress(arg_reg_3, | 4562 __ LoadAddress(arg_reg_3, |
| 4570 ExternalReference::isolate_address(masm->isolate())); | 4563 ExternalReference::isolate_address(masm->isolate())); |
| 4571 int argument_count = 3; | 4564 int argument_count = 3; |
| 4572 | 4565 |
| 4573 AllowExternalCallThatCantCauseGC scope(masm); | 4566 AllowExternalCallThatCantCauseGC scope(masm); |
| 4574 __ PrepareCallCFunction(argument_count); | 4567 __ PrepareCallCFunction(argument_count); |
| 4575 if (mode == INCREMENTAL_COMPACTION) { | 4568 __ CallCFunction( |
| 4576 __ CallCFunction( | 4569 ExternalReference::incremental_marking_record_write_function( |
| 4577 ExternalReference::incremental_evacuation_record_write_function( | 4570 masm->isolate()), |
| 4578 masm->isolate()), | 4571 argument_count); |
| 4579 argument_count); | |
| 4580 } else { | |
| 4581 ASSERT(mode == INCREMENTAL); | |
| 4582 __ CallCFunction( | |
| 4583 ExternalReference::incremental_marking_record_write_function( | |
| 4584 masm->isolate()), | |
| 4585 argument_count); | |
| 4586 } | |
| 4587 regs_.RestoreCallerSaveRegisters(masm, save_fp_regs_mode_); | 4572 regs_.RestoreCallerSaveRegisters(masm, save_fp_regs_mode_); |
| 4588 } | 4573 } |
| 4589 | 4574 |
| 4590 | 4575 |
| 4591 void RecordWriteStub::CheckNeedsToInformIncrementalMarker( | 4576 void RecordWriteStub::CheckNeedsToInformIncrementalMarker( |
| 4592 MacroAssembler* masm, | 4577 MacroAssembler* masm, |
| 4593 OnNoNeedToInformIncrementalMarker on_no_need, | 4578 OnNoNeedToInformIncrementalMarker on_no_need, |
| 4594 Mode mode) { | 4579 Mode mode) { |
| 4595 Label on_black; | 4580 Label on_black; |
| 4596 Label need_incremental; | 4581 Label need_incremental; |
| (...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4996 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); | 4981 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); |
| 4997 } else { | 4982 } else { |
| 4998 UNREACHABLE(); | 4983 UNREACHABLE(); |
| 4999 } | 4984 } |
| 5000 } | 4985 } |
| 5001 | 4986 |
| 5002 | 4987 |
| 5003 void ArrayConstructorStub::Generate(MacroAssembler* masm) { | 4988 void ArrayConstructorStub::Generate(MacroAssembler* masm) { |
| 5004 // ----------- S t a t e ------------- | 4989 // ----------- S t a t e ------------- |
| 5005 // -- rax : argc | 4990 // -- rax : argc |
| 5006 // -- rbx : feedback vector (fixed array or undefined) | 4991 // -- rbx : feedback vector (fixed array or megamorphic symbol) |
| 5007 // -- rdx : slot index (if ebx is fixed array) | 4992 // -- rdx : slot index (if ebx is fixed array) |
| 5008 // -- rdi : constructor | 4993 // -- rdi : constructor |
| 5009 // -- rsp[0] : return address | 4994 // -- rsp[0] : return address |
| 5010 // -- rsp[8] : last argument | 4995 // -- rsp[8] : last argument |
| 5011 // ----------------------------------- | 4996 // ----------------------------------- |
| 5012 Handle<Object> undefined_sentinel( | 4997 Handle<Object> megamorphic_sentinel = |
| 5013 masm->isolate()->heap()->undefined_value(), | 4998 TypeFeedbackInfo::MegamorphicSentinel(masm->isolate()); |
| 5014 masm->isolate()); | |
| 5015 | 4999 |
| 5016 if (FLAG_debug_code) { | 5000 if (FLAG_debug_code) { |
| 5017 // The array construct code is only set for the global and natives | 5001 // The array construct code is only set for the global and natives |
| 5018 // builtin Array functions which always have maps. | 5002 // builtin Array functions which always have maps. |
| 5019 | 5003 |
| 5020 // Initial map for the builtin Array function should be a map. | 5004 // Initial map for the builtin Array function should be a map. |
| 5021 __ movp(rcx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset)); | 5005 __ movp(rcx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset)); |
| 5022 // Will both indicate a NULL and a Smi. | 5006 // Will both indicate a NULL and a Smi. |
| 5023 STATIC_ASSERT(kSmiTag == 0); | 5007 STATIC_ASSERT(kSmiTag == 0); |
| 5024 Condition not_smi = NegateCondition(masm->CheckSmi(rcx)); | 5008 Condition not_smi = NegateCondition(masm->CheckSmi(rcx)); |
| 5025 __ Check(not_smi, kUnexpectedInitialMapForArrayFunction); | 5009 __ Check(not_smi, kUnexpectedInitialMapForArrayFunction); |
| 5026 __ CmpObjectType(rcx, MAP_TYPE, rcx); | 5010 __ CmpObjectType(rcx, MAP_TYPE, rcx); |
| 5027 __ Check(equal, kUnexpectedInitialMapForArrayFunction); | 5011 __ Check(equal, kUnexpectedInitialMapForArrayFunction); |
| 5028 | 5012 |
| 5029 // We should either have undefined in rbx or a valid fixed array. | 5013 // We should either have the megamorphic symbol in rbx or a valid |
| 5014 // fixed array. |
| 5030 Label okay_here; | 5015 Label okay_here; |
| 5031 Handle<Map> fixed_array_map = masm->isolate()->factory()->fixed_array_map(); | 5016 Handle<Map> fixed_array_map = masm->isolate()->factory()->fixed_array_map(); |
| 5032 __ Cmp(rbx, undefined_sentinel); | 5017 __ Cmp(rbx, megamorphic_sentinel); |
| 5033 __ j(equal, &okay_here); | 5018 __ j(equal, &okay_here); |
| 5034 __ Cmp(FieldOperand(rbx, 0), fixed_array_map); | 5019 __ Cmp(FieldOperand(rbx, 0), fixed_array_map); |
| 5035 __ Assert(equal, kExpectedFixedArrayInRegisterRbx); | 5020 __ Assert(equal, kExpectedFixedArrayInRegisterRbx); |
| 5036 | 5021 |
| 5037 // rdx should be a smi if we don't have undefined in rbx. | 5022 // rdx should be a smi if we don't have the megamorphic symbol in rbx. |
| 5038 __ AssertSmi(rdx); | 5023 __ AssertSmi(rdx); |
| 5039 | 5024 |
| 5040 __ bind(&okay_here); | 5025 __ bind(&okay_here); |
| 5041 } | 5026 } |
| 5042 | 5027 |
| 5043 Label no_info; | 5028 Label no_info; |
| 5044 // If the feedback slot is undefined, or contains anything other than an | 5029 // If the feedback slot is the megamorphic sentinel, or contains anything |
| 5045 // AllocationSite, call an array constructor that doesn't use AllocationSites. | 5030 // other than an AllocationSite, call an array constructor that doesn't use |
| 5046 __ Cmp(rbx, undefined_sentinel); | 5031 // AllocationSites. |
| 5032 __ Cmp(rbx, megamorphic_sentinel); |
| 5047 __ j(equal, &no_info); | 5033 __ j(equal, &no_info); |
| 5048 __ SmiToInteger32(rdx, rdx); | 5034 __ SmiToInteger32(rdx, rdx); |
| 5049 __ movp(rbx, FieldOperand(rbx, rdx, times_pointer_size, | 5035 __ movp(rbx, FieldOperand(rbx, rdx, times_pointer_size, |
| 5050 FixedArray::kHeaderSize)); | 5036 FixedArray::kHeaderSize)); |
| 5051 __ Integer32ToSmi(rdx, rdx); | 5037 __ Integer32ToSmi(rdx, rdx); |
| 5052 __ Cmp(FieldOperand(rbx, 0), | 5038 __ Cmp(FieldOperand(rbx, 0), |
| 5053 masm->isolate()->factory()->allocation_site_map()); | 5039 masm->isolate()->factory()->allocation_site_map()); |
| 5054 __ j(not_equal, &no_info); | 5040 __ j(not_equal, &no_info); |
| 5055 | 5041 |
| 5056 // Only look at the lower 16 bits of the transition info. | 5042 // Only look at the lower 16 bits of the transition info. |
| (...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5329 return_value_operand, | 5315 return_value_operand, |
| 5330 NULL); | 5316 NULL); |
| 5331 } | 5317 } |
| 5332 | 5318 |
| 5333 | 5319 |
| 5334 #undef __ | 5320 #undef __ |
| 5335 | 5321 |
| 5336 } } // namespace v8::internal | 5322 } } // namespace v8::internal |
| 5337 | 5323 |
| 5338 #endif // V8_TARGET_ARCH_X64 | 5324 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |