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 |