| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 1416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1427 bool object_is_smi, | 1427 bool object_is_smi, |
| 1428 Label* not_found) { | 1428 Label* not_found) { |
| 1429 // Use of registers. Register result is used as a temporary. | 1429 // Use of registers. Register result is used as a temporary. |
| 1430 Register number_string_cache = result; | 1430 Register number_string_cache = result; |
| 1431 Register mask = scratch3; | 1431 Register mask = scratch3; |
| 1432 | 1432 |
| 1433 // Load the number string cache. | 1433 // Load the number string cache. |
| 1434 __ LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex); | 1434 __ LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex); |
| 1435 | 1435 |
| 1436 // Make the hash mask from the length of the number string cache. It | 1436 // Make the hash mask from the length of the number string cache. It |
| 1437 // contains two elements (number and string) for each cache entry. | 1437 // contains three elements (number, string and age) for each cache entry. |
| 1438 __ ldr(mask, FieldMemOperand(number_string_cache, FixedArray::kLengthOffset)); | 1438 __ ldr(mask, FieldMemOperand(number_string_cache, FixedArray::kLengthOffset)); |
| 1439 // Divide length by two (length is a smi). | 1439 STATIC_ASSERT(Heap::kNSCSlotsPerEntry == 3); |
| 1440 __ mov(mask, Operand(mask, ASR, kSmiTagSize + 1)); | 1440 // Multiply mask by 2/3, making it a power of 2. |
| 1441 __ sub(mask, mask, Operand(1)); // Make mask. | 1441 __ and_(mask, mask, Operand(mask, LSL, 1)); |
| 1442 // Make mask. It is 4 times the number of entries (2 times for Smi tag, |
| 1443 // 2 times for the size of the array * 2/3). |
| 1444 STATIC_ASSERT(kSmiTagSize == 1); |
| 1445 STATIC_ASSERT(kPointerSize == 4); |
| 1446 __ sub(mask, mask, Operand(kPointerSize - 1)); |
| 1442 | 1447 |
| 1443 // Calculate the entry in the number string cache. The hash value in the | 1448 // Calculate the entry in the number string cache. The hash value in the |
| 1444 // number string cache for smis is just the smi value, and the hash for | 1449 // number string cache for smis is just the smi value, and the hash for |
| 1445 // doubles is the xor of the upper and lower words. See | 1450 // doubles is the xor of the upper and lower words. See |
| 1446 // Heap::GetNumberStringCache. | 1451 // Heap::GetNumberStringCache. |
| 1447 Isolate* isolate = masm->isolate(); | 1452 Isolate* isolate = masm->isolate(); |
| 1448 Label is_smi; | 1453 Label is_smi; |
| 1449 Label load_result_from_cache; | 1454 Label load_result_from_cache; |
| 1455 const int kNumberOffset = |
| 1456 FixedArray::kHeaderSize + kPointerSize * Heap::kNSCNumberOffset; |
| 1457 const int kStringOffset = |
| 1458 FixedArray::kHeaderSize + kPointerSize * Heap::kNSCStringOffset; |
| 1459 const int kAgeOffset = |
| 1460 FixedArray::kHeaderSize + kPointerSize * Heap::kNSCAgeOffset; |
| 1450 if (!object_is_smi) { | 1461 if (!object_is_smi) { |
| 1451 __ JumpIfSmi(object, &is_smi); | 1462 __ JumpIfSmi(object, &is_smi); |
| 1452 if (CpuFeatures::IsSupported(VFP3)) { | 1463 if (CpuFeatures::IsSupported(VFP3)) { |
| 1453 CpuFeatures::Scope scope(VFP3); | 1464 CpuFeatures::Scope scope(VFP3); |
| 1454 __ CheckMap(object, | 1465 __ CheckMap(object, |
| 1455 scratch1, | 1466 scratch1, |
| 1456 Heap::kHeapNumberMapRootIndex, | 1467 Heap::kHeapNumberMapRootIndex, |
| 1457 not_found, | 1468 not_found, |
| 1458 DONT_DO_SMI_CHECK); | 1469 DONT_DO_SMI_CHECK); |
| 1459 | 1470 |
| 1460 STATIC_ASSERT(8 == kDoubleSize); | 1471 STATIC_ASSERT(8 == kDoubleSize); |
| 1461 __ add(scratch1, | 1472 __ add(scratch1, |
| 1462 object, | 1473 object, |
| 1463 Operand(HeapNumber::kValueOffset - kHeapObjectTag)); | 1474 Operand(HeapNumber::kValueOffset - kHeapObjectTag)); |
| 1464 __ ldm(ia, scratch1, scratch1.bit() | scratch2.bit()); | 1475 __ ldm(ia, scratch1, scratch1.bit() | scratch2.bit()); |
| 1465 __ eor(scratch1, scratch1, Operand(scratch2)); | 1476 __ eor(scratch1, scratch1, Operand(scratch2)); |
| 1466 __ and_(scratch1, scratch1, Operand(mask)); | 1477 __ and_(scratch1, mask, Operand(scratch1, LSL, kPointerSizeLog2)); |
| 1467 | 1478 |
| 1468 // Calculate address of entry in string cache: each entry consists | 1479 // Calculate address of entry in string cache: each entry consists |
| 1469 // of two pointer sized fields. | 1480 // of three pointer sized fields, so we multiply by 3. |
| 1470 __ add(scratch1, | 1481 __ add(scratch1, scratch1, Operand(scratch1, LSL, 1)); |
| 1471 number_string_cache, | 1482 __ add(scratch1, scratch1, number_string_cache); |
| 1472 Operand(scratch1, LSL, kPointerSizeLog2 + 1)); | |
| 1473 | 1483 |
| 1474 Register probe = mask; | 1484 Register probe = mask; |
| 1475 __ ldr(probe, | 1485 __ ldr(probe, FieldMemOperand(scratch1, kNumberOffset)); |
| 1476 FieldMemOperand(scratch1, FixedArray::kHeaderSize)); | |
| 1477 __ JumpIfSmi(probe, not_found); | 1486 __ JumpIfSmi(probe, not_found); |
| 1478 __ sub(scratch2, object, Operand(kHeapObjectTag)); | 1487 __ sub(scratch2, object, Operand(kHeapObjectTag)); |
| 1479 __ vldr(d0, scratch2, HeapNumber::kValueOffset); | 1488 __ vldr(d0, scratch2, HeapNumber::kValueOffset); |
| 1480 __ sub(probe, probe, Operand(kHeapObjectTag)); | 1489 __ sub(probe, probe, Operand(kHeapObjectTag)); |
| 1481 __ vldr(d1, probe, HeapNumber::kValueOffset); | 1490 __ vldr(d1, probe, HeapNumber::kValueOffset); |
| 1482 __ VFPCompareAndSetFlags(d0, d1); | 1491 __ VFPCompareAndSetFlags(d0, d1); |
| 1483 __ b(ne, not_found); // The cache did not contain this value. | 1492 __ b(ne, not_found); // The cache did not contain this value. |
| 1484 __ b(&load_result_from_cache); | 1493 __ b(&load_result_from_cache); |
| 1485 } else { | 1494 } else { |
| 1486 __ b(not_found); | 1495 __ b(not_found); |
| 1487 } | 1496 } |
| 1488 } | 1497 } |
| 1489 | 1498 |
| 1490 __ bind(&is_smi); | 1499 __ bind(&is_smi); |
| 1491 Register scratch = scratch1; | 1500 STATIC_ASSERT(kSmiTag == 0); |
| 1492 __ and_(scratch, mask, Operand(object, ASR, 1)); | 1501 __ and_(scratch1, mask, Operand(object, LSL, kPointerSizeLog2 - kSmiTagSize)); |
| 1493 // Calculate address of entry in string cache: each entry consists | 1502 // Calculate address of entry in string cache: each entry consists |
| 1494 // of two pointer sized fields. | 1503 // of three pointer sized fields, so we multiply by 3. |
| 1495 __ add(scratch, | 1504 __ add(scratch1, scratch1, Operand(scratch1, LSL, 1)); |
| 1496 number_string_cache, | 1505 __ add(scratch1, scratch1, number_string_cache); |
| 1497 Operand(scratch, LSL, kPointerSizeLog2 + 1)); | |
| 1498 | 1506 |
| 1499 // Check if the entry is the smi we are looking for. | 1507 // Check if the entry is the smi we are looking for. |
| 1500 Register probe = mask; | 1508 Register probe = mask; |
| 1501 __ ldr(probe, FieldMemOperand(scratch, FixedArray::kHeaderSize)); | 1509 __ ldr(probe, FieldMemOperand(scratch1, kNumberOffset)); |
| 1502 __ cmp(object, probe); | 1510 __ cmp(object, probe); |
| 1503 __ b(ne, not_found); | 1511 __ b(ne, not_found); |
| 1504 | 1512 |
| 1505 // Get the result from the cache. | 1513 // Get the result from the cache. |
| 1506 __ bind(&load_result_from_cache); | 1514 __ bind(&load_result_from_cache); |
| 1507 __ ldr(result, | 1515 __ mov(ip, Operand(Smi::FromInt(Heap::kNSCMinAge))); |
| 1508 FieldMemOperand(scratch, FixedArray::kHeaderSize + kPointerSize)); | 1516 __ str(ip, FieldMemOperand(scratch1, kAgeOffset)); |
| 1517 __ ldr(result, FieldMemOperand(scratch1, kStringOffset)); |
| 1509 __ IncrementCounter(isolate->counters()->number_to_string_native(), | 1518 __ IncrementCounter(isolate->counters()->number_to_string_native(), |
| 1510 1, | 1519 1, |
| 1511 scratch1, | 1520 scratch1, |
| 1512 scratch2); | 1521 scratch2); |
| 1513 } | 1522 } |
| 1514 | 1523 |
| 1515 | 1524 |
| 1516 void NumberToStringStub::Generate(MacroAssembler* masm) { | 1525 void NumberToStringStub::Generate(MacroAssembler* masm) { |
| 1517 Label runtime; | 1526 Label runtime; |
| 1518 | 1527 |
| (...skipping 5643 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7162 | 7171 |
| 7163 // Fall through when we need to inform the incremental marker. | 7172 // Fall through when we need to inform the incremental marker. |
| 7164 } | 7173 } |
| 7165 | 7174 |
| 7166 | 7175 |
| 7167 #undef __ | 7176 #undef __ |
| 7168 | 7177 |
| 7169 } } // namespace v8::internal | 7178 } } // namespace v8::internal |
| 7170 | 7179 |
| 7171 #endif // V8_TARGET_ARCH_ARM | 7180 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |