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 "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_ARM | 7 #if V8_TARGET_ARCH_ARM |
8 | 8 |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 3304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3315 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase); | 3315 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase); |
3316 } | 3316 } |
3317 | 3317 |
3318 | 3318 |
3319 enum CopyCharactersFlags { | 3319 enum CopyCharactersFlags { |
3320 COPY_ASCII = 1, | 3320 COPY_ASCII = 1, |
3321 DEST_ALWAYS_ALIGNED = 2 | 3321 DEST_ALWAYS_ALIGNED = 2 |
3322 }; | 3322 }; |
3323 | 3323 |
3324 | 3324 |
3325 void StringHelper::GenerateCopyCharactersLong(MacroAssembler* masm, | 3325 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm, |
3326 Register dest, | 3326 Register dest, |
3327 Register src, | 3327 Register src, |
3328 Register count, | 3328 Register count, |
3329 Register scratch1, | 3329 Register scratch, |
3330 Register scratch2, | 3330 String::Encoding encoding) { |
3331 Register scratch3, | 3331 if (FLAG_debug_code) { |
3332 Register scratch4, | 3332 // Check that destination is word aligned. |
3333 int flags) { | |
3334 bool ascii = (flags & COPY_ASCII) != 0; | |
3335 bool dest_always_aligned = (flags & DEST_ALWAYS_ALIGNED) != 0; | |
3336 | |
3337 if (dest_always_aligned && FLAG_debug_code) { | |
3338 // Check that destination is actually word aligned if the flag says | |
3339 // that it is. | |
3340 __ tst(dest, Operand(kPointerAlignmentMask)); | 3333 __ tst(dest, Operand(kPointerAlignmentMask)); |
3341 __ Check(eq, kDestinationOfCopyNotAligned); | 3334 __ Check(eq, kDestinationOfCopyNotAligned); |
3342 } | 3335 } |
3343 | 3336 |
3344 const int kReadAlignment = 4; | |
3345 const int kReadAlignmentMask = kReadAlignment - 1; | |
3346 // Ensure that reading an entire aligned word containing the last character | |
3347 // of a string will not read outside the allocated area (because we pad up | |
3348 // to kObjectAlignment). | |
3349 STATIC_ASSERT(kObjectAlignment >= kReadAlignment); | |
3350 // Assumes word reads and writes are little endian. | 3337 // Assumes word reads and writes are little endian. |
3351 // Nothing to do for zero characters. | 3338 // Nothing to do for zero characters. |
3352 Label done; | 3339 Label done; |
3353 if (!ascii) { | 3340 if (encoding == String::TWO_BYTE_ENCODING) { |
3354 __ add(count, count, Operand(count), SetCC); | 3341 __ add(count, count, Operand(count), SetCC); |
3355 } else { | |
3356 __ cmp(count, Operand::Zero()); | |
3357 } | |
3358 __ b(eq, &done); | |
3359 | |
3360 // Assume that you cannot read (or write) unaligned. | |
3361 Label byte_loop; | |
3362 // Must copy at least eight bytes, otherwise just do it one byte at a time. | |
3363 __ cmp(count, Operand(8)); | |
3364 __ add(count, dest, Operand(count)); | |
3365 Register limit = count; // Read until src equals this. | |
3366 __ b(lt, &byte_loop); | |
3367 | |
3368 if (!dest_always_aligned) { | |
3369 // Align dest by byte copying. Copies between zero and three bytes. | |
3370 __ and_(scratch4, dest, Operand(kReadAlignmentMask), SetCC); | |
3371 Label dest_aligned; | |
3372 __ b(eq, &dest_aligned); | |
3373 __ cmp(scratch4, Operand(2)); | |
3374 __ ldrb(scratch1, MemOperand(src, 1, PostIndex)); | |
3375 __ ldrb(scratch2, MemOperand(src, 1, PostIndex), le); | |
3376 __ ldrb(scratch3, MemOperand(src, 1, PostIndex), lt); | |
3377 __ strb(scratch1, MemOperand(dest, 1, PostIndex)); | |
3378 __ strb(scratch2, MemOperand(dest, 1, PostIndex), le); | |
3379 __ strb(scratch3, MemOperand(dest, 1, PostIndex), lt); | |
3380 __ bind(&dest_aligned); | |
3381 } | 3342 } |
3382 | 3343 |
3383 Label simple_loop; | 3344 Register limit = count; // Read until dest equals this. |
| 3345 __ add(limit, dest, Operand(count)); |
3384 | 3346 |
3385 __ sub(scratch4, dest, Operand(src)); | 3347 Label loop_entry, loop; |
3386 __ and_(scratch4, scratch4, Operand(0x03), SetCC); | 3348 // Copy bytes from src to dest until dest hits limit. |
3387 __ b(eq, &simple_loop); | 3349 __ b(&loop_entry); |
3388 // Shift register is number of bits in a source word that | 3350 __ bind(&loop); |
3389 // must be combined with bits in the next source word in order | 3351 __ ldrb(scratch, MemOperand(src, 1, PostIndex), lt); |
3390 // to create a destination word. | 3352 __ strb(scratch, MemOperand(dest, 1, PostIndex)); |
3391 | 3353 __ bind(&loop_entry); |
3392 // Complex loop for src/dst that are not aligned the same way. | |
3393 { | |
3394 Label loop; | |
3395 __ mov(scratch4, Operand(scratch4, LSL, 3)); | |
3396 Register left_shift = scratch4; | |
3397 __ and_(src, src, Operand(~3)); // Round down to load previous word. | |
3398 __ ldr(scratch1, MemOperand(src, 4, PostIndex)); | |
3399 // Store the "shift" most significant bits of scratch in the least | |
3400 // signficant bits (i.e., shift down by (32-shift)). | |
3401 __ rsb(scratch2, left_shift, Operand(32)); | |
3402 Register right_shift = scratch2; | |
3403 __ mov(scratch1, Operand(scratch1, LSR, right_shift)); | |
3404 | |
3405 __ bind(&loop); | |
3406 __ ldr(scratch3, MemOperand(src, 4, PostIndex)); | |
3407 __ orr(scratch1, scratch1, Operand(scratch3, LSL, left_shift)); | |
3408 __ str(scratch1, MemOperand(dest, 4, PostIndex)); | |
3409 __ mov(scratch1, Operand(scratch3, LSR, right_shift)); | |
3410 // Loop if four or more bytes left to copy. | |
3411 __ sub(scratch3, limit, Operand(dest)); | |
3412 __ sub(scratch3, scratch3, Operand(4), SetCC); | |
3413 __ b(ge, &loop); | |
3414 } | |
3415 // There is now between zero and three bytes left to copy (negative that | |
3416 // number is in scratch3), and between one and three bytes already read into | |
3417 // scratch1 (eight times that number in scratch4). We may have read past | |
3418 // the end of the string, but because objects are aligned, we have not read | |
3419 // past the end of the object. | |
3420 // Find the minimum of remaining characters to move and preloaded characters | |
3421 // and write those as bytes. | |
3422 __ add(scratch3, scratch3, Operand(4), SetCC); | |
3423 __ b(eq, &done); | |
3424 __ cmp(scratch4, Operand(scratch3, LSL, 3), ne); | |
3425 // Move minimum of bytes read and bytes left to copy to scratch4. | |
3426 __ mov(scratch3, Operand(scratch4, LSR, 3), LeaveCC, lt); | |
3427 // Between one and three (value in scratch3) characters already read into | |
3428 // scratch ready to write. | |
3429 __ cmp(scratch3, Operand(2)); | |
3430 __ strb(scratch1, MemOperand(dest, 1, PostIndex)); | |
3431 __ mov(scratch1, Operand(scratch1, LSR, 8), LeaveCC, ge); | |
3432 __ strb(scratch1, MemOperand(dest, 1, PostIndex), ge); | |
3433 __ mov(scratch1, Operand(scratch1, LSR, 8), LeaveCC, gt); | |
3434 __ strb(scratch1, MemOperand(dest, 1, PostIndex), gt); | |
3435 // Copy any remaining bytes. | |
3436 __ b(&byte_loop); | |
3437 | |
3438 // Simple loop. | |
3439 // Copy words from src to dst, until less than four bytes left. | |
3440 // Both src and dest are word aligned. | |
3441 __ bind(&simple_loop); | |
3442 { | |
3443 Label loop; | |
3444 __ bind(&loop); | |
3445 __ ldr(scratch1, MemOperand(src, 4, PostIndex)); | |
3446 __ sub(scratch3, limit, Operand(dest)); | |
3447 __ str(scratch1, MemOperand(dest, 4, PostIndex)); | |
3448 // Compare to 8, not 4, because we do the substraction before increasing | |
3449 // dest. | |
3450 __ cmp(scratch3, Operand(8)); | |
3451 __ b(ge, &loop); | |
3452 } | |
3453 | |
3454 // Copy bytes from src to dst until dst hits limit. | |
3455 __ bind(&byte_loop); | |
3456 __ cmp(dest, Operand(limit)); | 3354 __ cmp(dest, Operand(limit)); |
3457 __ ldrb(scratch1, MemOperand(src, 1, PostIndex), lt); | 3355 __ b(lt, &loop); |
3458 __ b(ge, &done); | |
3459 __ strb(scratch1, MemOperand(dest, 1, PostIndex)); | |
3460 __ b(&byte_loop); | |
3461 | 3356 |
3462 __ bind(&done); | 3357 __ bind(&done); |
3463 } | 3358 } |
3464 | 3359 |
3465 | 3360 |
3466 void StringHelper::GenerateHashInit(MacroAssembler* masm, | 3361 void StringHelper::GenerateHashInit(MacroAssembler* masm, |
3467 Register hash, | 3362 Register hash, |
3468 Register character) { | 3363 Register character) { |
3469 // hash = character + (character << 10); | 3364 // hash = character + (character << 10); |
3470 __ LoadRoot(hash, Heap::kHashSeedRootIndex); | 3365 __ LoadRoot(hash, Heap::kHashSeedRootIndex); |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3676 // Locate first character of substring to copy. | 3571 // Locate first character of substring to copy. |
3677 __ add(r5, r5, r3); | 3572 __ add(r5, r5, r3); |
3678 // Locate first character of result. | 3573 // Locate first character of result. |
3679 __ add(r1, r0, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); | 3574 __ add(r1, r0, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
3680 | 3575 |
3681 // r0: result string | 3576 // r0: result string |
3682 // r1: first character of result string | 3577 // r1: first character of result string |
3683 // r2: result string length | 3578 // r2: result string length |
3684 // r5: first character of substring to copy | 3579 // r5: first character of substring to copy |
3685 STATIC_ASSERT((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0); | 3580 STATIC_ASSERT((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0); |
3686 StringHelper::GenerateCopyCharactersLong(masm, r1, r5, r2, r3, r4, r6, r9, | 3581 StringHelper::GenerateCopyCharacters( |
3687 COPY_ASCII | DEST_ALWAYS_ALIGNED); | 3582 masm, r1, r5, r2, r3, String::ONE_BYTE_ENCODING); |
3688 __ jmp(&return_r0); | 3583 __ jmp(&return_r0); |
3689 | 3584 |
3690 // Allocate and copy the resulting two-byte string. | 3585 // Allocate and copy the resulting two-byte string. |
3691 __ bind(&two_byte_sequential); | 3586 __ bind(&two_byte_sequential); |
3692 __ AllocateTwoByteString(r0, r2, r4, r6, r1, &runtime); | 3587 __ AllocateTwoByteString(r0, r2, r4, r6, r1, &runtime); |
3693 | 3588 |
3694 // Locate first character of substring to copy. | 3589 // Locate first character of substring to copy. |
3695 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); | 3590 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); |
3696 __ add(r5, r5, Operand(r3, LSL, 1)); | 3591 __ add(r5, r5, Operand(r3, LSL, 1)); |
3697 // Locate first character of result. | 3592 // Locate first character of result. |
3698 __ add(r1, r0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); | 3593 __ add(r1, r0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); |
3699 | 3594 |
3700 // r0: result string. | 3595 // r0: result string. |
3701 // r1: first character of result. | 3596 // r1: first character of result. |
3702 // r2: result length. | 3597 // r2: result length. |
3703 // r5: first character of substring to copy. | 3598 // r5: first character of substring to copy. |
3704 STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); | 3599 STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); |
3705 StringHelper::GenerateCopyCharactersLong( | 3600 StringHelper::GenerateCopyCharacters( |
3706 masm, r1, r5, r2, r3, r4, r6, r9, DEST_ALWAYS_ALIGNED); | 3601 masm, r1, r5, r2, r3, String::TWO_BYTE_ENCODING); |
3707 | 3602 |
3708 __ bind(&return_r0); | 3603 __ bind(&return_r0); |
3709 Counters* counters = isolate()->counters(); | 3604 Counters* counters = isolate()->counters(); |
3710 __ IncrementCounter(counters->sub_string_native(), 1, r3, r4); | 3605 __ IncrementCounter(counters->sub_string_native(), 1, r3, r4); |
3711 __ Drop(3); | 3606 __ Drop(3); |
3712 __ Ret(); | 3607 __ Ret(); |
3713 | 3608 |
3714 // Just jump to runtime to create the sub string. | 3609 // Just jump to runtime to create the sub string. |
3715 __ bind(&runtime); | 3610 __ bind(&runtime); |
3716 __ TailCallRuntime(Runtime::kHiddenSubString, 3, 1); | 3611 __ TailCallRuntime(Runtime::kHiddenSubString, 3, 1); |
(...skipping 1557 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5274 MemOperand(fp, 6 * kPointerSize), | 5169 MemOperand(fp, 6 * kPointerSize), |
5275 NULL); | 5170 NULL); |
5276 } | 5171 } |
5277 | 5172 |
5278 | 5173 |
5279 #undef __ | 5174 #undef __ |
5280 | 5175 |
5281 } } // namespace v8::internal | 5176 } } // namespace v8::internal |
5282 | 5177 |
5283 #endif // V8_TARGET_ARCH_ARM | 5178 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |