| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 1118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1129 // xmm1 : untagged double input argument | 1129 // xmm1 : untagged double input argument |
| 1130 // Output: | 1130 // Output: |
| 1131 // xmm1 : untagged double result. | 1131 // xmm1 : untagged double result. |
| 1132 | 1132 |
| 1133 Label runtime_call; | 1133 Label runtime_call; |
| 1134 Label runtime_call_clear_stack; | 1134 Label runtime_call_clear_stack; |
| 1135 Label skip_cache; | 1135 Label skip_cache; |
| 1136 const bool tagged = (argument_type_ == TAGGED); | 1136 const bool tagged = (argument_type_ == TAGGED); |
| 1137 if (tagged) { | 1137 if (tagged) { |
| 1138 Label input_not_smi, loaded; | 1138 Label input_not_smi, loaded; |
| 1139 |
| 1139 // Test that rax is a number. | 1140 // Test that rax is a number. |
| 1140 StackArgumentsAccessor args(rsp, 1, ARGUMENTS_DONT_CONTAIN_RECEIVER); | 1141 StackArgumentsAccessor args(rsp, 1, ARGUMENTS_DONT_CONTAIN_RECEIVER); |
| 1141 __ movq(rax, args.GetArgumentOperand(0)); | 1142 __ movq(rax, args.GetArgumentOperand(0)); |
| 1142 __ JumpIfNotSmi(rax, &input_not_smi, Label::kNear); | 1143 __ JumpIfNotSmi(rax, &input_not_smi, Label::kNear); |
| 1143 // Input is a smi. Untag and load it onto the FPU stack. | 1144 // Input is a smi. Untag and load it onto the FPU stack. |
| 1144 // Then load the bits of the double into rbx. | 1145 // Then load the bits of the double into rbx. |
| 1145 __ SmiToInteger32(rax, rax); | 1146 __ SmiToInteger32(rax, rax); |
| 1146 __ subq(rsp, Immediate(kDoubleSize)); | 1147 __ subq(rsp, Immediate(kDoubleSize)); |
| 1147 __ cvtlsi2sd(xmm1, rax); | 1148 __ cvtlsi2sd(xmm1, rax); |
| 1148 __ movsd(Operand(rsp, 0), xmm1); | 1149 __ movsd(Operand(rsp, 0), xmm1); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1192 ASSERT(IsPowerOf2(TranscendentalCache::SubCache::kCacheSize)); | 1193 ASSERT(IsPowerOf2(TranscendentalCache::SubCache::kCacheSize)); |
| 1193 __ andl(rcx, Immediate(TranscendentalCache::SubCache::kCacheSize - 1)); | 1194 __ andl(rcx, Immediate(TranscendentalCache::SubCache::kCacheSize - 1)); |
| 1194 | 1195 |
| 1195 // ST[0] == double value. | 1196 // ST[0] == double value. |
| 1196 // rbx = bits of double value. | 1197 // rbx = bits of double value. |
| 1197 // rcx = TranscendentalCache::hash(double value). | 1198 // rcx = TranscendentalCache::hash(double value). |
| 1198 ExternalReference cache_array = | 1199 ExternalReference cache_array = |
| 1199 ExternalReference::transcendental_cache_array_address(masm->isolate()); | 1200 ExternalReference::transcendental_cache_array_address(masm->isolate()); |
| 1200 __ movq(rax, cache_array); | 1201 __ movq(rax, cache_array); |
| 1201 int cache_array_index = | 1202 int cache_array_index = |
| 1202 type_ * sizeof(Isolate::Current()->transcendental_cache()->caches_[0]); | 1203 type_ * sizeof(masm->isolate()->transcendental_cache()->caches_[0]); |
| 1203 __ movq(rax, Operand(rax, cache_array_index)); | 1204 __ movq(rax, Operand(rax, cache_array_index)); |
| 1204 // rax points to the cache for the type type_. | 1205 // rax points to the cache for the type type_. |
| 1205 // If NULL, the cache hasn't been initialized yet, so go through runtime. | 1206 // If NULL, the cache hasn't been initialized yet, so go through runtime. |
| 1206 __ testq(rax, rax); | 1207 __ testq(rax, rax); |
| 1207 __ j(zero, &runtime_call_clear_stack); // Only clears stack if TAGGED. | 1208 __ j(zero, &runtime_call_clear_stack); // Only clears stack if TAGGED. |
| 1208 #ifdef DEBUG | 1209 #ifdef DEBUG |
| 1209 // Check that the layout of cache elements match expectations. | 1210 // Check that the layout of cache elements match expectations. |
| 1210 { // NOLINT - doesn't like a single brace on a line. | 1211 { // NOLINT - doesn't like a single brace on a line. |
| 1211 TranscendentalCache::SubCache::Element test_elem[2]; | 1212 TranscendentalCache::SubCache::Element test_elem[2]; |
| 1212 char* elem_start = reinterpret_cast<char*>(&test_elem[0]); | 1213 char* elem_start = reinterpret_cast<char*>(&test_elem[0]); |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1439 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). | 1440 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). |
| 1440 __ bind(&check_undefined_arg1); | 1441 __ bind(&check_undefined_arg1); |
| 1441 __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex); | 1442 __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex); |
| 1442 __ j(not_equal, conversion_failure); | 1443 __ j(not_equal, conversion_failure); |
| 1443 __ Set(r8, 0); | 1444 __ Set(r8, 0); |
| 1444 __ jmp(&load_arg2); | 1445 __ jmp(&load_arg2); |
| 1445 | 1446 |
| 1446 __ bind(&arg1_is_object); | 1447 __ bind(&arg1_is_object); |
| 1447 __ cmpq(FieldOperand(rdx, HeapObject::kMapOffset), heap_number_map); | 1448 __ cmpq(FieldOperand(rdx, HeapObject::kMapOffset), heap_number_map); |
| 1448 __ j(not_equal, &check_undefined_arg1); | 1449 __ j(not_equal, &check_undefined_arg1); |
| 1449 // Get the untagged integer version of the rdx heap number in rcx. | 1450 // Get the untagged integer version of the rdx heap number in r8. |
| 1450 DoubleToIStub stub1(rdx, r8, HeapNumber::kValueOffset - kHeapObjectTag, | 1451 __ TruncateHeapNumberToI(r8, rdx); |
| 1451 true); | |
| 1452 __ call(stub1.GetCode(masm->isolate()), RelocInfo::CODE_TARGET); | |
| 1453 | 1452 |
| 1454 // Here r8 has the untagged integer, rax has a Smi or a heap number. | 1453 // Here r8 has the untagged integer, rax has a Smi or a heap number. |
| 1455 __ bind(&load_arg2); | 1454 __ bind(&load_arg2); |
| 1456 // Test if arg2 is a Smi. | 1455 // Test if arg2 is a Smi. |
| 1457 __ JumpIfNotSmi(rax, &arg2_is_object); | 1456 __ JumpIfNotSmi(rax, &arg2_is_object); |
| 1458 __ SmiToInteger32(rcx, rax); | 1457 __ SmiToInteger32(rcx, rax); |
| 1459 __ jmp(&done); | 1458 __ jmp(&done); |
| 1460 | 1459 |
| 1461 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). | 1460 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). |
| 1462 __ bind(&check_undefined_arg2); | 1461 __ bind(&check_undefined_arg2); |
| 1463 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); | 1462 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); |
| 1464 __ j(not_equal, conversion_failure); | 1463 __ j(not_equal, conversion_failure); |
| 1465 __ Set(rcx, 0); | 1464 __ Set(rcx, 0); |
| 1466 __ jmp(&done); | 1465 __ jmp(&done); |
| 1467 | 1466 |
| 1468 __ bind(&arg2_is_object); | 1467 __ bind(&arg2_is_object); |
| 1469 __ cmpq(FieldOperand(rax, HeapObject::kMapOffset), heap_number_map); | 1468 __ cmpq(FieldOperand(rax, HeapObject::kMapOffset), heap_number_map); |
| 1470 __ j(not_equal, &check_undefined_arg2); | 1469 __ j(not_equal, &check_undefined_arg2); |
| 1471 // Get the untagged integer version of the rax heap number in rcx. | 1470 // Get the untagged integer version of the rax heap number in rcx. |
| 1472 DoubleToIStub stub2(rax, rcx, HeapNumber::kValueOffset - kHeapObjectTag, | 1471 __ TruncateHeapNumberToI(rcx, rax); |
| 1473 true); | |
| 1474 __ call(stub2.GetCode(masm->isolate()), RelocInfo::CODE_TARGET); | |
| 1475 | 1472 |
| 1476 __ bind(&done); | 1473 __ bind(&done); |
| 1477 __ movl(rax, r8); | 1474 __ movl(rax, r8); |
| 1478 } | 1475 } |
| 1479 | 1476 |
| 1480 | 1477 |
| 1481 void FloatingPointHelper::LoadSSE2SmiOperands(MacroAssembler* masm) { | 1478 void FloatingPointHelper::LoadSSE2SmiOperands(MacroAssembler* masm) { |
| 1482 __ SmiToInteger32(kScratchRegister, rdx); | 1479 __ SmiToInteger32(kScratchRegister, rdx); |
| 1483 __ cvtlsi2sd(xmm0, kScratchRegister); | 1480 __ cvtlsi2sd(xmm0, kScratchRegister); |
| 1484 __ SmiToInteger32(kScratchRegister, rax); | 1481 __ SmiToInteger32(kScratchRegister, rax); |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1641 } else if (exponent_type_ == TAGGED) { | 1638 } else if (exponent_type_ == TAGGED) { |
| 1642 __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear); | 1639 __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear); |
| 1643 __ SmiToInteger32(exponent, exponent); | 1640 __ SmiToInteger32(exponent, exponent); |
| 1644 __ jmp(&int_exponent); | 1641 __ jmp(&int_exponent); |
| 1645 | 1642 |
| 1646 __ bind(&exponent_not_smi); | 1643 __ bind(&exponent_not_smi); |
| 1647 __ movsd(double_exponent, FieldOperand(exponent, HeapNumber::kValueOffset)); | 1644 __ movsd(double_exponent, FieldOperand(exponent, HeapNumber::kValueOffset)); |
| 1648 } | 1645 } |
| 1649 | 1646 |
| 1650 if (exponent_type_ != INTEGER) { | 1647 if (exponent_type_ != INTEGER) { |
| 1651 Label fast_power; | 1648 Label fast_power, try_arithmetic_simplification; |
| 1652 // Detect integer exponents stored as double. | 1649 // Detect integer exponents stored as double. |
| 1650 __ DoubleToI(exponent, double_exponent, double_scratch, |
| 1651 TREAT_MINUS_ZERO_AS_ZERO, &try_arithmetic_simplification); |
| 1652 __ jmp(&int_exponent); |
| 1653 |
| 1654 __ bind(&try_arithmetic_simplification); |
| 1653 __ cvttsd2si(exponent, double_exponent); | 1655 __ cvttsd2si(exponent, double_exponent); |
| 1654 // Skip to runtime if possibly NaN (indicated by the indefinite integer). | 1656 // Skip to runtime if possibly NaN (indicated by the indefinite integer). |
| 1655 __ cmpl(exponent, Immediate(0x80000000u)); | 1657 __ cmpl(exponent, Immediate(0x80000000u)); |
| 1656 __ j(equal, &call_runtime); | 1658 __ j(equal, &call_runtime); |
| 1657 __ cvtlsi2sd(double_scratch, exponent); | |
| 1658 // Already ruled out NaNs for exponent. | |
| 1659 __ ucomisd(double_exponent, double_scratch); | |
| 1660 __ j(equal, &int_exponent); | |
| 1661 | 1659 |
| 1662 if (exponent_type_ == ON_STACK) { | 1660 if (exponent_type_ == ON_STACK) { |
| 1663 // Detect square root case. Crankshaft detects constant +/-0.5 at | 1661 // Detect square root case. Crankshaft detects constant +/-0.5 at |
| 1664 // compile time and uses DoMathPowHalf instead. We then skip this check | 1662 // compile time and uses DoMathPowHalf instead. We then skip this check |
| 1665 // for non-constant cases of +/-0.5 as these hardly occur. | 1663 // for non-constant cases of +/-0.5 as these hardly occur. |
| 1666 Label continue_sqrt, continue_rsqrt, not_plus_half; | 1664 Label continue_sqrt, continue_rsqrt, not_plus_half; |
| 1667 // Test for 0.5. | 1665 // Test for 0.5. |
| 1668 // Load double_scratch with 0.5. | 1666 // Load double_scratch with 0.5. |
| 1669 __ movq(scratch, V8_UINT64_C(0x3FE0000000000000), RelocInfo::NONE64); | 1667 __ movq(scratch, V8_UINT64_C(0x3FE0000000000000), RelocInfo::NONE64); |
| 1670 __ movq(double_scratch, scratch); | 1668 __ movq(double_scratch, scratch); |
| (...skipping 1814 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3485 | 3483 |
| 3486 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead | 3484 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead |
| 3487 // of the original receiver from the call site). | 3485 // of the original receiver from the call site). |
| 3488 __ bind(&non_function); | 3486 __ bind(&non_function); |
| 3489 __ movq(args.GetReceiverOperand(), rdi); | 3487 __ movq(args.GetReceiverOperand(), rdi); |
| 3490 __ Set(rax, argc_); | 3488 __ Set(rax, argc_); |
| 3491 __ Set(rbx, 0); | 3489 __ Set(rbx, 0); |
| 3492 __ SetCallKind(rcx, CALL_AS_METHOD); | 3490 __ SetCallKind(rcx, CALL_AS_METHOD); |
| 3493 __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION); | 3491 __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION); |
| 3494 Handle<Code> adaptor = | 3492 Handle<Code> adaptor = |
| 3495 Isolate::Current()->builtins()->ArgumentsAdaptorTrampoline(); | 3493 isolate->builtins()->ArgumentsAdaptorTrampoline(); |
| 3496 __ Jump(adaptor, RelocInfo::CODE_TARGET); | 3494 __ Jump(adaptor, RelocInfo::CODE_TARGET); |
| 3497 } | 3495 } |
| 3498 | 3496 |
| 3499 | 3497 |
| 3500 void CallConstructStub::Generate(MacroAssembler* masm) { | 3498 void CallConstructStub::Generate(MacroAssembler* masm) { |
| 3501 // rax : number of arguments | 3499 // rax : number of arguments |
| 3502 // rbx : cache cell for call target | 3500 // rbx : cache cell for call target |
| 3503 // rdi : constructor function | 3501 // rdi : constructor function |
| 3504 Label slow, non_function_call; | 3502 Label slow, non_function_call; |
| 3505 | 3503 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3540 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 3538 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
| 3541 RelocInfo::CODE_TARGET); | 3539 RelocInfo::CODE_TARGET); |
| 3542 } | 3540 } |
| 3543 | 3541 |
| 3544 | 3542 |
| 3545 bool CEntryStub::NeedsImmovableCode() { | 3543 bool CEntryStub::NeedsImmovableCode() { |
| 3546 return false; | 3544 return false; |
| 3547 } | 3545 } |
| 3548 | 3546 |
| 3549 | 3547 |
| 3550 bool CEntryStub::IsPregenerated() { | 3548 bool CEntryStub::IsPregenerated(Isolate* isolate) { |
| 3551 #ifdef _WIN64 | 3549 #ifdef _WIN64 |
| 3552 return result_size_ == 1; | 3550 return result_size_ == 1; |
| 3553 #else | 3551 #else |
| 3554 return true; | 3552 return true; |
| 3555 #endif | 3553 #endif |
| 3556 } | 3554 } |
| 3557 | 3555 |
| 3558 | 3556 |
| 3559 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { | 3557 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { |
| 3560 CEntryStub::GenerateAheadOfTime(isolate); | 3558 CEntryStub::GenerateAheadOfTime(isolate); |
| (...skipping 2333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5894 }; | 5892 }; |
| 5895 | 5893 |
| 5896 | 5894 |
| 5897 #define REG(Name) { kRegister_ ## Name ## _Code } | 5895 #define REG(Name) { kRegister_ ## Name ## _Code } |
| 5898 | 5896 |
| 5899 struct AheadOfTimeWriteBarrierStubList kAheadOfTime[] = { | 5897 struct AheadOfTimeWriteBarrierStubList kAheadOfTime[] = { |
| 5900 // Used in RegExpExecStub. | 5898 // Used in RegExpExecStub. |
| 5901 { REG(rbx), REG(rax), REG(rdi), EMIT_REMEMBERED_SET }, | 5899 { REG(rbx), REG(rax), REG(rdi), EMIT_REMEMBERED_SET }, |
| 5902 // Used in CompileArrayPushCall. | 5900 // Used in CompileArrayPushCall. |
| 5903 { REG(rbx), REG(rcx), REG(rdx), EMIT_REMEMBERED_SET }, | 5901 { REG(rbx), REG(rcx), REG(rdx), EMIT_REMEMBERED_SET }, |
| 5904 // Used in CompileStoreGlobal. | |
| 5905 { REG(rbx), REG(rcx), REG(rdx), OMIT_REMEMBERED_SET }, | |
| 5906 // Used in StoreStubCompiler::CompileStoreField and | 5902 // Used in StoreStubCompiler::CompileStoreField and |
| 5907 // KeyedStoreStubCompiler::CompileStoreField via GenerateStoreField. | 5903 // KeyedStoreStubCompiler::CompileStoreField via GenerateStoreField. |
| 5908 { REG(rdx), REG(rcx), REG(rbx), EMIT_REMEMBERED_SET }, | 5904 { REG(rdx), REG(rcx), REG(rbx), EMIT_REMEMBERED_SET }, |
| 5909 // GenerateStoreField calls the stub with two different permutations of | 5905 // GenerateStoreField calls the stub with two different permutations of |
| 5910 // registers. This is the second. | 5906 // registers. This is the second. |
| 5911 { REG(rbx), REG(rcx), REG(rdx), EMIT_REMEMBERED_SET }, | 5907 { REG(rbx), REG(rcx), REG(rdx), EMIT_REMEMBERED_SET }, |
| 5912 // StoreIC::GenerateNormal via GenerateDictionaryStore. | 5908 // StoreIC::GenerateNormal via GenerateDictionaryStore. |
| 5913 { REG(rbx), REG(r8), REG(r9), EMIT_REMEMBERED_SET }, | 5909 { REG(rbx), REG(r8), REG(r9), EMIT_REMEMBERED_SET }, |
| 5914 // KeyedStoreIC::GenerateGeneric. | 5910 // KeyedStoreIC::GenerateGeneric. |
| 5915 { REG(rbx), REG(rdx), REG(rcx), EMIT_REMEMBERED_SET}, | 5911 { REG(rbx), REG(rdx), REG(rcx), EMIT_REMEMBERED_SET}, |
| (...skipping 16 matching lines...) Expand all Loading... |
| 5932 // StringAddStub::Generate | 5928 // StringAddStub::Generate |
| 5933 { REG(rcx), REG(rdx), REG(rbx), EMIT_REMEMBERED_SET}, | 5929 { REG(rcx), REG(rdx), REG(rbx), EMIT_REMEMBERED_SET}, |
| 5934 // StringAddStub::Generate | 5930 // StringAddStub::Generate |
| 5935 { REG(rcx), REG(rax), REG(rbx), EMIT_REMEMBERED_SET}, | 5931 { REG(rcx), REG(rax), REG(rbx), EMIT_REMEMBERED_SET}, |
| 5936 // Null termination. | 5932 // Null termination. |
| 5937 { REG(no_reg), REG(no_reg), REG(no_reg), EMIT_REMEMBERED_SET} | 5933 { REG(no_reg), REG(no_reg), REG(no_reg), EMIT_REMEMBERED_SET} |
| 5938 }; | 5934 }; |
| 5939 | 5935 |
| 5940 #undef REG | 5936 #undef REG |
| 5941 | 5937 |
| 5942 bool RecordWriteStub::IsPregenerated() { | 5938 bool RecordWriteStub::IsPregenerated(Isolate* isolate) { |
| 5943 for (AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime; | 5939 for (AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime; |
| 5944 !entry->object.is(no_reg); | 5940 !entry->object.is(no_reg); |
| 5945 entry++) { | 5941 entry++) { |
| 5946 if (object_.is(entry->object) && | 5942 if (object_.is(entry->object) && |
| 5947 value_.is(entry->value) && | 5943 value_.is(entry->value) && |
| 5948 address_.is(entry->address) && | 5944 address_.is(entry->address) && |
| 5949 remembered_set_action_ == entry->action && | 5945 remembered_set_action_ == entry->action && |
| 5950 save_fp_regs_mode_ == kDontSaveFPRegs) { | 5946 save_fp_regs_mode_ == kDontSaveFPRegs) { |
| 5951 return true; | 5947 return true; |
| 5952 } | 5948 } |
| (...skipping 670 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6623 __ bind(&fast_elements_case); | 6619 __ bind(&fast_elements_case); |
| 6624 GenerateCase(masm, FAST_ELEMENTS); | 6620 GenerateCase(masm, FAST_ELEMENTS); |
| 6625 } | 6621 } |
| 6626 | 6622 |
| 6627 | 6623 |
| 6628 #undef __ | 6624 #undef __ |
| 6629 | 6625 |
| 6630 } } // namespace v8::internal | 6626 } } // namespace v8::internal |
| 6631 | 6627 |
| 6632 #endif // V8_TARGET_ARCH_X64 | 6628 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |