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_MIPS | 7 #if V8_TARGET_ARCH_MIPS |
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 1190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1201 const Register heapnumber = v0; | 1201 const Register heapnumber = v0; |
1202 const DoubleRegister double_base = f2; | 1202 const DoubleRegister double_base = f2; |
1203 const DoubleRegister double_exponent = f4; | 1203 const DoubleRegister double_exponent = f4; |
1204 const DoubleRegister double_result = f0; | 1204 const DoubleRegister double_result = f0; |
1205 const DoubleRegister double_scratch = f6; | 1205 const DoubleRegister double_scratch = f6; |
1206 const FPURegister single_scratch = f8; | 1206 const FPURegister single_scratch = f8; |
1207 const Register scratch = t5; | 1207 const Register scratch = t5; |
1208 const Register scratch2 = t3; | 1208 const Register scratch2 = t3; |
1209 | 1209 |
1210 Label call_runtime, done, int_exponent; | 1210 Label call_runtime, done, int_exponent; |
1211 if (exponent_type_ == ON_STACK) { | 1211 if (exponent_type() == ON_STACK) { |
1212 Label base_is_smi, unpack_exponent; | 1212 Label base_is_smi, unpack_exponent; |
1213 // The exponent and base are supplied as arguments on the stack. | 1213 // The exponent and base are supplied as arguments on the stack. |
1214 // This can only happen if the stub is called from non-optimized code. | 1214 // This can only happen if the stub is called from non-optimized code. |
1215 // Load input parameters from stack to double registers. | 1215 // Load input parameters from stack to double registers. |
1216 __ lw(base, MemOperand(sp, 1 * kPointerSize)); | 1216 __ lw(base, MemOperand(sp, 1 * kPointerSize)); |
1217 __ lw(exponent, MemOperand(sp, 0 * kPointerSize)); | 1217 __ lw(exponent, MemOperand(sp, 0 * kPointerSize)); |
1218 | 1218 |
1219 __ LoadRoot(heapnumbermap, Heap::kHeapNumberMapRootIndex); | 1219 __ LoadRoot(heapnumbermap, Heap::kHeapNumberMapRootIndex); |
1220 | 1220 |
1221 __ UntagAndJumpIfSmi(scratch, base, &base_is_smi); | 1221 __ UntagAndJumpIfSmi(scratch, base, &base_is_smi); |
1222 __ lw(scratch, FieldMemOperand(base, JSObject::kMapOffset)); | 1222 __ lw(scratch, FieldMemOperand(base, JSObject::kMapOffset)); |
1223 __ Branch(&call_runtime, ne, scratch, Operand(heapnumbermap)); | 1223 __ Branch(&call_runtime, ne, scratch, Operand(heapnumbermap)); |
1224 | 1224 |
1225 __ ldc1(double_base, FieldMemOperand(base, HeapNumber::kValueOffset)); | 1225 __ ldc1(double_base, FieldMemOperand(base, HeapNumber::kValueOffset)); |
1226 __ jmp(&unpack_exponent); | 1226 __ jmp(&unpack_exponent); |
1227 | 1227 |
1228 __ bind(&base_is_smi); | 1228 __ bind(&base_is_smi); |
1229 __ mtc1(scratch, single_scratch); | 1229 __ mtc1(scratch, single_scratch); |
1230 __ cvt_d_w(double_base, single_scratch); | 1230 __ cvt_d_w(double_base, single_scratch); |
1231 __ bind(&unpack_exponent); | 1231 __ bind(&unpack_exponent); |
1232 | 1232 |
1233 __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent); | 1233 __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent); |
1234 | 1234 |
1235 __ lw(scratch, FieldMemOperand(exponent, JSObject::kMapOffset)); | 1235 __ lw(scratch, FieldMemOperand(exponent, JSObject::kMapOffset)); |
1236 __ Branch(&call_runtime, ne, scratch, Operand(heapnumbermap)); | 1236 __ Branch(&call_runtime, ne, scratch, Operand(heapnumbermap)); |
1237 __ ldc1(double_exponent, | 1237 __ ldc1(double_exponent, |
1238 FieldMemOperand(exponent, HeapNumber::kValueOffset)); | 1238 FieldMemOperand(exponent, HeapNumber::kValueOffset)); |
1239 } else if (exponent_type_ == TAGGED) { | 1239 } else if (exponent_type() == TAGGED) { |
1240 // Base is already in double_base. | 1240 // Base is already in double_base. |
1241 __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent); | 1241 __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent); |
1242 | 1242 |
1243 __ ldc1(double_exponent, | 1243 __ ldc1(double_exponent, |
1244 FieldMemOperand(exponent, HeapNumber::kValueOffset)); | 1244 FieldMemOperand(exponent, HeapNumber::kValueOffset)); |
1245 } | 1245 } |
1246 | 1246 |
1247 if (exponent_type_ != INTEGER) { | 1247 if (exponent_type() != INTEGER) { |
1248 Label int_exponent_convert; | 1248 Label int_exponent_convert; |
1249 // Detect integer exponents stored as double. | 1249 // Detect integer exponents stored as double. |
1250 __ EmitFPUTruncate(kRoundToMinusInf, | 1250 __ EmitFPUTruncate(kRoundToMinusInf, |
1251 scratch, | 1251 scratch, |
1252 double_exponent, | 1252 double_exponent, |
1253 at, | 1253 at, |
1254 double_scratch, | 1254 double_scratch, |
1255 scratch2, | 1255 scratch2, |
1256 kCheckForInexactConversion); | 1256 kCheckForInexactConversion); |
1257 // scratch2 == 0 means there was no conversion error. | 1257 // scratch2 == 0 means there was no conversion error. |
1258 __ Branch(&int_exponent_convert, eq, scratch2, Operand(zero_reg)); | 1258 __ Branch(&int_exponent_convert, eq, scratch2, Operand(zero_reg)); |
1259 | 1259 |
1260 if (exponent_type_ == ON_STACK) { | 1260 if (exponent_type() == ON_STACK) { |
1261 // Detect square root case. Crankshaft detects constant +/-0.5 at | 1261 // Detect square root case. Crankshaft detects constant +/-0.5 at |
1262 // compile time and uses DoMathPowHalf instead. We then skip this check | 1262 // compile time and uses DoMathPowHalf instead. We then skip this check |
1263 // for non-constant cases of +/-0.5 as these hardly occur. | 1263 // for non-constant cases of +/-0.5 as these hardly occur. |
1264 Label not_plus_half; | 1264 Label not_plus_half; |
1265 | 1265 |
1266 // Test for 0.5. | 1266 // Test for 0.5. |
1267 __ Move(double_scratch, 0.5); | 1267 __ Move(double_scratch, 0.5); |
1268 __ BranchF(USE_DELAY_SLOT, | 1268 __ BranchF(USE_DELAY_SLOT, |
1269 ¬_plus_half, | 1269 ¬_plus_half, |
1270 NULL, | 1270 NULL, |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1319 __ MovFromFloatResult(double_result); | 1319 __ MovFromFloatResult(double_result); |
1320 __ jmp(&done); | 1320 __ jmp(&done); |
1321 | 1321 |
1322 __ bind(&int_exponent_convert); | 1322 __ bind(&int_exponent_convert); |
1323 } | 1323 } |
1324 | 1324 |
1325 // Calculate power with integer exponent. | 1325 // Calculate power with integer exponent. |
1326 __ bind(&int_exponent); | 1326 __ bind(&int_exponent); |
1327 | 1327 |
1328 // Get two copies of exponent in the registers scratch and exponent. | 1328 // Get two copies of exponent in the registers scratch and exponent. |
1329 if (exponent_type_ == INTEGER) { | 1329 if (exponent_type() == INTEGER) { |
1330 __ mov(scratch, exponent); | 1330 __ mov(scratch, exponent); |
1331 } else { | 1331 } else { |
1332 // Exponent has previously been stored into scratch as untagged integer. | 1332 // Exponent has previously been stored into scratch as untagged integer. |
1333 __ mov(exponent, scratch); | 1333 __ mov(exponent, scratch); |
1334 } | 1334 } |
1335 | 1335 |
1336 __ mov_d(double_scratch, double_base); // Back up base. | 1336 __ mov_d(double_scratch, double_base); // Back up base. |
1337 __ Move(double_result, 1.0); | 1337 __ Move(double_result, 1.0); |
1338 | 1338 |
1339 // Get absolute value of exponent. | 1339 // Get absolute value of exponent. |
(...skipping 27 matching lines...) Expand all Loading... |
1367 // Due to subnormals, x^-y == (1/x)^y does not hold in all cases. | 1367 // Due to subnormals, x^-y == (1/x)^y does not hold in all cases. |
1368 __ BranchF(&done, NULL, ne, double_result, kDoubleRegZero); | 1368 __ BranchF(&done, NULL, ne, double_result, kDoubleRegZero); |
1369 | 1369 |
1370 // double_exponent may not contain the exponent value if the input was a | 1370 // double_exponent may not contain the exponent value if the input was a |
1371 // smi. We set it with exponent value before bailing out. | 1371 // smi. We set it with exponent value before bailing out. |
1372 __ mtc1(exponent, single_scratch); | 1372 __ mtc1(exponent, single_scratch); |
1373 __ cvt_d_w(double_exponent, single_scratch); | 1373 __ cvt_d_w(double_exponent, single_scratch); |
1374 | 1374 |
1375 // Returning or bailing out. | 1375 // Returning or bailing out. |
1376 Counters* counters = isolate()->counters(); | 1376 Counters* counters = isolate()->counters(); |
1377 if (exponent_type_ == ON_STACK) { | 1377 if (exponent_type() == ON_STACK) { |
1378 // The arguments are still on the stack. | 1378 // The arguments are still on the stack. |
1379 __ bind(&call_runtime); | 1379 __ bind(&call_runtime); |
1380 __ TailCallRuntime(Runtime::kMathPowRT, 2, 1); | 1380 __ TailCallRuntime(Runtime::kMathPowRT, 2, 1); |
1381 | 1381 |
1382 // The stub is called from non-optimized code, which expects the result | 1382 // The stub is called from non-optimized code, which expects the result |
1383 // as heap number in exponent. | 1383 // as heap number in exponent. |
1384 __ bind(&done); | 1384 __ bind(&done); |
1385 __ AllocateHeapNumber( | 1385 __ AllocateHeapNumber( |
1386 heapnumber, scratch, scratch2, heapnumbermap, &call_runtime); | 1386 heapnumber, scratch, scratch2, heapnumbermap, &call_runtime); |
1387 __ sdc1(double_result, | 1387 __ sdc1(double_result, |
(...skipping 1625 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3013 | 3013 |
3014 if (call_as_method) { | 3014 if (call_as_method) { |
3015 __ bind(&wrap); | 3015 __ bind(&wrap); |
3016 // Wrap the receiver and patch it back onto the stack. | 3016 // Wrap the receiver and patch it back onto the stack. |
3017 EmitWrapCase(masm, argc, &cont); | 3017 EmitWrapCase(masm, argc, &cont); |
3018 } | 3018 } |
3019 } | 3019 } |
3020 | 3020 |
3021 | 3021 |
3022 void CallFunctionStub::Generate(MacroAssembler* masm) { | 3022 void CallFunctionStub::Generate(MacroAssembler* masm) { |
3023 CallFunctionNoFeedback(masm, argc_, NeedsChecks(), CallAsMethod()); | 3023 CallFunctionNoFeedback(masm, argc(), NeedsChecks(), CallAsMethod()); |
3024 } | 3024 } |
3025 | 3025 |
3026 | 3026 |
3027 void CallConstructStub::Generate(MacroAssembler* masm) { | 3027 void CallConstructStub::Generate(MacroAssembler* masm) { |
3028 // a0 : number of arguments | 3028 // a0 : number of arguments |
3029 // a1 : the function to call | 3029 // a1 : the function to call |
3030 // a2 : feedback vector | 3030 // a2 : feedback vector |
3031 // a3 : (only if a2 is not undefined) slot in feedback vector (Smi) | 3031 // a3 : (only if a2 is not undefined) slot in feedback vector (Smi) |
3032 Label slow, non_function_call; | 3032 Label slow, non_function_call; |
3033 | 3033 |
(...skipping 1746 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4780 __ mov(v0, a0); | 4780 __ mov(v0, a0); |
4781 } | 4781 } |
4782 | 4782 |
4783 | 4783 |
4784 void StubFailureTrampolineStub::Generate(MacroAssembler* masm) { | 4784 void StubFailureTrampolineStub::Generate(MacroAssembler* masm) { |
4785 CEntryStub ces(isolate(), 1, kSaveFPRegs); | 4785 CEntryStub ces(isolate(), 1, kSaveFPRegs); |
4786 __ Call(ces.GetCode(), RelocInfo::CODE_TARGET); | 4786 __ Call(ces.GetCode(), RelocInfo::CODE_TARGET); |
4787 int parameter_count_offset = | 4787 int parameter_count_offset = |
4788 StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset; | 4788 StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset; |
4789 __ lw(a1, MemOperand(fp, parameter_count_offset)); | 4789 __ lw(a1, MemOperand(fp, parameter_count_offset)); |
4790 if (function_mode_ == JS_FUNCTION_STUB_MODE) { | 4790 if (function_mode() == JS_FUNCTION_STUB_MODE) { |
4791 __ Addu(a1, a1, Operand(1)); | 4791 __ Addu(a1, a1, Operand(1)); |
4792 } | 4792 } |
4793 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); | 4793 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); |
4794 __ sll(a1, a1, kPointerSizeLog2); | 4794 __ sll(a1, a1, kPointerSizeLog2); |
4795 __ Ret(USE_DELAY_SLOT); | 4795 __ Ret(USE_DELAY_SLOT); |
4796 __ Addu(sp, sp, a1); | 4796 __ Addu(sp, sp, a1); |
4797 } | 4797 } |
4798 | 4798 |
4799 | 4799 |
4800 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { | 4800 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5006 stubh2.GetCode(); | 5006 stubh2.GetCode(); |
5007 InternalArrayNArgumentsConstructorStub stubh3(isolate, kinds[i]); | 5007 InternalArrayNArgumentsConstructorStub stubh3(isolate, kinds[i]); |
5008 stubh3.GetCode(); | 5008 stubh3.GetCode(); |
5009 } | 5009 } |
5010 } | 5010 } |
5011 | 5011 |
5012 | 5012 |
5013 void ArrayConstructorStub::GenerateDispatchToArrayStub( | 5013 void ArrayConstructorStub::GenerateDispatchToArrayStub( |
5014 MacroAssembler* masm, | 5014 MacroAssembler* masm, |
5015 AllocationSiteOverrideMode mode) { | 5015 AllocationSiteOverrideMode mode) { |
5016 if (argument_count_ == ANY) { | 5016 if (argument_count() == ANY) { |
5017 Label not_zero_case, not_one_case; | 5017 Label not_zero_case, not_one_case; |
5018 __ And(at, a0, a0); | 5018 __ And(at, a0, a0); |
5019 __ Branch(¬_zero_case, ne, at, Operand(zero_reg)); | 5019 __ Branch(¬_zero_case, ne, at, Operand(zero_reg)); |
5020 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); | 5020 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); |
5021 | 5021 |
5022 __ bind(¬_zero_case); | 5022 __ bind(¬_zero_case); |
5023 __ Branch(¬_one_case, gt, a0, Operand(1)); | 5023 __ Branch(¬_one_case, gt, a0, Operand(1)); |
5024 CreateArrayDispatchOneArgument(masm, mode); | 5024 CreateArrayDispatchOneArgument(masm, mode); |
5025 | 5025 |
5026 __ bind(¬_one_case); | 5026 __ bind(¬_one_case); |
5027 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); | 5027 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); |
5028 } else if (argument_count_ == NONE) { | 5028 } else if (argument_count() == NONE) { |
5029 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); | 5029 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); |
5030 } else if (argument_count_ == ONE) { | 5030 } else if (argument_count() == ONE) { |
5031 CreateArrayDispatchOneArgument(masm, mode); | 5031 CreateArrayDispatchOneArgument(masm, mode); |
5032 } else if (argument_count_ == MORE_THAN_ONE) { | 5032 } else if (argument_count() == MORE_THAN_ONE) { |
5033 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); | 5033 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); |
5034 } else { | 5034 } else { |
5035 UNREACHABLE(); | 5035 UNREACHABLE(); |
5036 } | 5036 } |
5037 } | 5037 } |
5038 | 5038 |
5039 | 5039 |
5040 void ArrayConstructorStub::Generate(MacroAssembler* masm) { | 5040 void ArrayConstructorStub::Generate(MacroAssembler* masm) { |
5041 // ----------- S t a t e ------------- | 5041 // ----------- S t a t e ------------- |
5042 // -- a0 : argc (only if argument_count_ == ANY) | 5042 // -- a0 : argc (only if argument_count() == ANY) |
5043 // -- a1 : constructor | 5043 // -- a1 : constructor |
5044 // -- a2 : AllocationSite or undefined | 5044 // -- a2 : AllocationSite or undefined |
5045 // -- sp[0] : return address | 5045 // -- sp[0] : return address |
5046 // -- sp[4] : last argument | 5046 // -- sp[4] : last argument |
5047 // ----------------------------------- | 5047 // ----------------------------------- |
5048 | 5048 |
5049 if (FLAG_debug_code) { | 5049 if (FLAG_debug_code) { |
5050 // The array construct code is only set for the global and natives | 5050 // The array construct code is only set for the global and natives |
5051 // builtin Array functions which always have maps. | 5051 // builtin Array functions which always have maps. |
5052 | 5052 |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5167 // -- sp[(argc - 1)* 4] : first argument | 5167 // -- sp[(argc - 1)* 4] : first argument |
5168 // -- sp[argc * 4] : receiver | 5168 // -- sp[argc * 4] : receiver |
5169 // ----------------------------------- | 5169 // ----------------------------------- |
5170 | 5170 |
5171 Register callee = a0; | 5171 Register callee = a0; |
5172 Register call_data = t0; | 5172 Register call_data = t0; |
5173 Register holder = a2; | 5173 Register holder = a2; |
5174 Register api_function_address = a1; | 5174 Register api_function_address = a1; |
5175 Register context = cp; | 5175 Register context = cp; |
5176 | 5176 |
5177 int argc = ArgumentBits::decode(bit_field_); | 5177 int argc = this->argc(); |
5178 bool is_store = IsStoreBits::decode(bit_field_); | 5178 bool is_store = this->is_store(); |
5179 bool call_data_undefined = CallDataUndefinedBits::decode(bit_field_); | 5179 bool call_data_undefined = this->call_data_undefined(); |
5180 | 5180 |
5181 typedef FunctionCallbackArguments FCA; | 5181 typedef FunctionCallbackArguments FCA; |
5182 | 5182 |
5183 STATIC_ASSERT(FCA::kContextSaveIndex == 6); | 5183 STATIC_ASSERT(FCA::kContextSaveIndex == 6); |
5184 STATIC_ASSERT(FCA::kCalleeIndex == 5); | 5184 STATIC_ASSERT(FCA::kCalleeIndex == 5); |
5185 STATIC_ASSERT(FCA::kDataIndex == 4); | 5185 STATIC_ASSERT(FCA::kDataIndex == 4); |
5186 STATIC_ASSERT(FCA::kReturnValueOffset == 3); | 5186 STATIC_ASSERT(FCA::kReturnValueOffset == 3); |
5187 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); | 5187 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); |
5188 STATIC_ASSERT(FCA::kIsolateIndex == 1); | 5188 STATIC_ASSERT(FCA::kIsolateIndex == 1); |
5189 STATIC_ASSERT(FCA::kHolderIndex == 0); | 5189 STATIC_ASSERT(FCA::kHolderIndex == 0); |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5286 MemOperand(fp, 6 * kPointerSize), | 5286 MemOperand(fp, 6 * kPointerSize), |
5287 NULL); | 5287 NULL); |
5288 } | 5288 } |
5289 | 5289 |
5290 | 5290 |
5291 #undef __ | 5291 #undef __ |
5292 | 5292 |
5293 } } // namespace v8::internal | 5293 } } // namespace v8::internal |
5294 | 5294 |
5295 #endif // V8_TARGET_ARCH_MIPS | 5295 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |