| 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 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_ARM | 7 #if V8_TARGET_ARCH_ARM |
| 8 | 8 |
| 9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| (...skipping 1130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1141 const Register heapnumber = r0; | 1141 const Register heapnumber = r0; |
| 1142 const DwVfpRegister double_base = d0; | 1142 const DwVfpRegister double_base = d0; |
| 1143 const DwVfpRegister double_exponent = d1; | 1143 const DwVfpRegister double_exponent = d1; |
| 1144 const DwVfpRegister double_result = d2; | 1144 const DwVfpRegister double_result = d2; |
| 1145 const DwVfpRegister double_scratch = d3; | 1145 const DwVfpRegister double_scratch = d3; |
| 1146 const SwVfpRegister single_scratch = s6; | 1146 const SwVfpRegister single_scratch = s6; |
| 1147 const Register scratch = r9; | 1147 const Register scratch = r9; |
| 1148 const Register scratch2 = r4; | 1148 const Register scratch2 = r4; |
| 1149 | 1149 |
| 1150 Label call_runtime, done, int_exponent; | 1150 Label call_runtime, done, int_exponent; |
| 1151 if (exponent_type_ == ON_STACK) { | 1151 if (exponent_type() == ON_STACK) { |
| 1152 Label base_is_smi, unpack_exponent; | 1152 Label base_is_smi, unpack_exponent; |
| 1153 // The exponent and base are supplied as arguments on the stack. | 1153 // The exponent and base are supplied as arguments on the stack. |
| 1154 // This can only happen if the stub is called from non-optimized code. | 1154 // This can only happen if the stub is called from non-optimized code. |
| 1155 // Load input parameters from stack to double registers. | 1155 // Load input parameters from stack to double registers. |
| 1156 __ ldr(base, MemOperand(sp, 1 * kPointerSize)); | 1156 __ ldr(base, MemOperand(sp, 1 * kPointerSize)); |
| 1157 __ ldr(exponent, MemOperand(sp, 0 * kPointerSize)); | 1157 __ ldr(exponent, MemOperand(sp, 0 * kPointerSize)); |
| 1158 | 1158 |
| 1159 __ LoadRoot(heapnumbermap, Heap::kHeapNumberMapRootIndex); | 1159 __ LoadRoot(heapnumbermap, Heap::kHeapNumberMapRootIndex); |
| 1160 | 1160 |
| 1161 __ UntagAndJumpIfSmi(scratch, base, &base_is_smi); | 1161 __ UntagAndJumpIfSmi(scratch, base, &base_is_smi); |
| 1162 __ ldr(scratch, FieldMemOperand(base, JSObject::kMapOffset)); | 1162 __ ldr(scratch, FieldMemOperand(base, JSObject::kMapOffset)); |
| 1163 __ cmp(scratch, heapnumbermap); | 1163 __ cmp(scratch, heapnumbermap); |
| 1164 __ b(ne, &call_runtime); | 1164 __ b(ne, &call_runtime); |
| 1165 | 1165 |
| 1166 __ vldr(double_base, FieldMemOperand(base, HeapNumber::kValueOffset)); | 1166 __ vldr(double_base, FieldMemOperand(base, HeapNumber::kValueOffset)); |
| 1167 __ jmp(&unpack_exponent); | 1167 __ jmp(&unpack_exponent); |
| 1168 | 1168 |
| 1169 __ bind(&base_is_smi); | 1169 __ bind(&base_is_smi); |
| 1170 __ vmov(single_scratch, scratch); | 1170 __ vmov(single_scratch, scratch); |
| 1171 __ vcvt_f64_s32(double_base, single_scratch); | 1171 __ vcvt_f64_s32(double_base, single_scratch); |
| 1172 __ bind(&unpack_exponent); | 1172 __ bind(&unpack_exponent); |
| 1173 | 1173 |
| 1174 __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent); | 1174 __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent); |
| 1175 | 1175 |
| 1176 __ ldr(scratch, FieldMemOperand(exponent, JSObject::kMapOffset)); | 1176 __ ldr(scratch, FieldMemOperand(exponent, JSObject::kMapOffset)); |
| 1177 __ cmp(scratch, heapnumbermap); | 1177 __ cmp(scratch, heapnumbermap); |
| 1178 __ b(ne, &call_runtime); | 1178 __ b(ne, &call_runtime); |
| 1179 __ vldr(double_exponent, | 1179 __ vldr(double_exponent, |
| 1180 FieldMemOperand(exponent, HeapNumber::kValueOffset)); | 1180 FieldMemOperand(exponent, HeapNumber::kValueOffset)); |
| 1181 } else if (exponent_type_ == TAGGED) { | 1181 } else if (exponent_type() == TAGGED) { |
| 1182 // Base is already in double_base. | 1182 // Base is already in double_base. |
| 1183 __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent); | 1183 __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent); |
| 1184 | 1184 |
| 1185 __ vldr(double_exponent, | 1185 __ vldr(double_exponent, |
| 1186 FieldMemOperand(exponent, HeapNumber::kValueOffset)); | 1186 FieldMemOperand(exponent, HeapNumber::kValueOffset)); |
| 1187 } | 1187 } |
| 1188 | 1188 |
| 1189 if (exponent_type_ != INTEGER) { | 1189 if (exponent_type() != INTEGER) { |
| 1190 Label int_exponent_convert; | 1190 Label int_exponent_convert; |
| 1191 // Detect integer exponents stored as double. | 1191 // Detect integer exponents stored as double. |
| 1192 __ vcvt_u32_f64(single_scratch, double_exponent); | 1192 __ vcvt_u32_f64(single_scratch, double_exponent); |
| 1193 // We do not check for NaN or Infinity here because comparing numbers on | 1193 // We do not check for NaN or Infinity here because comparing numbers on |
| 1194 // ARM correctly distinguishes NaNs. We end up calling the built-in. | 1194 // ARM correctly distinguishes NaNs. We end up calling the built-in. |
| 1195 __ vcvt_f64_u32(double_scratch, single_scratch); | 1195 __ vcvt_f64_u32(double_scratch, single_scratch); |
| 1196 __ VFPCompareAndSetFlags(double_scratch, double_exponent); | 1196 __ VFPCompareAndSetFlags(double_scratch, double_exponent); |
| 1197 __ b(eq, &int_exponent_convert); | 1197 __ b(eq, &int_exponent_convert); |
| 1198 | 1198 |
| 1199 if (exponent_type_ == ON_STACK) { | 1199 if (exponent_type() == ON_STACK) { |
| 1200 // Detect square root case. Crankshaft detects constant +/-0.5 at | 1200 // Detect square root case. Crankshaft detects constant +/-0.5 at |
| 1201 // compile time and uses DoMathPowHalf instead. We then skip this check | 1201 // compile time and uses DoMathPowHalf instead. We then skip this check |
| 1202 // for non-constant cases of +/-0.5 as these hardly occur. | 1202 // for non-constant cases of +/-0.5 as these hardly occur. |
| 1203 Label not_plus_half; | 1203 Label not_plus_half; |
| 1204 | 1204 |
| 1205 // Test for 0.5. | 1205 // Test for 0.5. |
| 1206 __ vmov(double_scratch, 0.5, scratch); | 1206 __ vmov(double_scratch, 0.5, scratch); |
| 1207 __ VFPCompareAndSetFlags(double_exponent, double_scratch); | 1207 __ VFPCompareAndSetFlags(double_exponent, double_scratch); |
| 1208 __ b(ne, ¬_plus_half); | 1208 __ b(ne, ¬_plus_half); |
| 1209 | 1209 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1254 | 1254 |
| 1255 __ bind(&int_exponent_convert); | 1255 __ bind(&int_exponent_convert); |
| 1256 __ vcvt_u32_f64(single_scratch, double_exponent); | 1256 __ vcvt_u32_f64(single_scratch, double_exponent); |
| 1257 __ vmov(scratch, single_scratch); | 1257 __ vmov(scratch, single_scratch); |
| 1258 } | 1258 } |
| 1259 | 1259 |
| 1260 // Calculate power with integer exponent. | 1260 // Calculate power with integer exponent. |
| 1261 __ bind(&int_exponent); | 1261 __ bind(&int_exponent); |
| 1262 | 1262 |
| 1263 // Get two copies of exponent in the registers scratch and exponent. | 1263 // Get two copies of exponent in the registers scratch and exponent. |
| 1264 if (exponent_type_ == INTEGER) { | 1264 if (exponent_type() == INTEGER) { |
| 1265 __ mov(scratch, exponent); | 1265 __ mov(scratch, exponent); |
| 1266 } else { | 1266 } else { |
| 1267 // Exponent has previously been stored into scratch as untagged integer. | 1267 // Exponent has previously been stored into scratch as untagged integer. |
| 1268 __ mov(exponent, scratch); | 1268 __ mov(exponent, scratch); |
| 1269 } | 1269 } |
| 1270 __ vmov(double_scratch, double_base); // Back up base. | 1270 __ vmov(double_scratch, double_base); // Back up base. |
| 1271 __ vmov(double_result, 1.0, scratch2); | 1271 __ vmov(double_result, 1.0, scratch2); |
| 1272 | 1272 |
| 1273 // Get absolute value of exponent. | 1273 // Get absolute value of exponent. |
| 1274 __ cmp(scratch, Operand::Zero()); | 1274 __ cmp(scratch, Operand::Zero()); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1290 // Due to subnormals, x^-y == (1/x)^y does not hold in all cases. | 1290 // Due to subnormals, x^-y == (1/x)^y does not hold in all cases. |
| 1291 __ VFPCompareAndSetFlags(double_result, 0.0); | 1291 __ VFPCompareAndSetFlags(double_result, 0.0); |
| 1292 __ b(ne, &done); | 1292 __ b(ne, &done); |
| 1293 // double_exponent may not containe the exponent value if the input was a | 1293 // double_exponent may not containe the exponent value if the input was a |
| 1294 // smi. We set it with exponent value before bailing out. | 1294 // smi. We set it with exponent value before bailing out. |
| 1295 __ vmov(single_scratch, exponent); | 1295 __ vmov(single_scratch, exponent); |
| 1296 __ vcvt_f64_s32(double_exponent, single_scratch); | 1296 __ vcvt_f64_s32(double_exponent, single_scratch); |
| 1297 | 1297 |
| 1298 // Returning or bailing out. | 1298 // Returning or bailing out. |
| 1299 Counters* counters = isolate()->counters(); | 1299 Counters* counters = isolate()->counters(); |
| 1300 if (exponent_type_ == ON_STACK) { | 1300 if (exponent_type() == ON_STACK) { |
| 1301 // The arguments are still on the stack. | 1301 // The arguments are still on the stack. |
| 1302 __ bind(&call_runtime); | 1302 __ bind(&call_runtime); |
| 1303 __ TailCallRuntime(Runtime::kMathPowRT, 2, 1); | 1303 __ TailCallRuntime(Runtime::kMathPowRT, 2, 1); |
| 1304 | 1304 |
| 1305 // The stub is called from non-optimized code, which expects the result | 1305 // The stub is called from non-optimized code, which expects the result |
| 1306 // as heap number in exponent. | 1306 // as heap number in exponent. |
| 1307 __ bind(&done); | 1307 __ bind(&done); |
| 1308 __ AllocateHeapNumber( | 1308 __ AllocateHeapNumber( |
| 1309 heapnumber, scratch, scratch2, heapnumbermap, &call_runtime); | 1309 heapnumber, scratch, scratch2, heapnumbermap, &call_runtime); |
| 1310 __ vstr(double_result, | 1310 __ vstr(double_result, |
| (...skipping 1579 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2890 } | 2890 } |
| 2891 | 2891 |
| 2892 if (call_as_method) { | 2892 if (call_as_method) { |
| 2893 __ bind(&wrap); | 2893 __ bind(&wrap); |
| 2894 EmitWrapCase(masm, argc, &cont); | 2894 EmitWrapCase(masm, argc, &cont); |
| 2895 } | 2895 } |
| 2896 } | 2896 } |
| 2897 | 2897 |
| 2898 | 2898 |
| 2899 void CallFunctionStub::Generate(MacroAssembler* masm) { | 2899 void CallFunctionStub::Generate(MacroAssembler* masm) { |
| 2900 CallFunctionNoFeedback(masm, argc_, NeedsChecks(), CallAsMethod()); | 2900 CallFunctionNoFeedback(masm, argc(), NeedsChecks(), CallAsMethod()); |
| 2901 } | 2901 } |
| 2902 | 2902 |
| 2903 | 2903 |
| 2904 void CallConstructStub::Generate(MacroAssembler* masm) { | 2904 void CallConstructStub::Generate(MacroAssembler* masm) { |
| 2905 // r0 : number of arguments | 2905 // r0 : number of arguments |
| 2906 // r1 : the function to call | 2906 // r1 : the function to call |
| 2907 // r2 : feedback vector | 2907 // r2 : feedback vector |
| 2908 // r3 : (only if r2 is not the megamorphic symbol) slot in feedback | 2908 // r3 : (only if r2 is not the megamorphic symbol) slot in feedback |
| 2909 // vector (Smi) | 2909 // vector (Smi) |
| 2910 Label slow, non_function_call; | 2910 Label slow, non_function_call; |
| (...skipping 1664 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4575 __ Ret(); | 4575 __ Ret(); |
| 4576 } | 4576 } |
| 4577 | 4577 |
| 4578 | 4578 |
| 4579 void StubFailureTrampolineStub::Generate(MacroAssembler* masm) { | 4579 void StubFailureTrampolineStub::Generate(MacroAssembler* masm) { |
| 4580 CEntryStub ces(isolate(), 1, kSaveFPRegs); | 4580 CEntryStub ces(isolate(), 1, kSaveFPRegs); |
| 4581 __ Call(ces.GetCode(), RelocInfo::CODE_TARGET); | 4581 __ Call(ces.GetCode(), RelocInfo::CODE_TARGET); |
| 4582 int parameter_count_offset = | 4582 int parameter_count_offset = |
| 4583 StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset; | 4583 StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset; |
| 4584 __ ldr(r1, MemOperand(fp, parameter_count_offset)); | 4584 __ ldr(r1, MemOperand(fp, parameter_count_offset)); |
| 4585 if (function_mode_ == JS_FUNCTION_STUB_MODE) { | 4585 if (function_mode() == JS_FUNCTION_STUB_MODE) { |
| 4586 __ add(r1, r1, Operand(1)); | 4586 __ add(r1, r1, Operand(1)); |
| 4587 } | 4587 } |
| 4588 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); | 4588 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); |
| 4589 __ mov(r1, Operand(r1, LSL, kPointerSizeLog2)); | 4589 __ mov(r1, Operand(r1, LSL, kPointerSizeLog2)); |
| 4590 __ add(sp, sp, r1); | 4590 __ add(sp, sp, r1); |
| 4591 __ Ret(); | 4591 __ Ret(); |
| 4592 } | 4592 } |
| 4593 | 4593 |
| 4594 | 4594 |
| 4595 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { | 4595 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4805 stubh2.GetCode(); | 4805 stubh2.GetCode(); |
| 4806 InternalArrayNArgumentsConstructorStub stubh3(isolate, kinds[i]); | 4806 InternalArrayNArgumentsConstructorStub stubh3(isolate, kinds[i]); |
| 4807 stubh3.GetCode(); | 4807 stubh3.GetCode(); |
| 4808 } | 4808 } |
| 4809 } | 4809 } |
| 4810 | 4810 |
| 4811 | 4811 |
| 4812 void ArrayConstructorStub::GenerateDispatchToArrayStub( | 4812 void ArrayConstructorStub::GenerateDispatchToArrayStub( |
| 4813 MacroAssembler* masm, | 4813 MacroAssembler* masm, |
| 4814 AllocationSiteOverrideMode mode) { | 4814 AllocationSiteOverrideMode mode) { |
| 4815 if (argument_count_ == ANY) { | 4815 if (argument_count() == ANY) { |
| 4816 Label not_zero_case, not_one_case; | 4816 Label not_zero_case, not_one_case; |
| 4817 __ tst(r0, r0); | 4817 __ tst(r0, r0); |
| 4818 __ b(ne, ¬_zero_case); | 4818 __ b(ne, ¬_zero_case); |
| 4819 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); | 4819 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); |
| 4820 | 4820 |
| 4821 __ bind(¬_zero_case); | 4821 __ bind(¬_zero_case); |
| 4822 __ cmp(r0, Operand(1)); | 4822 __ cmp(r0, Operand(1)); |
| 4823 __ b(gt, ¬_one_case); | 4823 __ b(gt, ¬_one_case); |
| 4824 CreateArrayDispatchOneArgument(masm, mode); | 4824 CreateArrayDispatchOneArgument(masm, mode); |
| 4825 | 4825 |
| 4826 __ bind(¬_one_case); | 4826 __ bind(¬_one_case); |
| 4827 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); | 4827 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); |
| 4828 } else if (argument_count_ == NONE) { | 4828 } else if (argument_count() == NONE) { |
| 4829 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); | 4829 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); |
| 4830 } else if (argument_count_ == ONE) { | 4830 } else if (argument_count() == ONE) { |
| 4831 CreateArrayDispatchOneArgument(masm, mode); | 4831 CreateArrayDispatchOneArgument(masm, mode); |
| 4832 } else if (argument_count_ == MORE_THAN_ONE) { | 4832 } else if (argument_count() == MORE_THAN_ONE) { |
| 4833 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); | 4833 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); |
| 4834 } else { | 4834 } else { |
| 4835 UNREACHABLE(); | 4835 UNREACHABLE(); |
| 4836 } | 4836 } |
| 4837 } | 4837 } |
| 4838 | 4838 |
| 4839 | 4839 |
| 4840 void ArrayConstructorStub::Generate(MacroAssembler* masm) { | 4840 void ArrayConstructorStub::Generate(MacroAssembler* masm) { |
| 4841 // ----------- S t a t e ------------- | 4841 // ----------- S t a t e ------------- |
| 4842 // -- r0 : argc (only if argument_count_ == ANY) | 4842 // -- r0 : argc (only if argument_count() == ANY) |
| 4843 // -- r1 : constructor | 4843 // -- r1 : constructor |
| 4844 // -- r2 : AllocationSite or undefined | 4844 // -- r2 : AllocationSite or undefined |
| 4845 // -- sp[0] : return address | 4845 // -- sp[0] : return address |
| 4846 // -- sp[4] : last argument | 4846 // -- sp[4] : last argument |
| 4847 // ----------------------------------- | 4847 // ----------------------------------- |
| 4848 | 4848 |
| 4849 if (FLAG_debug_code) { | 4849 if (FLAG_debug_code) { |
| 4850 // The array construct code is only set for the global and natives | 4850 // The array construct code is only set for the global and natives |
| 4851 // builtin Array functions which always have maps. | 4851 // builtin Array functions which always have maps. |
| 4852 | 4852 |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4966 // -- sp[(argc - 1)* 4] : first argument | 4966 // -- sp[(argc - 1)* 4] : first argument |
| 4967 // -- sp[argc * 4] : receiver | 4967 // -- sp[argc * 4] : receiver |
| 4968 // ----------------------------------- | 4968 // ----------------------------------- |
| 4969 | 4969 |
| 4970 Register callee = r0; | 4970 Register callee = r0; |
| 4971 Register call_data = r4; | 4971 Register call_data = r4; |
| 4972 Register holder = r2; | 4972 Register holder = r2; |
| 4973 Register api_function_address = r1; | 4973 Register api_function_address = r1; |
| 4974 Register context = cp; | 4974 Register context = cp; |
| 4975 | 4975 |
| 4976 int argc = ArgumentBits::decode(bit_field_); | 4976 int argc = this->argc(); |
| 4977 bool is_store = IsStoreBits::decode(bit_field_); | 4977 bool is_store = this->is_store(); |
| 4978 bool call_data_undefined = CallDataUndefinedBits::decode(bit_field_); | 4978 bool call_data_undefined = this->call_data_undefined(); |
| 4979 | 4979 |
| 4980 typedef FunctionCallbackArguments FCA; | 4980 typedef FunctionCallbackArguments FCA; |
| 4981 | 4981 |
| 4982 STATIC_ASSERT(FCA::kContextSaveIndex == 6); | 4982 STATIC_ASSERT(FCA::kContextSaveIndex == 6); |
| 4983 STATIC_ASSERT(FCA::kCalleeIndex == 5); | 4983 STATIC_ASSERT(FCA::kCalleeIndex == 5); |
| 4984 STATIC_ASSERT(FCA::kDataIndex == 4); | 4984 STATIC_ASSERT(FCA::kDataIndex == 4); |
| 4985 STATIC_ASSERT(FCA::kReturnValueOffset == 3); | 4985 STATIC_ASSERT(FCA::kReturnValueOffset == 3); |
| 4986 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); | 4986 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); |
| 4987 STATIC_ASSERT(FCA::kIsolateIndex == 1); | 4987 STATIC_ASSERT(FCA::kIsolateIndex == 1); |
| 4988 STATIC_ASSERT(FCA::kHolderIndex == 0); | 4988 STATIC_ASSERT(FCA::kHolderIndex == 0); |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5096 MemOperand(fp, 6 * kPointerSize), | 5096 MemOperand(fp, 6 * kPointerSize), |
| 5097 NULL); | 5097 NULL); |
| 5098 } | 5098 } |
| 5099 | 5099 |
| 5100 | 5100 |
| 5101 #undef __ | 5101 #undef __ |
| 5102 | 5102 |
| 5103 } } // namespace v8::internal | 5103 } } // namespace v8::internal |
| 5104 | 5104 |
| 5105 #endif // V8_TARGET_ARCH_ARM | 5105 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |