| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 #if V8_TARGET_ARCH_ARM64 | 5 #if V8_TARGET_ARCH_ARM64 |
| 6 | 6 |
| 7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
| 8 #include "src/base/division-by-constant.h" | 8 #include "src/base/division-by-constant.h" |
| 9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
| 10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
| (...skipping 3055 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3066 // Check relative positions of allocation top and limit addresses. | 3066 // Check relative positions of allocation top and limit addresses. |
| 3067 // The values must be adjacent in memory to allow the use of LDP. | 3067 // The values must be adjacent in memory to allow the use of LDP. |
| 3068 ExternalReference heap_allocation_top = | 3068 ExternalReference heap_allocation_top = |
| 3069 AllocationUtils::GetAllocationTopReference(isolate(), flags); | 3069 AllocationUtils::GetAllocationTopReference(isolate(), flags); |
| 3070 ExternalReference heap_allocation_limit = | 3070 ExternalReference heap_allocation_limit = |
| 3071 AllocationUtils::GetAllocationLimitReference(isolate(), flags); | 3071 AllocationUtils::GetAllocationLimitReference(isolate(), flags); |
| 3072 intptr_t top = reinterpret_cast<intptr_t>(heap_allocation_top.address()); | 3072 intptr_t top = reinterpret_cast<intptr_t>(heap_allocation_top.address()); |
| 3073 intptr_t limit = reinterpret_cast<intptr_t>(heap_allocation_limit.address()); | 3073 intptr_t limit = reinterpret_cast<intptr_t>(heap_allocation_limit.address()); |
| 3074 DCHECK((limit - top) == kPointerSize); | 3074 DCHECK((limit - top) == kPointerSize); |
| 3075 | 3075 |
| 3076 // Set up allocation top address and object size registers. | 3076 // Set up allocation top address and allocation limit registers. |
| 3077 Register top_address = scratch1; | 3077 Register top_address = scratch1; |
| 3078 Register allocation_limit = scratch2; | 3078 Register alloc_limit = scratch2; |
| 3079 Register result_end = scratch3; |
| 3079 Mov(top_address, Operand(heap_allocation_top)); | 3080 Mov(top_address, Operand(heap_allocation_top)); |
| 3080 | 3081 |
| 3081 if ((flags & RESULT_CONTAINS_TOP) == 0) { | 3082 if ((flags & RESULT_CONTAINS_TOP) == 0) { |
| 3082 // Load allocation top into result and the allocation limit. | 3083 // Load allocation top into result and allocation limit into alloc_limit. |
| 3083 Ldp(result, allocation_limit, MemOperand(top_address)); | 3084 Ldp(result, alloc_limit, MemOperand(top_address)); |
| 3084 } else { | 3085 } else { |
| 3085 if (emit_debug_code()) { | 3086 if (emit_debug_code()) { |
| 3086 // Assert that result actually contains top on entry. | 3087 // Assert that result actually contains top on entry. |
| 3087 Ldr(scratch3, MemOperand(top_address)); | 3088 Ldr(alloc_limit, MemOperand(top_address)); |
| 3088 Cmp(result, scratch3); | 3089 Cmp(result, alloc_limit); |
| 3089 Check(eq, kUnexpectedAllocationTop); | 3090 Check(eq, kUnexpectedAllocationTop); |
| 3090 } | 3091 } |
| 3091 // Load the allocation limit. 'result' already contains the allocation top. | 3092 // Load allocation limit. Result already contains allocation top. |
| 3092 Ldr(allocation_limit, MemOperand(top_address, limit - top)); | 3093 Ldr(alloc_limit, MemOperand(top_address, limit - top)); |
| 3093 } | 3094 } |
| 3094 | 3095 |
| 3095 // We can ignore DOUBLE_ALIGNMENT flags here because doubles and pointers have | 3096 // We can ignore DOUBLE_ALIGNMENT flags here because doubles and pointers have |
| 3096 // the same alignment on ARM64. | 3097 // the same alignment on ARM64. |
| 3097 STATIC_ASSERT(kPointerAlignment == kDoubleAlignment); | 3098 STATIC_ASSERT(kPointerAlignment == kDoubleAlignment); |
| 3098 | 3099 |
| 3099 // Calculate new top and bail out if new space is exhausted. | 3100 // Calculate new top and bail out if new space is exhausted. |
| 3100 Adds(scratch3, result, object_size); | 3101 Adds(result_end, result, object_size); |
| 3101 Ccmp(scratch3, allocation_limit, CFlag, cc); | 3102 Ccmp(result_end, alloc_limit, CFlag, cc); |
| 3102 B(hi, gc_required); | 3103 B(hi, gc_required); |
| 3103 Str(scratch3, MemOperand(top_address)); | 3104 Str(result_end, MemOperand(top_address)); |
| 3104 | 3105 |
| 3105 // Tag the object if requested. | 3106 // Tag the object if requested. |
| 3106 if ((flags & TAG_OBJECT) != 0) { | 3107 if ((flags & TAG_OBJECT) != 0) { |
| 3107 ObjectTag(result, result); | 3108 ObjectTag(result, result); |
| 3108 } | 3109 } |
| 3109 } | 3110 } |
| 3110 | 3111 |
| 3111 | 3112 |
| 3112 void MacroAssembler::Allocate(Register object_size, Register result, | 3113 void MacroAssembler::Allocate(Register object_size, Register result, |
| 3113 Register result_end, Register scratch, | 3114 Register result_end, Register scratch, |
| 3114 Label* gc_required, AllocationFlags flags) { | 3115 Label* gc_required, AllocationFlags flags) { |
| 3115 if (!FLAG_inline_new) { | 3116 if (!FLAG_inline_new) { |
| 3116 if (emit_debug_code()) { | 3117 if (emit_debug_code()) { |
| 3117 // Trash the registers to simulate an allocation failure. | 3118 // Trash the registers to simulate an allocation failure. |
| 3118 // We apply salt to the original zap value to easily spot the values. | 3119 // We apply salt to the original zap value to easily spot the values. |
| 3119 Mov(result, (kDebugZapValue & ~0xffL) | 0x11L); | 3120 Mov(result, (kDebugZapValue & ~0xffL) | 0x11L); |
| 3120 Mov(scratch, (kDebugZapValue & ~0xffL) | 0x21L); | 3121 Mov(scratch, (kDebugZapValue & ~0xffL) | 0x21L); |
| 3121 Mov(result_end, (kDebugZapValue & ~0xffL) | 0x21L); | 3122 Mov(result_end, (kDebugZapValue & ~0xffL) | 0x21L); |
| 3122 } | 3123 } |
| 3123 B(gc_required); | 3124 B(gc_required); |
| 3124 return; | 3125 return; |
| 3125 } | 3126 } |
| 3126 | 3127 |
| 3127 UseScratchRegisterScope temps(this); | 3128 UseScratchRegisterScope temps(this); |
| 3128 Register scratch2 = temps.AcquireX(); | 3129 Register scratch2 = temps.AcquireX(); |
| 3129 | 3130 |
| 3130 DCHECK(!AreAliased(object_size, result, scratch, scratch2, result_end)); | 3131 // |object_size| and |result_end| may overlap, other registers must not. |
| 3132 DCHECK(!AreAliased(object_size, result, scratch, scratch2)); |
| 3133 DCHECK(!AreAliased(result_end, result, scratch, scratch2)); |
| 3131 DCHECK(object_size.Is64Bits() && result.Is64Bits() && scratch.Is64Bits() && | 3134 DCHECK(object_size.Is64Bits() && result.Is64Bits() && scratch.Is64Bits() && |
| 3132 result_end.Is64Bits()); | 3135 result_end.Is64Bits()); |
| 3133 | 3136 |
| 3134 // Check relative positions of allocation top and limit addresses. | 3137 // Check relative positions of allocation top and limit addresses. |
| 3135 // The values must be adjacent in memory to allow the use of LDP. | 3138 // The values must be adjacent in memory to allow the use of LDP. |
| 3136 ExternalReference heap_allocation_top = | 3139 ExternalReference heap_allocation_top = |
| 3137 AllocationUtils::GetAllocationTopReference(isolate(), flags); | 3140 AllocationUtils::GetAllocationTopReference(isolate(), flags); |
| 3138 ExternalReference heap_allocation_limit = | 3141 ExternalReference heap_allocation_limit = |
| 3139 AllocationUtils::GetAllocationLimitReference(isolate(), flags); | 3142 AllocationUtils::GetAllocationLimitReference(isolate(), flags); |
| 3140 intptr_t top = reinterpret_cast<intptr_t>(heap_allocation_top.address()); | 3143 intptr_t top = reinterpret_cast<intptr_t>(heap_allocation_top.address()); |
| 3141 intptr_t limit = reinterpret_cast<intptr_t>(heap_allocation_limit.address()); | 3144 intptr_t limit = reinterpret_cast<intptr_t>(heap_allocation_limit.address()); |
| 3142 DCHECK((limit - top) == kPointerSize); | 3145 DCHECK((limit - top) == kPointerSize); |
| 3143 | 3146 |
| 3144 // Set up allocation top address and object size registers. | 3147 // Set up allocation top address and allocation limit registers. |
| 3145 Register top_address = scratch; | 3148 Register top_address = scratch; |
| 3146 Register allocation_limit = scratch2; | 3149 Register alloc_limit = scratch2; |
| 3147 Mov(top_address, heap_allocation_top); | 3150 Mov(top_address, heap_allocation_top); |
| 3148 | 3151 |
| 3149 if ((flags & RESULT_CONTAINS_TOP) == 0) { | 3152 if ((flags & RESULT_CONTAINS_TOP) == 0) { |
| 3150 // Load allocation top into result and the allocation limit. | 3153 // Load allocation top into result and allocation limit into alloc_limit. |
| 3151 Ldp(result, allocation_limit, MemOperand(top_address)); | 3154 Ldp(result, alloc_limit, MemOperand(top_address)); |
| 3152 } else { | 3155 } else { |
| 3153 if (emit_debug_code()) { | 3156 if (emit_debug_code()) { |
| 3154 // Assert that result actually contains top on entry. | 3157 // Assert that result actually contains top on entry. |
| 3155 Ldr(result_end, MemOperand(top_address)); | 3158 Ldr(alloc_limit, MemOperand(top_address)); |
| 3156 Cmp(result, result_end); | 3159 Cmp(result, alloc_limit); |
| 3157 Check(eq, kUnexpectedAllocationTop); | 3160 Check(eq, kUnexpectedAllocationTop); |
| 3158 } | 3161 } |
| 3159 // Load the allocation limit. 'result' already contains the allocation top. | 3162 // Load allocation limit. Result already contains allocation top. |
| 3160 Ldr(allocation_limit, MemOperand(top_address, limit - top)); | 3163 Ldr(alloc_limit, MemOperand(top_address, limit - top)); |
| 3161 } | 3164 } |
| 3162 | 3165 |
| 3163 // We can ignore DOUBLE_ALIGNMENT flags here because doubles and pointers have | 3166 // We can ignore DOUBLE_ALIGNMENT flags here because doubles and pointers have |
| 3164 // the same alignment on ARM64. | 3167 // the same alignment on ARM64. |
| 3165 STATIC_ASSERT(kPointerAlignment == kDoubleAlignment); | 3168 STATIC_ASSERT(kPointerAlignment == kDoubleAlignment); |
| 3166 | 3169 |
| 3167 // Calculate new top and bail out if new space is exhausted | 3170 // Calculate new top and bail out if new space is exhausted |
| 3168 if ((flags & SIZE_IN_WORDS) != 0) { | 3171 if ((flags & SIZE_IN_WORDS) != 0) { |
| 3169 Adds(result_end, result, Operand(object_size, LSL, kPointerSizeLog2)); | 3172 Adds(result_end, result, Operand(object_size, LSL, kPointerSizeLog2)); |
| 3170 } else { | 3173 } else { |
| 3171 Adds(result_end, result, object_size); | 3174 Adds(result_end, result, object_size); |
| 3172 } | 3175 } |
| 3173 | 3176 |
| 3174 if (emit_debug_code()) { | 3177 if (emit_debug_code()) { |
| 3175 Tst(result_end, kObjectAlignmentMask); | 3178 Tst(result_end, kObjectAlignmentMask); |
| 3176 Check(eq, kUnalignedAllocationInNewSpace); | 3179 Check(eq, kUnalignedAllocationInNewSpace); |
| 3177 } | 3180 } |
| 3178 | 3181 |
| 3179 Ccmp(result_end, allocation_limit, CFlag, cc); | 3182 Ccmp(result_end, alloc_limit, CFlag, cc); |
| 3180 B(hi, gc_required); | 3183 B(hi, gc_required); |
| 3181 Str(result_end, MemOperand(top_address)); | 3184 Str(result_end, MemOperand(top_address)); |
| 3182 | 3185 |
| 3183 // Tag the object if requested. | 3186 // Tag the object if requested. |
| 3184 if ((flags & TAG_OBJECT) != 0) { | 3187 if ((flags & TAG_OBJECT) != 0) { |
| 3185 ObjectTag(result, result); | 3188 ObjectTag(result, result); |
| 3186 } | 3189 } |
| 3187 } | 3190 } |
| 3188 | 3191 |
| 3189 | 3192 |
| (...skipping 1873 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5063 } | 5066 } |
| 5064 | 5067 |
| 5065 | 5068 |
| 5066 #undef __ | 5069 #undef __ |
| 5067 | 5070 |
| 5068 | 5071 |
| 5069 } // namespace internal | 5072 } // namespace internal |
| 5070 } // namespace v8 | 5073 } // namespace v8 |
| 5071 | 5074 |
| 5072 #endif // V8_TARGET_ARCH_ARM64 | 5075 #endif // V8_TARGET_ARCH_ARM64 |
| OLD | NEW |