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