| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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_ARM64 | 7 #if V8_TARGET_ARCH_ARM64 |
| 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 1030 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1041 FPRegister scratch0_double = d7; | 1041 FPRegister scratch0_double = d7; |
| 1042 | 1042 |
| 1043 // A fast-path for integer exponents. | 1043 // A fast-path for integer exponents. |
| 1044 Label exponent_is_smi, exponent_is_integer; | 1044 Label exponent_is_smi, exponent_is_integer; |
| 1045 // Bail out to runtime. | 1045 // Bail out to runtime. |
| 1046 Label call_runtime; | 1046 Label call_runtime; |
| 1047 // Allocate a heap number for the result, and return it. | 1047 // Allocate a heap number for the result, and return it. |
| 1048 Label done; | 1048 Label done; |
| 1049 | 1049 |
| 1050 // Unpack the inputs. | 1050 // Unpack the inputs. |
| 1051 if (exponent_type_ == ON_STACK) { | 1051 if (exponent_type() == ON_STACK) { |
| 1052 Label base_is_smi; | 1052 Label base_is_smi; |
| 1053 Label unpack_exponent; | 1053 Label unpack_exponent; |
| 1054 | 1054 |
| 1055 __ Pop(exponent_tagged, base_tagged); | 1055 __ Pop(exponent_tagged, base_tagged); |
| 1056 | 1056 |
| 1057 __ JumpIfSmi(base_tagged, &base_is_smi); | 1057 __ JumpIfSmi(base_tagged, &base_is_smi); |
| 1058 __ JumpIfNotHeapNumber(base_tagged, &call_runtime); | 1058 __ JumpIfNotHeapNumber(base_tagged, &call_runtime); |
| 1059 // base_tagged is a heap number, so load its double value. | 1059 // base_tagged is a heap number, so load its double value. |
| 1060 __ Ldr(base_double, FieldMemOperand(base_tagged, HeapNumber::kValueOffset)); | 1060 __ Ldr(base_double, FieldMemOperand(base_tagged, HeapNumber::kValueOffset)); |
| 1061 __ B(&unpack_exponent); | 1061 __ B(&unpack_exponent); |
| 1062 __ Bind(&base_is_smi); | 1062 __ Bind(&base_is_smi); |
| 1063 // base_tagged is a SMI, so untag it and convert it to a double. | 1063 // base_tagged is a SMI, so untag it and convert it to a double. |
| 1064 __ SmiUntagToDouble(base_double, base_tagged); | 1064 __ SmiUntagToDouble(base_double, base_tagged); |
| 1065 | 1065 |
| 1066 __ Bind(&unpack_exponent); | 1066 __ Bind(&unpack_exponent); |
| 1067 // x10 base_tagged The tagged base (input). | 1067 // x10 base_tagged The tagged base (input). |
| 1068 // x11 exponent_tagged The tagged exponent (input). | 1068 // x11 exponent_tagged The tagged exponent (input). |
| 1069 // d1 base_double The base as a double. | 1069 // d1 base_double The base as a double. |
| 1070 __ JumpIfSmi(exponent_tagged, &exponent_is_smi); | 1070 __ JumpIfSmi(exponent_tagged, &exponent_is_smi); |
| 1071 __ JumpIfNotHeapNumber(exponent_tagged, &call_runtime); | 1071 __ JumpIfNotHeapNumber(exponent_tagged, &call_runtime); |
| 1072 // exponent_tagged is a heap number, so load its double value. | 1072 // exponent_tagged is a heap number, so load its double value. |
| 1073 __ Ldr(exponent_double, | 1073 __ Ldr(exponent_double, |
| 1074 FieldMemOperand(exponent_tagged, HeapNumber::kValueOffset)); | 1074 FieldMemOperand(exponent_tagged, HeapNumber::kValueOffset)); |
| 1075 } else if (exponent_type_ == TAGGED) { | 1075 } else if (exponent_type() == TAGGED) { |
| 1076 __ JumpIfSmi(exponent_tagged, &exponent_is_smi); | 1076 __ JumpIfSmi(exponent_tagged, &exponent_is_smi); |
| 1077 __ Ldr(exponent_double, | 1077 __ Ldr(exponent_double, |
| 1078 FieldMemOperand(exponent_tagged, HeapNumber::kValueOffset)); | 1078 FieldMemOperand(exponent_tagged, HeapNumber::kValueOffset)); |
| 1079 } | 1079 } |
| 1080 | 1080 |
| 1081 // Handle double (heap number) exponents. | 1081 // Handle double (heap number) exponents. |
| 1082 if (exponent_type_ != INTEGER) { | 1082 if (exponent_type() != INTEGER) { |
| 1083 // Detect integer exponents stored as doubles and handle those in the | 1083 // Detect integer exponents stored as doubles and handle those in the |
| 1084 // integer fast-path. | 1084 // integer fast-path. |
| 1085 __ TryRepresentDoubleAsInt64(exponent_integer, exponent_double, | 1085 __ TryRepresentDoubleAsInt64(exponent_integer, exponent_double, |
| 1086 scratch0_double, &exponent_is_integer); | 1086 scratch0_double, &exponent_is_integer); |
| 1087 | 1087 |
| 1088 if (exponent_type_ == ON_STACK) { | 1088 if (exponent_type() == ON_STACK) { |
| 1089 FPRegister half_double = d3; | 1089 FPRegister half_double = d3; |
| 1090 FPRegister minus_half_double = d4; | 1090 FPRegister minus_half_double = d4; |
| 1091 // Detect square root case. Crankshaft detects constant +/-0.5 at compile | 1091 // Detect square root case. Crankshaft detects constant +/-0.5 at compile |
| 1092 // time and uses DoMathPowHalf instead. We then skip this check for | 1092 // time and uses DoMathPowHalf instead. We then skip this check for |
| 1093 // non-constant cases of +/-0.5 as these hardly occur. | 1093 // non-constant cases of +/-0.5 as these hardly occur. |
| 1094 | 1094 |
| 1095 __ Fmov(minus_half_double, -0.5); | 1095 __ Fmov(minus_half_double, -0.5); |
| 1096 __ Fmov(half_double, 0.5); | 1096 __ Fmov(half_double, 0.5); |
| 1097 __ Fcmp(minus_half_double, exponent_double); | 1097 __ Fcmp(minus_half_double, exponent_double); |
| 1098 __ Fccmp(half_double, exponent_double, NZFlag, ne); | 1098 __ Fccmp(half_double, exponent_double, NZFlag, ne); |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1229 __ Fdiv(result_double, scratch0_double, result_double); | 1229 __ Fdiv(result_double, scratch0_double, result_double); |
| 1230 // ECMA-262 only requires Math.pow to return an 'implementation-dependent | 1230 // ECMA-262 only requires Math.pow to return an 'implementation-dependent |
| 1231 // approximation' of base^exponent. However, mjsunit/math-pow uses Math.pow | 1231 // approximation' of base^exponent. However, mjsunit/math-pow uses Math.pow |
| 1232 // to calculate the subnormal value 2^-1074. This method of calculating | 1232 // to calculate the subnormal value 2^-1074. This method of calculating |
| 1233 // negative powers doesn't work because 2^1074 overflows to infinity. To | 1233 // negative powers doesn't work because 2^1074 overflows to infinity. To |
| 1234 // catch this corner-case, we bail out if the result was 0. (This can only | 1234 // catch this corner-case, we bail out if the result was 0. (This can only |
| 1235 // occur if the divisor is infinity or the base is zero.) | 1235 // occur if the divisor is infinity or the base is zero.) |
| 1236 __ Fcmp(result_double, 0.0); | 1236 __ Fcmp(result_double, 0.0); |
| 1237 __ B(&done, ne); | 1237 __ B(&done, ne); |
| 1238 | 1238 |
| 1239 if (exponent_type_ == ON_STACK) { | 1239 if (exponent_type() == ON_STACK) { |
| 1240 // Bail out to runtime code. | 1240 // Bail out to runtime code. |
| 1241 __ Bind(&call_runtime); | 1241 __ Bind(&call_runtime); |
| 1242 // Put the arguments back on the stack. | 1242 // Put the arguments back on the stack. |
| 1243 __ Push(base_tagged, exponent_tagged); | 1243 __ Push(base_tagged, exponent_tagged); |
| 1244 __ TailCallRuntime(Runtime::kMathPowRT, 2, 1); | 1244 __ TailCallRuntime(Runtime::kMathPowRT, 2, 1); |
| 1245 | 1245 |
| 1246 // Return. | 1246 // Return. |
| 1247 __ Bind(&done); | 1247 __ Bind(&done); |
| 1248 __ AllocateHeapNumber(result_tagged, &call_runtime, scratch0, scratch1, | 1248 __ AllocateHeapNumber(result_tagged, &call_runtime, scratch0, scratch1, |
| 1249 result_double); | 1249 result_double); |
| (...skipping 1890 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3140 | 3140 |
| 3141 if (call_as_method) { | 3141 if (call_as_method) { |
| 3142 __ Bind(&wrap); | 3142 __ Bind(&wrap); |
| 3143 EmitWrapCase(masm, argc, &cont); | 3143 EmitWrapCase(masm, argc, &cont); |
| 3144 } | 3144 } |
| 3145 } | 3145 } |
| 3146 | 3146 |
| 3147 | 3147 |
| 3148 void CallFunctionStub::Generate(MacroAssembler* masm) { | 3148 void CallFunctionStub::Generate(MacroAssembler* masm) { |
| 3149 ASM_LOCATION("CallFunctionStub::Generate"); | 3149 ASM_LOCATION("CallFunctionStub::Generate"); |
| 3150 CallFunctionNoFeedback(masm, argc_, NeedsChecks(), CallAsMethod()); | 3150 CallFunctionNoFeedback(masm, argc(), NeedsChecks(), CallAsMethod()); |
| 3151 } | 3151 } |
| 3152 | 3152 |
| 3153 | 3153 |
| 3154 void CallConstructStub::Generate(MacroAssembler* masm) { | 3154 void CallConstructStub::Generate(MacroAssembler* masm) { |
| 3155 ASM_LOCATION("CallConstructStub::Generate"); | 3155 ASM_LOCATION("CallConstructStub::Generate"); |
| 3156 // x0 : number of arguments | 3156 // x0 : number of arguments |
| 3157 // x1 : the function to call | 3157 // x1 : the function to call |
| 3158 // x2 : feedback vector | 3158 // x2 : feedback vector |
| 3159 // x3 : slot in feedback vector (smi) (if r2 is not the megamorphic symbol) | 3159 // x3 : slot in feedback vector (smi) (if r2 is not the megamorphic symbol) |
| 3160 Register function = x1; | 3160 Register function = x1; |
| (...skipping 1422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4583 __ Ret(); | 4583 __ Ret(); |
| 4584 } | 4584 } |
| 4585 | 4585 |
| 4586 | 4586 |
| 4587 void StubFailureTrampolineStub::Generate(MacroAssembler* masm) { | 4587 void StubFailureTrampolineStub::Generate(MacroAssembler* masm) { |
| 4588 CEntryStub ces(isolate(), 1, kSaveFPRegs); | 4588 CEntryStub ces(isolate(), 1, kSaveFPRegs); |
| 4589 __ Call(ces.GetCode(), RelocInfo::CODE_TARGET); | 4589 __ Call(ces.GetCode(), RelocInfo::CODE_TARGET); |
| 4590 int parameter_count_offset = | 4590 int parameter_count_offset = |
| 4591 StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset; | 4591 StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset; |
| 4592 __ Ldr(x1, MemOperand(fp, parameter_count_offset)); | 4592 __ Ldr(x1, MemOperand(fp, parameter_count_offset)); |
| 4593 if (function_mode_ == JS_FUNCTION_STUB_MODE) { | 4593 if (function_mode() == JS_FUNCTION_STUB_MODE) { |
| 4594 __ Add(x1, x1, 1); | 4594 __ Add(x1, x1, 1); |
| 4595 } | 4595 } |
| 4596 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); | 4596 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); |
| 4597 __ Drop(x1); | 4597 __ Drop(x1); |
| 4598 // Return to IC Miss stub, continuation still on stack. | 4598 // Return to IC Miss stub, continuation still on stack. |
| 4599 __ Ret(); | 4599 __ Ret(); |
| 4600 } | 4600 } |
| 4601 | 4601 |
| 4602 | 4602 |
| 4603 static unsigned int GetProfileEntryHookCallSize(MacroAssembler* masm) { | 4603 static unsigned int GetProfileEntryHookCallSize(MacroAssembler* masm) { |
| (...skipping 504 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5108 InternalArrayNArgumentsConstructorStub stubh3(isolate, kinds[i]); | 5108 InternalArrayNArgumentsConstructorStub stubh3(isolate, kinds[i]); |
| 5109 stubh3.GetCode(); | 5109 stubh3.GetCode(); |
| 5110 } | 5110 } |
| 5111 } | 5111 } |
| 5112 | 5112 |
| 5113 | 5113 |
| 5114 void ArrayConstructorStub::GenerateDispatchToArrayStub( | 5114 void ArrayConstructorStub::GenerateDispatchToArrayStub( |
| 5115 MacroAssembler* masm, | 5115 MacroAssembler* masm, |
| 5116 AllocationSiteOverrideMode mode) { | 5116 AllocationSiteOverrideMode mode) { |
| 5117 Register argc = x0; | 5117 Register argc = x0; |
| 5118 if (argument_count_ == ANY) { | 5118 if (argument_count() == ANY) { |
| 5119 Label zero_case, n_case; | 5119 Label zero_case, n_case; |
| 5120 __ Cbz(argc, &zero_case); | 5120 __ Cbz(argc, &zero_case); |
| 5121 __ Cmp(argc, 1); | 5121 __ Cmp(argc, 1); |
| 5122 __ B(ne, &n_case); | 5122 __ B(ne, &n_case); |
| 5123 | 5123 |
| 5124 // One argument. | 5124 // One argument. |
| 5125 CreateArrayDispatchOneArgument(masm, mode); | 5125 CreateArrayDispatchOneArgument(masm, mode); |
| 5126 | 5126 |
| 5127 __ Bind(&zero_case); | 5127 __ Bind(&zero_case); |
| 5128 // No arguments. | 5128 // No arguments. |
| 5129 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); | 5129 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); |
| 5130 | 5130 |
| 5131 __ Bind(&n_case); | 5131 __ Bind(&n_case); |
| 5132 // N arguments. | 5132 // N arguments. |
| 5133 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); | 5133 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); |
| 5134 | 5134 |
| 5135 } else if (argument_count_ == NONE) { | 5135 } else if (argument_count() == NONE) { |
| 5136 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); | 5136 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); |
| 5137 } else if (argument_count_ == ONE) { | 5137 } else if (argument_count() == ONE) { |
| 5138 CreateArrayDispatchOneArgument(masm, mode); | 5138 CreateArrayDispatchOneArgument(masm, mode); |
| 5139 } else if (argument_count_ == MORE_THAN_ONE) { | 5139 } else if (argument_count() == MORE_THAN_ONE) { |
| 5140 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); | 5140 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); |
| 5141 } else { | 5141 } else { |
| 5142 UNREACHABLE(); | 5142 UNREACHABLE(); |
| 5143 } | 5143 } |
| 5144 } | 5144 } |
| 5145 | 5145 |
| 5146 | 5146 |
| 5147 void ArrayConstructorStub::Generate(MacroAssembler* masm) { | 5147 void ArrayConstructorStub::Generate(MacroAssembler* masm) { |
| 5148 ASM_LOCATION("ArrayConstructorStub::Generate"); | 5148 ASM_LOCATION("ArrayConstructorStub::Generate"); |
| 5149 // ----------- S t a t e ------------- | 5149 // ----------- S t a t e ------------- |
| 5150 // -- x0 : argc (only if argument_count_ == ANY) | 5150 // -- x0 : argc (only if argument_count() == ANY) |
| 5151 // -- x1 : constructor | 5151 // -- x1 : constructor |
| 5152 // -- x2 : AllocationSite or undefined | 5152 // -- x2 : AllocationSite or undefined |
| 5153 // -- sp[0] : return address | 5153 // -- sp[0] : return address |
| 5154 // -- sp[4] : last argument | 5154 // -- sp[4] : last argument |
| 5155 // ----------------------------------- | 5155 // ----------------------------------- |
| 5156 Register constructor = x1; | 5156 Register constructor = x1; |
| 5157 Register allocation_site = x2; | 5157 Register allocation_site = x2; |
| 5158 | 5158 |
| 5159 if (FLAG_debug_code) { | 5159 if (FLAG_debug_code) { |
| 5160 // The array construct code is only set for the global and natives | 5160 // The array construct code is only set for the global and natives |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5292 // -- sp[(argc - 1) * 8] : first argument | 5292 // -- sp[(argc - 1) * 8] : first argument |
| 5293 // -- sp[argc * 8] : receiver | 5293 // -- sp[argc * 8] : receiver |
| 5294 // ----------------------------------- | 5294 // ----------------------------------- |
| 5295 | 5295 |
| 5296 Register callee = x0; | 5296 Register callee = x0; |
| 5297 Register call_data = x4; | 5297 Register call_data = x4; |
| 5298 Register holder = x2; | 5298 Register holder = x2; |
| 5299 Register api_function_address = x1; | 5299 Register api_function_address = x1; |
| 5300 Register context = cp; | 5300 Register context = cp; |
| 5301 | 5301 |
| 5302 int argc = ArgumentBits::decode(bit_field_); | 5302 int argc = this->argc(); |
| 5303 bool is_store = IsStoreBits::decode(bit_field_); | 5303 bool is_store = this->is_store(); |
| 5304 bool call_data_undefined = CallDataUndefinedBits::decode(bit_field_); | 5304 bool call_data_undefined = this->call_data_undefined(); |
| 5305 | 5305 |
| 5306 typedef FunctionCallbackArguments FCA; | 5306 typedef FunctionCallbackArguments FCA; |
| 5307 | 5307 |
| 5308 STATIC_ASSERT(FCA::kContextSaveIndex == 6); | 5308 STATIC_ASSERT(FCA::kContextSaveIndex == 6); |
| 5309 STATIC_ASSERT(FCA::kCalleeIndex == 5); | 5309 STATIC_ASSERT(FCA::kCalleeIndex == 5); |
| 5310 STATIC_ASSERT(FCA::kDataIndex == 4); | 5310 STATIC_ASSERT(FCA::kDataIndex == 4); |
| 5311 STATIC_ASSERT(FCA::kReturnValueOffset == 3); | 5311 STATIC_ASSERT(FCA::kReturnValueOffset == 3); |
| 5312 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); | 5312 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); |
| 5313 STATIC_ASSERT(FCA::kIsolateIndex == 1); | 5313 STATIC_ASSERT(FCA::kIsolateIndex == 1); |
| 5314 STATIC_ASSERT(FCA::kHolderIndex == 0); | 5314 STATIC_ASSERT(FCA::kHolderIndex == 0); |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5423 MemOperand(fp, 6 * kPointerSize), | 5423 MemOperand(fp, 6 * kPointerSize), |
| 5424 NULL); | 5424 NULL); |
| 5425 } | 5425 } |
| 5426 | 5426 |
| 5427 | 5427 |
| 5428 #undef __ | 5428 #undef __ |
| 5429 | 5429 |
| 5430 } } // namespace v8::internal | 5430 } } // namespace v8::internal |
| 5431 | 5431 |
| 5432 #endif // V8_TARGET_ARCH_ARM64 | 5432 #endif // V8_TARGET_ARCH_ARM64 |
| OLD | NEW |