OLD | NEW |
---|---|
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 3333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3344 } | 3344 } |
3345 | 3345 |
3346 __ mov(eax, FieldOperand(eax, String::kHashFieldOffset)); | 3346 __ mov(eax, FieldOperand(eax, String::kHashFieldOffset)); |
3347 __ IndexFromHash(eax, eax); | 3347 __ IndexFromHash(eax, eax); |
3348 | 3348 |
3349 context()->Plug(eax); | 3349 context()->Plug(eax); |
3350 } | 3350 } |
3351 | 3351 |
3352 | 3352 |
3353 void FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList<Expression*>* args) { | 3353 void FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList<Expression*>* args) { |
3354 Label bailout; | 3354 Label bailout, done, one_char_separator, long_separator, |
3355 Label done; | 3355 non_trivial_array, not_size_one_array, loop, loop_condition, |
3356 loop_1, loop_1_condition, loop_1a, loop_1a_condition, | |
3357 loop_2, loop_2_entry, loop_2a, loop_2a_condition, | |
3358 loop_3, loop_3_entry, loop_3a, loop_3a_condition, | |
3359 loop_3b, loop_3b_condition; | |
Lasse Reichstein
2011/01/13 09:20:32
That's a lot of loops. Could they be given more te
William Hesse
2011/01/13 16:25:59
Loops eliminated by making the string copy a macro
| |
3356 | 3360 |
3357 ASSERT(args->length() == 2); | 3361 ASSERT(args->length() == 2); |
3358 // We will leave the separator on the stack until the end of the function. | 3362 // We will leave the separator on the stack until the end of the function. |
3359 VisitForStackValue(args->at(1)); | 3363 VisitForStackValue(args->at(1)); |
3360 // Load this to eax (= array) | 3364 // Load this to eax (= array) |
3361 VisitForAccumulatorValue(args->at(0)); | 3365 VisitForAccumulatorValue(args->at(0)); |
3362 | 3366 |
3363 // All aliases of the same register have disjoint lifetimes. | 3367 // All aliases of the same register have disjoint lifetimes. |
3364 Register array = eax; | 3368 Register array = eax; |
3365 Register result_pos = no_reg; | 3369 Register elements = no_reg; // Will be eax. |
3370 Register result_pos = no_reg; // Will be eax. | |
3366 | 3371 |
3367 Register index = edi; | 3372 Register index = edi; |
3368 | 3373 |
3369 Register current_string_length = ecx; // Will be ecx when live. | 3374 Register current_string_length = ecx; |
3370 | 3375 |
3371 Register current_string = edx; | 3376 Register current_string = edx; |
3372 | 3377 |
3373 Register scratch = ebx; | 3378 Register scratch = ebx; |
3374 | 3379 |
3375 Register scratch_2 = esi; | 3380 Register array_length = esi; |
3376 Register new_padding_chars = scratch_2; | 3381 Register pos = no_reg; // Will be esi. |
3377 | 3382 |
3378 Operand separator = Operand(esp, 4 * kPointerSize); // Already pushed. | 3383 // Separator operand is already pushed. |
3379 Operand elements = Operand(esp, 3 * kPointerSize); | 3384 Operand separator_operand = Operand(esp, 3 * kPointerSize); |
3380 Operand result = Operand(esp, 2 * kPointerSize); | 3385 Operand elements_operand = Operand(esp, 2 * kPointerSize); |
3381 Operand padding_chars = Operand(esp, 1 * kPointerSize); | 3386 Operand result_operand = Operand(esp, 1 * kPointerSize); |
3382 Operand array_length = Operand(esp, 0); | 3387 Operand array_length_operand = Operand(esp, 0); |
3383 __ sub(Operand(esp), Immediate(4 * kPointerSize)); | 3388 __ sub(Operand(esp), Immediate(3 * kPointerSize)); |
3384 | 3389 |
3385 | 3390 // Check that the array is a JSArray |
3386 // Check that eax is a JSArray | |
3387 __ test(array, Immediate(kSmiTagMask)); | 3391 __ test(array, Immediate(kSmiTagMask)); |
3388 __ j(zero, &bailout); | 3392 __ j(zero, &bailout); |
3389 __ CmpObjectType(array, JS_ARRAY_TYPE, scratch); | 3393 __ CmpObjectType(array, JS_ARRAY_TYPE, scratch); |
3390 __ j(not_equal, &bailout); | 3394 __ j(not_equal, &bailout); |
3391 | 3395 |
3392 // Check that the array has fast elements. | 3396 // Check that the array has fast elements. |
3393 __ test_b(FieldOperand(scratch, Map::kBitField2Offset), | 3397 __ test_b(FieldOperand(scratch, Map::kBitField2Offset), |
3394 1 << Map::kHasFastElements); | 3398 1 << Map::kHasFastElements); |
Lasse Reichstein
2011/01/13 09:20:32
Will Copy-on-Write arrays have fast elements if qu
William Hesse
2011/01/13 16:25:59
Yes, they will (I checked).
| |
3395 __ j(zero, &bailout); | 3399 __ j(zero, &bailout); |
3396 | 3400 |
3397 // If the array is empty, return the empty string. | 3401 // If the array has length zero, return the empty string. |
3398 __ mov(scratch, FieldOperand(array, JSArray::kLengthOffset)); | 3402 __ mov(scratch, FieldOperand(array, JSArray::kLengthOffset)); |
3399 __ sar(scratch, 1); | 3403 __ sar(scratch, 1); |
3400 Label non_trivial; | 3404 __ j(not_zero, &non_trivial_array); |
3401 __ j(not_zero, &non_trivial); | 3405 __ mov(result_operand, Factory::empty_string()); |
3402 __ mov(result, Factory::empty_string()); | |
3403 __ jmp(&done); | 3406 __ jmp(&done); |
3404 | 3407 |
3405 __ bind(&non_trivial); | 3408 // Save the array length. |
3409 __ bind(&non_trivial_array); | |
3410 __ mov(array_length_operand, scratch); | |
3406 __ mov(array_length, scratch); | 3411 __ mov(array_length, scratch); |
3407 | 3412 |
3413 // Save the FixedArray containing array's elements. | |
3408 __ mov(scratch, FieldOperand(array, JSArray::kElementsOffset)); | 3414 __ mov(scratch, FieldOperand(array, JSArray::kElementsOffset)); |
3415 // End of array's live range. | |
3416 elements = array; | |
3417 array = no_reg; | |
3418 __ mov(elements_operand, scratch); | |
3409 __ mov(elements, scratch); | 3419 __ mov(elements, scratch); |
3410 | 3420 |
3411 // End of array's live range. | |
3412 result_pos = array; | |
3413 array = no_reg; | |
3414 | 3421 |
3422 // Check that all array elements are sequential ascii strings, and | |
Lasse Reichstein
2011/01/13 09:20:32
ascii -> ASCII.
William Hesse
2011/01/13 16:25:59
Both forms occur in our comments, about 1/3 lowerc
| |
3423 // accumulate the sum of their lengths. | |
Lasse Reichstein
2011/01/13 09:20:32
Say that the sum is maintained as a Smi value.
William Hesse
2011/01/13 16:25:59
Done.
| |
3424 __ Set(index, Immediate(0)); | |
3425 __ Set(current_string_length, Immediate(0)); | |
3426 // Loop condition: while (index < length). | |
3427 // Live loop registers: index, array_length, current_string, | |
3428 // scratch, current_string_length, elements. | |
3429 __ jmp(&loop_condition); | |
3430 __ bind(&loop); | |
3431 __ cmp(index, Operand(array_length)); | |
3432 __ j(greater_equal, &done); | |
3415 | 3433 |
3416 // Check that the separator is a flat ascii string. | 3434 __ mov(current_string, FieldOperand(elements, index, |
3417 __ mov(current_string, separator); | 3435 times_pointer_size, |
3436 FixedArray::kHeaderSize)); | |
3418 __ test(current_string, Immediate(kSmiTagMask)); | 3437 __ test(current_string, Immediate(kSmiTagMask)); |
3419 __ j(zero, &bailout); | 3438 __ j(zero, &bailout); |
3420 __ mov(scratch, FieldOperand(current_string, HeapObject::kMapOffset)); | 3439 __ mov(scratch, FieldOperand(current_string, HeapObject::kMapOffset)); |
3421 __ mov_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); | 3440 __ mov_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); |
Lasse Reichstein
2011/01/13 09:20:32
Use movzx_b to avoid depending on the remaining bi
William Hesse
2011/01/13 16:25:59
done.
| |
3422 __ and_(scratch, Immediate( | 3441 __ and_(scratch, Immediate( |
3423 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); | 3442 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); |
3424 __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag); | 3443 __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag); |
3425 __ j(not_equal, &bailout); | 3444 __ j(not_equal, &bailout); |
3426 // If the separator is the empty string, replace it with NULL. | 3445 __ add(current_string_length, |
3427 // The test for NULL is quicker than the empty string test, in a loop. | 3446 FieldOperand(current_string, SeqAsciiString::kLengthOffset)); |
3428 __ cmp(FieldOperand(current_string, SeqAsciiString::kLengthOffset), | 3447 __ j(overflow, &bailout); |
3429 Immediate(0)); | 3448 __ add(Operand(index), Immediate(1)); |
3430 Label separator_checked; | 3449 __ bind(&loop_condition); |
3431 __ j(not_zero, &separator_checked); | 3450 __ cmp(index, Operand(array_length)); |
3432 __ mov(separator, Immediate(0)); | 3451 __ j(less, &loop); |
3433 __ bind(&separator_checked); | |
3434 | 3452 |
3435 // Check that elements[0] is a flat ascii string, and copy it in new space. | 3453 // If array_length is 1, return elements[0], a string. |
3436 __ mov(scratch, elements); | 3454 __ cmp(array_length, 1); |
3437 __ mov(current_string, FieldOperand(scratch, FixedArray::kHeaderSize)); | 3455 __ j(not_equal, ¬_size_one_array); |
3456 __ mov(scratch, FieldOperand(elements, FixedArray::kHeaderSize)); | |
3457 __ mov(result_operand, scratch); | |
3458 __ jmp(&done); | |
3459 | |
3460 __ bind(¬_size_one_array); | |
3461 // End of elements live range | |
3462 result_pos = elements; | |
3463 elements = no_reg; | |
3464 | |
3465 // End of array_length live range. | |
3466 pos = array_length; | |
3467 array_length = no_reg; | |
3468 | |
3469 // Live register: | |
3470 // current_string_length: Sum of string lengths, as a smi. | |
3471 | |
3472 // Check that the separator is a flat ascii string. | |
Lasse Reichstein
2011/01/13 09:20:32
ASCII.
William Hesse
2011/01/13 16:25:59
Done.
| |
3473 __ mov(current_string, separator_operand); | |
3438 __ test(current_string, Immediate(kSmiTagMask)); | 3474 __ test(current_string, Immediate(kSmiTagMask)); |
3439 __ j(zero, &bailout); | 3475 __ j(zero, &bailout); |
3440 __ mov(scratch, FieldOperand(current_string, HeapObject::kMapOffset)); | 3476 __ mov(scratch, FieldOperand(current_string, HeapObject::kMapOffset)); |
3441 __ mov_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); | 3477 __ mov_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); |
3442 __ and_(scratch, Immediate( | 3478 __ and_(scratch, Immediate( |
3443 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); | 3479 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); |
3444 __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag); | 3480 __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag); |
3445 __ j(not_equal, &bailout); | 3481 __ j(not_equal, &bailout); |
3446 | 3482 |
3447 // Allocate space to copy it. Round up the size to the alignment granularity. | 3483 // Add (separator length times array_length) - separator length |
3448 __ mov(current_string_length, | 3484 // to current_string_length. |
3449 FieldOperand(current_string, String::kLengthOffset)); | 3485 __ mov(scratch, separator_operand); |
3450 __ shr(current_string_length, 1); | 3486 __ mov(scratch, FieldOperand(scratch, SeqAsciiString::kLengthOffset)); |
3451 | 3487 __ sub(current_string_length, Operand(scratch)); |
Lasse Reichstein
2011/01/13 09:20:32
Perhaps worth noting that this can (and may) give
William Hesse
2011/01/13 16:25:59
Done.
| |
3488 __ imul(scratch, array_length_operand); | |
3489 __ j(overflow, &bailout); | |
3490 __ add(current_string_length, Operand(scratch)); | |
3491 __ j(overflow, &bailout); | |
3492 | |
3493 __ shr(current_string_length, 1); | |
3452 // Live registers and stack values: | 3494 // Live registers and stack values: |
3453 // current_string_length: length of elements[0]. | 3495 // current_string_length: length of elements[0]. |
3454 | 3496 |
3455 // New string result in new space = elements[0] | 3497 // New string result in new space = elements[0] |
3456 __ AllocateAsciiString(result_pos, current_string_length, scratch_2, | 3498 __ AllocateAsciiString(result_pos, current_string_length, pos, |
3457 index, no_reg, &bailout); | 3499 index, current_string, &bailout); |
3458 __ mov(result, result_pos); | 3500 __ mov(result_operand, result_pos); |
3459 | 3501 __ lea(result_pos, FieldOperand(result_pos, SeqAsciiString::kHeaderSize)); |
3460 // Adjust current_string_length to include padding bytes at end of string. | 3502 |
3461 // Keep track of the number of padding bytes. | 3503 |
3462 __ mov(new_padding_chars, current_string_length); | 3504 __ mov(current_string, separator_operand); |
3463 __ add(Operand(current_string_length), Immediate(kObjectAlignmentMask)); | 3505 __ cmp(FieldOperand(current_string, SeqAsciiString::kLengthOffset), |
3464 __ and_(Operand(current_string_length), Immediate(~kObjectAlignmentMask)); | 3506 Immediate(Smi::FromInt(1))); |
3465 __ sub(new_padding_chars, Operand(current_string_length)); | 3507 __ j(equal, &one_char_separator); |
3466 __ neg(new_padding_chars); | 3508 __ j(greater, &long_separator); |
3467 __ mov(padding_chars, new_padding_chars); | 3509 |
3468 | 3510 |
3469 Label copy_loop_1_done; | 3511 // Empty separator case |
3470 Label copy_loop_1; | 3512 __ mov(index, Immediate(0)); |
3471 __ test(current_string_length, Operand(current_string_length)); | 3513 __ jmp(&loop_1_condition); |
3472 __ j(zero, ©_loop_1_done); | |
3473 __ bind(©_loop_1); | |
3474 __ sub(Operand(current_string_length), Immediate(kPointerSize)); | |
3475 __ mov(scratch, FieldOperand(current_string, current_string_length, | |
3476 times_1, SeqAsciiString::kHeaderSize)); | |
3477 __ mov(FieldOperand(result_pos, current_string_length, | |
3478 times_1, SeqAsciiString::kHeaderSize), | |
3479 scratch); | |
3480 __ j(not_zero, ©_loop_1); | |
3481 __ bind(©_loop_1_done); | |
3482 | |
3483 __ mov(index, Immediate(1)); | |
3484 // Loop condition: while (index < length). | 3514 // Loop condition: while (index < length). |
3485 Label loop; | 3515 __ bind(&loop_1); |
3486 __ bind(&loop); | 3516 // Each iteration of the loop concatenates one string to the result. |
3487 __ cmp(index, array_length); | 3517 // Live values in registers: |
3488 __ j(greater_equal, &done); | 3518 // index: which element of the elements array we are adding to the result. |
3489 | 3519 // result_pos: the position to which we are currently copying characters. |
3490 // If the separator is the empty string, signalled by NULL, skip it. | 3520 |
3491 Label separator_done; | |
3492 __ mov(current_string, separator); | |
3493 __ test(current_string, Operand(current_string)); | |
3494 __ j(zero, &separator_done); | |
3495 | |
3496 // Append separator to result. It is known to be a flat ascii string. | |
3497 __ AppendStringToTopOfNewSpace(current_string, current_string_length, | |
3498 result_pos, scratch, scratch_2, result, | |
3499 padding_chars, &bailout); | |
3500 __ bind(&separator_done); | |
3501 | |
3502 // Add next element of array to the end of the result. | |
3503 // Get current_string = array[index]. | 3521 // Get current_string = array[index]. |
3504 __ mov(scratch, elements); | 3522 __ mov(scratch, elements_operand); |
3505 __ mov(current_string, FieldOperand(scratch, index, | 3523 __ mov(current_string, FieldOperand(scratch, index, |
3506 times_pointer_size, | 3524 times_pointer_size, |
3507 FixedArray::kHeaderSize)); | 3525 FixedArray::kHeaderSize)); |
3508 // If current != flat ascii string drop result, return undefined. | 3526 __ mov(current_string_length, |
3509 __ test(current_string, Immediate(kSmiTagMask)); | 3527 FieldOperand(current_string, String::kLengthOffset)); |
3510 __ j(zero, &bailout); | 3528 __ shr(current_string_length, 1); |
3511 __ mov(scratch, FieldOperand(current_string, HeapObject::kMapOffset)); | 3529 __ lea(current_string, |
3512 __ mov_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); | 3530 FieldOperand(current_string, SeqAsciiString::kHeaderSize)); |
3513 __ and_(scratch, Immediate( | 3531 __ Set(pos, Immediate(0)); |
3514 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); | 3532 __ jmp(&loop_1a_condition); |
3515 __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag); | 3533 |
3516 __ j(not_equal, &bailout); | 3534 __ bind(&loop_1a); |
3517 | 3535 // Live registers: |
3518 // Append current to the result. | 3536 // current_string: the start of the current string's data. |
3519 __ AppendStringToTopOfNewSpace(current_string, current_string_length, | 3537 // pos: the index into the currently copied character of current_string. |
3520 result_pos, scratch, scratch_2, result, | 3538 // current_string_length: the length of the current string. |
3521 padding_chars, &bailout); | 3539 // scratch: the byte being copied. |
3540 // result_pos: the position to copy the current string to. | |
3541 // index: which element of the array is being copied (live across loop). | |
3542 __ mov_b(scratch, Operand(current_string, pos, times_1, 0)); | |
3543 __ mov_b(Operand(result_pos, pos, times_1, 0), scratch); | |
3544 __ inc(pos); | |
3545 __ bind(&loop_1a_condition); | |
3546 __ cmp(pos, Operand(current_string_length)); | |
3547 __ j(less, &loop_1a); | |
3548 | |
3549 __ add(result_pos, Operand(current_string_length)); | |
3522 __ add(Operand(index), Immediate(1)); | 3550 __ add(Operand(index), Immediate(1)); |
3523 __ jmp(&loop); // End while (index < length). | 3551 __ bind(&loop_1_condition); |
3552 __ cmp(index, array_length_operand); | |
3553 __ j(less, &loop_1); // End while (index < length). | |
3554 __ jmp(&done); | |
3555 | |
3556 | |
3557 | |
3558 // One-character separator case | |
3559 __ bind(&one_char_separator); | |
3560 // Replace separator with its ascii character value. | |
3561 __ mov_b(scratch, FieldOperand(current_string, SeqAsciiString::kHeaderSize)); | |
3562 __ mov_b(separator_operand, scratch); | |
3563 | |
3564 __ Set(index, Immediate(0)); | |
3565 // Jump into the loop after the code that copies the separator, so the first | |
3566 // element is not preceded by a separator | |
3567 __ jmp(&loop_2_entry); | |
3568 // Loop condition: while (index < length). | |
3569 __ bind(&loop_2); | |
3570 // Each iteration of the loop concatenates one string to the result. | |
3571 // Live values in registers: | |
3572 // index: which element of the elements array we are adding to the result. | |
3573 // result_pos: the position to which we are currently copying characters. | |
3574 | |
3575 // Copy the separator character to the result. | |
3576 __ mov_b(scratch, separator_operand); | |
3577 __ mov_b(Operand(result_pos, 0), scratch); | |
3578 __ inc(result_pos); | |
3579 | |
3580 __ bind(&loop_2_entry); | |
3581 // Get current_string = array[index]. | |
3582 __ mov(scratch, elements_operand); | |
3583 __ mov(current_string, FieldOperand(scratch, index, | |
3584 times_pointer_size, | |
3585 FixedArray::kHeaderSize)); | |
3586 __ mov(current_string_length, | |
3587 FieldOperand(current_string, String::kLengthOffset)); | |
3588 __ shr(current_string_length, 1); | |
3589 __ lea(current_string, | |
3590 FieldOperand(current_string, SeqAsciiString::kHeaderSize)); | |
3591 __ Set(pos, Immediate(0)); | |
3592 __ jmp(&loop_2a_condition); | |
3593 | |
3594 __ bind(&loop_2a); | |
3595 // Live registers: | |
3596 // current_string: the start of the current string's data. | |
3597 // pos: the index into the currently copied character of current_string. | |
3598 // current_string_length: the length of the current string. | |
3599 // scratch: the byte being copied. | |
3600 // result_pos: the position to copy the current string to. | |
3601 // index: which element of the array is being copied (live across loop). | |
3602 __ mov_b(scratch, Operand(current_string, pos, times_1, 0)); | |
3603 __ mov_b(Operand(result_pos, pos, times_1, 0), scratch); | |
3604 __ inc(pos); | |
3605 __ bind(&loop_2a_condition); | |
3606 __ cmp(pos, Operand(current_string_length)); | |
3607 __ j(less, &loop_2a); | |
3608 | |
3609 __ add(result_pos, Operand(current_string_length)); | |
3610 __ add(Operand(index), Immediate(1)); | |
3611 | |
3612 __ cmp(index, array_length_operand); | |
3613 __ j(less, &loop_2); // End while (index < length). | |
3614 __ jmp(&done); | |
3615 | |
3616 | |
3617 // Long separator case (separator is more than one character). | |
3618 __ bind(&long_separator); | |
3619 | |
3620 __ Set(index, Immediate(0)); | |
3621 // Jump into the loop after the code that copies the separator, so the first | |
3622 // element is not preceded by a separator | |
3623 __ jmp(&loop_3_entry); | |
3624 // Loop condition: while (index < length). | |
3625 __ bind(&loop_3); | |
3626 // Each iteration of the loop concatenates one string to the result. | |
3627 // Live values in registers: | |
3628 // index: which element of the elements array we are adding to the result. | |
3629 // result_pos: the position to which we are currently copying characters. | |
3630 | |
3631 // Copy the separator to the result. | |
3632 __ mov(current_string, separator_operand); | |
3633 __ mov(current_string_length, | |
3634 FieldOperand(current_string, String::kLengthOffset)); | |
3635 __ shr(current_string_length, 1); | |
3636 __ lea(current_string, | |
3637 FieldOperand(current_string, SeqAsciiString::kHeaderSize)); | |
3638 __ Set(pos, Immediate(0)); | |
3639 __ jmp(&loop_3a_condition); | |
3640 | |
3641 __ bind(&loop_3a); | |
3642 // Live registers: | |
3643 // current_string: the start of the separator's data. | |
3644 // pos: the index into the currently copied character of separator. | |
3645 // current_string_length: the length of the separator. | |
3646 // scratch: the byte being copied. | |
3647 // result_pos: the position to copy the separator to. | |
3648 // index: which element of the array is being copied (live across loop). | |
3649 __ mov_b(scratch, Operand(current_string, pos, times_1, 0)); | |
3650 __ mov_b(Operand(result_pos, pos, times_1, 0), scratch); | |
3651 __ inc(pos); | |
3652 __ bind(&loop_3a_condition); | |
3653 __ cmp(pos, Operand(current_string_length)); | |
3654 __ j(less, &loop_3a); | |
3655 | |
3656 __ add(result_pos, Operand(current_string_length)); | |
3657 | |
3658 __ bind(&loop_3_entry); | |
3659 // Get current_string = array[index]. | |
3660 __ mov(scratch, elements_operand); | |
3661 __ mov(current_string, FieldOperand(scratch, index, | |
3662 times_pointer_size, | |
3663 FixedArray::kHeaderSize)); | |
3664 __ mov(current_string_length, | |
3665 FieldOperand(current_string, String::kLengthOffset)); | |
3666 __ shr(current_string_length, 1); | |
3667 __ lea(current_string, | |
3668 FieldOperand(current_string, SeqAsciiString::kHeaderSize)); | |
3669 __ Set(pos, Immediate(0)); | |
3670 __ jmp(&loop_3b_condition); | |
3671 | |
3672 __ bind(&loop_3b); | |
3673 // Live registers: | |
3674 // current_string: the start of the current string's data. | |
3675 // pos: the index into the currently copied character of current_string. | |
3676 // current_string_length: the length of the current string. | |
3677 // scratch: the byte being copied. | |
3678 // result_pos: the position to copy the current string to. | |
3679 // index: which element of the array is being copied (live across loop). | |
3680 __ mov_b(scratch, Operand(current_string, pos, times_1, 0)); | |
3681 __ mov_b(Operand(result_pos, pos, times_1, 0), scratch); | |
3682 __ inc(pos); | |
3683 __ bind(&loop_3b_condition); | |
3684 __ cmp(pos, Operand(current_string_length)); | |
3685 __ j(less, &loop_3b); | |
3686 | |
3687 __ add(result_pos, Operand(current_string_length)); | |
3688 __ add(Operand(index), Immediate(1)); | |
3689 | |
3690 __ cmp(index, array_length_operand); | |
3691 __ j(less, &loop_3); // End while (index < length). | |
3692 __ jmp(&done); | |
3693 | |
3524 | 3694 |
3525 __ bind(&bailout); | 3695 __ bind(&bailout); |
3526 __ mov(result, Factory::undefined_value()); | 3696 __ mov(result_operand, Factory::undefined_value()); |
3527 __ bind(&done); | 3697 __ bind(&done); |
3528 __ mov(eax, result); | 3698 __ mov(eax, result_operand); |
3529 // Drop temp values from the stack, and restore context register. | 3699 // Drop temp values from the stack, and restore context register. |
3530 __ add(Operand(esp), Immediate(5 * kPointerSize)); | 3700 __ add(Operand(esp), Immediate(4 * kPointerSize)); |
3531 | 3701 |
3532 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 3702 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
3533 context()->Plug(eax); | 3703 context()->Plug(eax); |
3534 } | 3704 } |
3535 | 3705 |
3536 | 3706 |
3537 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 3707 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
3538 Handle<String> name = expr->name(); | 3708 Handle<String> name = expr->name(); |
3539 if (name->length() > 0 && name->Get(0) == '_') { | 3709 if (name->length() > 0 && name->Get(0) == '_') { |
3540 Comment cmnt(masm_, "[ InlineRuntimeCall"); | 3710 Comment cmnt(masm_, "[ InlineRuntimeCall"); |
(...skipping 732 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4273 // And return. | 4443 // And return. |
4274 __ ret(0); | 4444 __ ret(0); |
4275 } | 4445 } |
4276 | 4446 |
4277 | 4447 |
4278 #undef __ | 4448 #undef __ |
4279 | 4449 |
4280 } } // namespace v8::internal | 4450 } } // namespace v8::internal |
4281 | 4451 |
4282 #endif // V8_TARGET_ARCH_IA32 | 4452 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |