OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <limits.h> // For LONG_MIN, LONG_MAX. | 5 #include <limits.h> // For LONG_MIN, LONG_MAX. |
6 | 6 |
7 #if V8_TARGET_ARCH_MIPS64 | 7 #if V8_TARGET_ARCH_MIPS64 |
8 | 8 |
9 #include "src/base/division-by-constant.h" | 9 #include "src/base/division-by-constant.h" |
10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
(...skipping 3486 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3497 if (emit_debug_code()) { | 3497 if (emit_debug_code()) { |
3498 // Trash the registers to simulate an allocation failure. | 3498 // Trash the registers to simulate an allocation failure. |
3499 li(result, 0x7091); | 3499 li(result, 0x7091); |
3500 li(scratch1, 0x7191); | 3500 li(scratch1, 0x7191); |
3501 li(scratch2, 0x7291); | 3501 li(scratch2, 0x7291); |
3502 } | 3502 } |
3503 jmp(gc_required); | 3503 jmp(gc_required); |
3504 return; | 3504 return; |
3505 } | 3505 } |
3506 | 3506 |
3507 DCHECK(!result.is(scratch1)); | 3507 DCHECK(!AreAliased(result, scratch1, scratch2, t9)); |
3508 DCHECK(!result.is(scratch2)); | |
3509 DCHECK(!scratch1.is(scratch2)); | |
3510 DCHECK(!scratch1.is(t9)); | |
3511 DCHECK(!scratch2.is(t9)); | |
3512 DCHECK(!result.is(t9)); | |
3513 | 3508 |
3514 // Make object size into bytes. | 3509 // Make object size into bytes. |
3515 if ((flags & SIZE_IN_WORDS) != 0) { | 3510 if ((flags & SIZE_IN_WORDS) != 0) { |
3516 object_size *= kPointerSize; | 3511 object_size *= kPointerSize; |
3517 } | 3512 } |
3518 DCHECK(0 == (object_size & kObjectAlignmentMask)); | 3513 DCHECK(0 == (object_size & kObjectAlignmentMask)); |
3519 | 3514 |
3520 // Check relative positions of allocation top and limit addresses. | 3515 // Check relative positions of allocation top and limit addresses. |
3521 // ARM adds additional checks to make sure the ldm instruction can be | 3516 // ARM adds additional checks to make sure the ldm instruction can be |
3522 // used. On MIPS we don't have ldm so we don't need additional checks either. | 3517 // used. On MIPS we don't have ldm so we don't need additional checks either. |
3523 ExternalReference allocation_top = | 3518 ExternalReference allocation_top = |
3524 AllocationUtils::GetAllocationTopReference(isolate(), flags); | 3519 AllocationUtils::GetAllocationTopReference(isolate(), flags); |
3525 ExternalReference allocation_limit = | 3520 ExternalReference allocation_limit = |
3526 AllocationUtils::GetAllocationLimitReference(isolate(), flags); | 3521 AllocationUtils::GetAllocationLimitReference(isolate(), flags); |
3527 | 3522 |
3528 intptr_t top = | 3523 intptr_t top = reinterpret_cast<intptr_t>(allocation_top.address()); |
3529 reinterpret_cast<intptr_t>(allocation_top.address()); | 3524 intptr_t limit = reinterpret_cast<intptr_t>(allocation_limit.address()); |
3530 intptr_t limit = | |
3531 reinterpret_cast<intptr_t>(allocation_limit.address()); | |
3532 DCHECK((limit - top) == kPointerSize); | 3525 DCHECK((limit - top) == kPointerSize); |
3533 | 3526 |
3534 // Set up allocation top address and object size registers. | 3527 // Set up allocation top address and allocation limit registers. |
3535 Register topaddr = scratch1; | 3528 Register top_address = scratch1; |
3536 li(topaddr, Operand(allocation_top)); | 3529 // This code stores a temporary value in t9. |
| 3530 Register alloc_limit = t9; |
| 3531 Register result_end = scratch2; |
| 3532 li(top_address, Operand(allocation_top)); |
3537 | 3533 |
3538 // This code stores a temporary value in t9. | |
3539 if ((flags & RESULT_CONTAINS_TOP) == 0) { | 3534 if ((flags & RESULT_CONTAINS_TOP) == 0) { |
3540 // Load allocation top into result and allocation limit into t9. | 3535 // Load allocation top into result and allocation limit into alloc_limit. |
3541 ld(result, MemOperand(topaddr)); | 3536 ld(result, MemOperand(top_address)); |
3542 ld(t9, MemOperand(topaddr, kPointerSize)); | 3537 ld(alloc_limit, MemOperand(top_address, kPointerSize)); |
3543 } else { | 3538 } else { |
3544 if (emit_debug_code()) { | 3539 if (emit_debug_code()) { |
3545 // Assert that result actually contains top on entry. t9 is used | 3540 // Assert that result actually contains top on entry. |
3546 // immediately below so this use of t9 does not cause difference with | 3541 ld(alloc_limit, MemOperand(top_address)); |
3547 // respect to register content between debug and release mode. | 3542 Check(eq, kUnexpectedAllocationTop, result, Operand(alloc_limit)); |
3548 ld(t9, MemOperand(topaddr)); | |
3549 Check(eq, kUnexpectedAllocationTop, result, Operand(t9)); | |
3550 } | 3543 } |
3551 // Load allocation limit into t9. Result already contains allocation top. | 3544 // Load allocation limit. Result already contains allocation top. |
3552 ld(t9, MemOperand(topaddr, static_cast<int32_t>(limit - top))); | 3545 ld(alloc_limit, MemOperand(top_address, static_cast<int32_t>(limit - top))); |
3553 } | 3546 } |
3554 | 3547 |
3555 DCHECK(kPointerSize == kDoubleSize); | 3548 // We can ignore DOUBLE_ALIGNMENT flags here because doubles and pointers have |
| 3549 // the same alignment on ARM64. |
| 3550 STATIC_ASSERT(kPointerAlignment == kDoubleAlignment); |
| 3551 |
3556 if (emit_debug_code()) { | 3552 if (emit_debug_code()) { |
3557 And(at, result, Operand(kDoubleAlignmentMask)); | 3553 And(at, result, Operand(kDoubleAlignmentMask)); |
3558 Check(eq, kAllocationIsNotDoubleAligned, at, Operand(zero_reg)); | 3554 Check(eq, kAllocationIsNotDoubleAligned, at, Operand(zero_reg)); |
3559 } | 3555 } |
3560 | 3556 |
3561 // Calculate new top and bail out if new space is exhausted. Use result | 3557 // Calculate new top and bail out if new space is exhausted. Use result |
3562 // to calculate the new top. | 3558 // to calculate the new top. |
3563 Daddu(scratch2, result, Operand(object_size)); | 3559 Daddu(result_end, result, Operand(object_size)); |
3564 Branch(gc_required, Ugreater, scratch2, Operand(t9)); | 3560 Branch(gc_required, Ugreater, result_end, Operand(alloc_limit)); |
3565 sd(scratch2, MemOperand(topaddr)); | 3561 sd(result_end, MemOperand(top_address)); |
3566 | 3562 |
3567 // Tag object if requested. | 3563 // Tag object if requested. |
3568 if ((flags & TAG_OBJECT) != 0) { | 3564 if ((flags & TAG_OBJECT) != 0) { |
3569 Daddu(result, result, Operand(kHeapObjectTag)); | 3565 Daddu(result, result, Operand(kHeapObjectTag)); |
3570 } | 3566 } |
3571 } | 3567 } |
3572 | 3568 |
3573 | 3569 |
3574 void MacroAssembler::Allocate(Register object_size, Register result, | 3570 void MacroAssembler::Allocate(Register object_size, Register result, |
3575 Register result_end, Register scratch, | 3571 Register result_end, Register scratch, |
3576 Label* gc_required, AllocationFlags flags) { | 3572 Label* gc_required, AllocationFlags flags) { |
3577 if (!FLAG_inline_new) { | 3573 if (!FLAG_inline_new) { |
3578 if (emit_debug_code()) { | 3574 if (emit_debug_code()) { |
3579 // Trash the registers to simulate an allocation failure. | 3575 // Trash the registers to simulate an allocation failure. |
3580 li(result, 0x7091); | 3576 li(result, 0x7091); |
3581 li(scratch, 0x7191); | 3577 li(scratch, 0x7191); |
3582 li(result_end, 0x7291); | 3578 li(result_end, 0x7291); |
3583 } | 3579 } |
3584 jmp(gc_required); | 3580 jmp(gc_required); |
3585 return; | 3581 return; |
3586 } | 3582 } |
3587 | 3583 |
3588 DCHECK(!result.is(scratch)); | 3584 // |object_size| and |result_end| may overlap, other registers must not. |
3589 DCHECK(!result.is(result_end)); | 3585 DCHECK(!AreAliased(object_size, result, scratch, t9)); |
3590 DCHECK(!scratch.is(result_end)); | 3586 DCHECK(!AreAliased(result_end, result, scratch, t9)); |
3591 DCHECK(!object_size.is(t9)); | |
3592 DCHECK(!scratch.is(t9) && !result_end.is(t9) && !result.is(t9)); | |
3593 | 3587 |
3594 // Check relative positions of allocation top and limit addresses. | 3588 // Check relative positions of allocation top and limit addresses. |
3595 // ARM adds additional checks to make sure the ldm instruction can be | 3589 // ARM adds additional checks to make sure the ldm instruction can be |
3596 // used. On MIPS we don't have ldm so we don't need additional checks either. | 3590 // used. On MIPS we don't have ldm so we don't need additional checks either. |
3597 ExternalReference allocation_top = | 3591 ExternalReference allocation_top = |
3598 AllocationUtils::GetAllocationTopReference(isolate(), flags); | 3592 AllocationUtils::GetAllocationTopReference(isolate(), flags); |
3599 ExternalReference allocation_limit = | 3593 ExternalReference allocation_limit = |
3600 AllocationUtils::GetAllocationLimitReference(isolate(), flags); | 3594 AllocationUtils::GetAllocationLimitReference(isolate(), flags); |
3601 intptr_t top = | 3595 intptr_t top = reinterpret_cast<intptr_t>(allocation_top.address()); |
3602 reinterpret_cast<intptr_t>(allocation_top.address()); | 3596 intptr_t limit = reinterpret_cast<intptr_t>(allocation_limit.address()); |
3603 intptr_t limit = | |
3604 reinterpret_cast<intptr_t>(allocation_limit.address()); | |
3605 DCHECK((limit - top) == kPointerSize); | 3597 DCHECK((limit - top) == kPointerSize); |
3606 | 3598 |
3607 // Set up allocation top address and object size registers. | 3599 // Set up allocation top address and object size registers. |
3608 Register topaddr = scratch; | 3600 Register top_address = scratch; |
3609 li(topaddr, Operand(allocation_top)); | 3601 // This code stores a temporary value in t9. |
| 3602 Register alloc_limit = t9; |
| 3603 li(top_address, Operand(allocation_top)); |
3610 | 3604 |
3611 // This code stores a temporary value in t9. | |
3612 if ((flags & RESULT_CONTAINS_TOP) == 0) { | 3605 if ((flags & RESULT_CONTAINS_TOP) == 0) { |
3613 // Load allocation top into result and allocation limit into t9. | 3606 // Load allocation top into result and allocation limit into alloc_limit. |
3614 ld(result, MemOperand(topaddr)); | 3607 ld(result, MemOperand(top_address)); |
3615 ld(t9, MemOperand(topaddr, kPointerSize)); | 3608 ld(alloc_limit, MemOperand(top_address, kPointerSize)); |
3616 } else { | 3609 } else { |
3617 if (emit_debug_code()) { | 3610 if (emit_debug_code()) { |
3618 // Assert that result actually contains top on entry. t9 is used | 3611 // Assert that result actually contains top on entry. |
3619 // immediately below so this use of t9 does not cause difference with | 3612 ld(alloc_limit, MemOperand(top_address)); |
3620 // respect to register content between debug and release mode. | 3613 Check(eq, kUnexpectedAllocationTop, result, Operand(alloc_limit)); |
3621 ld(t9, MemOperand(topaddr)); | |
3622 Check(eq, kUnexpectedAllocationTop, result, Operand(t9)); | |
3623 } | 3614 } |
3624 // Load allocation limit into t9. Result already contains allocation top. | 3615 // Load allocation limit. Result already contains allocation top. |
3625 ld(t9, MemOperand(topaddr, static_cast<int32_t>(limit - top))); | 3616 ld(alloc_limit, MemOperand(top_address, static_cast<int32_t>(limit - top))); |
3626 } | 3617 } |
3627 | 3618 |
3628 DCHECK(kPointerSize == kDoubleSize); | 3619 // We can ignore DOUBLE_ALIGNMENT flags here because doubles and pointers have |
| 3620 // the same alignment on ARM64. |
| 3621 STATIC_ASSERT(kPointerAlignment == kDoubleAlignment); |
| 3622 |
3629 if (emit_debug_code()) { | 3623 if (emit_debug_code()) { |
3630 And(at, result, Operand(kDoubleAlignmentMask)); | 3624 And(at, result, Operand(kDoubleAlignmentMask)); |
3631 Check(eq, kAllocationIsNotDoubleAligned, at, Operand(zero_reg)); | 3625 Check(eq, kAllocationIsNotDoubleAligned, at, Operand(zero_reg)); |
3632 } | 3626 } |
3633 | 3627 |
3634 // Calculate new top and bail out if new space is exhausted. Use result | 3628 // Calculate new top and bail out if new space is exhausted. Use result |
3635 // to calculate the new top. Object size may be in words so a shift is | 3629 // to calculate the new top. Object size may be in words so a shift is |
3636 // required to get the number of bytes. | 3630 // required to get the number of bytes. |
3637 if ((flags & SIZE_IN_WORDS) != 0) { | 3631 if ((flags & SIZE_IN_WORDS) != 0) { |
3638 dsll(result_end, object_size, kPointerSizeLog2); | 3632 dsll(result_end, object_size, kPointerSizeLog2); |
3639 Daddu(result_end, result, result_end); | 3633 Daddu(result_end, result, result_end); |
3640 } else { | 3634 } else { |
3641 Daddu(result_end, result, Operand(object_size)); | 3635 Daddu(result_end, result, Operand(object_size)); |
3642 } | 3636 } |
3643 Branch(gc_required, Ugreater, result_end, Operand(t9)); | 3637 Branch(gc_required, Ugreater, result_end, Operand(alloc_limit)); |
3644 | 3638 |
3645 // Update allocation top. result temporarily holds the new top. | 3639 // Update allocation top. result temporarily holds the new top. |
3646 if (emit_debug_code()) { | 3640 if (emit_debug_code()) { |
3647 And(t9, result_end, Operand(kObjectAlignmentMask)); | 3641 And(at, result_end, Operand(kObjectAlignmentMask)); |
3648 Check(eq, kUnalignedAllocationInNewSpace, t9, Operand(zero_reg)); | 3642 Check(eq, kUnalignedAllocationInNewSpace, at, Operand(zero_reg)); |
3649 } | 3643 } |
3650 sd(result_end, MemOperand(topaddr)); | 3644 sd(result_end, MemOperand(top_address)); |
3651 | 3645 |
3652 // Tag object if requested. | 3646 // Tag object if requested. |
3653 if ((flags & TAG_OBJECT) != 0) { | 3647 if ((flags & TAG_OBJECT) != 0) { |
3654 Daddu(result, result, Operand(kHeapObjectTag)); | 3648 Daddu(result, result, Operand(kHeapObjectTag)); |
3655 } | 3649 } |
3656 } | 3650 } |
3657 | 3651 |
3658 | 3652 |
3659 void MacroAssembler::AllocateTwoByteString(Register result, | 3653 void MacroAssembler::AllocateTwoByteString(Register result, |
3660 Register length, | 3654 Register length, |
(...skipping 2601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6262 if (mag.shift > 0) sra(result, result, mag.shift); | 6256 if (mag.shift > 0) sra(result, result, mag.shift); |
6263 srl(at, dividend, 31); | 6257 srl(at, dividend, 31); |
6264 Addu(result, result, Operand(at)); | 6258 Addu(result, result, Operand(at)); |
6265 } | 6259 } |
6266 | 6260 |
6267 | 6261 |
6268 } // namespace internal | 6262 } // namespace internal |
6269 } // namespace v8 | 6263 } // namespace v8 |
6270 | 6264 |
6271 #endif // V8_TARGET_ARCH_MIPS64 | 6265 #endif // V8_TARGET_ARCH_MIPS64 |
OLD | NEW |