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 |