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_MIPS | 7 #if V8_TARGET_ARCH_MIPS |
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 4124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4135 Check(eq, kUnexpectedAllocationTop, result, Operand(alloc_limit)); | 4135 Check(eq, kUnexpectedAllocationTop, result, Operand(alloc_limit)); |
4136 } | 4136 } |
4137 // Load allocation limit. Result already contains allocation top. | 4137 // Load allocation limit. Result already contains allocation top. |
4138 lw(alloc_limit, MemOperand(top_address, limit - top)); | 4138 lw(alloc_limit, MemOperand(top_address, limit - top)); |
4139 } | 4139 } |
4140 | 4140 |
4141 if ((flags & DOUBLE_ALIGNMENT) != 0) { | 4141 if ((flags & DOUBLE_ALIGNMENT) != 0) { |
4142 // Align the next allocation. Storing the filler map without checking top is | 4142 // Align the next allocation. Storing the filler map without checking top is |
4143 // safe in new-space because the limit of the heap is aligned there. | 4143 // safe in new-space because the limit of the heap is aligned there. |
4144 DCHECK(kPointerAlignment * 2 == kDoubleAlignment); | 4144 DCHECK(kPointerAlignment * 2 == kDoubleAlignment); |
4145 And(result_end, result, Operand(kDoubleAlignmentMaskTagged)); | 4145 And(result_end, result, Operand(kDoubleAlignmentMask)); |
4146 Label aligned; | 4146 Label aligned; |
4147 Branch(&aligned, eq, result_end, Operand(zero_reg)); | 4147 Branch(&aligned, eq, result_end, Operand(zero_reg)); |
4148 if ((flags & PRETENURE) != 0) { | 4148 if ((flags & PRETENURE) != 0) { |
4149 Branch(gc_required, Ugreater_equal, result, Operand(alloc_limit)); | 4149 Branch(gc_required, Ugreater_equal, result, Operand(alloc_limit)); |
4150 } | 4150 } |
4151 li(result_end, Operand(isolate()->factory()->one_pointer_filler_map())); | 4151 li(result_end, Operand(isolate()->factory()->one_pointer_filler_map())); |
4152 sw(result_end, FieldMemOperand(result, 0)); | 4152 sw(result_end, MemOperand(result)); |
4153 Addu(result, result, Operand(kDoubleSize / 2)); | 4153 Addu(result, result, Operand(kDoubleSize / 2)); |
4154 bind(&aligned); | 4154 bind(&aligned); |
4155 } | 4155 } |
4156 | 4156 |
4157 // Calculate new top and bail out if new space is exhausted. Use result | 4157 // Calculate new top and bail out if new space is exhausted. Use result |
4158 // to calculate the new top. | 4158 // to calculate the new top. |
4159 Addu(result_end, result, Operand(object_size)); | 4159 Addu(result_end, result, Operand(object_size)); |
4160 Branch(gc_required, Ugreater, result_end, Operand(alloc_limit)); | 4160 Branch(gc_required, Ugreater, result_end, Operand(alloc_limit)); |
4161 | 4161 |
4162 if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) { | 4162 if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) { |
4163 // The top pointer is not updated for allocation folding dominators. | 4163 // The top pointer is not updated for allocation folding dominators. |
4164 sw(result_end, MemOperand(top_address)); | 4164 sw(result_end, MemOperand(top_address)); |
4165 } | 4165 } |
| 4166 |
| 4167 // Tag object. |
| 4168 Addu(result, result, Operand(kHeapObjectTag)); |
4166 } | 4169 } |
4167 | 4170 |
4168 | 4171 |
4169 void MacroAssembler::Allocate(Register object_size, Register result, | 4172 void MacroAssembler::Allocate(Register object_size, Register result, |
4170 Register result_end, Register scratch, | 4173 Register result_end, Register scratch, |
4171 Label* gc_required, AllocationFlags flags) { | 4174 Label* gc_required, AllocationFlags flags) { |
4172 DCHECK((flags & ALLOCATION_FOLDED) == 0); | 4175 DCHECK((flags & ALLOCATION_FOLDED) == 0); |
4173 if (!FLAG_inline_new) { | 4176 if (!FLAG_inline_new) { |
4174 if (emit_debug_code()) { | 4177 if (emit_debug_code()) { |
4175 // Trash the registers to simulate an allocation failure. | 4178 // Trash the registers to simulate an allocation failure. |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4215 Check(eq, kUnexpectedAllocationTop, result, Operand(alloc_limit)); | 4218 Check(eq, kUnexpectedAllocationTop, result, Operand(alloc_limit)); |
4216 } | 4219 } |
4217 // Load allocation limit. Result already contains allocation top. | 4220 // Load allocation limit. Result already contains allocation top. |
4218 lw(alloc_limit, MemOperand(top_address, limit - top)); | 4221 lw(alloc_limit, MemOperand(top_address, limit - top)); |
4219 } | 4222 } |
4220 | 4223 |
4221 if ((flags & DOUBLE_ALIGNMENT) != 0) { | 4224 if ((flags & DOUBLE_ALIGNMENT) != 0) { |
4222 // Align the next allocation. Storing the filler map without checking top is | 4225 // Align the next allocation. Storing the filler map without checking top is |
4223 // safe in new-space because the limit of the heap is aligned there. | 4226 // safe in new-space because the limit of the heap is aligned there. |
4224 DCHECK(kPointerAlignment * 2 == kDoubleAlignment); | 4227 DCHECK(kPointerAlignment * 2 == kDoubleAlignment); |
4225 And(result_end, result, Operand(kDoubleAlignmentMaskTagged)); | 4228 And(result_end, result, Operand(kDoubleAlignmentMask)); |
4226 Label aligned; | 4229 Label aligned; |
4227 Branch(&aligned, eq, result_end, Operand(zero_reg)); | 4230 Branch(&aligned, eq, result_end, Operand(zero_reg)); |
4228 if ((flags & PRETENURE) != 0) { | 4231 if ((flags & PRETENURE) != 0) { |
4229 Branch(gc_required, Ugreater_equal, result, Operand(alloc_limit)); | 4232 Branch(gc_required, Ugreater_equal, result, Operand(alloc_limit)); |
4230 } | 4233 } |
4231 li(result_end, Operand(isolate()->factory()->one_pointer_filler_map())); | 4234 li(result_end, Operand(isolate()->factory()->one_pointer_filler_map())); |
4232 sw(result_end, FieldMemOperand(result, 0)); | 4235 sw(result_end, MemOperand(result)); |
4233 Addu(result, result, Operand(kDoubleSize / 2)); | 4236 Addu(result, result, Operand(kDoubleSize / 2)); |
4234 bind(&aligned); | 4237 bind(&aligned); |
4235 } | 4238 } |
4236 | 4239 |
4237 // Calculate new top and bail out if new space is exhausted. Use result | 4240 // Calculate new top and bail out if new space is exhausted. Use result |
4238 // to calculate the new top. Object size may be in words so a shift is | 4241 // to calculate the new top. Object size may be in words so a shift is |
4239 // required to get the number of bytes. | 4242 // required to get the number of bytes. |
4240 if ((flags & SIZE_IN_WORDS) != 0) { | 4243 if ((flags & SIZE_IN_WORDS) != 0) { |
4241 Lsa(result_end, result, object_size, kPointerSizeLog2); | 4244 Lsa(result_end, result, object_size, kPointerSizeLog2); |
4242 } else { | 4245 } else { |
4243 Addu(result_end, result, Operand(object_size)); | 4246 Addu(result_end, result, Operand(object_size)); |
4244 } | 4247 } |
4245 | 4248 |
4246 Branch(gc_required, Ugreater, result_end, Operand(alloc_limit)); | 4249 Branch(gc_required, Ugreater, result_end, Operand(alloc_limit)); |
4247 | 4250 |
4248 // Update allocation top. result temporarily holds the new top. | 4251 // Update allocation top. result temporarily holds the new top. |
4249 if (emit_debug_code()) { | 4252 if (emit_debug_code()) { |
4250 And(alloc_limit, result_end, Operand(kObjectAlignmentMask)); | 4253 And(alloc_limit, result_end, Operand(kObjectAlignmentMask)); |
4251 Check(ne, kUnalignedAllocationInNewSpace, alloc_limit, Operand(zero_reg)); | 4254 Check(eq, kUnalignedAllocationInNewSpace, alloc_limit, Operand(zero_reg)); |
4252 } | 4255 } |
4253 | 4256 |
4254 if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) { | 4257 if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) { |
4255 // The top pointer is not updated for allocation folding dominators. | 4258 // The top pointer is not updated for allocation folding dominators. |
4256 sw(result_end, MemOperand(top_address)); | 4259 sw(result_end, MemOperand(top_address)); |
4257 } | 4260 } |
| 4261 |
| 4262 // Tag object. |
| 4263 Addu(result, result, Operand(kHeapObjectTag)); |
4258 } | 4264 } |
4259 | 4265 |
4260 void MacroAssembler::FastAllocate(int object_size, Register result, | 4266 void MacroAssembler::FastAllocate(int object_size, Register result, |
4261 Register scratch1, Register scratch2, | 4267 Register scratch1, Register scratch2, |
4262 AllocationFlags flags) { | 4268 AllocationFlags flags) { |
4263 DCHECK(object_size <= Page::kMaxRegularHeapObjectSize); | 4269 DCHECK(object_size <= Page::kMaxRegularHeapObjectSize); |
4264 DCHECK(!AreAliased(result, scratch1, scratch2, t9, at)); | 4270 DCHECK(!AreAliased(result, scratch1, scratch2, t9, at)); |
4265 | 4271 |
4266 // Make object size into bytes. | 4272 // Make object size into bytes. |
4267 if ((flags & SIZE_IN_WORDS) != 0) { | 4273 if ((flags & SIZE_IN_WORDS) != 0) { |
4268 object_size *= kPointerSize; | 4274 object_size *= kPointerSize; |
4269 } | 4275 } |
4270 DCHECK_EQ(0, object_size & kObjectAlignmentMask); | 4276 DCHECK_EQ(0, object_size & kObjectAlignmentMask); |
4271 | 4277 |
4272 ExternalReference allocation_top = | 4278 ExternalReference allocation_top = |
4273 AllocationUtils::GetAllocationTopReference(isolate(), flags); | 4279 AllocationUtils::GetAllocationTopReference(isolate(), flags); |
4274 | 4280 |
4275 // Set up allocation top address and allocation limit registers. | 4281 // Set up allocation top address and allocation limit registers. |
4276 Register top_address = scratch1; | 4282 Register top_address = scratch1; |
4277 // This code stores a temporary value in t9. | 4283 // This code stores a temporary value in t9. |
4278 Register result_end = scratch2; | 4284 Register result_end = scratch2; |
4279 li(top_address, Operand(allocation_top)); | 4285 li(top_address, Operand(allocation_top)); |
4280 lw(result, MemOperand(top_address)); | 4286 lw(result, MemOperand(top_address)); |
4281 | 4287 |
4282 if ((flags & DOUBLE_ALIGNMENT) != 0) { | 4288 if ((flags & DOUBLE_ALIGNMENT) != 0) { |
4283 // Align the next allocation. Storing the filler map without checking top is | 4289 // Align the next allocation. Storing the filler map without checking top is |
4284 // safe in new-space because the limit of the heap is aligned there. | 4290 // safe in new-space because the limit of the heap is aligned there. |
4285 DCHECK(kPointerAlignment * 2 == kDoubleAlignment); | 4291 DCHECK(kPointerAlignment * 2 == kDoubleAlignment); |
4286 And(result_end, result, Operand(kDoubleAlignmentMaskTagged)); | 4292 And(result_end, result, Operand(kDoubleAlignmentMask)); |
4287 Label aligned; | 4293 Label aligned; |
4288 Branch(&aligned, eq, result_end, Operand(zero_reg)); | 4294 Branch(&aligned, eq, result_end, Operand(zero_reg)); |
4289 li(result_end, Operand(isolate()->factory()->one_pointer_filler_map())); | 4295 li(result_end, Operand(isolate()->factory()->one_pointer_filler_map())); |
4290 sw(result_end, FieldMemOperand(result, 0)); | 4296 sw(result_end, MemOperand(result)); |
4291 Addu(result, result, Operand(kDoubleSize / 2)); | 4297 Addu(result, result, Operand(kDoubleSize / 2)); |
4292 bind(&aligned); | 4298 bind(&aligned); |
4293 } | 4299 } |
4294 | 4300 |
4295 Addu(result_end, result, Operand(object_size)); | 4301 Addu(result_end, result, Operand(object_size)); |
4296 | 4302 |
4297 // The top pointer is not updated for allocation folding dominators. | 4303 // The top pointer is not updated for allocation folding dominators. |
4298 sw(result_end, MemOperand(top_address)); | 4304 sw(result_end, MemOperand(top_address)); |
| 4305 |
| 4306 Addu(result, result, Operand(kHeapObjectTag)); |
4299 } | 4307 } |
4300 | 4308 |
4301 void MacroAssembler::FastAllocate(Register object_size, Register result, | 4309 void MacroAssembler::FastAllocate(Register object_size, Register result, |
4302 Register result_end, Register scratch, | 4310 Register result_end, Register scratch, |
4303 AllocationFlags flags) { | 4311 AllocationFlags flags) { |
4304 // |object_size| and |result_end| may overlap if the DOUBLE_ALIGNMENT flag | 4312 // |object_size| and |result_end| may overlap if the DOUBLE_ALIGNMENT flag |
4305 // is not specified. Other registers must not overlap. | 4313 // is not specified. Other registers must not overlap. |
4306 DCHECK(!AreAliased(object_size, result, scratch, t9, at)); | 4314 DCHECK(!AreAliased(object_size, result, scratch, t9, at)); |
4307 DCHECK(!AreAliased(result_end, result, scratch, t9, at)); | 4315 DCHECK(!AreAliased(result_end, result, scratch, t9, at)); |
4308 DCHECK((flags & DOUBLE_ALIGNMENT) == 0 || !object_size.is(result_end)); | 4316 DCHECK((flags & DOUBLE_ALIGNMENT) == 0 || !object_size.is(result_end)); |
4309 | 4317 |
4310 ExternalReference allocation_top = | 4318 ExternalReference allocation_top = |
4311 AllocationUtils::GetAllocationTopReference(isolate(), flags); | 4319 AllocationUtils::GetAllocationTopReference(isolate(), flags); |
4312 | 4320 |
4313 // Set up allocation top address and allocation limit registers. | 4321 // Set up allocation top address and allocation limit registers. |
4314 Register top_address = scratch; | 4322 Register top_address = scratch; |
4315 // This code stores a temporary value in t9. | 4323 // This code stores a temporary value in t9. |
4316 li(top_address, Operand(allocation_top)); | 4324 li(top_address, Operand(allocation_top)); |
4317 lw(result, MemOperand(top_address)); | 4325 lw(result, MemOperand(top_address)); |
4318 | 4326 |
4319 if ((flags & DOUBLE_ALIGNMENT) != 0) { | 4327 if ((flags & DOUBLE_ALIGNMENT) != 0) { |
4320 // Align the next allocation. Storing the filler map without checking top is | 4328 // Align the next allocation. Storing the filler map without checking top is |
4321 // safe in new-space because the limit of the heap is aligned there. | 4329 // safe in new-space because the limit of the heap is aligned there. |
4322 DCHECK(kPointerAlignment * 2 == kDoubleAlignment); | 4330 DCHECK(kPointerAlignment * 2 == kDoubleAlignment); |
4323 And(result_end, result, Operand(kDoubleAlignmentMaskTagged)); | 4331 And(result_end, result, Operand(kDoubleAlignmentMask)); |
4324 Label aligned; | 4332 Label aligned; |
4325 Branch(&aligned, eq, result_end, Operand(zero_reg)); | 4333 Branch(&aligned, eq, result_end, Operand(zero_reg)); |
4326 li(result_end, Operand(isolate()->factory()->one_pointer_filler_map())); | 4334 li(result_end, Operand(isolate()->factory()->one_pointer_filler_map())); |
4327 sw(result_end, FieldMemOperand(result, 0)); | 4335 sw(result_end, MemOperand(result)); |
4328 Addu(result, result, Operand(kDoubleSize / 2)); | 4336 Addu(result, result, Operand(kDoubleSize / 2)); |
4329 bind(&aligned); | 4337 bind(&aligned); |
4330 } | 4338 } |
4331 | 4339 |
4332 // Calculate new top and bail out if new space is exhausted. Use result | 4340 // Calculate new top and bail out if new space is exhausted. Use result |
4333 // to calculate the new top. Object size may be in words so a shift is | 4341 // to calculate the new top. Object size may be in words so a shift is |
4334 // required to get the number of bytes. | 4342 // required to get the number of bytes. |
4335 if ((flags & SIZE_IN_WORDS) != 0) { | 4343 if ((flags & SIZE_IN_WORDS) != 0) { |
4336 Lsa(result_end, result, object_size, kPointerSizeLog2); | 4344 Lsa(result_end, result, object_size, kPointerSizeLog2); |
4337 } else { | 4345 } else { |
4338 Addu(result_end, result, Operand(object_size)); | 4346 Addu(result_end, result, Operand(object_size)); |
4339 } | 4347 } |
4340 | 4348 |
4341 // The top pointer is not updated for allocation folding dominators. | 4349 // The top pointer is not updated for allocation folding dominators. |
4342 sw(result_end, MemOperand(top_address)); | 4350 sw(result_end, MemOperand(top_address)); |
| 4351 |
| 4352 Addu(result, result, Operand(kHeapObjectTag)); |
4343 } | 4353 } |
4344 | 4354 |
4345 void MacroAssembler::AllocateTwoByteString(Register result, | 4355 void MacroAssembler::AllocateTwoByteString(Register result, |
4346 Register length, | 4356 Register length, |
4347 Register scratch1, | 4357 Register scratch1, |
4348 Register scratch2, | 4358 Register scratch2, |
4349 Register scratch3, | 4359 Register scratch3, |
4350 Label* gc_required) { | 4360 Label* gc_required) { |
4351 // Calculate the number of bytes needed for the characters in the string while | 4361 // Calculate the number of bytes needed for the characters in the string while |
4352 // observing object alignment. | 4362 // observing object alignment. |
(...skipping 2429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6782 if (mag.shift > 0) sra(result, result, mag.shift); | 6792 if (mag.shift > 0) sra(result, result, mag.shift); |
6783 srl(at, dividend, 31); | 6793 srl(at, dividend, 31); |
6784 Addu(result, result, Operand(at)); | 6794 Addu(result, result, Operand(at)); |
6785 } | 6795 } |
6786 | 6796 |
6787 | 6797 |
6788 } // namespace internal | 6798 } // namespace internal |
6789 } // namespace v8 | 6799 } // namespace v8 |
6790 | 6800 |
6791 #endif // V8_TARGET_ARCH_MIPS | 6801 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |