Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(135)

Side by Side Diff: src/arm/macro-assembler-arm.cc

Issue 2028633002: Provide a tagged allocation top pointer. Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Update Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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_ARM 7 #if V8_TARGET_ARCH_ARM
8 8
9 #include "src/base/bits.h" 9 #include "src/base/bits.h"
10 #include "src/base/division-by-constant.h" 10 #include "src/base/division-by-constant.h"
(...skipping 1991 matching lines...) Expand 10 before | Expand all | Expand 10 after
2002 Check(eq, kUnexpectedAllocationTop); 2002 Check(eq, kUnexpectedAllocationTop);
2003 } 2003 }
2004 // Load allocation limit. Result already contains allocation top. 2004 // Load allocation limit. Result already contains allocation top.
2005 ldr(alloc_limit, MemOperand(top_address, limit - top)); 2005 ldr(alloc_limit, MemOperand(top_address, limit - top));
2006 } 2006 }
2007 2007
2008 if ((flags & DOUBLE_ALIGNMENT) != 0) { 2008 if ((flags & DOUBLE_ALIGNMENT) != 0) {
2009 // Align the next allocation. Storing the filler map without checking top is 2009 // Align the next allocation. Storing the filler map without checking top is
2010 // safe in new-space because the limit of the heap is aligned there. 2010 // safe in new-space because the limit of the heap is aligned there.
2011 STATIC_ASSERT(kPointerAlignment * 2 == kDoubleAlignment); 2011 STATIC_ASSERT(kPointerAlignment * 2 == kDoubleAlignment);
2012 and_(result_end, result, Operand(kDoubleAlignmentMask), SetCC); 2012 and_(result_end, result, Operand(kDoubleAlignmentMaskTagged), SetCC);
2013 Label aligned; 2013 Label aligned;
2014 b(eq, &aligned); 2014 b(eq, &aligned);
2015 if ((flags & PRETENURE) != 0) { 2015 if ((flags & PRETENURE) != 0) {
2016 cmp(result, Operand(alloc_limit)); 2016 cmp(result, Operand(alloc_limit));
2017 b(hs, gc_required); 2017 b(hs, gc_required);
2018 } 2018 }
2019 mov(result_end, Operand(isolate()->factory()->one_pointer_filler_map())); 2019 mov(result_end, Operand(isolate()->factory()->one_pointer_filler_map()));
2020 str(result_end, MemOperand(result, kDoubleSize / 2, PostIndex)); 2020 str(result_end, MemOperand(result, -kHeapObjectTag));
2021 add(result_end, result_end, Operand(kDoubleSize / 2));
2021 bind(&aligned); 2022 bind(&aligned);
2022 } 2023 }
2023 2024
2024 // Calculate new top and bail out if new space is exhausted. Use result 2025 // Calculate new top and bail out if new space is exhausted. Use result
2025 // to calculate the new top. We must preserve the ip register at this 2026 // to calculate the new top. We must preserve the ip register at this
2026 // point, so we cannot just use add(). 2027 // point, so we cannot just use add().
2027 DCHECK(object_size > 0); 2028 DCHECK(object_size > 0);
2028 Register source = result; 2029 Register source = result;
2029 Condition cond = al; 2030 Condition cond = al;
2030 int shift = 0; 2031 int shift = 0;
(...skipping 12 matching lines...) Expand all
2043 } 2044 }
2044 } 2045 }
2045 2046
2046 cmp(result_end, Operand(alloc_limit)); 2047 cmp(result_end, Operand(alloc_limit));
2047 b(hi, gc_required); 2048 b(hi, gc_required);
2048 2049
2049 if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) { 2050 if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
2050 // The top pointer is not updated for allocation folding dominators. 2051 // The top pointer is not updated for allocation folding dominators.
2051 str(result_end, MemOperand(top_address)); 2052 str(result_end, MemOperand(top_address));
2052 } 2053 }
2053
2054 // Tag object.
2055 add(result, result, Operand(kHeapObjectTag));
2056 } 2054 }
2057 2055
2058 2056
2059 void MacroAssembler::Allocate(Register object_size, Register result, 2057 void MacroAssembler::Allocate(Register object_size, Register result,
2060 Register result_end, Register scratch, 2058 Register result_end, Register scratch,
2061 Label* gc_required, AllocationFlags flags) { 2059 Label* gc_required, AllocationFlags flags) {
2062 DCHECK((flags & ALLOCATION_FOLDED) == 0); 2060 DCHECK((flags & ALLOCATION_FOLDED) == 0);
2063 if (!FLAG_inline_new) { 2061 if (!FLAG_inline_new) {
2064 if (emit_debug_code()) { 2062 if (emit_debug_code()) {
2065 // Trash the registers to simulate an allocation failure. 2063 // Trash the registers to simulate an allocation failure.
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
2108 Check(eq, kUnexpectedAllocationTop); 2106 Check(eq, kUnexpectedAllocationTop);
2109 } 2107 }
2110 // Load allocation limit. Result already contains allocation top. 2108 // Load allocation limit. Result already contains allocation top.
2111 ldr(alloc_limit, MemOperand(top_address, limit - top)); 2109 ldr(alloc_limit, MemOperand(top_address, limit - top));
2112 } 2110 }
2113 2111
2114 if ((flags & DOUBLE_ALIGNMENT) != 0) { 2112 if ((flags & DOUBLE_ALIGNMENT) != 0) {
2115 // Align the next allocation. Storing the filler map without checking top is 2113 // Align the next allocation. Storing the filler map without checking top is
2116 // safe in new-space because the limit of the heap is aligned there. 2114 // safe in new-space because the limit of the heap is aligned there.
2117 DCHECK(kPointerAlignment * 2 == kDoubleAlignment); 2115 DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
2118 and_(result_end, result, Operand(kDoubleAlignmentMask), SetCC); 2116 and_(result_end, result, Operand(kDoubleAlignmentMaskTagged), SetCC);
2119 Label aligned; 2117 Label aligned;
2120 b(eq, &aligned); 2118 b(eq, &aligned);
2121 if ((flags & PRETENURE) != 0) { 2119 if ((flags & PRETENURE) != 0) {
2122 cmp(result, Operand(alloc_limit)); 2120 cmp(result, Operand(alloc_limit));
2123 b(hs, gc_required); 2121 b(hs, gc_required);
2124 } 2122 }
2125 mov(result_end, Operand(isolate()->factory()->one_pointer_filler_map())); 2123 mov(result_end, Operand(isolate()->factory()->one_pointer_filler_map()));
2126 str(result_end, MemOperand(result, kDoubleSize / 2, PostIndex)); 2124 str(result_end, MemOperand(result, -kHeapObjectTag));
2125 add(result_end, result_end, Operand(kDoubleSize / 2));
2127 bind(&aligned); 2126 bind(&aligned);
2128 } 2127 }
2129 2128
2130 // Calculate new top and bail out if new space is exhausted. Use result 2129 // Calculate new top and bail out if new space is exhausted. Use result
2131 // to calculate the new top. Object size may be in words so a shift is 2130 // to calculate the new top. Object size may be in words so a shift is
2132 // required to get the number of bytes. 2131 // required to get the number of bytes.
2133 if ((flags & SIZE_IN_WORDS) != 0) { 2132 if ((flags & SIZE_IN_WORDS) != 0) {
2134 add(result_end, result, Operand(object_size, LSL, kPointerSizeLog2), SetCC); 2133 add(result_end, result, Operand(object_size, LSL, kPointerSizeLog2), SetCC);
2135 } else { 2134 } else {
2136 add(result_end, result, Operand(object_size), SetCC); 2135 add(result_end, result, Operand(object_size), SetCC);
2137 } 2136 }
2138 2137
2139 cmp(result_end, Operand(alloc_limit)); 2138 cmp(result_end, Operand(alloc_limit));
2140 b(hi, gc_required); 2139 b(hi, gc_required);
2141 2140
2142 // Update allocation top. result temporarily holds the new top. 2141 // Update allocation top. result temporarily holds the new top.
2143 if (emit_debug_code()) { 2142 if (emit_debug_code()) {
2144 tst(result_end, Operand(kObjectAlignmentMask)); 2143 tst(result_end, Operand(kObjectAlignmentMask));
2145 Check(eq, kUnalignedAllocationInNewSpace); 2144 Check(ne, kUnalignedAllocationInNewSpace);
2146 } 2145 }
2147 if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) { 2146 if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
2148 // The top pointer is not updated for allocation folding dominators. 2147 // The top pointer is not updated for allocation folding dominators.
2149 str(result_end, MemOperand(top_address)); 2148 str(result_end, MemOperand(top_address));
2150 } 2149 }
2151
2152 // Tag object.
2153 add(result, result, Operand(kHeapObjectTag));
2154 } 2150 }
2155 2151
2156 void MacroAssembler::FastAllocate(Register object_size, Register result, 2152 void MacroAssembler::FastAllocate(Register object_size, Register result,
2157 Register result_end, Register scratch, 2153 Register result_end, Register scratch,
2158 AllocationFlags flags) { 2154 AllocationFlags flags) {
2159 // |object_size| and |result_end| may overlap if the DOUBLE_ALIGNMENT flag 2155 // |object_size| and |result_end| may overlap if the DOUBLE_ALIGNMENT flag
2160 // is not specified. Other registers must not overlap. 2156 // is not specified. Other registers must not overlap.
2161 DCHECK(!AreAliased(object_size, result, scratch, ip)); 2157 DCHECK(!AreAliased(object_size, result, scratch, ip));
2162 DCHECK(!AreAliased(result_end, result, scratch, ip)); 2158 DCHECK(!AreAliased(result_end, result, scratch, ip));
2163 DCHECK((flags & DOUBLE_ALIGNMENT) == 0 || !object_size.is(result_end)); 2159 DCHECK((flags & DOUBLE_ALIGNMENT) == 0 || !object_size.is(result_end));
2164 2160
2165 ExternalReference allocation_top = 2161 ExternalReference allocation_top =
2166 AllocationUtils::GetAllocationTopReference(isolate(), flags); 2162 AllocationUtils::GetAllocationTopReference(isolate(), flags);
2167 2163
2168 Register top_address = scratch; 2164 Register top_address = scratch;
2169 mov(top_address, Operand(allocation_top)); 2165 mov(top_address, Operand(allocation_top));
2170 ldr(result, MemOperand(top_address)); 2166 ldr(result, MemOperand(top_address));
2171 2167
2172 if ((flags & DOUBLE_ALIGNMENT) != 0) { 2168 if ((flags & DOUBLE_ALIGNMENT) != 0) {
2173 // Align the next allocation. Storing the filler map without checking top is 2169 // Align the next allocation. Storing the filler map without checking top is
2174 // safe in new-space because the limit of the heap is aligned there. 2170 // safe in new-space because the limit of the heap is aligned there.
2175 DCHECK(kPointerAlignment * 2 == kDoubleAlignment); 2171 DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
2176 and_(result_end, result, Operand(kDoubleAlignmentMask), SetCC); 2172 and_(result_end, result, Operand(kDoubleAlignmentMaskTagged), SetCC);
2177 Label aligned; 2173 Label aligned;
2178 b(eq, &aligned); 2174 b(eq, &aligned);
2179 mov(result_end, Operand(isolate()->factory()->one_pointer_filler_map())); 2175 mov(result_end, Operand(isolate()->factory()->one_pointer_filler_map()));
2180 str(result_end, MemOperand(result, kDoubleSize / 2, PostIndex)); 2176 str(result_end, MemOperand(result, -kHeapObjectTag));
2177 add(result_end, result_end, Operand(kDoubleSize / 2));
2181 bind(&aligned); 2178 bind(&aligned);
2182 } 2179 }
2183 2180
2184 // Calculate new top using result. Object size may be in words so a shift is 2181 // Calculate new top using result. Object size may be in words so a shift is
2185 // required to get the number of bytes. 2182 // required to get the number of bytes.
2186 if ((flags & SIZE_IN_WORDS) != 0) { 2183 if ((flags & SIZE_IN_WORDS) != 0) {
2187 add(result_end, result, Operand(object_size, LSL, kPointerSizeLog2), SetCC); 2184 add(result_end, result, Operand(object_size, LSL, kPointerSizeLog2), SetCC);
2188 } else { 2185 } else {
2189 add(result_end, result, Operand(object_size), SetCC); 2186 add(result_end, result, Operand(object_size), SetCC);
2190 } 2187 }
2191 2188
2192 // Update allocation top. result temporarily holds the new top. 2189 // Update allocation top. result temporarily holds the new top.
2193 if (emit_debug_code()) { 2190 if (emit_debug_code()) {
2194 tst(result_end, Operand(kObjectAlignmentMask)); 2191 tst(result_end, Operand(kObjectAlignmentMask));
2195 Check(eq, kUnalignedAllocationInNewSpace); 2192 Check(ne, kUnalignedAllocationInNewSpace);
2196 } 2193 }
2197 // The top pointer is not updated for allocation folding dominators. 2194 // The top pointer is not updated for allocation folding dominators.
2198 str(result_end, MemOperand(top_address)); 2195 str(result_end, MemOperand(top_address));
2199
2200 add(result, result, Operand(kHeapObjectTag));
2201 } 2196 }
2202 2197
2203 void MacroAssembler::FastAllocate(int object_size, Register result, 2198 void MacroAssembler::FastAllocate(int object_size, Register result,
2204 Register scratch1, Register scratch2, 2199 Register scratch1, Register scratch2,
2205 AllocationFlags flags) { 2200 AllocationFlags flags) {
2206 DCHECK(object_size <= Page::kMaxRegularHeapObjectSize); 2201 DCHECK(object_size <= Page::kMaxRegularHeapObjectSize);
2207 DCHECK(!AreAliased(result, scratch1, scratch2, ip)); 2202 DCHECK(!AreAliased(result, scratch1, scratch2, ip));
2208 2203
2209 // Make object size into bytes. 2204 // Make object size into bytes.
2210 if ((flags & SIZE_IN_WORDS) != 0) { 2205 if ((flags & SIZE_IN_WORDS) != 0) {
2211 object_size *= kPointerSize; 2206 object_size *= kPointerSize;
2212 } 2207 }
2213 DCHECK_EQ(0, object_size & kObjectAlignmentMask); 2208 DCHECK_EQ(0, object_size & kObjectAlignmentMask);
2214 2209
2215 ExternalReference allocation_top = 2210 ExternalReference allocation_top =
2216 AllocationUtils::GetAllocationTopReference(isolate(), flags); 2211 AllocationUtils::GetAllocationTopReference(isolate(), flags);
2217 2212
2218 // Set up allocation top address register. 2213 // Set up allocation top address register.
2219 Register top_address = scratch1; 2214 Register top_address = scratch1;
2220 Register result_end = scratch2; 2215 Register result_end = scratch2;
2221 mov(top_address, Operand(allocation_top)); 2216 mov(top_address, Operand(allocation_top));
2222 ldr(result, MemOperand(top_address)); 2217 ldr(result, MemOperand(top_address));
2223 2218
2224 if ((flags & DOUBLE_ALIGNMENT) != 0) { 2219 if ((flags & DOUBLE_ALIGNMENT) != 0) {
2225 // Align the next allocation. Storing the filler map without checking top is 2220 // Align the next allocation. Storing the filler map without checking top is
2226 // safe in new-space because the limit of the heap is aligned there. 2221 // safe in new-space because the limit of the heap is aligned there.
2227 STATIC_ASSERT(kPointerAlignment * 2 == kDoubleAlignment); 2222 STATIC_ASSERT(kPointerAlignment * 2 == kDoubleAlignment);
2228 and_(result_end, result, Operand(kDoubleAlignmentMask), SetCC); 2223 and_(result_end, result, Operand(kDoubleAlignmentMaskTagged), SetCC);
2229 Label aligned; 2224 Label aligned;
2230 b(eq, &aligned); 2225 b(eq, &aligned);
2231 mov(result_end, Operand(isolate()->factory()->one_pointer_filler_map())); 2226 mov(result_end, Operand(isolate()->factory()->one_pointer_filler_map()));
2232 str(result_end, MemOperand(result, kDoubleSize / 2, PostIndex)); 2227 str(result_end, MemOperand(result, -kHeapObjectTag));
2228 add(result_end, result_end, Operand(kDoubleSize / 2));
2233 bind(&aligned); 2229 bind(&aligned);
2234 } 2230 }
2235 2231
2236 // Calculate new top using result. Object size may be in words so a shift is 2232 // Calculate new top using result. Object size may be in words so a shift is
2237 // required to get the number of bytes. We must preserve the ip register at 2233 // required to get the number of bytes. We must preserve the ip register at
2238 // this point, so we cannot just use add(). 2234 // this point, so we cannot just use add().
2239 DCHECK(object_size > 0); 2235 DCHECK(object_size > 0);
2240 Register source = result; 2236 Register source = result;
2241 Condition cond = al; 2237 Condition cond = al;
2242 int shift = 0; 2238 int shift = 0;
2243 while (object_size != 0) { 2239 while (object_size != 0) {
2244 if (((object_size >> shift) & 0x03) == 0) { 2240 if (((object_size >> shift) & 0x03) == 0) {
2245 shift += 2; 2241 shift += 2;
2246 } else { 2242 } else {
2247 int bits = object_size & (0xff << shift); 2243 int bits = object_size & (0xff << shift);
2248 object_size -= bits; 2244 object_size -= bits;
2249 shift += 8; 2245 shift += 8;
2250 Operand bits_operand(bits); 2246 Operand bits_operand(bits);
2251 DCHECK(bits_operand.instructions_required(this) == 1); 2247 DCHECK(bits_operand.instructions_required(this) == 1);
2252 add(result_end, source, bits_operand, LeaveCC, cond); 2248 add(result_end, source, bits_operand, LeaveCC, cond);
2253 source = result_end; 2249 source = result_end;
2254 cond = cc; 2250 cond = cc;
2255 } 2251 }
2256 } 2252 }
2257 2253
2258 // The top pointer is not updated for allocation folding dominators. 2254 // The top pointer is not updated for allocation folding dominators.
2259 str(result_end, MemOperand(top_address)); 2255 str(result_end, MemOperand(top_address));
2260
2261 add(result, result, Operand(kHeapObjectTag));
2262 } 2256 }
2263 2257
2264 void MacroAssembler::AllocateTwoByteString(Register result, 2258 void MacroAssembler::AllocateTwoByteString(Register result,
2265 Register length, 2259 Register length,
2266 Register scratch1, 2260 Register scratch1,
2267 Register scratch2, 2261 Register scratch2,
2268 Register scratch3, 2262 Register scratch3,
2269 Label* gc_required) { 2263 Label* gc_required) {
2270 // Calculate the number of bytes needed for the characters in the string while 2264 // Calculate the number of bytes needed for the characters in the string while
2271 // observing object alignment. 2265 // observing object alignment.
(...skipping 1734 matching lines...) Expand 10 before | Expand all | Expand 10 after
4006 } 4000 }
4007 } 4001 }
4008 if (mag.shift > 0) mov(result, Operand(result, ASR, mag.shift)); 4002 if (mag.shift > 0) mov(result, Operand(result, ASR, mag.shift));
4009 add(result, result, Operand(dividend, LSR, 31)); 4003 add(result, result, Operand(dividend, LSR, 31));
4010 } 4004 }
4011 4005
4012 } // namespace internal 4006 } // namespace internal
4013 } // namespace v8 4007 } // namespace v8
4014 4008
4015 #endif // V8_TARGET_ARCH_ARM 4009 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/code-stubs-arm.cc ('k') | src/arm64/code-stubs-arm64.cc » ('j') | src/heap/spaces.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698