| 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 1583 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1594 __ lw(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); | 1594 __ lw(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); |
| 1595 | 1595 |
| 1596 // Check that the elements are in fast mode and writable. | 1596 // Check that the elements are in fast mode and writable. |
| 1597 __ CheckMap(elements, | 1597 __ CheckMap(elements, |
| 1598 v0, | 1598 v0, |
| 1599 Heap::kFixedArrayMapRootIndex, | 1599 Heap::kFixedArrayMapRootIndex, |
| 1600 &call_builtin, | 1600 &call_builtin, |
| 1601 DONT_DO_SMI_CHECK); | 1601 DONT_DO_SMI_CHECK); |
| 1602 | 1602 |
| 1603 if (argc == 1) { // Otherwise fall through to call the builtin. | 1603 if (argc == 1) { // Otherwise fall through to call the builtin. |
| 1604 Label exit, attempt_to_grow_elements; | 1604 Label attempt_to_grow_elements; |
| 1605 | 1605 |
| 1606 // Get the array's length into v0 and calculate new length. | 1606 // Get the array's length into v0 and calculate new length. |
| 1607 __ lw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1607 __ lw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 1608 STATIC_ASSERT(kSmiTagSize == 1); | 1608 STATIC_ASSERT(kSmiTagSize == 1); |
| 1609 STATIC_ASSERT(kSmiTag == 0); | 1609 STATIC_ASSERT(kSmiTag == 0); |
| 1610 __ Addu(v0, v0, Operand(Smi::FromInt(argc))); | 1610 __ Addu(v0, v0, Operand(Smi::FromInt(argc))); |
| 1611 | 1611 |
| 1612 // Get the element's length. | 1612 // Get the element's length. |
| 1613 __ lw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset)); | 1613 __ lw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset)); |
| 1614 | 1614 |
| 1615 // Check if we could survive without allocation. | 1615 // Check if we could survive without allocation. |
| 1616 __ Branch(&attempt_to_grow_elements, gt, v0, Operand(t0)); | 1616 __ Branch(&attempt_to_grow_elements, gt, v0, Operand(t0)); |
| 1617 | 1617 |
| 1618 // Check if value is a smi. |
| 1619 Label with_write_barrier; |
| 1620 __ lw(t0, MemOperand(sp, (argc - 1) * kPointerSize)); |
| 1621 __ JumpIfNotSmi(t0, &with_write_barrier); |
| 1622 |
| 1618 // Save new length. | 1623 // Save new length. |
| 1619 __ sw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1624 __ sw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 1620 | 1625 |
| 1621 // Push the element. | 1626 // Push the element. |
| 1622 __ lw(t0, MemOperand(sp, (argc - 1) * kPointerSize)); | |
| 1623 // We may need a register containing the address end_elements below, | 1627 // We may need a register containing the address end_elements below, |
| 1624 // so write back the value in end_elements. | 1628 // so write back the value in end_elements. |
| 1625 __ sll(end_elements, v0, kPointerSizeLog2 - kSmiTagSize); | 1629 __ sll(end_elements, v0, kPointerSizeLog2 - kSmiTagSize); |
| 1626 __ Addu(end_elements, elements, end_elements); | 1630 __ Addu(end_elements, elements, end_elements); |
| 1627 const int kEndElementsOffset = | 1631 const int kEndElementsOffset = |
| 1628 FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize; | 1632 FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize; |
| 1629 __ Addu(end_elements, end_elements, kEndElementsOffset); | 1633 __ Addu(end_elements, end_elements, kEndElementsOffset); |
| 1630 __ sw(t0, MemOperand(end_elements)); | 1634 __ sw(t0, MemOperand(end_elements)); |
| 1631 | 1635 |
| 1632 // Check for a smi. | 1636 // Check for a smi. |
| 1633 Label with_write_barrier; | |
| 1634 __ JumpIfNotSmi(t0, &with_write_barrier); | |
| 1635 __ bind(&exit); | |
| 1636 __ Drop(argc + 1); | 1637 __ Drop(argc + 1); |
| 1637 __ Ret(); | 1638 __ Ret(); |
| 1638 | 1639 |
| 1639 __ bind(&with_write_barrier); | 1640 __ bind(&with_write_barrier); |
| 1641 |
| 1642 __ lw(t2, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| 1643 __ CheckFastSmiOnlyElements(t2, t2, &call_builtin); |
| 1644 |
| 1645 // Save new length. |
| 1646 __ sw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 1647 |
| 1648 // Push the element. |
| 1649 // We may need a register containing the address end_elements below, |
| 1650 // so write back the value in end_elements. |
| 1651 __ sll(end_elements, v0, kPointerSizeLog2 - kSmiTagSize); |
| 1652 __ Addu(end_elements, elements, end_elements); |
| 1653 __ Addu(end_elements, end_elements, kEndElementsOffset); |
| 1654 __ sw(t0, MemOperand(end_elements)); |
| 1655 |
| 1640 __ RecordWrite(elements, | 1656 __ RecordWrite(elements, |
| 1641 end_elements, | 1657 end_elements, |
| 1642 t0, | 1658 t0, |
| 1643 kRAHasNotBeenSaved, | 1659 kRAHasNotBeenSaved, |
| 1644 kDontSaveFPRegs, | 1660 kDontSaveFPRegs, |
| 1645 EMIT_REMEMBERED_SET, | 1661 EMIT_REMEMBERED_SET, |
| 1646 OMIT_SMI_CHECK); | 1662 OMIT_SMI_CHECK); |
| 1647 __ Drop(argc + 1); | 1663 __ Drop(argc + 1); |
| 1648 __ Ret(); | 1664 __ Ret(); |
| 1649 | 1665 |
| 1650 __ bind(&attempt_to_grow_elements); | 1666 __ bind(&attempt_to_grow_elements); |
| 1651 // v0: array's length + 1. | 1667 // v0: array's length + 1. |
| 1652 // t0: elements' length. | 1668 // t0: elements' length. |
| 1653 | 1669 |
| 1654 if (!FLAG_inline_new) { | 1670 if (!FLAG_inline_new) { |
| 1655 __ Branch(&call_builtin); | 1671 __ Branch(&call_builtin); |
| 1656 } | 1672 } |
| 1657 | 1673 |
| 1674 __ lw(a2, MemOperand(sp, (argc - 1) * kPointerSize)); |
| 1675 // Growing elements that are SMI-only requires special handling in case |
| 1676 // the new element is non-Smi. For now, delegate to the builtin. |
| 1677 Label no_fast_elements_check; |
| 1678 __ JumpIfSmi(a2, &no_fast_elements_check); |
| 1679 __ lw(t3, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| 1680 __ CheckFastObjectElements(t3, t3, &call_builtin); |
| 1681 __ bind(&no_fast_elements_check); |
| 1682 |
| 1658 ExternalReference new_space_allocation_top = | 1683 ExternalReference new_space_allocation_top = |
| 1659 ExternalReference::new_space_allocation_top_address( | 1684 ExternalReference::new_space_allocation_top_address( |
| 1660 masm()->isolate()); | 1685 masm()->isolate()); |
| 1661 ExternalReference new_space_allocation_limit = | 1686 ExternalReference new_space_allocation_limit = |
| 1662 ExternalReference::new_space_allocation_limit_address( | 1687 ExternalReference::new_space_allocation_limit_address( |
| 1663 masm()->isolate()); | 1688 masm()->isolate()); |
| 1664 | 1689 |
| 1665 const int kAllocationDelta = 4; | 1690 const int kAllocationDelta = 4; |
| 1666 // Load top and check if it is the end of elements. | 1691 // Load top and check if it is the end of elements. |
| 1667 __ sll(end_elements, v0, kPointerSizeLog2 - kSmiTagSize); | 1692 __ sll(end_elements, v0, kPointerSizeLog2 - kSmiTagSize); |
| 1668 __ Addu(end_elements, elements, end_elements); | 1693 __ Addu(end_elements, elements, end_elements); |
| 1669 __ Addu(end_elements, end_elements, Operand(kEndElementsOffset)); | 1694 __ Addu(end_elements, end_elements, Operand(kEndElementsOffset)); |
| 1670 __ li(t3, Operand(new_space_allocation_top)); | 1695 __ li(t3, Operand(new_space_allocation_top)); |
| 1671 __ lw(t2, MemOperand(t3)); | 1696 __ lw(t2, MemOperand(t3)); |
| 1672 __ Branch(&call_builtin, ne, end_elements, Operand(t2)); | 1697 __ Branch(&call_builtin, ne, end_elements, Operand(t2)); |
| 1673 | 1698 |
| 1674 __ li(t5, Operand(new_space_allocation_limit)); | 1699 __ li(t5, Operand(new_space_allocation_limit)); |
| 1675 __ lw(t5, MemOperand(t5)); | 1700 __ lw(t5, MemOperand(t5)); |
| 1676 __ Addu(t2, t2, Operand(kAllocationDelta * kPointerSize)); | 1701 __ Addu(t2, t2, Operand(kAllocationDelta * kPointerSize)); |
| 1677 __ Branch(&call_builtin, hi, t2, Operand(t5)); | 1702 __ Branch(&call_builtin, hi, t2, Operand(t5)); |
| 1678 | 1703 |
| 1679 // We fit and could grow elements. | 1704 // We fit and could grow elements. |
| 1680 // Update new_space_allocation_top. | 1705 // Update new_space_allocation_top. |
| 1681 __ sw(t2, MemOperand(t3)); | 1706 __ sw(t2, MemOperand(t3)); |
| 1682 // Push the argument. | 1707 // Push the argument. |
| 1683 __ lw(t2, MemOperand(sp, (argc - 1) * kPointerSize)); | 1708 __ sw(a2, MemOperand(end_elements)); |
| 1684 __ sw(t2, MemOperand(end_elements)); | |
| 1685 // Fill the rest with holes. | 1709 // Fill the rest with holes. |
| 1686 __ LoadRoot(t2, Heap::kTheHoleValueRootIndex); | 1710 __ LoadRoot(t2, Heap::kTheHoleValueRootIndex); |
| 1687 for (int i = 1; i < kAllocationDelta; i++) { | 1711 for (int i = 1; i < kAllocationDelta; i++) { |
| 1688 __ sw(t2, MemOperand(end_elements, i * kPointerSize)); | 1712 __ sw(t2, MemOperand(end_elements, i * kPointerSize)); |
| 1689 } | 1713 } |
| 1690 | 1714 |
| 1691 // Update elements' and array's sizes. | 1715 // Update elements' and array's sizes. |
| 1692 __ sw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1716 __ sw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 1693 __ Addu(t0, t0, Operand(Smi::FromInt(kAllocationDelta))); | 1717 __ Addu(t0, t0, Operand(Smi::FromInt(kAllocationDelta))); |
| 1694 __ sw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset)); | 1718 __ sw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset)); |
| (...skipping 1550 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3245 DO_SMI_CHECK); | 3269 DO_SMI_CHECK); |
| 3246 | 3270 |
| 3247 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); | 3271 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
| 3248 __ Jump(ic, RelocInfo::CODE_TARGET); | 3272 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 3249 | 3273 |
| 3250 // Return the generated code. | 3274 // Return the generated code. |
| 3251 return GetCode(NORMAL, NULL); | 3275 return GetCode(NORMAL, NULL); |
| 3252 } | 3276 } |
| 3253 | 3277 |
| 3254 | 3278 |
| 3255 MaybeObject* KeyedStoreStubCompiler::CompileStoreMegamorphic( | 3279 MaybeObject* KeyedStoreStubCompiler::CompileStorePolymorphic( |
| 3256 MapList* receiver_maps, | 3280 MapList* receiver_maps, |
| 3257 CodeList* handler_ics) { | 3281 CodeList* handler_stubs, |
| 3282 MapList* transitioned_maps) { |
| 3258 // ----------- S t a t e ------------- | 3283 // ----------- S t a t e ------------- |
| 3259 // -- a0 : value | 3284 // -- a0 : value |
| 3260 // -- a1 : key | 3285 // -- a1 : key |
| 3261 // -- a2 : receiver | 3286 // -- a2 : receiver |
| 3262 // -- ra : return address | 3287 // -- ra : return address |
| 3263 // -- a3 : scratch | 3288 // -- a3 : scratch |
| 3264 // ----------------------------------- | 3289 // ----------------------------------- |
| 3265 Label miss; | 3290 Label miss; |
| 3266 __ JumpIfSmi(a2, &miss); | 3291 __ JumpIfSmi(a2, &miss); |
| 3267 | 3292 |
| 3268 int receiver_count = receiver_maps->length(); | 3293 int receiver_count = receiver_maps->length(); |
| 3269 __ lw(a3, FieldMemOperand(a2, HeapObject::kMapOffset)); | 3294 __ lw(a3, FieldMemOperand(a2, HeapObject::kMapOffset)); |
| 3270 for (int current = 0; current < receiver_count; ++current) { | 3295 for (int i = 0; i < receiver_count; ++i) { |
| 3271 Handle<Map> map(receiver_maps->at(current)); | 3296 Handle<Map> map(receiver_maps->at(i)); |
| 3272 Handle<Code> code(handler_ics->at(current)); | 3297 Handle<Code> code(handler_stubs->at(i)); |
| 3273 __ Jump(code, RelocInfo::CODE_TARGET, eq, a3, Operand(map)); | 3298 if (transitioned_maps->at(i) == NULL) { |
| 3299 __ Jump(code, RelocInfo::CODE_TARGET, eq, a3, Operand(map)); |
| 3300 } else { |
| 3301 Label next_map; |
| 3302 __ Branch(&next_map, eq, a3, Operand(map)); |
| 3303 __ li(t0, Operand(Handle<Map>(transitioned_maps->at(i)))); |
| 3304 __ Jump(code, RelocInfo::CODE_TARGET); |
| 3305 __ bind(&next_map); |
| 3306 } |
| 3274 } | 3307 } |
| 3275 | 3308 |
| 3276 __ bind(&miss); | 3309 __ bind(&miss); |
| 3277 Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss(); | 3310 Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
| 3278 __ Jump(miss_ic, RelocInfo::CODE_TARGET); | 3311 __ Jump(miss_ic, RelocInfo::CODE_TARGET); |
| 3279 | 3312 |
| 3280 // Return the generated code. | 3313 // Return the generated code. |
| 3281 return GetCode(NORMAL, NULL, MEGAMORPHIC); | 3314 return GetCode(NORMAL, NULL, MEGAMORPHIC); |
| 3282 } | 3315 } |
| 3283 | 3316 |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3492 return true; | 3525 return true; |
| 3493 | 3526 |
| 3494 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 3527 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 3495 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 3528 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 3496 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 3529 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 3497 case EXTERNAL_PIXEL_ELEMENTS: | 3530 case EXTERNAL_PIXEL_ELEMENTS: |
| 3498 return false; | 3531 return false; |
| 3499 | 3532 |
| 3500 case EXTERNAL_FLOAT_ELEMENTS: | 3533 case EXTERNAL_FLOAT_ELEMENTS: |
| 3501 case EXTERNAL_DOUBLE_ELEMENTS: | 3534 case EXTERNAL_DOUBLE_ELEMENTS: |
| 3502 case FAST_SMI_ELEMENTS: | 3535 case FAST_SMI_ONLY_ELEMENTS: |
| 3503 case FAST_ELEMENTS: | 3536 case FAST_ELEMENTS: |
| 3504 case FAST_DOUBLE_ELEMENTS: | 3537 case FAST_DOUBLE_ELEMENTS: |
| 3505 case DICTIONARY_ELEMENTS: | 3538 case DICTIONARY_ELEMENTS: |
| 3506 case NON_STRICT_ARGUMENTS_ELEMENTS: | 3539 case NON_STRICT_ARGUMENTS_ELEMENTS: |
| 3507 UNREACHABLE(); | 3540 UNREACHABLE(); |
| 3508 return false; | 3541 return false; |
| 3509 } | 3542 } |
| 3510 return false; | 3543 return false; |
| 3511 } | 3544 } |
| 3512 | 3545 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3589 if (CpuFeatures::IsSupported(FPU)) { | 3622 if (CpuFeatures::IsSupported(FPU)) { |
| 3590 CpuFeatures::Scope scope(FPU); | 3623 CpuFeatures::Scope scope(FPU); |
| 3591 __ ldc1(f0, MemOperand(t3, 0)); | 3624 __ ldc1(f0, MemOperand(t3, 0)); |
| 3592 } else { | 3625 } else { |
| 3593 // t3: pointer to the beginning of the double we want to load. | 3626 // t3: pointer to the beginning of the double we want to load. |
| 3594 __ lw(a2, MemOperand(t3, 0)); | 3627 __ lw(a2, MemOperand(t3, 0)); |
| 3595 __ lw(a3, MemOperand(t3, Register::kSizeInBytes)); | 3628 __ lw(a3, MemOperand(t3, Register::kSizeInBytes)); |
| 3596 } | 3629 } |
| 3597 break; | 3630 break; |
| 3598 case FAST_ELEMENTS: | 3631 case FAST_ELEMENTS: |
| 3632 case FAST_SMI_ONLY_ELEMENTS: |
| 3599 case FAST_DOUBLE_ELEMENTS: | 3633 case FAST_DOUBLE_ELEMENTS: |
| 3600 case DICTIONARY_ELEMENTS: | 3634 case DICTIONARY_ELEMENTS: |
| 3601 case NON_STRICT_ARGUMENTS_ELEMENTS: | 3635 case NON_STRICT_ARGUMENTS_ELEMENTS: |
| 3602 UNREACHABLE(); | 3636 UNREACHABLE(); |
| 3603 break; | 3637 break; |
| 3604 } | 3638 } |
| 3605 | 3639 |
| 3606 // For integer array types: | 3640 // For integer array types: |
| 3607 // a2: value | 3641 // a2: value |
| 3608 // For float array type: | 3642 // For float array type: |
| (...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3949 t0, f2); // These are: scratch2, single_scratch. | 3983 t0, f2); // These are: scratch2, single_scratch. |
| 3950 if (destination == FloatingPointHelper::kFPURegisters) { | 3984 if (destination == FloatingPointHelper::kFPURegisters) { |
| 3951 CpuFeatures::Scope scope(FPU); | 3985 CpuFeatures::Scope scope(FPU); |
| 3952 __ sdc1(f0, MemOperand(a3, 0)); | 3986 __ sdc1(f0, MemOperand(a3, 0)); |
| 3953 } else { | 3987 } else { |
| 3954 __ sw(t2, MemOperand(a3, 0)); | 3988 __ sw(t2, MemOperand(a3, 0)); |
| 3955 __ sw(t3, MemOperand(a3, Register::kSizeInBytes)); | 3989 __ sw(t3, MemOperand(a3, Register::kSizeInBytes)); |
| 3956 } | 3990 } |
| 3957 break; | 3991 break; |
| 3958 case FAST_ELEMENTS: | 3992 case FAST_ELEMENTS: |
| 3993 case FAST_SMI_ONLY_ELEMENTS: |
| 3959 case FAST_DOUBLE_ELEMENTS: | 3994 case FAST_DOUBLE_ELEMENTS: |
| 3960 case DICTIONARY_ELEMENTS: | 3995 case DICTIONARY_ELEMENTS: |
| 3961 case NON_STRICT_ARGUMENTS_ELEMENTS: | 3996 case NON_STRICT_ARGUMENTS_ELEMENTS: |
| 3962 UNREACHABLE(); | 3997 UNREACHABLE(); |
| 3963 break; | 3998 break; |
| 3964 } | 3999 } |
| 3965 | 4000 |
| 3966 // Entry registers are intact, a0 holds the value which is the return value. | 4001 // Entry registers are intact, a0 holds the value which is the return value. |
| 3967 __ mov(v0, a0); | 4002 __ mov(v0, a0); |
| 3968 __ Ret(); | 4003 __ Ret(); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4013 case EXTERNAL_INT_ELEMENTS: | 4048 case EXTERNAL_INT_ELEMENTS: |
| 4014 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 4049 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 4015 __ sll(t8, key, 1); | 4050 __ sll(t8, key, 1); |
| 4016 __ addu(t8, a3, t8); | 4051 __ addu(t8, a3, t8); |
| 4017 __ sw(t3, MemOperand(t8, 0)); | 4052 __ sw(t3, MemOperand(t8, 0)); |
| 4018 break; | 4053 break; |
| 4019 case EXTERNAL_PIXEL_ELEMENTS: | 4054 case EXTERNAL_PIXEL_ELEMENTS: |
| 4020 case EXTERNAL_FLOAT_ELEMENTS: | 4055 case EXTERNAL_FLOAT_ELEMENTS: |
| 4021 case EXTERNAL_DOUBLE_ELEMENTS: | 4056 case EXTERNAL_DOUBLE_ELEMENTS: |
| 4022 case FAST_ELEMENTS: | 4057 case FAST_ELEMENTS: |
| 4058 case FAST_SMI_ONLY_ELEMENTS: |
| 4023 case FAST_DOUBLE_ELEMENTS: | 4059 case FAST_DOUBLE_ELEMENTS: |
| 4024 case DICTIONARY_ELEMENTS: | 4060 case DICTIONARY_ELEMENTS: |
| 4025 case NON_STRICT_ARGUMENTS_ELEMENTS: | 4061 case NON_STRICT_ARGUMENTS_ELEMENTS: |
| 4026 UNREACHABLE(); | 4062 UNREACHABLE(); |
| 4027 break; | 4063 break; |
| 4028 } | 4064 } |
| 4029 } | 4065 } |
| 4030 | 4066 |
| 4031 // Entry registers are intact, a0 holds the value | 4067 // Entry registers are intact, a0 holds the value |
| 4032 // which is the return value. | 4068 // which is the return value. |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4184 case EXTERNAL_INT_ELEMENTS: | 4220 case EXTERNAL_INT_ELEMENTS: |
| 4185 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 4221 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 4186 __ sll(t8, key, 1); | 4222 __ sll(t8, key, 1); |
| 4187 __ addu(t8, a3, t8); | 4223 __ addu(t8, a3, t8); |
| 4188 __ sw(t3, MemOperand(t8, 0)); | 4224 __ sw(t3, MemOperand(t8, 0)); |
| 4189 break; | 4225 break; |
| 4190 case EXTERNAL_PIXEL_ELEMENTS: | 4226 case EXTERNAL_PIXEL_ELEMENTS: |
| 4191 case EXTERNAL_FLOAT_ELEMENTS: | 4227 case EXTERNAL_FLOAT_ELEMENTS: |
| 4192 case EXTERNAL_DOUBLE_ELEMENTS: | 4228 case EXTERNAL_DOUBLE_ELEMENTS: |
| 4193 case FAST_ELEMENTS: | 4229 case FAST_ELEMENTS: |
| 4230 case FAST_SMI_ONLY_ELEMENTS: |
| 4194 case FAST_DOUBLE_ELEMENTS: | 4231 case FAST_DOUBLE_ELEMENTS: |
| 4195 case DICTIONARY_ELEMENTS: | 4232 case DICTIONARY_ELEMENTS: |
| 4196 case NON_STRICT_ARGUMENTS_ELEMENTS: | 4233 case NON_STRICT_ARGUMENTS_ELEMENTS: |
| 4197 UNREACHABLE(); | 4234 UNREACHABLE(); |
| 4198 break; | 4235 break; |
| 4199 } | 4236 } |
| 4200 } | 4237 } |
| 4201 } | 4238 } |
| 4202 } | 4239 } |
| 4203 | 4240 |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4333 masm->isolate()->builtins()->KeyedLoadIC_Slow(); | 4370 masm->isolate()->builtins()->KeyedLoadIC_Slow(); |
| 4334 __ Jump(slow_ic, RelocInfo::CODE_TARGET); | 4371 __ Jump(slow_ic, RelocInfo::CODE_TARGET); |
| 4335 | 4372 |
| 4336 __ bind(&miss_force_generic); | 4373 __ bind(&miss_force_generic); |
| 4337 Handle<Code> miss_ic = | 4374 Handle<Code> miss_ic = |
| 4338 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); | 4375 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); |
| 4339 __ Jump(miss_ic, RelocInfo::CODE_TARGET); | 4376 __ Jump(miss_ic, RelocInfo::CODE_TARGET); |
| 4340 } | 4377 } |
| 4341 | 4378 |
| 4342 | 4379 |
| 4343 void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm, | 4380 void KeyedStoreStubCompiler::GenerateStoreFastElement( |
| 4344 bool is_js_array) { | 4381 MacroAssembler* masm, |
| 4382 bool is_js_array, |
| 4383 ElementsKind elements_kind) { |
| 4345 // ----------- S t a t e ------------- | 4384 // ----------- S t a t e ------------- |
| 4346 // -- a0 : value | 4385 // -- a0 : value |
| 4347 // -- a1 : key | 4386 // -- a1 : key |
| 4348 // -- a2 : receiver | 4387 // -- a2 : receiver |
| 4349 // -- ra : return address | 4388 // -- ra : return address |
| 4350 // -- a3 : scratch | 4389 // -- a3 : scratch |
| 4351 // -- a4 : scratch (elements) | 4390 // -- a4 : scratch (elements) |
| 4352 // ----------------------------------- | 4391 // ----------------------------------- |
| 4353 Label miss_force_generic; | 4392 Label miss_force_generic, transition_elements_kind; |
| 4354 | 4393 |
| 4355 Register value_reg = a0; | 4394 Register value_reg = a0; |
| 4356 Register key_reg = a1; | 4395 Register key_reg = a1; |
| 4357 Register receiver_reg = a2; | 4396 Register receiver_reg = a2; |
| 4358 Register scratch = a3; | 4397 Register scratch = a3; |
| 4359 Register elements_reg = t0; | 4398 Register elements_reg = t0; |
| 4360 Register scratch2 = t1; | 4399 Register scratch2 = t1; |
| 4361 Register scratch3 = t2; | 4400 Register scratch3 = t2; |
| 4362 | 4401 |
| 4363 // This stub is meant to be tail-jumped to, the receiver must already | 4402 // This stub is meant to be tail-jumped to, the receiver must already |
| (...skipping 13 matching lines...) Expand all Loading... |
| 4377 | 4416 |
| 4378 // Check that the key is within bounds. | 4417 // Check that the key is within bounds. |
| 4379 if (is_js_array) { | 4418 if (is_js_array) { |
| 4380 __ lw(scratch, FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); | 4419 __ lw(scratch, FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); |
| 4381 } else { | 4420 } else { |
| 4382 __ lw(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset)); | 4421 __ lw(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset)); |
| 4383 } | 4422 } |
| 4384 // Compare smis. | 4423 // Compare smis. |
| 4385 __ Branch(&miss_force_generic, hs, key_reg, Operand(scratch)); | 4424 __ Branch(&miss_force_generic, hs, key_reg, Operand(scratch)); |
| 4386 | 4425 |
| 4387 __ Addu(scratch, | 4426 if (elements_kind == FAST_SMI_ONLY_ELEMENTS) { |
| 4388 elements_reg, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 4427 __ JumpIfNotSmi(value_reg, &transition_elements_kind); |
| 4389 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); | 4428 __ Addu(scratch, |
| 4390 __ sll(scratch2, key_reg, kPointerSizeLog2 - kSmiTagSize); | 4429 elements_reg, |
| 4391 __ Addu(scratch, scratch, scratch2); | 4430 Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 4392 __ sw(value_reg, MemOperand(scratch)); | 4431 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); |
| 4393 __ mov(receiver_reg, value_reg); | 4432 __ sll(scratch2, key_reg, kPointerSizeLog2 - kSmiTagSize); |
| 4394 __ RecordWrite(elements_reg, // Object. | 4433 __ Addu(scratch, scratch, scratch2); |
| 4395 scratch, // Address. | 4434 __ sw(value_reg, MemOperand(scratch)); |
| 4396 receiver_reg, // Value. | 4435 } else { |
| 4397 kRAHasNotBeenSaved, | 4436 ASSERT(elements_kind == FAST_ELEMENTS); |
| 4398 kDontSaveFPRegs); | 4437 __ Addu(scratch, |
| 4399 | 4438 elements_reg, |
| 4439 Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 4440 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); |
| 4441 __ sll(scratch2, key_reg, kPointerSizeLog2 - kSmiTagSize); |
| 4442 __ Addu(scratch, scratch, scratch2); |
| 4443 __ sw(value_reg, MemOperand(scratch)); |
| 4444 __ mov(receiver_reg, value_reg); |
| 4445 ASSERT(elements_kind == FAST_ELEMENTS); |
| 4446 __ RecordWrite(elements_reg, // Object. |
| 4447 scratch, // Address. |
| 4448 receiver_reg, // Value. |
| 4449 kRAHasNotBeenSaved, |
| 4450 kDontSaveFPRegs); |
| 4451 } |
| 4400 // value_reg (a0) is preserved. | 4452 // value_reg (a0) is preserved. |
| 4401 // Done. | 4453 // Done. |
| 4402 __ Ret(); | 4454 __ Ret(); |
| 4403 | 4455 |
| 4404 __ bind(&miss_force_generic); | 4456 __ bind(&miss_force_generic); |
| 4405 Handle<Code> ic = | 4457 Handle<Code> ic = |
| 4406 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | 4458 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); |
| 4407 __ Jump(ic, RelocInfo::CODE_TARGET); | 4459 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 4460 |
| 4461 __ bind(&transition_elements_kind); |
| 4462 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); |
| 4463 __ Jump(ic_miss, RelocInfo::CODE_TARGET); |
| 4408 } | 4464 } |
| 4409 | 4465 |
| 4410 | 4466 |
| 4411 void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( | 4467 void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( |
| 4412 MacroAssembler* masm, | 4468 MacroAssembler* masm, |
| 4413 bool is_js_array) { | 4469 bool is_js_array) { |
| 4414 // ----------- S t a t e ------------- | 4470 // ----------- S t a t e ------------- |
| 4415 // -- a0 : value | 4471 // -- a0 : value |
| 4416 // -- a1 : key | 4472 // -- a1 : key |
| 4417 // -- a2 : receiver | 4473 // -- a2 : receiver |
| 4418 // -- ra : return address | 4474 // -- ra : return address |
| 4419 // -- a3 : scratch | 4475 // -- a3 : scratch |
| 4420 // -- t0 : scratch (elements_reg) | 4476 // -- t0 : scratch (elements_reg) |
| 4421 // -- t1 : scratch (mantissa_reg) | 4477 // -- t1 : scratch (mantissa_reg) |
| 4422 // -- t2 : scratch (exponent_reg) | 4478 // -- t2 : scratch (exponent_reg) |
| 4423 // -- t3 : scratch4 | 4479 // -- t3 : scratch4 |
| 4424 // ----------------------------------- | 4480 // ----------------------------------- |
| 4425 Label miss_force_generic, smi_value, is_nan, maybe_nan, have_double_value; | 4481 Label miss_force_generic, transition_elements_kind; |
| 4426 | 4482 |
| 4427 Register value_reg = a0; | 4483 Register value_reg = a0; |
| 4428 Register key_reg = a1; | 4484 Register key_reg = a1; |
| 4429 Register receiver_reg = a2; | 4485 Register receiver_reg = a2; |
| 4430 Register scratch = a3; | 4486 Register elements_reg = a3; |
| 4431 Register elements_reg = t0; | 4487 Register scratch1 = t0; |
| 4432 Register mantissa_reg = t1; | 4488 Register scratch2 = t1; |
| 4433 Register exponent_reg = t2; | 4489 Register scratch3 = t2; |
| 4434 Register scratch4 = t3; | 4490 Register scratch4 = t3; |
| 4435 | 4491 |
| 4436 // This stub is meant to be tail-jumped to, the receiver must already | 4492 // This stub is meant to be tail-jumped to, the receiver must already |
| 4437 // have been verified by the caller to not be a smi. | 4493 // have been verified by the caller to not be a smi. |
| 4438 __ JumpIfNotSmi(key_reg, &miss_force_generic); | 4494 __ JumpIfNotSmi(key_reg, &miss_force_generic); |
| 4439 | 4495 |
| 4440 __ lw(elements_reg, | 4496 __ lw(elements_reg, |
| 4441 FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); | 4497 FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); |
| 4442 | 4498 |
| 4443 // Check that the key is within bounds. | 4499 // Check that the key is within bounds. |
| 4444 if (is_js_array) { | 4500 if (is_js_array) { |
| 4445 __ lw(scratch, FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); | 4501 __ lw(scratch1, FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); |
| 4446 } else { | 4502 } else { |
| 4447 __ lw(scratch, | 4503 __ lw(scratch1, |
| 4448 FieldMemOperand(elements_reg, FixedArray::kLengthOffset)); | 4504 FieldMemOperand(elements_reg, FixedArray::kLengthOffset)); |
| 4449 } | 4505 } |
| 4450 // Compare smis, unsigned compare catches both negative and out-of-bound | 4506 // Compare smis, unsigned compare catches both negative and out-of-bound |
| 4451 // indexes. | 4507 // indexes. |
| 4452 __ Branch(&miss_force_generic, hs, key_reg, Operand(scratch)); | 4508 __ Branch(&miss_force_generic, hs, key_reg, Operand(scratch1)); |
| 4453 | 4509 |
| 4454 // Handle smi values specially. | 4510 __ StoreNumberToDoubleElements(value_reg, |
| 4455 __ JumpIfSmi(value_reg, &smi_value); | 4511 key_reg, |
| 4512 receiver_reg, |
| 4513 elements_reg, |
| 4514 scratch1, |
| 4515 scratch2, |
| 4516 scratch3, |
| 4517 scratch4, |
| 4518 &transition_elements_kind); |
| 4456 | 4519 |
| 4457 // Ensure that the object is a heap number | |
| 4458 __ CheckMap(value_reg, | |
| 4459 scratch, | |
| 4460 masm->isolate()->factory()->heap_number_map(), | |
| 4461 &miss_force_generic, | |
| 4462 DONT_DO_SMI_CHECK); | |
| 4463 | |
| 4464 // Check for nan: all NaN values have a value greater (signed) than 0x7ff00000 | |
| 4465 // in the exponent. | |
| 4466 __ li(scratch, Operand(kNaNOrInfinityLowerBoundUpper32)); | |
| 4467 __ lw(exponent_reg, FieldMemOperand(value_reg, HeapNumber::kExponentOffset)); | |
| 4468 __ Branch(&maybe_nan, ge, exponent_reg, Operand(scratch)); | |
| 4469 | |
| 4470 __ lw(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset)); | |
| 4471 | |
| 4472 __ bind(&have_double_value); | |
| 4473 __ sll(scratch4, key_reg, kDoubleSizeLog2 - kSmiTagSize); | |
| 4474 __ Addu(scratch, elements_reg, Operand(scratch4)); | |
| 4475 __ sw(mantissa_reg, FieldMemOperand(scratch, FixedDoubleArray::kHeaderSize)); | |
| 4476 uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32); | |
| 4477 __ sw(exponent_reg, FieldMemOperand(scratch, offset)); | |
| 4478 __ Ret(USE_DELAY_SLOT); | 4520 __ Ret(USE_DELAY_SLOT); |
| 4479 __ mov(v0, value_reg); // In delay slot. | 4521 __ mov(v0, value_reg); // In delay slot. |
| 4480 | 4522 |
| 4481 __ bind(&maybe_nan); | |
| 4482 // Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise | |
| 4483 // it's an Infinity, and the non-NaN code path applies. | |
| 4484 __ li(scratch, Operand(kNaNOrInfinityLowerBoundUpper32)); | |
| 4485 __ Branch(&is_nan, gt, exponent_reg, Operand(scratch)); | |
| 4486 __ lw(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset)); | |
| 4487 __ Branch(&have_double_value, eq, mantissa_reg, Operand(zero_reg)); | |
| 4488 | |
| 4489 __ bind(&is_nan); | |
| 4490 // Load canonical NaN for storing into the double array. | |
| 4491 uint64_t nan_int64 = BitCast<uint64_t>( | |
| 4492 FixedDoubleArray::canonical_not_the_hole_nan_as_double()); | |
| 4493 __ li(mantissa_reg, Operand(static_cast<uint32_t>(nan_int64))); | |
| 4494 __ li(exponent_reg, Operand(static_cast<uint32_t>(nan_int64 >> 32))); | |
| 4495 __ jmp(&have_double_value); | |
| 4496 | |
| 4497 __ bind(&smi_value); | |
| 4498 __ Addu(scratch, elements_reg, | |
| 4499 Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag)); | |
| 4500 __ sll(scratch4, key_reg, kDoubleSizeLog2 - kSmiTagSize); | |
| 4501 __ Addu(scratch, scratch, scratch4); | |
| 4502 // scratch is now effective address of the double element | |
| 4503 | |
| 4504 FloatingPointHelper::Destination destination; | |
| 4505 if (CpuFeatures::IsSupported(FPU)) { | |
| 4506 destination = FloatingPointHelper::kFPURegisters; | |
| 4507 } else { | |
| 4508 destination = FloatingPointHelper::kCoreRegisters; | |
| 4509 } | |
| 4510 | |
| 4511 Register untagged_value = receiver_reg; | |
| 4512 __ SmiUntag(untagged_value, value_reg); | |
| 4513 FloatingPointHelper::ConvertIntToDouble( | |
| 4514 masm, | |
| 4515 untagged_value, | |
| 4516 destination, | |
| 4517 f0, | |
| 4518 mantissa_reg, | |
| 4519 exponent_reg, | |
| 4520 scratch4, | |
| 4521 f2); | |
| 4522 if (destination == FloatingPointHelper::kFPURegisters) { | |
| 4523 CpuFeatures::Scope scope(FPU); | |
| 4524 __ sdc1(f0, MemOperand(scratch, 0)); | |
| 4525 } else { | |
| 4526 __ sw(mantissa_reg, MemOperand(scratch, 0)); | |
| 4527 __ sw(exponent_reg, MemOperand(scratch, Register::kSizeInBytes)); | |
| 4528 } | |
| 4529 __ Ret(USE_DELAY_SLOT); | |
| 4530 __ mov(v0, value_reg); // In delay slot. | |
| 4531 | |
| 4532 // Handle store cache miss, replacing the ic with the generic stub. | 4523 // Handle store cache miss, replacing the ic with the generic stub. |
| 4533 __ bind(&miss_force_generic); | 4524 __ bind(&miss_force_generic); |
| 4534 Handle<Code> ic = | 4525 Handle<Code> ic = |
| 4535 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | 4526 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); |
| 4536 __ Jump(ic, RelocInfo::CODE_TARGET); | 4527 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 4528 |
| 4529 __ bind(&transition_elements_kind); |
| 4530 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); |
| 4531 __ Jump(ic_miss, RelocInfo::CODE_TARGET); |
| 4537 } | 4532 } |
| 4538 | 4533 |
| 4539 | 4534 |
| 4540 #undef __ | 4535 #undef __ |
| 4541 | 4536 |
| 4542 } } // namespace v8::internal | 4537 } } // namespace v8::internal |
| 4543 | 4538 |
| 4544 #endif // V8_TARGET_ARCH_MIPS | 4539 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |