OLD | NEW |
1 | 1 |
2 // Copyright 2012 the V8 project authors. All rights reserved. | 2 // Copyright 2012 the V8 project authors. All rights reserved. |
3 // Use of this source code is governed by a BSD-style license that can be | 3 // Use of this source code is governed by a BSD-style license that can be |
4 // found in the LICENSE file. | 4 // found in the LICENSE file. |
5 | 5 |
6 #include <limits.h> // For LONG_MIN, LONG_MAX. | 6 #include <limits.h> // For LONG_MIN, LONG_MAX. |
7 | 7 |
8 #if V8_TARGET_ARCH_MIPS | 8 #if V8_TARGET_ARCH_MIPS |
9 | 9 |
10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
(...skipping 3252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3263 if (emit_debug_code()) { | 3263 if (emit_debug_code()) { |
3264 // Trash the registers to simulate an allocation failure. | 3264 // Trash the registers to simulate an allocation failure. |
3265 li(result, 0x7091); | 3265 li(result, 0x7091); |
3266 li(scratch1, 0x7191); | 3266 li(scratch1, 0x7191); |
3267 li(scratch2, 0x7291); | 3267 li(scratch2, 0x7291); |
3268 } | 3268 } |
3269 jmp(gc_required); | 3269 jmp(gc_required); |
3270 return; | 3270 return; |
3271 } | 3271 } |
3272 | 3272 |
3273 DCHECK(!result.is(scratch1)); | 3273 DCHECK(!AreAliased(result, scratch1, scratch2, t9)); |
3274 DCHECK(!result.is(scratch2)); | |
3275 DCHECK(!scratch1.is(scratch2)); | |
3276 DCHECK(!scratch1.is(t9)); | |
3277 DCHECK(!scratch2.is(t9)); | |
3278 DCHECK(!result.is(t9)); | |
3279 | 3274 |
3280 // Make object size into bytes. | 3275 // Make object size into bytes. |
3281 if ((flags & SIZE_IN_WORDS) != 0) { | 3276 if ((flags & SIZE_IN_WORDS) != 0) { |
3282 object_size *= kPointerSize; | 3277 object_size *= kPointerSize; |
3283 } | 3278 } |
3284 DCHECK_EQ(0, object_size & kObjectAlignmentMask); | 3279 DCHECK_EQ(0, object_size & kObjectAlignmentMask); |
3285 | 3280 |
3286 // Check relative positions of allocation top and limit addresses. | 3281 // Check relative positions of allocation top and limit addresses. |
3287 // ARM adds additional checks to make sure the ldm instruction can be | 3282 // ARM adds additional checks to make sure the ldm instruction can be |
3288 // used. On MIPS we don't have ldm so we don't need additional checks either. | 3283 // used. On MIPS we don't have ldm so we don't need additional checks either. |
3289 ExternalReference allocation_top = | 3284 ExternalReference allocation_top = |
3290 AllocationUtils::GetAllocationTopReference(isolate(), flags); | 3285 AllocationUtils::GetAllocationTopReference(isolate(), flags); |
3291 ExternalReference allocation_limit = | 3286 ExternalReference allocation_limit = |
3292 AllocationUtils::GetAllocationLimitReference(isolate(), flags); | 3287 AllocationUtils::GetAllocationLimitReference(isolate(), flags); |
3293 | 3288 |
3294 intptr_t top = | 3289 intptr_t top = reinterpret_cast<intptr_t>(allocation_top.address()); |
3295 reinterpret_cast<intptr_t>(allocation_top.address()); | 3290 intptr_t limit = reinterpret_cast<intptr_t>(allocation_limit.address()); |
3296 intptr_t limit = | |
3297 reinterpret_cast<intptr_t>(allocation_limit.address()); | |
3298 DCHECK((limit - top) == kPointerSize); | 3291 DCHECK((limit - top) == kPointerSize); |
3299 | 3292 |
3300 // Set up allocation top address and object size registers. | 3293 // Set up allocation top address and allocation limit registers. |
3301 Register topaddr = scratch1; | 3294 Register top_address = scratch1; |
3302 li(topaddr, Operand(allocation_top)); | 3295 // This code stores a temporary value in t9. |
| 3296 Register alloc_limit = t9; |
| 3297 Register result_end = scratch2; |
| 3298 li(top_address, Operand(allocation_top)); |
3303 | 3299 |
3304 // This code stores a temporary value in t9. | |
3305 if ((flags & RESULT_CONTAINS_TOP) == 0) { | 3300 if ((flags & RESULT_CONTAINS_TOP) == 0) { |
3306 // Load allocation top into result and allocation limit into t9. | 3301 // Load allocation top into result and allocation limit into alloc_limit. |
3307 lw(result, MemOperand(topaddr)); | 3302 lw(result, MemOperand(top_address)); |
3308 lw(t9, MemOperand(topaddr, kPointerSize)); | 3303 lw(alloc_limit, MemOperand(top_address, kPointerSize)); |
3309 } else { | 3304 } else { |
3310 if (emit_debug_code()) { | 3305 if (emit_debug_code()) { |
3311 // Assert that result actually contains top on entry. t9 is used | 3306 // Assert that result actually contains top on entry. |
3312 // immediately below so this use of t9 does not cause difference with | 3307 lw(alloc_limit, MemOperand(top_address)); |
3313 // respect to register content between debug and release mode. | 3308 Check(eq, kUnexpectedAllocationTop, result, Operand(alloc_limit)); |
3314 lw(t9, MemOperand(topaddr)); | |
3315 Check(eq, kUnexpectedAllocationTop, result, Operand(t9)); | |
3316 } | 3309 } |
3317 // Load allocation limit into t9. Result already contains allocation top. | 3310 // Load allocation limit. Result already contains allocation top. |
3318 lw(t9, MemOperand(topaddr, limit - top)); | 3311 lw(alloc_limit, MemOperand(top_address, limit - top)); |
3319 } | 3312 } |
3320 | 3313 |
3321 if ((flags & DOUBLE_ALIGNMENT) != 0) { | 3314 if ((flags & DOUBLE_ALIGNMENT) != 0) { |
3322 // Align the next allocation. Storing the filler map without checking top is | 3315 // Align the next allocation. Storing the filler map without checking top is |
3323 // safe in new-space because the limit of the heap is aligned there. | 3316 // safe in new-space because the limit of the heap is aligned there. |
3324 DCHECK(kPointerAlignment * 2 == kDoubleAlignment); | 3317 DCHECK(kPointerAlignment * 2 == kDoubleAlignment); |
3325 And(scratch2, result, Operand(kDoubleAlignmentMask)); | 3318 And(result_end, result, Operand(kDoubleAlignmentMask)); |
3326 Label aligned; | 3319 Label aligned; |
3327 Branch(&aligned, eq, scratch2, Operand(zero_reg)); | 3320 Branch(&aligned, eq, result_end, Operand(zero_reg)); |
3328 if ((flags & PRETENURE) != 0) { | 3321 if ((flags & PRETENURE) != 0) { |
3329 Branch(gc_required, Ugreater_equal, result, Operand(t9)); | 3322 Branch(gc_required, Ugreater_equal, result, Operand(alloc_limit)); |
3330 } | 3323 } |
3331 li(scratch2, Operand(isolate()->factory()->one_pointer_filler_map())); | 3324 li(result_end, Operand(isolate()->factory()->one_pointer_filler_map())); |
3332 sw(scratch2, MemOperand(result)); | 3325 sw(result_end, MemOperand(result)); |
3333 Addu(result, result, Operand(kDoubleSize / 2)); | 3326 Addu(result, result, Operand(kDoubleSize / 2)); |
3334 bind(&aligned); | 3327 bind(&aligned); |
3335 } | 3328 } |
3336 | 3329 |
3337 // Calculate new top and bail out if new space is exhausted. Use result | 3330 // Calculate new top and bail out if new space is exhausted. Use result |
3338 // to calculate the new top. | 3331 // to calculate the new top. |
3339 Addu(scratch2, result, Operand(object_size)); | 3332 Addu(result_end, result, Operand(object_size)); |
3340 Branch(gc_required, Ugreater, scratch2, Operand(t9)); | 3333 Branch(gc_required, Ugreater, result_end, Operand(alloc_limit)); |
3341 sw(scratch2, MemOperand(topaddr)); | 3334 sw(result_end, MemOperand(top_address)); |
3342 | 3335 |
3343 // Tag object if requested. | 3336 // Tag object if requested. |
3344 if ((flags & TAG_OBJECT) != 0) { | 3337 if ((flags & TAG_OBJECT) != 0) { |
3345 Addu(result, result, Operand(kHeapObjectTag)); | 3338 Addu(result, result, Operand(kHeapObjectTag)); |
3346 } | 3339 } |
3347 } | 3340 } |
3348 | 3341 |
3349 | 3342 |
3350 void MacroAssembler::Allocate(Register object_size, Register result, | 3343 void MacroAssembler::Allocate(Register object_size, Register result, |
3351 Register result_end, Register scratch1, | 3344 Register result_end, Register scratch, |
3352 Label* gc_required, AllocationFlags flags) { | 3345 Label* gc_required, AllocationFlags flags) { |
3353 if (!FLAG_inline_new) { | 3346 if (!FLAG_inline_new) { |
3354 if (emit_debug_code()) { | 3347 if (emit_debug_code()) { |
3355 // Trash the registers to simulate an allocation failure. | 3348 // Trash the registers to simulate an allocation failure. |
3356 li(result, 0x7091); | 3349 li(result, 0x7091); |
3357 li(scratch1, 0x7191); | 3350 li(scratch, 0x7191); |
3358 li(result_end, 0x7291); | 3351 li(result_end, 0x7291); |
3359 } | 3352 } |
3360 jmp(gc_required); | 3353 jmp(gc_required); |
3361 return; | 3354 return; |
3362 } | 3355 } |
3363 | 3356 |
3364 DCHECK(!result.is(scratch1)); | 3357 // |object_size| and |result_end| may overlap if the DOUBLE_ALIGNMENT flag |
3365 DCHECK(!result.is(result_end)); | 3358 // is not specified. Other registers must not overlap. |
3366 DCHECK(!scratch1.is(result_end)); | 3359 DCHECK(!AreAliased(object_size, result, scratch, t9)); |
3367 DCHECK(!object_size.is(t9)); | 3360 DCHECK(!AreAliased(result_end, result, scratch, t9)); |
3368 DCHECK(!scratch1.is(t9) && !result_end.is(t9) && !result.is(t9)); | 3361 DCHECK((flags & DOUBLE_ALIGNMENT) == 0 || !object_size.is(result_end)); |
3369 | 3362 |
3370 // Check relative positions of allocation top and limit addresses. | 3363 // Check relative positions of allocation top and limit addresses. |
3371 // ARM adds additional checks to make sure the ldm instruction can be | 3364 // ARM adds additional checks to make sure the ldm instruction can be |
3372 // used. On MIPS we don't have ldm so we don't need additional checks either. | 3365 // used. On MIPS we don't have ldm so we don't need additional checks either. |
3373 ExternalReference allocation_top = | 3366 ExternalReference allocation_top = |
3374 AllocationUtils::GetAllocationTopReference(isolate(), flags); | 3367 AllocationUtils::GetAllocationTopReference(isolate(), flags); |
3375 ExternalReference allocation_limit = | 3368 ExternalReference allocation_limit = |
3376 AllocationUtils::GetAllocationLimitReference(isolate(), flags); | 3369 AllocationUtils::GetAllocationLimitReference(isolate(), flags); |
3377 intptr_t top = | 3370 intptr_t top = reinterpret_cast<intptr_t>(allocation_top.address()); |
3378 reinterpret_cast<intptr_t>(allocation_top.address()); | 3371 intptr_t limit = reinterpret_cast<intptr_t>(allocation_limit.address()); |
3379 intptr_t limit = | |
3380 reinterpret_cast<intptr_t>(allocation_limit.address()); | |
3381 DCHECK((limit - top) == kPointerSize); | 3372 DCHECK((limit - top) == kPointerSize); |
3382 | 3373 |
3383 // Set up allocation top address and object size registers. | 3374 // Set up allocation top address and allocation limit registers. |
3384 Register topaddr = scratch1; | 3375 Register top_address = scratch; |
3385 li(topaddr, Operand(allocation_top)); | 3376 // This code stores a temporary value in t9. |
| 3377 Register alloc_limit = t9; |
| 3378 li(top_address, Operand(allocation_top)); |
3386 | 3379 |
3387 // This code stores a temporary value in t9. | |
3388 if ((flags & RESULT_CONTAINS_TOP) == 0) { | 3380 if ((flags & RESULT_CONTAINS_TOP) == 0) { |
3389 // Load allocation top into result and allocation limit into t9. | 3381 // Load allocation top into result and allocation limit into alloc_limit. |
3390 lw(result, MemOperand(topaddr)); | 3382 lw(result, MemOperand(top_address)); |
3391 lw(t9, MemOperand(topaddr, kPointerSize)); | 3383 lw(alloc_limit, MemOperand(top_address, kPointerSize)); |
3392 } else { | 3384 } else { |
3393 if (emit_debug_code()) { | 3385 if (emit_debug_code()) { |
3394 // Assert that result actually contains top on entry. t9 is used | 3386 // Assert that result actually contains top on entry. |
3395 // immediately below so this use of t9 does not cause difference with | 3387 lw(alloc_limit, MemOperand(top_address)); |
3396 // respect to register content between debug and release mode. | 3388 Check(eq, kUnexpectedAllocationTop, result, Operand(alloc_limit)); |
3397 lw(t9, MemOperand(topaddr)); | |
3398 Check(eq, kUnexpectedAllocationTop, result, Operand(t9)); | |
3399 } | 3389 } |
3400 // Load allocation limit into t9. Result already contains allocation top. | 3390 // Load allocation limit. Result already contains allocation top. |
3401 lw(t9, MemOperand(topaddr, limit - top)); | 3391 lw(alloc_limit, MemOperand(top_address, limit - top)); |
3402 } | 3392 } |
3403 | 3393 |
3404 if ((flags & DOUBLE_ALIGNMENT) != 0) { | 3394 if ((flags & DOUBLE_ALIGNMENT) != 0) { |
3405 // Align the next allocation. Storing the filler map without checking top is | 3395 // Align the next allocation. Storing the filler map without checking top is |
3406 // safe in new-space because the limit of the heap is aligned there. | 3396 // safe in new-space because the limit of the heap is aligned there. |
3407 DCHECK(kPointerAlignment * 2 == kDoubleAlignment); | 3397 DCHECK(kPointerAlignment * 2 == kDoubleAlignment); |
3408 And(result_end, result, Operand(kDoubleAlignmentMask)); | 3398 And(result_end, result, Operand(kDoubleAlignmentMask)); |
3409 Label aligned; | 3399 Label aligned; |
3410 Branch(&aligned, eq, result_end, Operand(zero_reg)); | 3400 Branch(&aligned, eq, result_end, Operand(zero_reg)); |
3411 if ((flags & PRETENURE) != 0) { | 3401 if ((flags & PRETENURE) != 0) { |
3412 Branch(gc_required, Ugreater_equal, result, Operand(t9)); | 3402 Branch(gc_required, Ugreater_equal, result, Operand(alloc_limit)); |
3413 } | 3403 } |
3414 li(result_end, Operand(isolate()->factory()->one_pointer_filler_map())); | 3404 li(result_end, Operand(isolate()->factory()->one_pointer_filler_map())); |
3415 sw(result_end, MemOperand(result)); | 3405 sw(result_end, MemOperand(result)); |
3416 Addu(result, result, Operand(kDoubleSize / 2)); | 3406 Addu(result, result, Operand(kDoubleSize / 2)); |
3417 bind(&aligned); | 3407 bind(&aligned); |
3418 } | 3408 } |
3419 | 3409 |
3420 // Calculate new top and bail out if new space is exhausted. Use result | 3410 // Calculate new top and bail out if new space is exhausted. Use result |
3421 // to calculate the new top. Object size may be in words so a shift is | 3411 // to calculate the new top. Object size may be in words so a shift is |
3422 // required to get the number of bytes. | 3412 // required to get the number of bytes. |
3423 if ((flags & SIZE_IN_WORDS) != 0) { | 3413 if ((flags & SIZE_IN_WORDS) != 0) { |
3424 sll(result_end, object_size, kPointerSizeLog2); | 3414 sll(result_end, object_size, kPointerSizeLog2); |
3425 Addu(result_end, result, result_end); | 3415 Addu(result_end, result, result_end); |
3426 } else { | 3416 } else { |
3427 Addu(result_end, result, Operand(object_size)); | 3417 Addu(result_end, result, Operand(object_size)); |
3428 } | 3418 } |
3429 Branch(gc_required, Ugreater, result_end, Operand(t9)); | 3419 Branch(gc_required, Ugreater, result_end, Operand(alloc_limit)); |
3430 | 3420 |
3431 // Update allocation top. result temporarily holds the new top. | 3421 // Update allocation top. result temporarily holds the new top. |
3432 if (emit_debug_code()) { | 3422 if (emit_debug_code()) { |
3433 And(t9, result_end, Operand(kObjectAlignmentMask)); | 3423 And(alloc_limit, result_end, Operand(kObjectAlignmentMask)); |
3434 Check(eq, kUnalignedAllocationInNewSpace, t9, Operand(zero_reg)); | 3424 Check(eq, kUnalignedAllocationInNewSpace, alloc_limit, Operand(zero_reg)); |
3435 } | 3425 } |
3436 sw(result_end, MemOperand(topaddr)); | 3426 sw(result_end, MemOperand(top_address)); |
3437 | 3427 |
3438 // Tag object if requested. | 3428 // Tag object if requested. |
3439 if ((flags & TAG_OBJECT) != 0) { | 3429 if ((flags & TAG_OBJECT) != 0) { |
3440 Addu(result, result, Operand(kHeapObjectTag)); | 3430 Addu(result, result, Operand(kHeapObjectTag)); |
3441 } | 3431 } |
3442 } | 3432 } |
3443 | 3433 |
3444 | 3434 |
3445 void MacroAssembler::AllocateTwoByteString(Register result, | 3435 void MacroAssembler::AllocateTwoByteString(Register result, |
3446 Register length, | 3436 Register length, |
(...skipping 2398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5845 if (mag.shift > 0) sra(result, result, mag.shift); | 5835 if (mag.shift > 0) sra(result, result, mag.shift); |
5846 srl(at, dividend, 31); | 5836 srl(at, dividend, 31); |
5847 Addu(result, result, Operand(at)); | 5837 Addu(result, result, Operand(at)); |
5848 } | 5838 } |
5849 | 5839 |
5850 | 5840 |
5851 } // namespace internal | 5841 } // namespace internal |
5852 } // namespace v8 | 5842 } // namespace v8 |
5853 | 5843 |
5854 #endif // V8_TARGET_ARCH_MIPS | 5844 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |