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 |
11 // with the distribution. | 11 // with the distribution. |
12 // * Neither the name of Google Inc. nor the names of its | 12 // * Neither the name of Google Inc. nor the names of its |
13 // contributors may be used to endorse or promote products derived | 13 // contributors may be used to endorse or promote products derived |
14 // from this software without specific prior written permission. | 14 // from this software without specific prior written permission. |
15 // | 15 // |
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
28 #include "v8.h" | 28 #include "v8.h" |
29 | 29 |
30 #if defined(V8_TARGET_ARCH_A64) | 30 #if V8_TARGET_ARCH_A64 |
31 | 31 |
32 #include "bootstrapper.h" | 32 #include "bootstrapper.h" |
33 #include "code-stubs.h" | 33 #include "code-stubs.h" |
34 #include "regexp-macro-assembler.h" | 34 #include "regexp-macro-assembler.h" |
35 #include "stub-cache.h" | 35 #include "stub-cache.h" |
36 | 36 |
37 namespace v8 { | 37 namespace v8 { |
38 namespace internal { | 38 namespace internal { |
39 | 39 |
40 | 40 |
(...skipping 19 matching lines...) Expand all Loading... |
60 // x1: constant properties | 60 // x1: constant properties |
61 // x0: object literal flags | 61 // x0: object literal flags |
62 static Register registers[] = { x3, x2, x1, x0 }; | 62 static Register registers[] = { x3, x2, x1, x0 }; |
63 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]); | 63 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]); |
64 descriptor->register_params_ = registers; | 64 descriptor->register_params_ = registers; |
65 descriptor->deoptimization_handler_ = | 65 descriptor->deoptimization_handler_ = |
66 Runtime::FunctionForId(Runtime::kCreateObjectLiteralShallow)->entry; | 66 Runtime::FunctionForId(Runtime::kCreateObjectLiteralShallow)->entry; |
67 } | 67 } |
68 | 68 |
69 | 69 |
| 70 void CreateAllocationSiteStub::InitializeInterfaceDescriptor( |
| 71 Isolate* isolate, |
| 72 CodeStubInterfaceDescriptor* descriptor) { |
| 73 // x2: cache cell |
| 74 static Register registers[] = { x2 }; |
| 75 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]); |
| 76 descriptor->register_params_ = registers; |
| 77 descriptor->deoptimization_handler_ = NULL; |
| 78 } |
| 79 |
| 80 |
70 void KeyedLoadFastElementStub::InitializeInterfaceDescriptor( | 81 void KeyedLoadFastElementStub::InitializeInterfaceDescriptor( |
71 Isolate* isolate, | 82 Isolate* isolate, |
72 CodeStubInterfaceDescriptor* descriptor) { | 83 CodeStubInterfaceDescriptor* descriptor) { |
73 // x1: receiver | 84 // x1: receiver |
74 // x0: key | 85 // x0: key |
75 static Register registers[] = { x1, x0 }; | 86 static Register registers[] = { x1, x0 }; |
76 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]); | 87 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]); |
77 descriptor->register_params_ = registers; | 88 descriptor->register_params_ = registers; |
78 descriptor->deoptimization_handler_ = | 89 descriptor->deoptimization_handler_ = |
79 FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure); | 90 FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure); |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
233 // x0: value | 244 // x0: value |
234 static Register registers[] = { x0 }; | 245 static Register registers[] = { x0 }; |
235 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]); | 246 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]); |
236 descriptor->register_params_ = registers; | 247 descriptor->register_params_ = registers; |
237 descriptor->deoptimization_handler_ = FUNCTION_ADDR(ToBooleanIC_Miss); | 248 descriptor->deoptimization_handler_ = FUNCTION_ADDR(ToBooleanIC_Miss); |
238 descriptor->SetMissHandler( | 249 descriptor->SetMissHandler( |
239 ExternalReference(IC_Utility(IC::kToBooleanIC_Miss), isolate)); | 250 ExternalReference(IC_Utility(IC::kToBooleanIC_Miss), isolate)); |
240 } | 251 } |
241 | 252 |
242 | 253 |
| 254 void UnaryOpStub::InitializeInterfaceDescriptor( |
| 255 Isolate* isolate, |
| 256 CodeStubInterfaceDescriptor* descriptor) { |
| 257 // x0: value |
| 258 static Register registers[] = { x0 }; |
| 259 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]); |
| 260 descriptor->register_params_ = registers; |
| 261 descriptor->deoptimization_handler_ = FUNCTION_ADDR(UnaryOpIC_Miss); |
| 262 } |
| 263 |
| 264 |
| 265 void StoreGlobalStub::InitializeInterfaceDescriptor( |
| 266 Isolate* isolate, |
| 267 CodeStubInterfaceDescriptor* descriptor) { |
| 268 // x1: receiver |
| 269 // x2: key (unused) |
| 270 // x0: value |
| 271 static Register registers[] = { x1, x2, x0 }; |
| 272 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]); |
| 273 descriptor->register_params_ = registers; |
| 274 descriptor->deoptimization_handler_ = |
| 275 FUNCTION_ADDR(StoreIC_MissFromStubFailure); |
| 276 } |
| 277 |
| 278 |
243 #define __ ACCESS_MASM(masm) | 279 #define __ ACCESS_MASM(masm) |
244 | 280 |
245 | 281 |
246 void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm) { | 282 void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm) { |
247 // Update the static counter each time a new code stub is generated. | 283 // Update the static counter each time a new code stub is generated. |
248 Isolate* isolate = masm->isolate(); | 284 Isolate* isolate = masm->isolate(); |
249 isolate->counters()->code_stubs()->Increment(); | 285 isolate->counters()->code_stubs()->Increment(); |
250 | 286 |
251 CodeStubInterfaceDescriptor* descriptor = GetInterfaceDescriptor(isolate); | 287 CodeStubInterfaceDescriptor* descriptor = GetInterfaceDescriptor(isolate); |
252 int param_count = descriptor->register_param_count_; | 288 int param_count = descriptor->register_param_count_; |
(...skipping 787 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1040 } | 1076 } |
1041 | 1077 |
1042 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) | 1078 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) |
1043 // tagged as a small integer. | 1079 // tagged as a small integer. |
1044 __ InvokeBuiltin(native, JUMP_FUNCTION); | 1080 __ InvokeBuiltin(native, JUMP_FUNCTION); |
1045 | 1081 |
1046 __ Bind(&miss); | 1082 __ Bind(&miss); |
1047 GenerateMiss(masm); | 1083 GenerateMiss(masm); |
1048 } | 1084 } |
1049 | 1085 |
| 1086 |
1050 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) { | 1087 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) { |
1051 // Preserve caller-saved registers x0-x7 and x10-x15. We don't care if x8, x9, | 1088 // Preserve caller-saved registers x0-x7 and x10-x15. We don't care if x8, x9, |
1052 // ip0 and ip1 are corrupted by the call into C. | 1089 // ip0 and ip1 are corrupted by the call into C. |
1053 CPURegList saved_regs = kCallerSaved; | 1090 CPURegList saved_regs = kCallerSaved; |
1054 saved_regs.Remove(ip0); | 1091 saved_regs.Remove(ip0); |
1055 saved_regs.Remove(ip1); | 1092 saved_regs.Remove(ip1); |
1056 saved_regs.Remove(x8); | 1093 saved_regs.Remove(x8); |
1057 saved_regs.Remove(x9); | 1094 saved_regs.Remove(x9); |
1058 | 1095 |
1059 // We don't allow a GC during a store buffer overflow so there is no need to | 1096 // We don't allow a GC during a store buffer overflow so there is no need to |
(...skipping 20 matching lines...) Expand all Loading... |
1080 | 1117 |
1081 void StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime( | 1118 void StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime( |
1082 Isolate* isolate) { | 1119 Isolate* isolate) { |
1083 StoreBufferOverflowStub stub1(kDontSaveFPRegs); | 1120 StoreBufferOverflowStub stub1(kDontSaveFPRegs); |
1084 stub1.GetCode(isolate)->set_is_pregenerated(true); | 1121 stub1.GetCode(isolate)->set_is_pregenerated(true); |
1085 StoreBufferOverflowStub stub2(kSaveFPRegs); | 1122 StoreBufferOverflowStub stub2(kSaveFPRegs); |
1086 stub2.GetCode(isolate)->set_is_pregenerated(true); | 1123 stub2.GetCode(isolate)->set_is_pregenerated(true); |
1087 } | 1124 } |
1088 | 1125 |
1089 | 1126 |
1090 void UnaryOpStub::PrintName(StringStream* stream) { | |
1091 const char* op_name = Token::Name(op_); | |
1092 const char* overwrite_name = NULL; | |
1093 switch (mode_) { | |
1094 case UNARY_NO_OVERWRITE: | |
1095 overwrite_name = "Alloc"; | |
1096 break; | |
1097 case UNARY_OVERWRITE: | |
1098 overwrite_name = "Overwrite"; | |
1099 break; | |
1100 default: | |
1101 UNREACHABLE(); | |
1102 } | |
1103 stream->Add("UnaryOpStub_%s_%s_%s", | |
1104 op_name, | |
1105 overwrite_name, | |
1106 UnaryOpIC::GetName(operand_type_)); | |
1107 } | |
1108 | |
1109 | |
1110 void UnaryOpStub::Generate(MacroAssembler* masm) { | |
1111 switch (operand_type_) { | |
1112 case UnaryOpIC::UNINITIALIZED: | |
1113 GenerateTypeTransition(masm); | |
1114 break; | |
1115 case UnaryOpIC::SMI: | |
1116 GenerateSmiStub(masm); | |
1117 break; | |
1118 case UnaryOpIC::NUMBER: | |
1119 GenerateNumberStub(masm); | |
1120 break; | |
1121 case UnaryOpIC::GENERIC: | |
1122 GenerateGenericStub(masm); | |
1123 break; | |
1124 } | |
1125 } | |
1126 | |
1127 | |
1128 void UnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) { | |
1129 __ Mov(x1, Operand(Smi::FromInt(op_))); | |
1130 __ Mov(x2, Operand(Smi::FromInt(mode_))); | |
1131 __ Mov(x3, Operand(Smi::FromInt(operand_type_))); | |
1132 // x0 contains the operand | |
1133 __ Push(x0, x1, x2, x3); | |
1134 | |
1135 __ TailCallExternalReference( | |
1136 ExternalReference(IC_Utility(IC::kUnaryOp_Patch), masm->isolate()), 4, 1); | |
1137 } | |
1138 | |
1139 | |
1140 void UnaryOpStub::GenerateSmiStub(MacroAssembler* masm) { | |
1141 switch (op_) { | |
1142 case Token::SUB: | |
1143 GenerateSmiStubSub(masm); | |
1144 break; | |
1145 case Token::BIT_NOT: | |
1146 GenerateSmiStubBitNot(masm); | |
1147 break; | |
1148 default: | |
1149 UNREACHABLE(); | |
1150 } | |
1151 } | |
1152 | |
1153 | |
1154 void UnaryOpStub::GenerateSmiStubSub(MacroAssembler* masm) { | |
1155 Label non_smi, slow; | |
1156 GenerateSmiCodeSub(masm, &non_smi, &slow); | |
1157 __ Bind(&non_smi); | |
1158 __ Bind(&slow); | |
1159 GenerateTypeTransition(masm); | |
1160 } | |
1161 | |
1162 | |
1163 void UnaryOpStub::GenerateSmiStubBitNot(MacroAssembler* masm) { | |
1164 Label non_smi; | |
1165 GenerateSmiCodeBitNot(masm, &non_smi); | |
1166 __ Bind(&non_smi); | |
1167 GenerateTypeTransition(masm); | |
1168 } | |
1169 | |
1170 | |
1171 void UnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm, | |
1172 Label* non_smi, | |
1173 Label* slow) { | |
1174 __ JumpIfNotSmi(x0, non_smi); | |
1175 | |
1176 // The result of negating zero or the smallest negative smi is not a smi. | |
1177 __ Ands(x1, x0, 0x7fffffff00000000UL); | |
1178 __ B(eq, slow); | |
1179 | |
1180 __ Neg(x0, x0); | |
1181 __ Ret(); | |
1182 } | |
1183 | |
1184 | |
1185 void UnaryOpStub::GenerateSmiCodeBitNot(MacroAssembler* masm, | |
1186 Label* non_smi) { | |
1187 __ JumpIfNotSmi(x0, non_smi); | |
1188 | |
1189 // Eor the top 32 bits with 0xffffffff to invert. | |
1190 __ Eor(x0, x0, 0xffffffff00000000UL); | |
1191 __ Ret(); | |
1192 } | |
1193 | |
1194 | |
1195 void UnaryOpStub::GenerateNumberStub(MacroAssembler* masm) { | |
1196 switch (op_) { | |
1197 case Token::SUB: | |
1198 GenerateNumberStubSub(masm); | |
1199 break; | |
1200 case Token::BIT_NOT: | |
1201 GenerateNumberStubBitNot(masm); | |
1202 break; | |
1203 default: | |
1204 UNREACHABLE(); | |
1205 } | |
1206 } | |
1207 | |
1208 | |
1209 void UnaryOpStub::GenerateNumberStubSub(MacroAssembler* masm) { | |
1210 Label non_smi, slow, call_builtin; | |
1211 GenerateSmiCodeSub(masm, &non_smi, &call_builtin); | |
1212 __ Bind(&non_smi); | |
1213 GenerateHeapNumberCodeSub(masm, &slow); | |
1214 __ Bind(&slow); | |
1215 GenerateTypeTransition(masm); | |
1216 __ Bind(&call_builtin); | |
1217 __ Push(x0); | |
1218 __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_FUNCTION); | |
1219 } | |
1220 | |
1221 | |
1222 void UnaryOpStub::GenerateNumberStubBitNot(MacroAssembler* masm) { | |
1223 Label non_smi, slow; | |
1224 GenerateSmiCodeBitNot(masm, &non_smi); | |
1225 __ Bind(&non_smi); | |
1226 GenerateHeapNumberCodeBitNot(masm, &slow); | |
1227 __ Bind(&slow); | |
1228 GenerateTypeTransition(masm); | |
1229 } | |
1230 | |
1231 | |
1232 void UnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm, | |
1233 Label* slow) { | |
1234 Register heap_num = x0; | |
1235 Register heap_num_map = x1; | |
1236 | |
1237 __ LoadRoot(heap_num_map, Heap::kHeapNumberMapRootIndex); | |
1238 __ JumpIfNotHeapNumber(heap_num, slow, heap_num_map); | |
1239 | |
1240 if (mode_ == UNARY_OVERWRITE) { | |
1241 Register exponent = w2; | |
1242 | |
1243 // Flip the sign bit of the existing heap number. | |
1244 __ Ldr(exponent, FieldMemOperand(heap_num, HeapNumber::kExponentOffset)); | |
1245 __ Eor(exponent, exponent, HeapNumber::kSignMask); | |
1246 __ Str(exponent, FieldMemOperand(heap_num, HeapNumber::kExponentOffset)); | |
1247 } else { | |
1248 Register allocated_num = x0; | |
1249 Register double_bits = x2; | |
1250 Register heap_num_orig = x3; | |
1251 | |
1252 __ Mov(heap_num_orig, heap_num); | |
1253 | |
1254 // Create a new heap number. | |
1255 Label slow_allocate_heapnumber, heapnumber_allocated; | |
1256 __ AllocateHeapNumber(allocated_num, &slow_allocate_heapnumber, x6, x7, | |
1257 heap_num_map); | |
1258 __ B(&heapnumber_allocated); | |
1259 | |
1260 __ Bind(&slow_allocate_heapnumber); | |
1261 { | |
1262 FrameScope scope(masm, StackFrame::INTERNAL); | |
1263 __ Push(heap_num_orig); | |
1264 __ CallRuntime(Runtime::kNumberAlloc, 0); | |
1265 __ Pop(heap_num_orig); | |
1266 // allocated_num is x0, so contains the result of the runtime allocation. | |
1267 } | |
1268 | |
1269 __ Bind(&heapnumber_allocated); | |
1270 // Load the original heap number as a double precision float, and flip the | |
1271 // sign bit. | |
1272 STATIC_ASSERT(HeapNumber::kExponentOffset == | |
1273 (HeapNumber::kMantissaOffset + 4)); | |
1274 __ Ldr(double_bits, FieldMemOperand(heap_num_orig, | |
1275 HeapNumber::kMantissaOffset)); | |
1276 __ Eor(double_bits, double_bits, Double::kSignMask); | |
1277 | |
1278 // Store the negated double to the newly allocated heap number. | |
1279 __ Str(double_bits, FieldMemOperand(allocated_num, | |
1280 HeapNumber::kValueOffset)); | |
1281 } | |
1282 __ Ret(); | |
1283 } | |
1284 | |
1285 | |
1286 void UnaryOpStub::GenerateHeapNumberCodeBitNot(MacroAssembler* masm, | |
1287 Label* slow) { | |
1288 Register heap_num = x0; | |
1289 Register smi_num = x0; | |
1290 | |
1291 __ JumpIfNotHeapNumber(heap_num, slow); | |
1292 | |
1293 // Convert the heap number to a smi. | |
1294 __ HeapNumberECMA262ToInt32(smi_num, heap_num, x6, x7, d0, | |
1295 MacroAssembler::SMI); | |
1296 | |
1297 // Eor the top 32 bits with 0xffffffff to invert. | |
1298 __ Eor(x0, smi_num, 0xffffffff00000000UL); | |
1299 __ Ret(); | |
1300 } | |
1301 | |
1302 | |
1303 void UnaryOpStub::GenerateGenericStub(MacroAssembler* masm) { | |
1304 switch (op_) { | |
1305 case Token::SUB: { | |
1306 Label non_smi, slow; | |
1307 GenerateSmiCodeSub(masm, &non_smi, &slow); | |
1308 __ Bind(&non_smi); | |
1309 GenerateHeapNumberCodeSub(masm, &slow); | |
1310 __ Bind(&slow); | |
1311 __ Push(x0); | |
1312 __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_FUNCTION); | |
1313 break; | |
1314 } | |
1315 case Token::BIT_NOT: { | |
1316 Label non_smi, slow; | |
1317 GenerateSmiCodeBitNot(masm, &non_smi); | |
1318 __ Bind(&non_smi); | |
1319 GenerateHeapNumberCodeBitNot(masm, &slow); | |
1320 __ Bind(&slow); | |
1321 __ Push(x0); | |
1322 __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_FUNCTION); | |
1323 break; | |
1324 } | |
1325 default: | |
1326 UNREACHABLE(); | |
1327 } | |
1328 } | |
1329 | |
1330 | |
1331 void BinaryOpStub::Initialize() { | 1127 void BinaryOpStub::Initialize() { |
1332 // Nothing to do here. | 1128 // Nothing to do here. |
1333 } | 1129 } |
1334 | 1130 |
1335 | 1131 |
1336 void BinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) { | 1132 void BinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) { |
1337 ASM_LOCATION("BinaryOpStub::GenerateTypeTransition"); | 1133 ASM_LOCATION("BinaryOpStub::GenerateTypeTransition"); |
1338 Label get_result; | 1134 Label get_result; |
1339 | 1135 |
1340 __ Mov(x12, Operand(Smi::FromInt(MinorKey()))); | 1136 __ Mov(x12, Operand(Smi::FromInt(MinorKey()))); |
(...skipping 1160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2501 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { | 2297 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { |
2502 // It is important that the following stubs are generated in this order | 2298 // It is important that the following stubs are generated in this order |
2503 // because pregenerated stubs can only call other pregenerated stubs. | 2299 // because pregenerated stubs can only call other pregenerated stubs. |
2504 // RecordWriteStub uses StoreBufferOverflowStub, which in turn uses | 2300 // RecordWriteStub uses StoreBufferOverflowStub, which in turn uses |
2505 // CEntryStub. | 2301 // CEntryStub. |
2506 CEntryStub::GenerateAheadOfTime(isolate); | 2302 CEntryStub::GenerateAheadOfTime(isolate); |
2507 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); | 2303 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); |
2508 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); | 2304 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); |
2509 RecordWriteStub::GenerateFixedRegStubsAheadOfTime(isolate); | 2305 RecordWriteStub::GenerateFixedRegStubsAheadOfTime(isolate); |
2510 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate); | 2306 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate); |
| 2307 CreateAllocationSiteStub::GenerateAheadOfTime(isolate); |
2511 } | 2308 } |
2512 | 2309 |
2513 | 2310 |
2514 void CodeStub::GenerateFPStubs(Isolate* isolate) { | 2311 void CodeStub::GenerateFPStubs(Isolate* isolate) { |
2515 // Floating-point code doesn't get special handling in A64, so there's | 2312 // Floating-point code doesn't get special handling in A64, so there's |
2516 // nothing to do here. | 2313 // nothing to do here. |
2517 USE(isolate); | 2314 USE(isolate); |
2518 } | 2315 } |
2519 | 2316 |
2520 | 2317 |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2745 | 2542 |
2746 void CEntryStub::Generate(MacroAssembler* masm) { | 2543 void CEntryStub::Generate(MacroAssembler* masm) { |
2747 // The Abort mechanism relies on CallRuntime, which in turn relies on | 2544 // The Abort mechanism relies on CallRuntime, which in turn relies on |
2748 // CEntryStub, so until this stub has been generated, we have to use a | 2545 // CEntryStub, so until this stub has been generated, we have to use a |
2749 // fall-back Abort mechanism. | 2546 // fall-back Abort mechanism. |
2750 // | 2547 // |
2751 // Note that this stub must be generated before any use of Abort. | 2548 // Note that this stub must be generated before any use of Abort. |
2752 masm->set_use_real_aborts(false); | 2549 masm->set_use_real_aborts(false); |
2753 | 2550 |
2754 ASM_LOCATION("CEntryStub::Generate entry"); | 2551 ASM_LOCATION("CEntryStub::Generate entry"); |
| 2552 ProfileEntryHookStub::MaybeCallEntryHook(masm); |
| 2553 |
2755 // Register parameters: | 2554 // Register parameters: |
2756 // x0: argc (including receiver, untagged) | 2555 // x0: argc (including receiver, untagged) |
2757 // x1: target | 2556 // x1: target |
2758 // | 2557 // |
2759 // The stack on entry holds the arguments and the receiver, with the receiver | 2558 // The stack on entry holds the arguments and the receiver, with the receiver |
2760 // at the highest address: | 2559 // at the highest address: |
2761 // | 2560 // |
2762 // jssp]argc-1]: receiver | 2561 // jssp]argc-1]: receiver |
2763 // jssp[argc-2]: arg[argc-2] | 2562 // jssp[argc-2]: arg[argc-2] |
2764 // ... ... | 2563 // ... ... |
(...skipping 1705 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4470 ASSERT_EQ(*TypeFeedbackCells::UninitializedSentinel(masm->isolate()), | 4269 ASSERT_EQ(*TypeFeedbackCells::UninitializedSentinel(masm->isolate()), |
4471 masm->isolate()->heap()->the_hole_value()); | 4270 masm->isolate()->heap()->the_hole_value()); |
4472 | 4271 |
4473 // Load the cache state. | 4272 // Load the cache state. |
4474 __ Ldr(x3, FieldMemOperand(x2, Cell::kValueOffset)); | 4273 __ Ldr(x3, FieldMemOperand(x2, Cell::kValueOffset)); |
4475 | 4274 |
4476 // A monomorphic cache hit or an already megamorphic state: invoke the | 4275 // A monomorphic cache hit or an already megamorphic state: invoke the |
4477 // function without changing the state. | 4276 // function without changing the state. |
4478 __ Cmp(x3, x1); | 4277 __ Cmp(x3, x1); |
4479 __ B(eq, &done); | 4278 __ B(eq, &done); |
4480 __ JumpIfRoot(x3, Heap::kUndefinedValueRootIndex, &done); | |
4481 | 4279 |
4482 // Special handling of the Array() function, which caches not only the | 4280 // If we came here, we need to see if we are the array function. |
4483 // monomorphic Array function but the initial ElementsKind with special | 4281 // If we didn't have a matching function, and we didn't find the megamorph |
4484 // sentinels | 4282 // sentinel, then we have in the cell either some other function or an |
4485 Handle<Object> terminal_kind_sentinel = | 4283 // AllocationSite. Do a map check on the object in ecx. |
4486 TypeFeedbackCells::MonomorphicArraySentinel(masm->isolate(), | 4284 __ Ldr(x5, FieldMemOperand(x3, AllocationSite::kMapOffset)); |
4487 LAST_FAST_ELEMENTS_KIND); | 4285 __ JumpIfNotRoot(x5, Heap::kAllocationSiteMapRootIndex, &miss); |
4488 __ JumpIfNotSmi(x3, &miss); | 4286 |
4489 __ Cmp(x3, Operand(terminal_kind_sentinel)); | |
4490 __ B(gt, &miss); | |
4491 // Make sure the function is the Array() function | 4287 // Make sure the function is the Array() function |
4492 __ LoadArrayFunction(x3); | 4288 __ LoadArrayFunction(x3); |
4493 __ Cmp(x1, x3); | 4289 __ Cmp(x1, x3); |
4494 __ B(ne, &megamorphic); | 4290 __ B(ne, &megamorphic); |
4495 __ B(&done); | 4291 __ B(&done); |
4496 | 4292 |
4497 __ Bind(&miss); | 4293 __ Bind(&miss); |
4498 | 4294 |
4499 // A monomorphic miss (i.e, here the cache is not uninitialized) goes | 4295 // A monomorphic miss (i.e, here the cache is not uninitialized) goes |
4500 // megamorphic. | 4296 // megamorphic. |
4501 __ JumpIfRoot(x3, Heap::kTheHoleValueRootIndex, &initialize); | 4297 __ JumpIfRoot(x3, Heap::kTheHoleValueRootIndex, &initialize); |
4502 // MegamorphicSentinel is an immortal immovable object (undefined) so no | 4298 // MegamorphicSentinel is an immortal immovable object (undefined) so no |
4503 // write-barrier is needed. | 4299 // write-barrier is needed. |
4504 __ Bind(&megamorphic); | 4300 __ Bind(&megamorphic); |
4505 __ LoadRoot(x3, Heap::kUndefinedValueRootIndex); | 4301 __ LoadRoot(x3, Heap::kUndefinedValueRootIndex); |
4506 __ Str(x3, FieldMemOperand(x2, Cell::kValueOffset)); | 4302 __ Str(x3, FieldMemOperand(x2, Cell::kValueOffset)); |
4507 __ B(&done); | 4303 __ B(&done); |
4508 | 4304 |
4509 // An uninitialized cache is patched with the function or sentinel to | 4305 // An uninitialized cache is patched with the function or sentinel to |
4510 // indicate the ElementsKind if function is the Array constructor. | 4306 // indicate the ElementsKind if function is the Array constructor. |
4511 __ Bind(&initialize); | 4307 __ Bind(&initialize); |
4512 // Make sure the function is the Array() function | 4308 // Make sure the function is the Array() function |
4513 __ LoadArrayFunction(x3); | 4309 __ LoadArrayFunction(x3); |
4514 __ Cmp(x1, x3); | 4310 __ Cmp(x1, x3); |
4515 __ B(ne, ¬_array_function); | 4311 __ B(ne, ¬_array_function); |
4516 | 4312 |
4517 // The target function is the Array constructor, install a sentinel value in | 4313 // The target function is the Array constructor, |
4518 // the constructor's type info cell that will track the initial ElementsKind | 4314 // Create an AllocationSite if we don't already have it, store it in the cell |
4519 // that should be used for the array when its constructed. | 4315 { |
4520 Handle<Object> initial_kind_sentinel = | 4316 FrameScope scope(masm, StackFrame::INTERNAL); |
4521 TypeFeedbackCells::MonomorphicArraySentinel(masm->isolate(), | 4317 CreateAllocationSiteStub create_stub; |
4522 GetInitialFastElementsKind()); | 4318 __ Push(x0, x1, x2); |
4523 __ Mov(x3, Operand(initial_kind_sentinel)); | 4319 __ CallStub(&create_stub); |
4524 __ Str(x3, FieldMemOperand(x2, Cell::kValueOffset)); | 4320 __ Pop(x2, x1, x0); |
| 4321 } |
4525 __ B(&done); | 4322 __ B(&done); |
4526 | 4323 |
4527 __ Bind(¬_array_function); | 4324 __ Bind(¬_array_function); |
4528 // An uninitialized cache is patched with the function. | 4325 // An uninitialized cache is patched with the function. |
4529 __ Str(x1, FieldMemOperand(x2, Cell::kValueOffset)); | 4326 __ Str(x1, FieldMemOperand(x2, Cell::kValueOffset)); |
4530 // No need for a write barrier here - cells are rescanned. | 4327 // No need for a write barrier here - cells are rescanned. |
4531 | 4328 |
4532 __ Bind(&done); | 4329 __ Bind(&done); |
4533 } | 4330 } |
4534 | 4331 |
(...skipping 2080 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6615 } | 6412 } |
6616 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); | 6413 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); |
6617 __ Add(__ StackPointer(), __ StackPointer(), | 6414 __ Add(__ StackPointer(), __ StackPointer(), |
6618 Operand(x1, LSL, kPointerSizeLog2)); | 6415 Operand(x1, LSL, kPointerSizeLog2)); |
6619 // Return to IC Miss stub, continuation still on stack. | 6416 // Return to IC Miss stub, continuation still on stack. |
6620 __ Ret(); | 6417 __ Ret(); |
6621 } | 6418 } |
6622 | 6419 |
6623 | 6420 |
6624 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { | 6421 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { |
6625 if (entry_hook_ != NULL) { | 6422 if (masm->isolate()->function_entry_hook() != NULL) { |
6626 // TODO(all) this needs a literal pool blocking scope and predictable code | 6423 // TODO(all): This needs to be reliably consistent with |
6627 // size. | 6424 // kReturnAddressDistanceFromFunctionStart in ::Generate. |
| 6425 Assembler::BlockConstPoolScope no_const_pools(masm); |
| 6426 AllowStubCallsScope allow_stub_calls(masm, true); |
6628 ProfileEntryHookStub stub; | 6427 ProfileEntryHookStub stub; |
6629 __ Push(lr); | 6428 __ Push(lr); |
6630 __ CallStub(&stub); | 6429 __ CallStub(&stub); |
6631 __ Pop(lr); | 6430 __ Pop(lr); |
6632 } | 6431 } |
6633 } | 6432 } |
6634 | 6433 |
6635 | 6434 |
6636 void ProfileEntryHookStub::Generate(MacroAssembler* masm) { | 6435 void ProfileEntryHookStub::Generate(MacroAssembler* masm) { |
6637 // The entry hook is a "BumpSystemStackPointer" instruction (sub), followed by | 6436 // The entry hook is a "BumpSystemStackPointer" instruction (sub), followed by |
6638 // a "Push lr" instruction, followed by a call. | 6437 // a "Push lr" instruction, followed by a call. |
6639 // TODO(jbramley): Verify that this call is always made with relocation. | 6438 // TODO(jbramley): Verify that this call is always made with relocation. |
6640 static const int kReturnAddressDistanceFromFunctionStart = | 6439 static const int kReturnAddressDistanceFromFunctionStart = |
6641 Assembler::kCallSizeWithRelocation + (2 * kInstructionSize); | 6440 Assembler::kCallSizeWithRelocation + (2 * kInstructionSize); |
6642 | 6441 |
6643 // Save live volatile registers. | 6442 // Save all kCallerSaved registers (including lr), since this can be called |
6644 __ Push(lr, x1, x5); | 6443 // from anywhere. |
6645 static const int kNumSavedRegs = 3; | 6444 // TODO(jbramley): What about FP registers? |
| 6445 __ PushCPURegList(kCallerSaved); |
| 6446 ASSERT(kCallerSaved.IncludesAliasOf(lr)); |
| 6447 const int kNumSavedRegs = kCallerSaved.Count(); |
6646 | 6448 |
6647 // Compute the function's address as the first argument. | 6449 // Compute the function's address as the first argument. |
6648 __ Sub(x0, lr, kReturnAddressDistanceFromFunctionStart); | 6450 __ Sub(x0, lr, kReturnAddressDistanceFromFunctionStart); |
6649 | 6451 |
6650 #if defined(V8_HOST_ARCH_A64) | 6452 #if V8_HOST_ARCH_A64 |
6651 __ Mov(x10, Operand(reinterpret_cast<intptr_t>(&entry_hook_))); | 6453 uintptr_t entry_hook = |
6652 __ Ldr(x10, MemOperand(x10)); | 6454 reinterpret_cast<uintptr_t>(masm->isolate()->function_entry_hook()); |
| 6455 __ Mov(x10, entry_hook); |
6653 #else | 6456 #else |
6654 // Under the simulator we need to indirect the entry hook through a trampoline | 6457 // Under the simulator we need to indirect the entry hook through a trampoline |
6655 // function at a known address. | 6458 // function at a known address. |
6656 Address trampoline_address = reinterpret_cast<Address>( | 6459 ApiFunction dispatcher(FUNCTION_ADDR(EntryHookTrampoline)); |
6657 reinterpret_cast<intptr_t>(EntryHookTrampoline)); | |
6658 ApiFunction dispatcher(trampoline_address); | |
6659 __ Mov(x10, Operand(ExternalReference(&dispatcher, | 6460 __ Mov(x10, Operand(ExternalReference(&dispatcher, |
6660 ExternalReference::BUILTIN_CALL, | 6461 ExternalReference::BUILTIN_CALL, |
6661 masm->isolate()))); | 6462 masm->isolate()))); |
6662 #endif | 6463 #endif |
6663 | 6464 |
6664 // The caller's return address is above the saved temporaries. | 6465 // The caller's return address is above the saved temporaries. |
6665 // Grab its location for the second argument to the hook. | 6466 // Grab its location for the second argument to the hook. |
6666 __ Add(x1, __ StackPointer(), kNumSavedRegs * kPointerSize); | 6467 __ Add(x1, __ StackPointer(), kNumSavedRegs * kPointerSize); |
6667 | 6468 |
6668 { | 6469 { |
6669 // Create a dummy frame, as CallCFunction requires this. | 6470 // Create a dummy frame, as CallCFunction requires this. |
6670 FrameScope frame(masm, StackFrame::MANUAL); | 6471 FrameScope frame(masm, StackFrame::MANUAL); |
6671 __ CallCFunction(x10, 2, 0); | 6472 __ CallCFunction(x10, 2, 0); |
6672 } | 6473 } |
6673 | 6474 |
6674 __ Pop(x5, x1, lr); | 6475 __ PopCPURegList(kCallerSaved); |
6675 __ Ret(); | 6476 __ Ret(); |
6676 } | 6477 } |
6677 | 6478 |
6678 | 6479 |
6679 void DirectCEntryStub::Generate(MacroAssembler* masm) { | 6480 void DirectCEntryStub::Generate(MacroAssembler* masm) { |
6680 // When calling into C++ code the stack pointer must be csp. | 6481 // When calling into C++ code the stack pointer must be csp. |
6681 // Therefore this code must use csp for peek/poke operations when the | 6482 // Therefore this code must use csp for peek/poke operations when the |
6682 // stub is generated. When the stub is called | 6483 // stub is generated. When the stub is called |
6683 // (via DirectCEntryStub::GenerateCall), the caller must setup an ExitFrame | 6484 // (via DirectCEntryStub::GenerateCall), the caller must setup an ExitFrame |
6684 // and configure the stack pointer *before* doing the call. | 6485 // and configure the stack pointer *before* doing the call. |
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6985 Register type_info_cell = x2; | 6786 Register type_info_cell = x2; |
6986 Register kind = x3; | 6787 Register kind = x3; |
6987 | 6788 |
6988 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); | 6789 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); |
6989 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); | 6790 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); |
6990 STATIC_ASSERT(FAST_ELEMENTS == 2); | 6791 STATIC_ASSERT(FAST_ELEMENTS == 2); |
6991 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3); | 6792 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3); |
6992 STATIC_ASSERT(FAST_DOUBLE_ELEMENTS == 4); | 6793 STATIC_ASSERT(FAST_DOUBLE_ELEMENTS == 4); |
6993 STATIC_ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5); | 6794 STATIC_ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5); |
6994 | 6795 |
6995 Handle<Object> undefined_sentinel( | |
6996 masm->isolate()->heap()->undefined_value(), | |
6997 masm->isolate()); | |
6998 | |
6999 // Is the low bit set? If so, the array is holey. | 6796 // Is the low bit set? If so, the array is holey. |
7000 Label normal_sequence; | 6797 Label normal_sequence; |
7001 __ Tbnz(kind, 0, &normal_sequence); | 6798 __ Tbnz(kind, 0, &normal_sequence); |
7002 | 6799 |
7003 // Look at the last argument. | 6800 // Look at the last argument. |
7004 // TODO(jbramley): What does a 0 argument represent? | 6801 // TODO(jbramley): What does a 0 argument represent? |
7005 __ Peek(x10, 0); | 6802 __ Peek(x10, 0); |
7006 __ Cbz(x10, &normal_sequence); | 6803 __ Cbz(x10, &normal_sequence); |
7007 | 6804 |
7008 // We are going to create a holey array, but our kind is non-holey. | 6805 // We are going to create a holey array, but our kind is non-holey. |
7009 // Fix kind and retry. | 6806 // Fix kind and retry (only if we have an allocation site in the cell). |
7010 __ Orr(kind, kind, 1); | 6807 __ Orr(kind, kind, 1); |
7011 __ Cmp(type_info_cell, Operand(undefined_sentinel)); | 6808 __ JumpIfRoot(type_info_cell, Heap::kUndefinedValueRootIndex, |
7012 __ B(eq, &normal_sequence); | 6809 &normal_sequence); |
| 6810 |
| 6811 __ Ldr(x10, FieldMemOperand(type_info_cell, Cell::kValueOffset)); |
| 6812 __ Ldr(x10, FieldMemOperand(x10, 0)); |
| 6813 __ JumpIfNotRoot(x10, Heap::kAllocationSiteMapRootIndex, &normal_sequence); |
7013 | 6814 |
7014 // Save the resulting elements kind in type info. | 6815 // Save the resulting elements kind in type info. |
7015 // TODO(jbramley): Tag and store at the same time. | 6816 // TODO(jbramley): Tag and store at the same time. |
7016 __ SmiTag(x10, kind); | 6817 __ SmiTag(x10, kind); |
7017 __ Str(x10, FieldMemOperand(type_info_cell, kPointerSize)); | 6818 __ Ldr(x11, FieldMemOperand(type_info_cell, Cell::kValueOffset)); |
| 6819 __ Str(x10, FieldMemOperand(x11, AllocationSite::kPayloadOffset)); |
7018 | 6820 |
7019 __ Bind(&normal_sequence); | 6821 __ Bind(&normal_sequence); |
7020 int last_index = GetSequenceIndexFromFastElementsKind( | 6822 int last_index = GetSequenceIndexFromFastElementsKind( |
7021 TERMINAL_FAST_ELEMENTS_KIND); | 6823 TERMINAL_FAST_ELEMENTS_KIND); |
7022 for (int i = 0; i <= last_index; ++i) { | 6824 for (int i = 0; i <= last_index; ++i) { |
7023 Label next; | 6825 Label next; |
7024 ElementsKind candidate_kind = GetFastElementsKindFromSequenceIndex(i); | 6826 ElementsKind candidate_kind = GetFastElementsKindFromSequenceIndex(i); |
7025 // TODO(jbramley): Is this the best way to handle this? Can we make the tail | 6827 // TODO(jbramley): Is this the best way to handle this? Can we make the tail |
7026 // calls conditional, rather than hopping over each one? | 6828 // calls conditional, rather than hopping over each one? |
7027 __ CompareAndBranch(kind, candidate_kind, ne, &next); | 6829 __ CompareAndBranch(kind, candidate_kind, ne, &next); |
7028 ArraySingleArgumentConstructorStub stub(candidate_kind); | 6830 ArraySingleArgumentConstructorStub stub(candidate_kind); |
7029 __ TailCallStub(&stub); | 6831 __ TailCallStub(&stub); |
7030 __ Bind(&next); | 6832 __ Bind(&next); |
7031 } | 6833 } |
7032 | 6834 |
7033 // If we reached this point there is a problem. | 6835 // If we reached this point there is a problem. |
7034 __ Abort("Unexpected ElementsKind in array constructor"); | 6836 __ Abort("Unexpected ElementsKind in array constructor"); |
7035 } | 6837 } |
7036 | 6838 |
7037 | 6839 |
7038 template<class T> | 6840 template<class T> |
7039 static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) { | 6841 static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) { |
7040 int to_index = GetSequenceIndexFromFastElementsKind( | 6842 int to_index = GetSequenceIndexFromFastElementsKind( |
7041 TERMINAL_FAST_ELEMENTS_KIND); | 6843 TERMINAL_FAST_ELEMENTS_KIND); |
7042 for (int i = 0; i <= to_index; ++i) { | 6844 for (int i = 0; i <= to_index; ++i) { |
7043 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); | 6845 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); |
7044 T stub(kind); | 6846 T stub(kind); |
7045 stub.GetCode(isolate)->set_is_pregenerated(true); | 6847 stub.GetCode(isolate)->set_is_pregenerated(true); |
7046 if (AllocationSiteInfo::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE) { | 6848 if (AllocationSite::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE) { |
7047 T stub1(kind, true); | 6849 T stub1(kind, CONTEXT_CHECK_REQUIRED, DISABLE_ALLOCATION_SITES); |
7048 stub1.GetCode(isolate)->set_is_pregenerated(true); | 6850 stub1.GetCode(isolate)->set_is_pregenerated(true); |
7049 } | 6851 } |
7050 } | 6852 } |
7051 } | 6853 } |
7052 | 6854 |
7053 | 6855 |
7054 void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) { | 6856 void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) { |
7055 ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>( | 6857 ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>( |
7056 isolate); | 6858 isolate); |
7057 ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>( | 6859 ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>( |
(...skipping 19 matching lines...) Expand all Loading... |
7077 | 6879 |
7078 | 6880 |
7079 void ArrayConstructorStub::Generate(MacroAssembler* masm) { | 6881 void ArrayConstructorStub::Generate(MacroAssembler* masm) { |
7080 // ----------- S t a t e ------------- | 6882 // ----------- S t a t e ------------- |
7081 // -- x0 : argc (only if argument_count_ == ANY) | 6883 // -- x0 : argc (only if argument_count_ == ANY) |
7082 // -- x1 : constructor | 6884 // -- x1 : constructor |
7083 // -- x2 : type info cell | 6885 // -- x2 : type info cell |
7084 // -- sp[0] : return address | 6886 // -- sp[0] : return address |
7085 // -- sp[4] : last argument | 6887 // -- sp[4] : last argument |
7086 // ----------------------------------- | 6888 // ----------------------------------- |
7087 Handle<Object> undefined_sentinel( | |
7088 masm->isolate()->heap()->undefined_value(), masm->isolate()); | |
7089 | |
7090 Register argc = x0; | 6889 Register argc = x0; |
7091 Register constructor = x1; | 6890 Register constructor = x1; |
7092 Register type_info_cell = x2; | 6891 Register type_info_cell = x2; |
7093 | 6892 |
7094 if (FLAG_debug_code) { | 6893 if (FLAG_debug_code) { |
7095 // The array construct code is only set for the global and natives | 6894 // The array construct code is only set for the global and natives |
7096 // builtin Array functions which always have maps. | 6895 // builtin Array functions which always have maps. |
7097 | 6896 |
7098 Label unexpected_map, map_ok; | 6897 Label unexpected_map, map_ok; |
7099 // Initial map for the builtin Array function should be a map. | 6898 // Initial map for the builtin Array function should be a map. |
7100 __ Ldr(x10, FieldMemOperand(constructor, | 6899 __ Ldr(x10, FieldMemOperand(constructor, |
7101 JSFunction::kPrototypeOrInitialMapOffset)); | 6900 JSFunction::kPrototypeOrInitialMapOffset)); |
7102 // Will both indicate a NULL and a Smi. | 6901 // Will both indicate a NULL and a Smi. |
7103 __ JumpIfSmi(x10, &unexpected_map); | 6902 __ JumpIfSmi(x10, &unexpected_map); |
7104 __ JumpIfObjectType(x10, x10, x11, MAP_TYPE, &map_ok); | 6903 __ JumpIfObjectType(x10, x10, x11, MAP_TYPE, &map_ok); |
7105 __ Bind(&unexpected_map); | 6904 __ Bind(&unexpected_map); |
7106 __ Abort("Unexpected initial map for Array function"); | 6905 __ Abort("Unexpected initial map for Array function"); |
7107 __ Bind(&map_ok); | 6906 __ Bind(&map_ok); |
7108 | 6907 |
7109 // In type_info_cell, we expect either undefined or a valid Cell. | 6908 // In type_info_cell, we expect either undefined or a valid Cell. |
7110 Label okay_here; | 6909 Label okay_here; |
7111 Handle<Map> cell_map(masm->isolate()->heap()->global_property_cell_map()); | 6910 Handle<Map> cell_map(masm->isolate()->heap()->global_property_cell_map()); |
7112 __ CompareAndBranch(type_info_cell, Operand(undefined_sentinel), | 6911 __ JumpIfRoot(type_info_cell, Heap::kUndefinedValueRootIndex, &okay_here); |
7113 eq, &okay_here); | |
7114 __ Ldr(x10, FieldMemOperand(type_info_cell, Cell::kMapOffset)); | 6912 __ Ldr(x10, FieldMemOperand(type_info_cell, Cell::kMapOffset)); |
7115 __ Cmp(x10, Operand(cell_map)); | 6913 __ Cmp(x10, Operand(cell_map)); |
7116 __ Assert(eq, "Expected property cell in type_info_cell"); | 6914 __ Assert(eq, "Expected property cell in type_info_cell"); |
7117 __ Bind(&okay_here); | 6915 __ Bind(&okay_here); |
7118 } | 6916 } |
7119 | 6917 |
7120 Register kind = x3; | 6918 Register kind = x3; |
7121 Label no_info, switch_ready; | 6919 Label no_info, switch_ready; |
7122 // Get the elements kind and case on that. | 6920 // Get the elements kind and case on that. |
7123 __ CompareAndBranch(type_info_cell, Operand(undefined_sentinel), | 6921 __ JumpIfRoot(type_info_cell, Heap::kUndefinedValueRootIndex, &no_info); |
7124 eq, &no_info); | |
7125 __ Ldr(kind, FieldMemOperand(type_info_cell, PropertyCell::kValueOffset)); | 6922 __ Ldr(kind, FieldMemOperand(type_info_cell, PropertyCell::kValueOffset)); |
7126 __ JumpIfNotSmi(kind, &no_info); | 6923 |
7127 __ SmiUntag(kind); | 6924 // The type cell may have undefined in its value. |
| 6925 __ JumpIfRoot(kind, Heap::kUndefinedValueRootIndex, &no_info); |
| 6926 |
| 6927 // We should have an allocation site object |
| 6928 if (FLAG_debug_code) { |
| 6929 __ Ldr(x10, FieldMemOperand(kind, AllocationSite::kMapOffset)); |
| 6930 __ CompareRoot(x10, Heap::kAllocationSiteMapRootIndex); |
| 6931 __ Assert(eq, "Expected AllocationSite object."); |
| 6932 } |
| 6933 |
| 6934 __ Ldrsw(kind, UntagSmiFieldMemOperand(kind, AllocationSite::kPayloadOffset)); |
7128 __ B(&switch_ready); | 6935 __ B(&switch_ready); |
7129 | 6936 |
7130 __ Bind(&no_info); | 6937 __ Bind(&no_info); |
7131 __ Mov(kind, GetInitialFastElementsKind()); | 6938 __ Mov(kind, GetInitialFastElementsKind()); |
7132 __ Bind(&switch_ready); | 6939 __ Bind(&switch_ready); |
7133 | 6940 |
7134 if (argument_count_ == ANY) { | 6941 if (argument_count_ == ANY) { |
7135 Label zero_case, n_case; | 6942 Label zero_case, n_case; |
7136 __ Cbz(argc, &zero_case); | 6943 __ Cbz(argc, &zero_case); |
7137 __ Cmp(argc, 1); | 6944 __ Cmp(argc, 1); |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7252 __ Bind(&fast_elements_case); | 7059 __ Bind(&fast_elements_case); |
7253 GenerateCase(masm, FAST_ELEMENTS); | 7060 GenerateCase(masm, FAST_ELEMENTS); |
7254 } | 7061 } |
7255 | 7062 |
7256 | 7063 |
7257 #undef __ | 7064 #undef __ |
7258 | 7065 |
7259 } } // namespace v8::internal | 7066 } } // namespace v8::internal |
7260 | 7067 |
7261 #endif // V8_TARGET_ARCH_A64 | 7068 #endif // V8_TARGET_ARCH_A64 |
OLD | NEW |