| 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 4044 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4055 break; | 4055 break; |
| 4056 case Token::BIT_NOT: | 4056 case Token::BIT_NOT: |
| 4057 __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_JS); | 4057 __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_JS); |
| 4058 break; | 4058 break; |
| 4059 default: | 4059 default: |
| 4060 UNREACHABLE(); | 4060 UNREACHABLE(); |
| 4061 } | 4061 } |
| 4062 } | 4062 } |
| 4063 | 4063 |
| 4064 | 4064 |
| 4065 void MathPowStub::Generate(MacroAssembler* masm) { |
| 4066 Label call_runtime; |
| 4067 |
| 4068 if (CpuFeatures::IsSupported(VFP3)) { |
| 4069 CpuFeatures::Scope scope(VFP3); |
| 4070 |
| 4071 Label base_not_smi; |
| 4072 Label exponent_not_smi; |
| 4073 Label convert_exponent; |
| 4074 |
| 4075 const Register base = r0; |
| 4076 const Register exponent = r1; |
| 4077 const Register heapnumbermap = r5; |
| 4078 const Register heapnumber = r6; |
| 4079 const DoubleRegister double_base = d0; |
| 4080 const DoubleRegister double_exponent = d1; |
| 4081 const DoubleRegister double_result = d2; |
| 4082 const SwVfpRegister single_scratch = s0; |
| 4083 const Register scratch = r9; |
| 4084 const Register scratch2 = r7; |
| 4085 |
| 4086 __ LoadRoot(heapnumbermap, Heap::kHeapNumberMapRootIndex); |
| 4087 __ ldr(base, MemOperand(sp, 1 * kPointerSize)); |
| 4088 __ ldr(exponent, MemOperand(sp, 0 * kPointerSize)); |
| 4089 |
| 4090 // Convert base to double value and store it in d0. |
| 4091 __ JumpIfNotSmi(base, &base_not_smi); |
| 4092 // Base is a Smi. Untag and convert it. |
| 4093 __ SmiUntag(base); |
| 4094 __ vmov(single_scratch, base); |
| 4095 __ vcvt_f64_s32(double_base, single_scratch); |
| 4096 __ b(&convert_exponent); |
| 4097 |
| 4098 __ bind(&base_not_smi); |
| 4099 __ ldr(scratch, FieldMemOperand(base, JSObject::kMapOffset)); |
| 4100 __ cmp(scratch, heapnumbermap); |
| 4101 __ b(ne, &call_runtime); |
| 4102 // Base is a heapnumber. Load it into double register. |
| 4103 __ vldr(double_base, FieldMemOperand(base, HeapNumber::kValueOffset)); |
| 4104 |
| 4105 __ bind(&convert_exponent); |
| 4106 __ JumpIfNotSmi(exponent, &exponent_not_smi); |
| 4107 __ SmiUntag(exponent); |
| 4108 |
| 4109 // The base is in a double register and the exponent is |
| 4110 // an untagged smi. Allocate a heap number and call a |
| 4111 // C function for integer exponents. The register containing |
| 4112 // the heap number is callee-saved. |
| 4113 __ AllocateHeapNumber(heapnumber, |
| 4114 scratch, |
| 4115 scratch2, |
| 4116 heapnumbermap, |
| 4117 &call_runtime); |
| 4118 __ push(lr); |
| 4119 __ PrepareCallCFunction(3, scratch); |
| 4120 __ mov(r2, exponent); |
| 4121 __ vmov(r0, r1, double_base); |
| 4122 __ CallCFunction(ExternalReference::power_double_int_function(), 3); |
| 4123 __ pop(lr); |
| 4124 __ GetCFunctionDoubleResult(double_result); |
| 4125 __ vstr(double_result, |
| 4126 FieldMemOperand(heapnumber, HeapNumber::kValueOffset)); |
| 4127 __ mov(r0, heapnumber); |
| 4128 __ Ret(2 * kPointerSize); |
| 4129 |
| 4130 __ bind(&exponent_not_smi); |
| 4131 __ ldr(scratch, FieldMemOperand(exponent, JSObject::kMapOffset)); |
| 4132 __ cmp(scratch, heapnumbermap); |
| 4133 __ b(ne, &call_runtime); |
| 4134 // Exponent is a heapnumber. Load it into double register. |
| 4135 __ vldr(double_exponent, |
| 4136 FieldMemOperand(exponent, HeapNumber::kValueOffset)); |
| 4137 |
| 4138 // The base and the exponent are in double registers. |
| 4139 // Allocate a heap number and call a C function for |
| 4140 // double exponents. The register containing |
| 4141 // the heap number is callee-saved. |
| 4142 __ AllocateHeapNumber(heapnumber, |
| 4143 scratch, |
| 4144 scratch2, |
| 4145 heapnumbermap, |
| 4146 &call_runtime); |
| 4147 __ push(lr); |
| 4148 __ PrepareCallCFunction(4, scratch); |
| 4149 __ vmov(r0, r1, double_base); |
| 4150 __ vmov(r2, r3, double_exponent); |
| 4151 __ CallCFunction(ExternalReference::power_double_double_function(), 4); |
| 4152 __ pop(lr); |
| 4153 __ GetCFunctionDoubleResult(double_result); |
| 4154 __ vstr(double_result, |
| 4155 FieldMemOperand(heapnumber, HeapNumber::kValueOffset)); |
| 4156 __ mov(r0, heapnumber); |
| 4157 __ Ret(2 * kPointerSize); |
| 4158 } |
| 4159 |
| 4160 __ bind(&call_runtime); |
| 4161 __ TailCallRuntime(Runtime::kMath_pow_cfunction, 2, 1); |
| 4162 } |
| 4163 |
| 4164 |
| 4165 bool CEntryStub::NeedsImmovableCode() { |
| 4166 return true; |
| 4167 } |
| 4168 |
| 4169 |
| 4065 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { | 4170 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { |
| 4066 __ Throw(r0); | 4171 __ Throw(r0); |
| 4067 } | 4172 } |
| 4068 | 4173 |
| 4069 | 4174 |
| 4070 void CEntryStub::GenerateThrowUncatchable(MacroAssembler* masm, | 4175 void CEntryStub::GenerateThrowUncatchable(MacroAssembler* masm, |
| 4071 UncatchableExceptionType type) { | 4176 UncatchableExceptionType type) { |
| 4072 __ ThrowUncatchable(type, r0); | 4177 __ ThrowUncatchable(type, r0); |
| 4073 } | 4178 } |
| 4074 | 4179 |
| (...skipping 2661 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6736 void DirectCEntryStub::GenerateCall(MacroAssembler* masm, | 6841 void DirectCEntryStub::GenerateCall(MacroAssembler* masm, |
| 6737 Register target) { | 6842 Register target) { |
| 6738 __ mov(lr, Operand(reinterpret_cast<intptr_t>(GetCode().location()), | 6843 __ mov(lr, Operand(reinterpret_cast<intptr_t>(GetCode().location()), |
| 6739 RelocInfo::CODE_TARGET)); | 6844 RelocInfo::CODE_TARGET)); |
| 6740 // Push return address (accessible to GC through exit frame pc). | 6845 // Push return address (accessible to GC through exit frame pc). |
| 6741 __ str(pc, MemOperand(sp, 0)); | 6846 __ str(pc, MemOperand(sp, 0)); |
| 6742 __ Jump(target); // Call the C++ function. | 6847 __ Jump(target); // Call the C++ function. |
| 6743 } | 6848 } |
| 6744 | 6849 |
| 6745 | 6850 |
| 6746 void GenerateFastPixelArrayLoad(MacroAssembler* masm, | |
| 6747 Register receiver, | |
| 6748 Register key, | |
| 6749 Register elements_map, | |
| 6750 Register elements, | |
| 6751 Register scratch1, | |
| 6752 Register scratch2, | |
| 6753 Register result, | |
| 6754 Label* not_pixel_array, | |
| 6755 Label* key_not_smi, | |
| 6756 Label* out_of_range) { | |
| 6757 // Register use: | |
| 6758 // | |
| 6759 // receiver - holds the receiver on entry. | |
| 6760 // Unchanged unless 'result' is the same register. | |
| 6761 // | |
| 6762 // key - holds the smi key on entry. | |
| 6763 // Unchanged unless 'result' is the same register. | |
| 6764 // | |
| 6765 // elements - set to be the receiver's elements on exit. | |
| 6766 // | |
| 6767 // elements_map - set to be the map of the receiver's elements | |
| 6768 // on exit. | |
| 6769 // | |
| 6770 // result - holds the result of the pixel array load on exit, | |
| 6771 // tagged as a smi if successful. | |
| 6772 // | |
| 6773 // Scratch registers: | |
| 6774 // | |
| 6775 // scratch1 - used a scratch register in map check, if map | |
| 6776 // check is successful, contains the length of the | |
| 6777 // pixel array, the pointer to external elements and | |
| 6778 // the untagged result. | |
| 6779 // | |
| 6780 // scratch2 - holds the untaged key. | |
| 6781 | |
| 6782 // Some callers already have verified that the key is a smi. key_not_smi is | |
| 6783 // set to NULL as a sentinel for that case. Otherwise, add an explicit check | |
| 6784 // to ensure the key is a smi must be added. | |
| 6785 if (key_not_smi != NULL) { | |
| 6786 __ JumpIfNotSmi(key, key_not_smi); | |
| 6787 } else { | |
| 6788 if (FLAG_debug_code) { | |
| 6789 __ AbortIfNotSmi(key); | |
| 6790 } | |
| 6791 } | |
| 6792 __ SmiUntag(scratch2, key); | |
| 6793 | |
| 6794 // Verify that the receiver has pixel array elements. | |
| 6795 __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); | |
| 6796 __ CheckMap(elements, scratch1, Heap::kPixelArrayMapRootIndex, | |
| 6797 not_pixel_array, true); | |
| 6798 | |
| 6799 // Key must be in range of the pixel array. | |
| 6800 __ ldr(scratch1, FieldMemOperand(elements, PixelArray::kLengthOffset)); | |
| 6801 __ cmp(scratch2, scratch1); | |
| 6802 __ b(hs, out_of_range); // unsigned check handles negative keys. | |
| 6803 | |
| 6804 // Perform the indexed load and tag the result as a smi. | |
| 6805 __ ldr(scratch1, | |
| 6806 FieldMemOperand(elements, PixelArray::kExternalPointerOffset)); | |
| 6807 __ ldrb(scratch1, MemOperand(scratch1, scratch2)); | |
| 6808 __ SmiTag(r0, scratch1); | |
| 6809 __ Ret(); | |
| 6810 } | |
| 6811 | |
| 6812 | |
| 6813 void GenerateFastPixelArrayStore(MacroAssembler* masm, | |
| 6814 Register receiver, | |
| 6815 Register key, | |
| 6816 Register value, | |
| 6817 Register elements, | |
| 6818 Register elements_map, | |
| 6819 Register scratch1, | |
| 6820 Register scratch2, | |
| 6821 bool load_elements_from_receiver, | |
| 6822 bool load_elements_map_from_elements, | |
| 6823 Label* key_not_smi, | |
| 6824 Label* value_not_smi, | |
| 6825 Label* not_pixel_array, | |
| 6826 Label* out_of_range) { | |
| 6827 // Register use: | |
| 6828 // receiver - holds the receiver and is unchanged unless the | |
| 6829 // store succeeds. | |
| 6830 // key - holds the key (must be a smi) and is unchanged. | |
| 6831 // value - holds the value (must be a smi) and is unchanged. | |
| 6832 // elements - holds the element object of the receiver on entry if | |
| 6833 // load_elements_from_receiver is false, otherwise used | |
| 6834 // internally to store the pixel arrays elements and | |
| 6835 // external array pointer. | |
| 6836 // elements_map - holds the map of the element object if | |
| 6837 // load_elements_map_from_elements is false, otherwise | |
| 6838 // loaded with the element map. | |
| 6839 // | |
| 6840 Register external_pointer = elements; | |
| 6841 Register untagged_key = scratch1; | |
| 6842 Register untagged_value = scratch2; | |
| 6843 | |
| 6844 if (load_elements_from_receiver) { | |
| 6845 __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); | |
| 6846 } | |
| 6847 | |
| 6848 // By passing NULL as not_pixel_array, callers signal that they have already | |
| 6849 // verified that the receiver has pixel array elements. | |
| 6850 if (not_pixel_array != NULL) { | |
| 6851 if (load_elements_map_from_elements) { | |
| 6852 __ ldr(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset)); | |
| 6853 } | |
| 6854 __ LoadRoot(ip, Heap::kPixelArrayMapRootIndex); | |
| 6855 __ cmp(elements_map, ip); | |
| 6856 __ b(ne, not_pixel_array); | |
| 6857 } else { | |
| 6858 if (FLAG_debug_code) { | |
| 6859 // Map check should have already made sure that elements is a pixel array. | |
| 6860 __ ldr(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset)); | |
| 6861 __ LoadRoot(ip, Heap::kPixelArrayMapRootIndex); | |
| 6862 __ cmp(elements_map, ip); | |
| 6863 __ Assert(eq, "Elements isn't a pixel array"); | |
| 6864 } | |
| 6865 } | |
| 6866 | |
| 6867 // Some callers already have verified that the key is a smi. key_not_smi is | |
| 6868 // set to NULL as a sentinel for that case. Otherwise, add an explicit check | |
| 6869 // to ensure the key is a smi must be added. | |
| 6870 if (key_not_smi != NULL) { | |
| 6871 __ JumpIfNotSmi(key, key_not_smi); | |
| 6872 } else { | |
| 6873 if (FLAG_debug_code) { | |
| 6874 __ AbortIfNotSmi(key); | |
| 6875 } | |
| 6876 } | |
| 6877 | |
| 6878 __ SmiUntag(untagged_key, key); | |
| 6879 | |
| 6880 // Perform bounds check. | |
| 6881 __ ldr(scratch2, FieldMemOperand(elements, PixelArray::kLengthOffset)); | |
| 6882 __ cmp(untagged_key, scratch2); | |
| 6883 __ b(hs, out_of_range); // unsigned check handles negative keys. | |
| 6884 | |
| 6885 __ JumpIfNotSmi(value, value_not_smi); | |
| 6886 __ SmiUntag(untagged_value, value); | |
| 6887 | |
| 6888 // Clamp the value to [0..255]. | |
| 6889 __ Usat(untagged_value, 8, Operand(untagged_value)); | |
| 6890 // Get the pointer to the external array. This clobbers elements. | |
| 6891 __ ldr(external_pointer, | |
| 6892 FieldMemOperand(elements, PixelArray::kExternalPointerOffset)); | |
| 6893 __ strb(untagged_value, MemOperand(external_pointer, untagged_key)); | |
| 6894 __ Ret(); | |
| 6895 } | |
| 6896 | |
| 6897 | |
| 6898 #undef __ | 6851 #undef __ |
| 6899 | 6852 |
| 6900 } } // namespace v8::internal | 6853 } } // namespace v8::internal |
| 6901 | 6854 |
| 6902 #endif // V8_TARGET_ARCH_ARM | 6855 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |