| 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_MIPS64 | 7 #if V8_TARGET_ARCH_MIPS64 |
| 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 1184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1195 const Register heapnumber = v0; | 1195 const Register heapnumber = v0; |
| 1196 const DoubleRegister double_base = f2; | 1196 const DoubleRegister double_base = f2; |
| 1197 const DoubleRegister double_exponent = f4; | 1197 const DoubleRegister double_exponent = f4; |
| 1198 const DoubleRegister double_result = f0; | 1198 const DoubleRegister double_result = f0; |
| 1199 const DoubleRegister double_scratch = f6; | 1199 const DoubleRegister double_scratch = f6; |
| 1200 const FPURegister single_scratch = f8; | 1200 const FPURegister single_scratch = f8; |
| 1201 const Register scratch = t1; | 1201 const Register scratch = t1; |
| 1202 const Register scratch2 = a7; | 1202 const Register scratch2 = a7; |
| 1203 | 1203 |
| 1204 Label call_runtime, done, int_exponent; | 1204 Label call_runtime, done, int_exponent; |
| 1205 if (exponent_type_ == ON_STACK) { | 1205 if (exponent_type() == ON_STACK) { |
| 1206 Label base_is_smi, unpack_exponent; | 1206 Label base_is_smi, unpack_exponent; |
| 1207 // The exponent and base are supplied as arguments on the stack. | 1207 // The exponent and base are supplied as arguments on the stack. |
| 1208 // This can only happen if the stub is called from non-optimized code. | 1208 // This can only happen if the stub is called from non-optimized code. |
| 1209 // Load input parameters from stack to double registers. | 1209 // Load input parameters from stack to double registers. |
| 1210 __ ld(base, MemOperand(sp, 1 * kPointerSize)); | 1210 __ ld(base, MemOperand(sp, 1 * kPointerSize)); |
| 1211 __ ld(exponent, MemOperand(sp, 0 * kPointerSize)); | 1211 __ ld(exponent, MemOperand(sp, 0 * kPointerSize)); |
| 1212 | 1212 |
| 1213 __ LoadRoot(heapnumbermap, Heap::kHeapNumberMapRootIndex); | 1213 __ LoadRoot(heapnumbermap, Heap::kHeapNumberMapRootIndex); |
| 1214 | 1214 |
| 1215 __ UntagAndJumpIfSmi(scratch, base, &base_is_smi); | 1215 __ UntagAndJumpIfSmi(scratch, base, &base_is_smi); |
| 1216 __ ld(scratch, FieldMemOperand(base, JSObject::kMapOffset)); | 1216 __ ld(scratch, FieldMemOperand(base, JSObject::kMapOffset)); |
| 1217 __ Branch(&call_runtime, ne, scratch, Operand(heapnumbermap)); | 1217 __ Branch(&call_runtime, ne, scratch, Operand(heapnumbermap)); |
| 1218 | 1218 |
| 1219 __ ldc1(double_base, FieldMemOperand(base, HeapNumber::kValueOffset)); | 1219 __ ldc1(double_base, FieldMemOperand(base, HeapNumber::kValueOffset)); |
| 1220 __ jmp(&unpack_exponent); | 1220 __ jmp(&unpack_exponent); |
| 1221 | 1221 |
| 1222 __ bind(&base_is_smi); | 1222 __ bind(&base_is_smi); |
| 1223 __ mtc1(scratch, single_scratch); | 1223 __ mtc1(scratch, single_scratch); |
| 1224 __ cvt_d_w(double_base, single_scratch); | 1224 __ cvt_d_w(double_base, single_scratch); |
| 1225 __ bind(&unpack_exponent); | 1225 __ bind(&unpack_exponent); |
| 1226 | 1226 |
| 1227 __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent); | 1227 __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent); |
| 1228 | 1228 |
| 1229 __ ld(scratch, FieldMemOperand(exponent, JSObject::kMapOffset)); | 1229 __ ld(scratch, FieldMemOperand(exponent, JSObject::kMapOffset)); |
| 1230 __ Branch(&call_runtime, ne, scratch, Operand(heapnumbermap)); | 1230 __ Branch(&call_runtime, ne, scratch, Operand(heapnumbermap)); |
| 1231 __ ldc1(double_exponent, | 1231 __ ldc1(double_exponent, |
| 1232 FieldMemOperand(exponent, HeapNumber::kValueOffset)); | 1232 FieldMemOperand(exponent, HeapNumber::kValueOffset)); |
| 1233 } else if (exponent_type_ == TAGGED) { | 1233 } else if (exponent_type() == TAGGED) { |
| 1234 // Base is already in double_base. | 1234 // Base is already in double_base. |
| 1235 __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent); | 1235 __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent); |
| 1236 | 1236 |
| 1237 __ ldc1(double_exponent, | 1237 __ ldc1(double_exponent, |
| 1238 FieldMemOperand(exponent, HeapNumber::kValueOffset)); | 1238 FieldMemOperand(exponent, HeapNumber::kValueOffset)); |
| 1239 } | 1239 } |
| 1240 | 1240 |
| 1241 if (exponent_type_ != INTEGER) { | 1241 if (exponent_type() != INTEGER) { |
| 1242 Label int_exponent_convert; | 1242 Label int_exponent_convert; |
| 1243 // Detect integer exponents stored as double. | 1243 // Detect integer exponents stored as double. |
| 1244 __ EmitFPUTruncate(kRoundToMinusInf, | 1244 __ EmitFPUTruncate(kRoundToMinusInf, |
| 1245 scratch, | 1245 scratch, |
| 1246 double_exponent, | 1246 double_exponent, |
| 1247 at, | 1247 at, |
| 1248 double_scratch, | 1248 double_scratch, |
| 1249 scratch2, | 1249 scratch2, |
| 1250 kCheckForInexactConversion); | 1250 kCheckForInexactConversion); |
| 1251 // scratch2 == 0 means there was no conversion error. | 1251 // scratch2 == 0 means there was no conversion error. |
| 1252 __ Branch(&int_exponent_convert, eq, scratch2, Operand(zero_reg)); | 1252 __ Branch(&int_exponent_convert, eq, scratch2, Operand(zero_reg)); |
| 1253 | 1253 |
| 1254 if (exponent_type_ == ON_STACK) { | 1254 if (exponent_type() == ON_STACK) { |
| 1255 // Detect square root case. Crankshaft detects constant +/-0.5 at | 1255 // Detect square root case. Crankshaft detects constant +/-0.5 at |
| 1256 // compile time and uses DoMathPowHalf instead. We then skip this check | 1256 // compile time and uses DoMathPowHalf instead. We then skip this check |
| 1257 // for non-constant cases of +/-0.5 as these hardly occur. | 1257 // for non-constant cases of +/-0.5 as these hardly occur. |
| 1258 Label not_plus_half; | 1258 Label not_plus_half; |
| 1259 | 1259 |
| 1260 // Test for 0.5. | 1260 // Test for 0.5. |
| 1261 __ Move(double_scratch, 0.5); | 1261 __ Move(double_scratch, 0.5); |
| 1262 __ BranchF(USE_DELAY_SLOT, | 1262 __ BranchF(USE_DELAY_SLOT, |
| 1263 ¬_plus_half, | 1263 ¬_plus_half, |
| 1264 NULL, | 1264 NULL, |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1313 __ MovFromFloatResult(double_result); | 1313 __ MovFromFloatResult(double_result); |
| 1314 __ jmp(&done); | 1314 __ jmp(&done); |
| 1315 | 1315 |
| 1316 __ bind(&int_exponent_convert); | 1316 __ bind(&int_exponent_convert); |
| 1317 } | 1317 } |
| 1318 | 1318 |
| 1319 // Calculate power with integer exponent. | 1319 // Calculate power with integer exponent. |
| 1320 __ bind(&int_exponent); | 1320 __ bind(&int_exponent); |
| 1321 | 1321 |
| 1322 // Get two copies of exponent in the registers scratch and exponent. | 1322 // Get two copies of exponent in the registers scratch and exponent. |
| 1323 if (exponent_type_ == INTEGER) { | 1323 if (exponent_type() == INTEGER) { |
| 1324 __ mov(scratch, exponent); | 1324 __ mov(scratch, exponent); |
| 1325 } else { | 1325 } else { |
| 1326 // Exponent has previously been stored into scratch as untagged integer. | 1326 // Exponent has previously been stored into scratch as untagged integer. |
| 1327 __ mov(exponent, scratch); | 1327 __ mov(exponent, scratch); |
| 1328 } | 1328 } |
| 1329 | 1329 |
| 1330 __ mov_d(double_scratch, double_base); // Back up base. | 1330 __ mov_d(double_scratch, double_base); // Back up base. |
| 1331 __ Move(double_result, 1.0); | 1331 __ Move(double_result, 1.0); |
| 1332 | 1332 |
| 1333 // Get absolute value of exponent. | 1333 // Get absolute value of exponent. |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1361 // Due to subnormals, x^-y == (1/x)^y does not hold in all cases. | 1361 // Due to subnormals, x^-y == (1/x)^y does not hold in all cases. |
| 1362 __ BranchF(&done, NULL, ne, double_result, kDoubleRegZero); | 1362 __ BranchF(&done, NULL, ne, double_result, kDoubleRegZero); |
| 1363 | 1363 |
| 1364 // double_exponent may not contain the exponent value if the input was a | 1364 // double_exponent may not contain the exponent value if the input was a |
| 1365 // smi. We set it with exponent value before bailing out. | 1365 // smi. We set it with exponent value before bailing out. |
| 1366 __ mtc1(exponent, single_scratch); | 1366 __ mtc1(exponent, single_scratch); |
| 1367 __ cvt_d_w(double_exponent, single_scratch); | 1367 __ cvt_d_w(double_exponent, single_scratch); |
| 1368 | 1368 |
| 1369 // Returning or bailing out. | 1369 // Returning or bailing out. |
| 1370 Counters* counters = isolate()->counters(); | 1370 Counters* counters = isolate()->counters(); |
| 1371 if (exponent_type_ == ON_STACK) { | 1371 if (exponent_type() == ON_STACK) { |
| 1372 // The arguments are still on the stack. | 1372 // The arguments are still on the stack. |
| 1373 __ bind(&call_runtime); | 1373 __ bind(&call_runtime); |
| 1374 __ TailCallRuntime(Runtime::kMathPowRT, 2, 1); | 1374 __ TailCallRuntime(Runtime::kMathPowRT, 2, 1); |
| 1375 | 1375 |
| 1376 // The stub is called from non-optimized code, which expects the result | 1376 // The stub is called from non-optimized code, which expects the result |
| 1377 // as heap number in exponent. | 1377 // as heap number in exponent. |
| 1378 __ bind(&done); | 1378 __ bind(&done); |
| 1379 __ AllocateHeapNumber( | 1379 __ AllocateHeapNumber( |
| 1380 heapnumber, scratch, scratch2, heapnumbermap, &call_runtime); | 1380 heapnumber, scratch, scratch2, heapnumbermap, &call_runtime); |
| 1381 __ sdc1(double_result, | 1381 __ sdc1(double_result, |
| (...skipping 1665 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3047 | 3047 |
| 3048 if (call_as_method) { | 3048 if (call_as_method) { |
| 3049 __ bind(&wrap); | 3049 __ bind(&wrap); |
| 3050 // Wrap the receiver and patch it back onto the stack. | 3050 // Wrap the receiver and patch it back onto the stack. |
| 3051 EmitWrapCase(masm, argc, &cont); | 3051 EmitWrapCase(masm, argc, &cont); |
| 3052 } | 3052 } |
| 3053 } | 3053 } |
| 3054 | 3054 |
| 3055 | 3055 |
| 3056 void CallFunctionStub::Generate(MacroAssembler* masm) { | 3056 void CallFunctionStub::Generate(MacroAssembler* masm) { |
| 3057 CallFunctionNoFeedback(masm, argc_, NeedsChecks(), CallAsMethod()); | 3057 CallFunctionNoFeedback(masm, argc(), NeedsChecks(), CallAsMethod()); |
| 3058 } | 3058 } |
| 3059 | 3059 |
| 3060 | 3060 |
| 3061 void CallConstructStub::Generate(MacroAssembler* masm) { | 3061 void CallConstructStub::Generate(MacroAssembler* masm) { |
| 3062 // a0 : number of arguments | 3062 // a0 : number of arguments |
| 3063 // a1 : the function to call | 3063 // a1 : the function to call |
| 3064 // a2 : feedback vector | 3064 // a2 : feedback vector |
| 3065 // a3 : (only if a2 is not undefined) slot in feedback vector (Smi) | 3065 // a3 : (only if a2 is not undefined) slot in feedback vector (Smi) |
| 3066 Label slow, non_function_call; | 3066 Label slow, non_function_call; |
| 3067 // Check that the function is not a smi. | 3067 // Check that the function is not a smi. |
| (...skipping 1749 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4817 __ mov(v0, a0); | 4817 __ mov(v0, a0); |
| 4818 } | 4818 } |
| 4819 | 4819 |
| 4820 | 4820 |
| 4821 void StubFailureTrampolineStub::Generate(MacroAssembler* masm) { | 4821 void StubFailureTrampolineStub::Generate(MacroAssembler* masm) { |
| 4822 CEntryStub ces(isolate(), 1, kSaveFPRegs); | 4822 CEntryStub ces(isolate(), 1, kSaveFPRegs); |
| 4823 __ Call(ces.GetCode(), RelocInfo::CODE_TARGET); | 4823 __ Call(ces.GetCode(), RelocInfo::CODE_TARGET); |
| 4824 int parameter_count_offset = | 4824 int parameter_count_offset = |
| 4825 StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset; | 4825 StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset; |
| 4826 __ ld(a1, MemOperand(fp, parameter_count_offset)); | 4826 __ ld(a1, MemOperand(fp, parameter_count_offset)); |
| 4827 if (function_mode_ == JS_FUNCTION_STUB_MODE) { | 4827 if (function_mode() == JS_FUNCTION_STUB_MODE) { |
| 4828 __ Daddu(a1, a1, Operand(1)); | 4828 __ Daddu(a1, a1, Operand(1)); |
| 4829 } | 4829 } |
| 4830 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); | 4830 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); |
| 4831 __ dsll(a1, a1, kPointerSizeLog2); | 4831 __ dsll(a1, a1, kPointerSizeLog2); |
| 4832 __ Ret(USE_DELAY_SLOT); | 4832 __ Ret(USE_DELAY_SLOT); |
| 4833 __ Daddu(sp, sp, a1); | 4833 __ Daddu(sp, sp, a1); |
| 4834 } | 4834 } |
| 4835 | 4835 |
| 4836 | 4836 |
| 4837 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { | 4837 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5043 stubh2.GetCode(); | 5043 stubh2.GetCode(); |
| 5044 InternalArrayNArgumentsConstructorStub stubh3(isolate, kinds[i]); | 5044 InternalArrayNArgumentsConstructorStub stubh3(isolate, kinds[i]); |
| 5045 stubh3.GetCode(); | 5045 stubh3.GetCode(); |
| 5046 } | 5046 } |
| 5047 } | 5047 } |
| 5048 | 5048 |
| 5049 | 5049 |
| 5050 void ArrayConstructorStub::GenerateDispatchToArrayStub( | 5050 void ArrayConstructorStub::GenerateDispatchToArrayStub( |
| 5051 MacroAssembler* masm, | 5051 MacroAssembler* masm, |
| 5052 AllocationSiteOverrideMode mode) { | 5052 AllocationSiteOverrideMode mode) { |
| 5053 if (argument_count_ == ANY) { | 5053 if (argument_count() == ANY) { |
| 5054 Label not_zero_case, not_one_case; | 5054 Label not_zero_case, not_one_case; |
| 5055 __ And(at, a0, a0); | 5055 __ And(at, a0, a0); |
| 5056 __ Branch(¬_zero_case, ne, at, Operand(zero_reg)); | 5056 __ Branch(¬_zero_case, ne, at, Operand(zero_reg)); |
| 5057 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); | 5057 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); |
| 5058 | 5058 |
| 5059 __ bind(¬_zero_case); | 5059 __ bind(¬_zero_case); |
| 5060 __ Branch(¬_one_case, gt, a0, Operand(1)); | 5060 __ Branch(¬_one_case, gt, a0, Operand(1)); |
| 5061 CreateArrayDispatchOneArgument(masm, mode); | 5061 CreateArrayDispatchOneArgument(masm, mode); |
| 5062 | 5062 |
| 5063 __ bind(¬_one_case); | 5063 __ bind(¬_one_case); |
| 5064 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); | 5064 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); |
| 5065 } else if (argument_count_ == NONE) { | 5065 } else if (argument_count() == NONE) { |
| 5066 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); | 5066 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); |
| 5067 } else if (argument_count_ == ONE) { | 5067 } else if (argument_count() == ONE) { |
| 5068 CreateArrayDispatchOneArgument(masm, mode); | 5068 CreateArrayDispatchOneArgument(masm, mode); |
| 5069 } else if (argument_count_ == MORE_THAN_ONE) { | 5069 } else if (argument_count() == MORE_THAN_ONE) { |
| 5070 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); | 5070 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); |
| 5071 } else { | 5071 } else { |
| 5072 UNREACHABLE(); | 5072 UNREACHABLE(); |
| 5073 } | 5073 } |
| 5074 } | 5074 } |
| 5075 | 5075 |
| 5076 | 5076 |
| 5077 void ArrayConstructorStub::Generate(MacroAssembler* masm) { | 5077 void ArrayConstructorStub::Generate(MacroAssembler* masm) { |
| 5078 // ----------- S t a t e ------------- | 5078 // ----------- S t a t e ------------- |
| 5079 // -- a0 : argc (only if argument_count_ == ANY) | 5079 // -- a0 : argc (only if argument_count() == ANY) |
| 5080 // -- a1 : constructor | 5080 // -- a1 : constructor |
| 5081 // -- a2 : AllocationSite or undefined | 5081 // -- a2 : AllocationSite or undefined |
| 5082 // -- sp[0] : return address | 5082 // -- sp[0] : return address |
| 5083 // -- sp[4] : last argument | 5083 // -- sp[4] : last argument |
| 5084 // ----------------------------------- | 5084 // ----------------------------------- |
| 5085 | 5085 |
| 5086 if (FLAG_debug_code) { | 5086 if (FLAG_debug_code) { |
| 5087 // The array construct code is only set for the global and natives | 5087 // The array construct code is only set for the global and natives |
| 5088 // builtin Array functions which always have maps. | 5088 // builtin Array functions which always have maps. |
| 5089 | 5089 |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5204 // -- sp[(argc - 1)* 4] : first argument | 5204 // -- sp[(argc - 1)* 4] : first argument |
| 5205 // -- sp[argc * 4] : receiver | 5205 // -- sp[argc * 4] : receiver |
| 5206 // ----------------------------------- | 5206 // ----------------------------------- |
| 5207 | 5207 |
| 5208 Register callee = a0; | 5208 Register callee = a0; |
| 5209 Register call_data = a4; | 5209 Register call_data = a4; |
| 5210 Register holder = a2; | 5210 Register holder = a2; |
| 5211 Register api_function_address = a1; | 5211 Register api_function_address = a1; |
| 5212 Register context = cp; | 5212 Register context = cp; |
| 5213 | 5213 |
| 5214 int argc = ArgumentBits::decode(bit_field_); | 5214 int argc = this->argc(); |
| 5215 bool is_store = IsStoreBits::decode(bit_field_); | 5215 bool is_store = this->is_store(); |
| 5216 bool call_data_undefined = CallDataUndefinedBits::decode(bit_field_); | 5216 bool call_data_undefined = this->call_data_undefined(); |
| 5217 | 5217 |
| 5218 typedef FunctionCallbackArguments FCA; | 5218 typedef FunctionCallbackArguments FCA; |
| 5219 | 5219 |
| 5220 STATIC_ASSERT(FCA::kContextSaveIndex == 6); | 5220 STATIC_ASSERT(FCA::kContextSaveIndex == 6); |
| 5221 STATIC_ASSERT(FCA::kCalleeIndex == 5); | 5221 STATIC_ASSERT(FCA::kCalleeIndex == 5); |
| 5222 STATIC_ASSERT(FCA::kDataIndex == 4); | 5222 STATIC_ASSERT(FCA::kDataIndex == 4); |
| 5223 STATIC_ASSERT(FCA::kReturnValueOffset == 3); | 5223 STATIC_ASSERT(FCA::kReturnValueOffset == 3); |
| 5224 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); | 5224 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); |
| 5225 STATIC_ASSERT(FCA::kIsolateIndex == 1); | 5225 STATIC_ASSERT(FCA::kIsolateIndex == 1); |
| 5226 STATIC_ASSERT(FCA::kHolderIndex == 0); | 5226 STATIC_ASSERT(FCA::kHolderIndex == 0); |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5323 MemOperand(fp, 6 * kPointerSize), | 5323 MemOperand(fp, 6 * kPointerSize), |
| 5324 NULL); | 5324 NULL); |
| 5325 } | 5325 } |
| 5326 | 5326 |
| 5327 | 5327 |
| 5328 #undef __ | 5328 #undef __ |
| 5329 | 5329 |
| 5330 } } // namespace v8::internal | 5330 } } // namespace v8::internal |
| 5331 | 5331 |
| 5332 #endif // V8_TARGET_ARCH_MIPS64 | 5332 #endif // V8_TARGET_ARCH_MIPS64 |
| OLD | NEW |