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 |