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 #if V8_TARGET_ARCH_MIPS | 5 #if V8_TARGET_ARCH_MIPS |
6 | 6 |
7 // Note on Mips implementation: | 7 // Note on Mips implementation: |
8 // | 8 // |
9 // The result_register() for mips is the 'v0' register, which is defined | 9 // The result_register() for mips is the 'v0' register, which is defined |
10 // by the ABI to contain function return values. However, the first | 10 // by the ABI to contain function return values. However, the first |
(...skipping 3419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3430 void FullCodeGenerator::EmitGetSuperConstructor(CallRuntime* expr) { | 3430 void FullCodeGenerator::EmitGetSuperConstructor(CallRuntime* expr) { |
3431 ZoneList<Expression*>* args = expr->arguments(); | 3431 ZoneList<Expression*>* args = expr->arguments(); |
3432 DCHECK_EQ(1, args->length()); | 3432 DCHECK_EQ(1, args->length()); |
3433 VisitForAccumulatorValue(args->at(0)); | 3433 VisitForAccumulatorValue(args->at(0)); |
3434 __ AssertFunction(v0); | 3434 __ AssertFunction(v0); |
3435 __ lw(v0, FieldMemOperand(v0, HeapObject::kMapOffset)); | 3435 __ lw(v0, FieldMemOperand(v0, HeapObject::kMapOffset)); |
3436 __ lw(v0, FieldMemOperand(v0, Map::kPrototypeOffset)); | 3436 __ lw(v0, FieldMemOperand(v0, Map::kPrototypeOffset)); |
3437 context()->Plug(v0); | 3437 context()->Plug(v0); |
3438 } | 3438 } |
3439 | 3439 |
| 3440 |
| 3441 void FullCodeGenerator::EmitFastOneByteArrayJoin(CallRuntime* expr) { |
| 3442 Label bailout, done, one_char_separator, long_separator, |
| 3443 non_trivial_array, not_size_one_array, loop, |
| 3444 empty_separator_loop, one_char_separator_loop, |
| 3445 one_char_separator_loop_entry, long_separator_loop; |
| 3446 ZoneList<Expression*>* args = expr->arguments(); |
| 3447 DCHECK(args->length() == 2); |
| 3448 VisitForStackValue(args->at(1)); |
| 3449 VisitForAccumulatorValue(args->at(0)); |
| 3450 |
| 3451 // All aliases of the same register have disjoint lifetimes. |
| 3452 Register array = v0; |
| 3453 Register elements = no_reg; // Will be v0. |
| 3454 Register result = no_reg; // Will be v0. |
| 3455 Register separator = a1; |
| 3456 Register array_length = a2; |
| 3457 Register result_pos = no_reg; // Will be a2. |
| 3458 Register string_length = a3; |
| 3459 Register string = t0; |
| 3460 Register element = t1; |
| 3461 Register elements_end = t2; |
| 3462 Register scratch1 = t3; |
| 3463 Register scratch2 = t5; |
| 3464 Register scratch3 = t4; |
| 3465 |
| 3466 // Separator operand is on the stack. |
| 3467 __ pop(separator); |
| 3468 |
| 3469 // Check that the array is a JSArray. |
| 3470 __ JumpIfSmi(array, &bailout); |
| 3471 __ GetObjectType(array, scratch1, scratch2); |
| 3472 __ Branch(&bailout, ne, scratch2, Operand(JS_ARRAY_TYPE)); |
| 3473 |
| 3474 // Check that the array has fast elements. |
| 3475 __ CheckFastElements(scratch1, scratch2, &bailout); |
| 3476 |
| 3477 // If the array has length zero, return the empty string. |
| 3478 __ lw(array_length, FieldMemOperand(array, JSArray::kLengthOffset)); |
| 3479 __ SmiUntag(array_length); |
| 3480 __ Branch(&non_trivial_array, ne, array_length, Operand(zero_reg)); |
| 3481 __ LoadRoot(v0, Heap::kempty_stringRootIndex); |
| 3482 __ Branch(&done); |
| 3483 |
| 3484 __ bind(&non_trivial_array); |
| 3485 |
| 3486 // Get the FixedArray containing array's elements. |
| 3487 elements = array; |
| 3488 __ lw(elements, FieldMemOperand(array, JSArray::kElementsOffset)); |
| 3489 array = no_reg; // End of array's live range. |
| 3490 |
| 3491 // Check that all array elements are sequential one-byte strings, and |
| 3492 // accumulate the sum of their lengths, as a smi-encoded value. |
| 3493 __ mov(string_length, zero_reg); |
| 3494 __ Addu(element, |
| 3495 elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 3496 __ Lsa(elements_end, element, array_length, kPointerSizeLog2); |
| 3497 // Loop condition: while (element < elements_end). |
| 3498 // Live values in registers: |
| 3499 // elements: Fixed array of strings. |
| 3500 // array_length: Length of the fixed array of strings (not smi) |
| 3501 // separator: Separator string |
| 3502 // string_length: Accumulated sum of string lengths (smi). |
| 3503 // element: Current array element. |
| 3504 // elements_end: Array end. |
| 3505 if (generate_debug_code_) { |
| 3506 __ Assert(gt, kNoEmptyArraysHereInEmitFastOneByteArrayJoin, array_length, |
| 3507 Operand(zero_reg)); |
| 3508 } |
| 3509 __ bind(&loop); |
| 3510 __ lw(string, MemOperand(element)); |
| 3511 __ Addu(element, element, kPointerSize); |
| 3512 __ JumpIfSmi(string, &bailout); |
| 3513 __ lw(scratch1, FieldMemOperand(string, HeapObject::kMapOffset)); |
| 3514 __ lbu(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); |
| 3515 __ JumpIfInstanceTypeIsNotSequentialOneByte(scratch1, scratch2, &bailout); |
| 3516 __ lw(scratch1, FieldMemOperand(string, SeqOneByteString::kLengthOffset)); |
| 3517 __ AddBranchOvf(string_length, string_length, Operand(scratch1), &bailout); |
| 3518 __ Branch(&loop, lt, element, Operand(elements_end)); |
| 3519 |
| 3520 // If array_length is 1, return elements[0], a string. |
| 3521 __ Branch(¬_size_one_array, ne, array_length, Operand(1)); |
| 3522 __ lw(v0, FieldMemOperand(elements, FixedArray::kHeaderSize)); |
| 3523 __ Branch(&done); |
| 3524 |
| 3525 __ bind(¬_size_one_array); |
| 3526 |
| 3527 // Live values in registers: |
| 3528 // separator: Separator string |
| 3529 // array_length: Length of the array. |
| 3530 // string_length: Sum of string lengths (smi). |
| 3531 // elements: FixedArray of strings. |
| 3532 |
| 3533 // Check that the separator is a flat one-byte string. |
| 3534 __ JumpIfSmi(separator, &bailout); |
| 3535 __ lw(scratch1, FieldMemOperand(separator, HeapObject::kMapOffset)); |
| 3536 __ lbu(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); |
| 3537 __ JumpIfInstanceTypeIsNotSequentialOneByte(scratch1, scratch2, &bailout); |
| 3538 |
| 3539 // Add (separator length times array_length) - separator length to the |
| 3540 // string_length to get the length of the result string. array_length is not |
| 3541 // smi but the other values are, so the result is a smi. |
| 3542 __ lw(scratch1, FieldMemOperand(separator, SeqOneByteString::kLengthOffset)); |
| 3543 __ Subu(string_length, string_length, Operand(scratch1)); |
| 3544 __ Mul(scratch3, scratch2, array_length, scratch1); |
| 3545 // Check for smi overflow. No overflow if higher 33 bits of 64-bit result are |
| 3546 // zero. |
| 3547 __ Branch(&bailout, ne, scratch3, Operand(zero_reg)); |
| 3548 __ And(scratch3, scratch2, Operand(0x80000000)); |
| 3549 __ Branch(&bailout, ne, scratch3, Operand(zero_reg)); |
| 3550 __ AddBranchOvf(string_length, string_length, Operand(scratch2), &bailout); |
| 3551 __ SmiUntag(string_length); |
| 3552 |
| 3553 // Bailout for large object allocations. |
| 3554 __ Branch(&bailout, gt, string_length, |
| 3555 Operand(Page::kMaxRegularHeapObjectSize)); |
| 3556 |
| 3557 // Get first element in the array to free up the elements register to be used |
| 3558 // for the result. |
| 3559 __ Addu(element, |
| 3560 elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 3561 result = elements; // End of live range for elements. |
| 3562 elements = no_reg; |
| 3563 // Live values in registers: |
| 3564 // element: First array element |
| 3565 // separator: Separator string |
| 3566 // string_length: Length of result string (not smi) |
| 3567 // array_length: Length of the array. |
| 3568 __ AllocateOneByteString(result, string_length, scratch1, scratch2, |
| 3569 elements_end, &bailout); |
| 3570 // Prepare for looping. Set up elements_end to end of the array. Set |
| 3571 // result_pos to the position of the result where to write the first |
| 3572 // character. |
| 3573 __ Lsa(elements_end, element, array_length, kPointerSizeLog2); |
| 3574 result_pos = array_length; // End of live range for array_length. |
| 3575 array_length = no_reg; |
| 3576 __ Addu(result_pos, |
| 3577 result, |
| 3578 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
| 3579 |
| 3580 // Check the length of the separator. |
| 3581 __ lw(scratch1, FieldMemOperand(separator, SeqOneByteString::kLengthOffset)); |
| 3582 __ li(at, Operand(Smi::FromInt(1))); |
| 3583 __ Branch(&one_char_separator, eq, scratch1, Operand(at)); |
| 3584 __ Branch(&long_separator, gt, scratch1, Operand(at)); |
| 3585 |
| 3586 // Empty separator case. |
| 3587 __ bind(&empty_separator_loop); |
| 3588 // Live values in registers: |
| 3589 // result_pos: the position to which we are currently copying characters. |
| 3590 // element: Current array element. |
| 3591 // elements_end: Array end. |
| 3592 |
| 3593 // Copy next array element to the result. |
| 3594 __ lw(string, MemOperand(element)); |
| 3595 __ Addu(element, element, kPointerSize); |
| 3596 __ lw(string_length, FieldMemOperand(string, String::kLengthOffset)); |
| 3597 __ SmiUntag(string_length); |
| 3598 __ Addu(string, string, SeqOneByteString::kHeaderSize - kHeapObjectTag); |
| 3599 __ CopyBytes(string, result_pos, string_length, scratch1); |
| 3600 // End while (element < elements_end). |
| 3601 __ Branch(&empty_separator_loop, lt, element, Operand(elements_end)); |
| 3602 DCHECK(result.is(v0)); |
| 3603 __ Branch(&done); |
| 3604 |
| 3605 // One-character separator case. |
| 3606 __ bind(&one_char_separator); |
| 3607 // Replace separator with its one-byte character value. |
| 3608 __ lbu(separator, FieldMemOperand(separator, SeqOneByteString::kHeaderSize)); |
| 3609 // Jump into the loop after the code that copies the separator, so the first |
| 3610 // element is not preceded by a separator. |
| 3611 __ jmp(&one_char_separator_loop_entry); |
| 3612 |
| 3613 __ bind(&one_char_separator_loop); |
| 3614 // Live values in registers: |
| 3615 // result_pos: the position to which we are currently copying characters. |
| 3616 // element: Current array element. |
| 3617 // elements_end: Array end. |
| 3618 // separator: Single separator one-byte char (in lower byte). |
| 3619 |
| 3620 // Copy the separator character to the result. |
| 3621 __ sb(separator, MemOperand(result_pos)); |
| 3622 __ Addu(result_pos, result_pos, 1); |
| 3623 |
| 3624 // Copy next array element to the result. |
| 3625 __ bind(&one_char_separator_loop_entry); |
| 3626 __ lw(string, MemOperand(element)); |
| 3627 __ Addu(element, element, kPointerSize); |
| 3628 __ lw(string_length, FieldMemOperand(string, String::kLengthOffset)); |
| 3629 __ SmiUntag(string_length); |
| 3630 __ Addu(string, string, SeqOneByteString::kHeaderSize - kHeapObjectTag); |
| 3631 __ CopyBytes(string, result_pos, string_length, scratch1); |
| 3632 // End while (element < elements_end). |
| 3633 __ Branch(&one_char_separator_loop, lt, element, Operand(elements_end)); |
| 3634 DCHECK(result.is(v0)); |
| 3635 __ Branch(&done); |
| 3636 |
| 3637 // Long separator case (separator is more than one character). Entry is at the |
| 3638 // label long_separator below. |
| 3639 __ bind(&long_separator_loop); |
| 3640 // Live values in registers: |
| 3641 // result_pos: the position to which we are currently copying characters. |
| 3642 // element: Current array element. |
| 3643 // elements_end: Array end. |
| 3644 // separator: Separator string. |
| 3645 |
| 3646 // Copy the separator to the result. |
| 3647 __ lw(string_length, FieldMemOperand(separator, String::kLengthOffset)); |
| 3648 __ SmiUntag(string_length); |
| 3649 __ Addu(string, |
| 3650 separator, |
| 3651 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
| 3652 __ CopyBytes(string, result_pos, string_length, scratch1); |
| 3653 |
| 3654 __ bind(&long_separator); |
| 3655 __ lw(string, MemOperand(element)); |
| 3656 __ Addu(element, element, kPointerSize); |
| 3657 __ lw(string_length, FieldMemOperand(string, String::kLengthOffset)); |
| 3658 __ SmiUntag(string_length); |
| 3659 __ Addu(string, string, SeqOneByteString::kHeaderSize - kHeapObjectTag); |
| 3660 __ CopyBytes(string, result_pos, string_length, scratch1); |
| 3661 // End while (element < elements_end). |
| 3662 __ Branch(&long_separator_loop, lt, element, Operand(elements_end)); |
| 3663 DCHECK(result.is(v0)); |
| 3664 __ Branch(&done); |
| 3665 |
| 3666 __ bind(&bailout); |
| 3667 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); |
| 3668 __ bind(&done); |
| 3669 context()->Plug(v0); |
| 3670 } |
| 3671 |
3440 | 3672 |
3441 void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) { | 3673 void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) { |
3442 DCHECK(expr->arguments()->length() == 0); | 3674 DCHECK(expr->arguments()->length() == 0); |
3443 ExternalReference debug_is_active = | 3675 ExternalReference debug_is_active = |
3444 ExternalReference::debug_is_active_address(isolate()); | 3676 ExternalReference::debug_is_active_address(isolate()); |
3445 __ li(at, Operand(debug_is_active)); | 3677 __ li(at, Operand(debug_is_active)); |
3446 __ lb(v0, MemOperand(at)); | 3678 __ lb(v0, MemOperand(at)); |
3447 __ SmiTag(v0); | 3679 __ SmiTag(v0); |
3448 context()->Plug(v0); | 3680 context()->Plug(v0); |
3449 } | 3681 } |
(...skipping 838 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4288 reinterpret_cast<uint32_t>( | 4520 reinterpret_cast<uint32_t>( |
4289 isolate->builtins()->OsrAfterStackCheck()->entry())); | 4521 isolate->builtins()->OsrAfterStackCheck()->entry())); |
4290 return OSR_AFTER_STACK_CHECK; | 4522 return OSR_AFTER_STACK_CHECK; |
4291 } | 4523 } |
4292 | 4524 |
4293 | 4525 |
4294 } // namespace internal | 4526 } // namespace internal |
4295 } // namespace v8 | 4527 } // namespace v8 |
4296 | 4528 |
4297 #endif // V8_TARGET_ARCH_MIPS | 4529 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |