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