| 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 |