OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
219 } | 219 } |
220 | 220 |
221 | 221 |
222 void InternalArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor( | 222 void InternalArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor( |
223 Isolate* isolate, | 223 Isolate* isolate, |
224 CodeStubInterfaceDescriptor* descriptor) { | 224 CodeStubInterfaceDescriptor* descriptor) { |
225 InitializeInternalArrayConstructorDescriptor(isolate, descriptor, -1); | 225 InitializeInternalArrayConstructorDescriptor(isolate, descriptor, -1); |
226 } | 226 } |
227 | 227 |
228 | 228 |
229 void UnaryOpStub::InitializeInterfaceDescriptor( | |
230 Isolate* isolate, | |
231 CodeStubInterfaceDescriptor* descriptor) { | |
232 static Register registers[] = { r0 }; | |
233 descriptor->register_param_count_ = 1; | |
234 descriptor->register_params_ = registers; | |
235 descriptor->deoptimization_handler_ = | |
236 FUNCTION_ADDR(UnaryOpIC_Miss); | |
237 } | |
238 | |
239 | |
240 #define __ ACCESS_MASM(masm) | 229 #define __ ACCESS_MASM(masm) |
241 | 230 |
242 | |
243 static void EmitIdenticalObjectComparison(MacroAssembler* masm, | 231 static void EmitIdenticalObjectComparison(MacroAssembler* masm, |
244 Label* slow, | 232 Label* slow, |
245 Condition cond); | 233 Condition cond); |
246 static void EmitSmiNonsmiComparison(MacroAssembler* masm, | 234 static void EmitSmiNonsmiComparison(MacroAssembler* masm, |
247 Register lhs, | 235 Register lhs, |
248 Register rhs, | 236 Register rhs, |
249 Label* lhs_not_nan, | 237 Label* lhs_not_nan, |
250 Label* slow, | 238 Label* slow, |
251 bool strict); | 239 bool strict); |
252 static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm, | 240 static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm, |
(...skipping 1041 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1294 __ CallCFunction( | 1282 __ CallCFunction( |
1295 ExternalReference::store_buffer_overflow_function(masm->isolate()), | 1283 ExternalReference::store_buffer_overflow_function(masm->isolate()), |
1296 argument_count); | 1284 argument_count); |
1297 if (save_doubles_ == kSaveFPRegs) { | 1285 if (save_doubles_ == kSaveFPRegs) { |
1298 __ RestoreFPRegs(sp, scratch); | 1286 __ RestoreFPRegs(sp, scratch); |
1299 } | 1287 } |
1300 __ ldm(ia_w, sp, kCallerSaved | pc.bit()); // Also pop pc to get Ret(0). | 1288 __ ldm(ia_w, sp, kCallerSaved | pc.bit()); // Also pop pc to get Ret(0). |
1301 } | 1289 } |
1302 | 1290 |
1303 | 1291 |
| 1292 void UnaryOpStub::PrintName(StringStream* stream) { |
| 1293 const char* op_name = Token::Name(op_); |
| 1294 const char* overwrite_name = NULL; // Make g++ happy. |
| 1295 switch (mode_) { |
| 1296 case UNARY_NO_OVERWRITE: overwrite_name = "Alloc"; break; |
| 1297 case UNARY_OVERWRITE: overwrite_name = "Overwrite"; break; |
| 1298 } |
| 1299 stream->Add("UnaryOpStub_%s_%s_%s", |
| 1300 op_name, |
| 1301 overwrite_name, |
| 1302 UnaryOpIC::GetName(operand_type_)); |
| 1303 } |
| 1304 |
| 1305 |
| 1306 // TODO(svenpanne): Use virtual functions instead of switch. |
| 1307 void UnaryOpStub::Generate(MacroAssembler* masm) { |
| 1308 switch (operand_type_) { |
| 1309 case UnaryOpIC::UNINITIALIZED: |
| 1310 GenerateTypeTransition(masm); |
| 1311 break; |
| 1312 case UnaryOpIC::SMI: |
| 1313 GenerateSmiStub(masm); |
| 1314 break; |
| 1315 case UnaryOpIC::NUMBER: |
| 1316 GenerateNumberStub(masm); |
| 1317 break; |
| 1318 case UnaryOpIC::GENERIC: |
| 1319 GenerateGenericStub(masm); |
| 1320 break; |
| 1321 } |
| 1322 } |
| 1323 |
| 1324 |
| 1325 void UnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) { |
| 1326 __ mov(r3, Operand(r0)); // the operand |
| 1327 __ mov(r2, Operand(Smi::FromInt(op_))); |
| 1328 __ mov(r1, Operand(Smi::FromInt(mode_))); |
| 1329 __ mov(r0, Operand(Smi::FromInt(operand_type_))); |
| 1330 __ Push(r3, r2, r1, r0); |
| 1331 |
| 1332 __ TailCallExternalReference( |
| 1333 ExternalReference(IC_Utility(IC::kUnaryOp_Patch), masm->isolate()), 4, 1); |
| 1334 } |
| 1335 |
| 1336 |
| 1337 // TODO(svenpanne): Use virtual functions instead of switch. |
| 1338 void UnaryOpStub::GenerateSmiStub(MacroAssembler* masm) { |
| 1339 switch (op_) { |
| 1340 case Token::SUB: |
| 1341 GenerateSmiStubSub(masm); |
| 1342 break; |
| 1343 case Token::BIT_NOT: |
| 1344 GenerateSmiStubBitNot(masm); |
| 1345 break; |
| 1346 default: |
| 1347 UNREACHABLE(); |
| 1348 } |
| 1349 } |
| 1350 |
| 1351 |
| 1352 void UnaryOpStub::GenerateSmiStubSub(MacroAssembler* masm) { |
| 1353 Label non_smi, slow; |
| 1354 GenerateSmiCodeSub(masm, &non_smi, &slow); |
| 1355 __ bind(&non_smi); |
| 1356 __ bind(&slow); |
| 1357 GenerateTypeTransition(masm); |
| 1358 } |
| 1359 |
| 1360 |
| 1361 void UnaryOpStub::GenerateSmiStubBitNot(MacroAssembler* masm) { |
| 1362 Label non_smi; |
| 1363 GenerateSmiCodeBitNot(masm, &non_smi); |
| 1364 __ bind(&non_smi); |
| 1365 GenerateTypeTransition(masm); |
| 1366 } |
| 1367 |
| 1368 |
| 1369 void UnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm, |
| 1370 Label* non_smi, |
| 1371 Label* slow) { |
| 1372 __ JumpIfNotSmi(r0, non_smi); |
| 1373 |
| 1374 // The result of negating zero or the smallest negative smi is not a smi. |
| 1375 __ bic(ip, r0, Operand(0x80000000), SetCC); |
| 1376 __ b(eq, slow); |
| 1377 |
| 1378 // Return '0 - value'. |
| 1379 __ rsb(r0, r0, Operand::Zero()); |
| 1380 __ Ret(); |
| 1381 } |
| 1382 |
| 1383 |
| 1384 void UnaryOpStub::GenerateSmiCodeBitNot(MacroAssembler* masm, |
| 1385 Label* non_smi) { |
| 1386 __ JumpIfNotSmi(r0, non_smi); |
| 1387 |
| 1388 // Flip bits and revert inverted smi-tag. |
| 1389 __ mvn(r0, Operand(r0)); |
| 1390 __ bic(r0, r0, Operand(kSmiTagMask)); |
| 1391 __ Ret(); |
| 1392 } |
| 1393 |
| 1394 |
| 1395 // TODO(svenpanne): Use virtual functions instead of switch. |
| 1396 void UnaryOpStub::GenerateNumberStub(MacroAssembler* masm) { |
| 1397 switch (op_) { |
| 1398 case Token::SUB: |
| 1399 GenerateNumberStubSub(masm); |
| 1400 break; |
| 1401 case Token::BIT_NOT: |
| 1402 GenerateNumberStubBitNot(masm); |
| 1403 break; |
| 1404 default: |
| 1405 UNREACHABLE(); |
| 1406 } |
| 1407 } |
| 1408 |
| 1409 |
| 1410 void UnaryOpStub::GenerateNumberStubSub(MacroAssembler* masm) { |
| 1411 Label non_smi, slow, call_builtin; |
| 1412 GenerateSmiCodeSub(masm, &non_smi, &call_builtin); |
| 1413 __ bind(&non_smi); |
| 1414 GenerateHeapNumberCodeSub(masm, &slow); |
| 1415 __ bind(&slow); |
| 1416 GenerateTypeTransition(masm); |
| 1417 __ bind(&call_builtin); |
| 1418 GenerateGenericCodeFallback(masm); |
| 1419 } |
| 1420 |
| 1421 |
| 1422 void UnaryOpStub::GenerateNumberStubBitNot(MacroAssembler* masm) { |
| 1423 Label non_smi, slow; |
| 1424 GenerateSmiCodeBitNot(masm, &non_smi); |
| 1425 __ bind(&non_smi); |
| 1426 GenerateHeapNumberCodeBitNot(masm, &slow); |
| 1427 __ bind(&slow); |
| 1428 GenerateTypeTransition(masm); |
| 1429 } |
| 1430 |
| 1431 void UnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm, |
| 1432 Label* slow) { |
| 1433 EmitCheckForHeapNumber(masm, r0, r1, r6, slow); |
| 1434 // r0 is a heap number. Get a new heap number in r1. |
| 1435 if (mode_ == UNARY_OVERWRITE) { |
| 1436 __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); |
| 1437 __ eor(r2, r2, Operand(HeapNumber::kSignMask)); // Flip sign. |
| 1438 __ str(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); |
| 1439 } else { |
| 1440 Label slow_allocate_heapnumber, heapnumber_allocated; |
| 1441 __ AllocateHeapNumber(r1, r2, r3, r6, &slow_allocate_heapnumber); |
| 1442 __ jmp(&heapnumber_allocated); |
| 1443 |
| 1444 __ bind(&slow_allocate_heapnumber); |
| 1445 { |
| 1446 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1447 __ push(r0); |
| 1448 __ CallRuntime(Runtime::kNumberAlloc, 0); |
| 1449 __ mov(r1, Operand(r0)); |
| 1450 __ pop(r0); |
| 1451 } |
| 1452 |
| 1453 __ bind(&heapnumber_allocated); |
| 1454 __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); |
| 1455 __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); |
| 1456 __ str(r3, FieldMemOperand(r1, HeapNumber::kMantissaOffset)); |
| 1457 __ eor(r2, r2, Operand(HeapNumber::kSignMask)); // Flip sign. |
| 1458 __ str(r2, FieldMemOperand(r1, HeapNumber::kExponentOffset)); |
| 1459 __ mov(r0, Operand(r1)); |
| 1460 } |
| 1461 __ Ret(); |
| 1462 } |
| 1463 |
| 1464 |
| 1465 void UnaryOpStub::GenerateHeapNumberCodeBitNot(MacroAssembler* masm, |
| 1466 Label* slow) { |
| 1467 EmitCheckForHeapNumber(masm, r0, r1, r6, slow); |
| 1468 |
| 1469 // Convert the heap number in r0 to an untagged integer in r1. |
| 1470 __ vldr(d0, FieldMemOperand(r0, HeapNumber::kValueOffset)); |
| 1471 __ ECMAToInt32(r1, d0, r2, r3, r4, d1); |
| 1472 |
| 1473 // Do the bitwise operation and check if the result fits in a smi. |
| 1474 Label try_float; |
| 1475 __ mvn(r1, Operand(r1)); |
| 1476 __ cmn(r1, Operand(0x40000000)); |
| 1477 __ b(mi, &try_float); |
| 1478 |
| 1479 // Tag the result as a smi and we're done. |
| 1480 __ SmiTag(r0, r1); |
| 1481 __ Ret(); |
| 1482 |
| 1483 // Try to store the result in a heap number. |
| 1484 __ bind(&try_float); |
| 1485 if (mode_ == UNARY_NO_OVERWRITE) { |
| 1486 Label slow_allocate_heapnumber, heapnumber_allocated; |
| 1487 __ AllocateHeapNumber(r0, r3, r4, r6, &slow_allocate_heapnumber); |
| 1488 __ jmp(&heapnumber_allocated); |
| 1489 |
| 1490 __ bind(&slow_allocate_heapnumber); |
| 1491 { |
| 1492 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1493 // Push the lower bit of the result (left shifted to look like a smi). |
| 1494 __ mov(r2, Operand(r1, LSL, 31)); |
| 1495 // Push the 31 high bits (bit 0 cleared to look like a smi). |
| 1496 __ bic(r1, r1, Operand(1)); |
| 1497 __ Push(r2, r1); |
| 1498 __ CallRuntime(Runtime::kNumberAlloc, 0); |
| 1499 __ Pop(r2, r1); // Restore the result. |
| 1500 __ orr(r1, r1, Operand(r2, LSR, 31)); |
| 1501 } |
| 1502 __ bind(&heapnumber_allocated); |
| 1503 } |
| 1504 |
| 1505 __ vmov(s0, r1); |
| 1506 __ vcvt_f64_s32(d0, s0); |
| 1507 __ vstr(d0, FieldMemOperand(r0, HeapNumber::kValueOffset)); |
| 1508 __ Ret(); |
| 1509 } |
| 1510 |
| 1511 |
| 1512 // TODO(svenpanne): Use virtual functions instead of switch. |
| 1513 void UnaryOpStub::GenerateGenericStub(MacroAssembler* masm) { |
| 1514 switch (op_) { |
| 1515 case Token::SUB: |
| 1516 GenerateGenericStubSub(masm); |
| 1517 break; |
| 1518 case Token::BIT_NOT: |
| 1519 GenerateGenericStubBitNot(masm); |
| 1520 break; |
| 1521 default: |
| 1522 UNREACHABLE(); |
| 1523 } |
| 1524 } |
| 1525 |
| 1526 |
| 1527 void UnaryOpStub::GenerateGenericStubSub(MacroAssembler* masm) { |
| 1528 Label non_smi, slow; |
| 1529 GenerateSmiCodeSub(masm, &non_smi, &slow); |
| 1530 __ bind(&non_smi); |
| 1531 GenerateHeapNumberCodeSub(masm, &slow); |
| 1532 __ bind(&slow); |
| 1533 GenerateGenericCodeFallback(masm); |
| 1534 } |
| 1535 |
| 1536 |
| 1537 void UnaryOpStub::GenerateGenericStubBitNot(MacroAssembler* masm) { |
| 1538 Label non_smi, slow; |
| 1539 GenerateSmiCodeBitNot(masm, &non_smi); |
| 1540 __ bind(&non_smi); |
| 1541 GenerateHeapNumberCodeBitNot(masm, &slow); |
| 1542 __ bind(&slow); |
| 1543 GenerateGenericCodeFallback(masm); |
| 1544 } |
| 1545 |
| 1546 |
| 1547 void UnaryOpStub::GenerateGenericCodeFallback(MacroAssembler* masm) { |
| 1548 // Handle the slow case by jumping to the JavaScript builtin. |
| 1549 __ push(r0); |
| 1550 switch (op_) { |
| 1551 case Token::SUB: |
| 1552 __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_FUNCTION); |
| 1553 break; |
| 1554 case Token::BIT_NOT: |
| 1555 __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_FUNCTION); |
| 1556 break; |
| 1557 default: |
| 1558 UNREACHABLE(); |
| 1559 } |
| 1560 } |
| 1561 |
| 1562 |
1304 // Generates code to call a C function to do a double operation. | 1563 // Generates code to call a C function to do a double operation. |
1305 // This code never falls through, but returns with a heap number containing | 1564 // This code never falls through, but returns with a heap number containing |
1306 // the result in r0. | 1565 // the result in r0. |
1307 // Register heapnumber_result must be a heap number in which the | 1566 // Register heapnumber_result must be a heap number in which the |
1308 // result of the operation will be stored. | 1567 // result of the operation will be stored. |
1309 // Requires the following layout on entry: | 1568 // Requires the following layout on entry: |
1310 // d0: Left value. | 1569 // d0: Left value. |
1311 // d1: Right value. | 1570 // d1: Right value. |
1312 // If soft float ABI, use also r0, r1, r2, r3. | 1571 // If soft float ABI, use also r0, r1, r2, r3. |
1313 static void CallCCodeForDoubleOperation(MacroAssembler* masm, | 1572 static void CallCCodeForDoubleOperation(MacroAssembler* masm, |
(...skipping 5851 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7165 __ bind(&fast_elements_case); | 7424 __ bind(&fast_elements_case); |
7166 GenerateCase(masm, FAST_ELEMENTS); | 7425 GenerateCase(masm, FAST_ELEMENTS); |
7167 } | 7426 } |
7168 | 7427 |
7169 | 7428 |
7170 #undef __ | 7429 #undef __ |
7171 | 7430 |
7172 } } // namespace v8::internal | 7431 } } // namespace v8::internal |
7173 | 7432 |
7174 #endif // V8_TARGET_ARCH_ARM | 7433 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |