| 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 #if V8_TARGET_ARCH_IA32 | 5 #if V8_TARGET_ARCH_IA32 |
| 6 | 6 |
| 7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
| 8 #include "src/base/division-by-constant.h" | 8 #include "src/base/division-by-constant.h" |
| 9 #include "src/base/utils/random-number-generator.h" | 9 #include "src/base/utils/random-number-generator.h" |
| 10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
| (...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 388 Label done; | 388 Label done; |
| 389 cmp(src, Immediate(0)); | 389 cmp(src, Immediate(0)); |
| 390 ExternalReference uint32_bias = ExternalReference::address_of_uint32_bias(); | 390 ExternalReference uint32_bias = ExternalReference::address_of_uint32_bias(); |
| 391 Cvtsi2sd(dst, src); | 391 Cvtsi2sd(dst, src); |
| 392 j(not_sign, &done, Label::kNear); | 392 j(not_sign, &done, Label::kNear); |
| 393 addsd(dst, Operand::StaticVariable(uint32_bias)); | 393 addsd(dst, Operand::StaticVariable(uint32_bias)); |
| 394 bind(&done); | 394 bind(&done); |
| 395 } | 395 } |
| 396 | 396 |
| 397 | 397 |
| 398 void MacroAssembler::RecordWriteArray( | |
| 399 Register object, | |
| 400 Register value, | |
| 401 Register index, | |
| 402 SaveFPRegsMode save_fp, | |
| 403 RememberedSetAction remembered_set_action, | |
| 404 SmiCheck smi_check, | |
| 405 PointersToHereCheck pointers_to_here_check_for_value) { | |
| 406 // First, check if a write barrier is even needed. The tests below | |
| 407 // catch stores of Smis. | |
| 408 Label done; | |
| 409 | |
| 410 // Skip barrier if writing a smi. | |
| 411 if (smi_check == INLINE_SMI_CHECK) { | |
| 412 DCHECK_EQ(0, kSmiTag); | |
| 413 test(value, Immediate(kSmiTagMask)); | |
| 414 j(zero, &done); | |
| 415 } | |
| 416 | |
| 417 // Array access: calculate the destination address in the same manner as | |
| 418 // KeyedStoreIC::GenerateGeneric. Multiply a smi by 2 to get an offset | |
| 419 // into an array of words. | |
| 420 Register dst = index; | |
| 421 lea(dst, Operand(object, index, times_half_pointer_size, | |
| 422 FixedArray::kHeaderSize - kHeapObjectTag)); | |
| 423 | |
| 424 RecordWrite(object, dst, value, save_fp, remembered_set_action, | |
| 425 OMIT_SMI_CHECK, pointers_to_here_check_for_value); | |
| 426 | |
| 427 bind(&done); | |
| 428 | |
| 429 // Clobber clobbered input registers when running with the debug-code flag | |
| 430 // turned on to provoke errors. | |
| 431 if (emit_debug_code()) { | |
| 432 mov(value, Immediate(bit_cast<int32_t>(kZapValue))); | |
| 433 mov(index, Immediate(bit_cast<int32_t>(kZapValue))); | |
| 434 } | |
| 435 } | |
| 436 | |
| 437 | |
| 438 void MacroAssembler::RecordWriteField( | 398 void MacroAssembler::RecordWriteField( |
| 439 Register object, | 399 Register object, |
| 440 int offset, | 400 int offset, |
| 441 Register value, | 401 Register value, |
| 442 Register dst, | 402 Register dst, |
| 443 SaveFPRegsMode save_fp, | 403 SaveFPRegsMode save_fp, |
| 444 RememberedSetAction remembered_set_action, | 404 RememberedSetAction remembered_set_action, |
| 445 SmiCheck smi_check, | 405 SmiCheck smi_check, |
| 446 PointersToHereCheck pointers_to_here_check_for_value) { | 406 PointersToHereCheck pointers_to_here_check_for_value) { |
| 447 // First, check if a write barrier is even needed. The tests below | 407 // First, check if a write barrier is even needed. The tests below |
| (...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 830 SmiCheckType smi_check_type) { | 790 SmiCheckType smi_check_type) { |
| 831 if (smi_check_type == DO_SMI_CHECK) { | 791 if (smi_check_type == DO_SMI_CHECK) { |
| 832 JumpIfSmi(obj, fail); | 792 JumpIfSmi(obj, fail); |
| 833 } | 793 } |
| 834 | 794 |
| 835 CompareMap(obj, map); | 795 CompareMap(obj, map); |
| 836 j(not_equal, fail); | 796 j(not_equal, fail); |
| 837 } | 797 } |
| 838 | 798 |
| 839 | 799 |
| 840 void MacroAssembler::DispatchWeakMap(Register obj, Register scratch1, | |
| 841 Register scratch2, Handle<WeakCell> cell, | |
| 842 Handle<Code> success, | |
| 843 SmiCheckType smi_check_type) { | |
| 844 Label fail; | |
| 845 if (smi_check_type == DO_SMI_CHECK) { | |
| 846 JumpIfSmi(obj, &fail); | |
| 847 } | |
| 848 mov(scratch1, FieldOperand(obj, HeapObject::kMapOffset)); | |
| 849 CmpWeakValue(scratch1, cell, scratch2); | |
| 850 j(equal, success); | |
| 851 | |
| 852 bind(&fail); | |
| 853 } | |
| 854 | |
| 855 | |
| 856 Condition MacroAssembler::IsObjectStringType(Register heap_object, | 800 Condition MacroAssembler::IsObjectStringType(Register heap_object, |
| 857 Register map, | 801 Register map, |
| 858 Register instance_type) { | 802 Register instance_type) { |
| 859 mov(map, FieldOperand(heap_object, HeapObject::kMapOffset)); | 803 mov(map, FieldOperand(heap_object, HeapObject::kMapOffset)); |
| 860 movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset)); | 804 movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset)); |
| 861 STATIC_ASSERT(kNotStringTag != 0); | 805 STATIC_ASSERT(kNotStringTag != 0); |
| 862 test(instance_type, Immediate(kIsNotStringMask)); | 806 test(instance_type, Immediate(kIsNotStringMask)); |
| 863 return zero; | 807 return zero; |
| 864 } | 808 } |
| 865 | 809 |
| 866 | 810 |
| 867 Condition MacroAssembler::IsObjectNameType(Register heap_object, | |
| 868 Register map, | |
| 869 Register instance_type) { | |
| 870 mov(map, FieldOperand(heap_object, HeapObject::kMapOffset)); | |
| 871 movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset)); | |
| 872 cmpb(instance_type, Immediate(LAST_NAME_TYPE)); | |
| 873 return below_equal; | |
| 874 } | |
| 875 | |
| 876 | |
| 877 void MacroAssembler::FCmp() { | 811 void MacroAssembler::FCmp() { |
| 878 fucomip(); | 812 fucomip(); |
| 879 fstp(0); | 813 fstp(0); |
| 880 } | 814 } |
| 881 | 815 |
| 882 | 816 |
| 883 void MacroAssembler::AssertNumber(Register object) { | |
| 884 if (emit_debug_code()) { | |
| 885 Label ok; | |
| 886 JumpIfSmi(object, &ok); | |
| 887 cmp(FieldOperand(object, HeapObject::kMapOffset), | |
| 888 isolate()->factory()->heap_number_map()); | |
| 889 Check(equal, kOperandNotANumber); | |
| 890 bind(&ok); | |
| 891 } | |
| 892 } | |
| 893 | |
| 894 void MacroAssembler::AssertNotNumber(Register object) { | |
| 895 if (emit_debug_code()) { | |
| 896 test(object, Immediate(kSmiTagMask)); | |
| 897 Check(not_equal, kOperandIsANumber); | |
| 898 cmp(FieldOperand(object, HeapObject::kMapOffset), | |
| 899 isolate()->factory()->heap_number_map()); | |
| 900 Check(not_equal, kOperandIsANumber); | |
| 901 } | |
| 902 } | |
| 903 | |
| 904 void MacroAssembler::AssertSmi(Register object) { | 817 void MacroAssembler::AssertSmi(Register object) { |
| 905 if (emit_debug_code()) { | 818 if (emit_debug_code()) { |
| 906 test(object, Immediate(kSmiTagMask)); | 819 test(object, Immediate(kSmiTagMask)); |
| 907 Check(equal, kOperandIsNotASmi); | 820 Check(equal, kOperandIsNotASmi); |
| 908 } | 821 } |
| 909 } | 822 } |
| 910 | 823 |
| 911 | 824 |
| 912 void MacroAssembler::AssertString(Register object) { | |
| 913 if (emit_debug_code()) { | |
| 914 test(object, Immediate(kSmiTagMask)); | |
| 915 Check(not_equal, kOperandIsASmiAndNotAString); | |
| 916 push(object); | |
| 917 mov(object, FieldOperand(object, HeapObject::kMapOffset)); | |
| 918 CmpInstanceType(object, FIRST_NONSTRING_TYPE); | |
| 919 pop(object); | |
| 920 Check(below, kOperandIsNotAString); | |
| 921 } | |
| 922 } | |
| 923 | |
| 924 | |
| 925 void MacroAssembler::AssertName(Register object) { | |
| 926 if (emit_debug_code()) { | |
| 927 test(object, Immediate(kSmiTagMask)); | |
| 928 Check(not_equal, kOperandIsASmiAndNotAName); | |
| 929 push(object); | |
| 930 mov(object, FieldOperand(object, HeapObject::kMapOffset)); | |
| 931 CmpInstanceType(object, LAST_NAME_TYPE); | |
| 932 pop(object); | |
| 933 Check(below_equal, kOperandIsNotAName); | |
| 934 } | |
| 935 } | |
| 936 | |
| 937 | |
| 938 void MacroAssembler::AssertFunction(Register object) { | 825 void MacroAssembler::AssertFunction(Register object) { |
| 939 if (emit_debug_code()) { | 826 if (emit_debug_code()) { |
| 940 test(object, Immediate(kSmiTagMask)); | 827 test(object, Immediate(kSmiTagMask)); |
| 941 Check(not_equal, kOperandIsASmiAndNotAFunction); | 828 Check(not_equal, kOperandIsASmiAndNotAFunction); |
| 942 Push(object); | 829 Push(object); |
| 943 CmpObjectType(object, JS_FUNCTION_TYPE, object); | 830 CmpObjectType(object, JS_FUNCTION_TYPE, object); |
| 944 Pop(object); | 831 Pop(object); |
| 945 Check(equal, kOperandIsNotAFunction); | 832 Check(equal, kOperandIsNotAFunction); |
| 946 } | 833 } |
| 947 } | 834 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 962 if (emit_debug_code()) { | 849 if (emit_debug_code()) { |
| 963 test(object, Immediate(kSmiTagMask)); | 850 test(object, Immediate(kSmiTagMask)); |
| 964 Check(not_equal, kOperandIsASmiAndNotAGeneratorObject); | 851 Check(not_equal, kOperandIsASmiAndNotAGeneratorObject); |
| 965 Push(object); | 852 Push(object); |
| 966 CmpObjectType(object, JS_GENERATOR_OBJECT_TYPE, object); | 853 CmpObjectType(object, JS_GENERATOR_OBJECT_TYPE, object); |
| 967 Pop(object); | 854 Pop(object); |
| 968 Check(equal, kOperandIsNotAGeneratorObject); | 855 Check(equal, kOperandIsNotAGeneratorObject); |
| 969 } | 856 } |
| 970 } | 857 } |
| 971 | 858 |
| 972 void MacroAssembler::AssertReceiver(Register object) { | |
| 973 if (emit_debug_code()) { | |
| 974 test(object, Immediate(kSmiTagMask)); | |
| 975 Check(not_equal, kOperandIsASmiAndNotAReceiver); | |
| 976 Push(object); | |
| 977 STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); | |
| 978 CmpObjectType(object, FIRST_JS_RECEIVER_TYPE, object); | |
| 979 Pop(object); | |
| 980 Check(above_equal, kOperandIsNotAReceiver); | |
| 981 } | |
| 982 } | |
| 983 | |
| 984 | |
| 985 void MacroAssembler::AssertUndefinedOrAllocationSite(Register object) { | 859 void MacroAssembler::AssertUndefinedOrAllocationSite(Register object) { |
| 986 if (emit_debug_code()) { | 860 if (emit_debug_code()) { |
| 987 Label done_checking; | 861 Label done_checking; |
| 988 AssertNotSmi(object); | 862 AssertNotSmi(object); |
| 989 cmp(object, isolate()->factory()->undefined_value()); | 863 cmp(object, isolate()->factory()->undefined_value()); |
| 990 j(equal, &done_checking); | 864 j(equal, &done_checking); |
| 991 cmp(FieldOperand(object, 0), | 865 cmp(FieldOperand(object, 0), |
| 992 Immediate(isolate()->factory()->allocation_site_map())); | 866 Immediate(isolate()->factory()->allocation_site_map())); |
| 993 Assert(equal, kExpectedUndefinedOrCell); | 867 Assert(equal, kExpectedUndefinedOrCell); |
| 994 bind(&done_checking); | 868 bind(&done_checking); |
| (...skipping 646 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1641 int bit_index) { | 1515 int bit_index) { |
| 1642 bit_index += kSmiTagSize + kSmiShiftSize; | 1516 bit_index += kSmiTagSize + kSmiShiftSize; |
| 1643 DCHECK(base::bits::IsPowerOfTwo32(kBitsPerByte)); | 1517 DCHECK(base::bits::IsPowerOfTwo32(kBitsPerByte)); |
| 1644 int byte_index = bit_index / kBitsPerByte; | 1518 int byte_index = bit_index / kBitsPerByte; |
| 1645 int byte_bit_index = bit_index & (kBitsPerByte - 1); | 1519 int byte_bit_index = bit_index & (kBitsPerByte - 1); |
| 1646 test_b(FieldOperand(object, field_offset + byte_index), | 1520 test_b(FieldOperand(object, field_offset + byte_index), |
| 1647 Immediate(1 << byte_bit_index)); | 1521 Immediate(1 << byte_bit_index)); |
| 1648 } | 1522 } |
| 1649 | 1523 |
| 1650 | 1524 |
| 1651 | |
| 1652 void MacroAssembler::NegativeZeroTest(Register result, | |
| 1653 Register op, | |
| 1654 Label* then_label) { | |
| 1655 Label ok; | |
| 1656 test(result, result); | |
| 1657 j(not_zero, &ok, Label::kNear); | |
| 1658 test(op, op); | |
| 1659 j(sign, then_label, Label::kNear); | |
| 1660 bind(&ok); | |
| 1661 } | |
| 1662 | |
| 1663 | |
| 1664 void MacroAssembler::NegativeZeroTest(Register result, | |
| 1665 Register op1, | |
| 1666 Register op2, | |
| 1667 Register scratch, | |
| 1668 Label* then_label) { | |
| 1669 Label ok; | |
| 1670 test(result, result); | |
| 1671 j(not_zero, &ok, Label::kNear); | |
| 1672 mov(scratch, op1); | |
| 1673 or_(scratch, op2); | |
| 1674 j(sign, then_label, Label::kNear); | |
| 1675 bind(&ok); | |
| 1676 } | |
| 1677 | |
| 1678 | |
| 1679 void MacroAssembler::CallStub(CodeStub* stub, TypeFeedbackId ast_id) { | 1525 void MacroAssembler::CallStub(CodeStub* stub, TypeFeedbackId ast_id) { |
| 1680 DCHECK(AllowThisStubCall(stub)); // Calls are not allowed in some stubs. | 1526 DCHECK(AllowThisStubCall(stub)); // Calls are not allowed in some stubs. |
| 1681 call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id); | 1527 call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id); |
| 1682 } | 1528 } |
| 1683 | 1529 |
| 1684 | 1530 |
| 1685 void MacroAssembler::TailCallStub(CodeStub* stub) { | 1531 void MacroAssembler::TailCallStub(CodeStub* stub) { |
| 1686 jmp(stub->GetCode(), RelocInfo::CODE_TARGET); | 1532 jmp(stub->GetCode(), RelocInfo::CODE_TARGET); |
| 1687 } | 1533 } |
| 1688 | 1534 |
| 1689 | 1535 |
| 1690 void MacroAssembler::StubReturn(int argc) { | |
| 1691 DCHECK(argc >= 1 && generating_stub()); | |
| 1692 ret((argc - 1) * kPointerSize); | |
| 1693 } | |
| 1694 | |
| 1695 | 1536 |
| 1696 bool MacroAssembler::AllowThisStubCall(CodeStub* stub) { | 1537 bool MacroAssembler::AllowThisStubCall(CodeStub* stub) { |
| 1697 return has_frame_ || !stub->SometimesSetsUpAFrame(); | 1538 return has_frame_ || !stub->SometimesSetsUpAFrame(); |
| 1698 } | 1539 } |
| 1699 | 1540 |
| 1700 void MacroAssembler::CallRuntime(const Runtime::Function* f, | 1541 void MacroAssembler::CallRuntime(const Runtime::Function* f, |
| 1701 int num_arguments, | 1542 int num_arguments, |
| 1702 SaveFPRegsMode save_doubles) { | 1543 SaveFPRegsMode save_doubles) { |
| 1703 // If the expected number of arguments of the runtime function is | 1544 // If the expected number of arguments of the runtime function is |
| 1704 // constant, we check that the actual number of arguments match the | 1545 // constant, we check that the actual number of arguments match the |
| (...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2124 mov(result, object); | 1965 mov(result, object); |
| 2125 } | 1966 } |
| 2126 | 1967 |
| 2127 | 1968 |
| 2128 void MacroAssembler::CmpHeapObject(Register reg, Handle<HeapObject> object) { | 1969 void MacroAssembler::CmpHeapObject(Register reg, Handle<HeapObject> object) { |
| 2129 cmp(reg, object); | 1970 cmp(reg, object); |
| 2130 } | 1971 } |
| 2131 | 1972 |
| 2132 void MacroAssembler::PushHeapObject(Handle<HeapObject> object) { Push(object); } | 1973 void MacroAssembler::PushHeapObject(Handle<HeapObject> object) { Push(object); } |
| 2133 | 1974 |
| 2134 void MacroAssembler::CmpWeakValue(Register value, Handle<WeakCell> cell, | |
| 2135 Register scratch) { | |
| 2136 mov(scratch, cell); | |
| 2137 cmp(value, FieldOperand(scratch, WeakCell::kValueOffset)); | |
| 2138 } | |
| 2139 | |
| 2140 | |
| 2141 void MacroAssembler::GetWeakValue(Register value, Handle<WeakCell> cell) { | 1975 void MacroAssembler::GetWeakValue(Register value, Handle<WeakCell> cell) { |
| 2142 mov(value, cell); | 1976 mov(value, cell); |
| 2143 mov(value, FieldOperand(value, WeakCell::kValueOffset)); | 1977 mov(value, FieldOperand(value, WeakCell::kValueOffset)); |
| 2144 } | 1978 } |
| 2145 | 1979 |
| 2146 | 1980 |
| 2147 void MacroAssembler::LoadWeakValue(Register value, Handle<WeakCell> cell, | 1981 void MacroAssembler::LoadWeakValue(Register value, Handle<WeakCell> cell, |
| 2148 Label* miss) { | 1982 Label* miss) { |
| 2149 GetWeakValue(value, cell); | 1983 GetWeakValue(value, cell); |
| 2150 JumpIfSmi(value, miss); | 1984 JumpIfSmi(value, miss); |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2403 bind(&skip); | 2237 bind(&skip); |
| 2404 } | 2238 } |
| 2405 } | 2239 } |
| 2406 | 2240 |
| 2407 | 2241 |
| 2408 void MacroAssembler::Assert(Condition cc, BailoutReason reason) { | 2242 void MacroAssembler::Assert(Condition cc, BailoutReason reason) { |
| 2409 if (emit_debug_code()) Check(cc, reason); | 2243 if (emit_debug_code()) Check(cc, reason); |
| 2410 } | 2244 } |
| 2411 | 2245 |
| 2412 | 2246 |
| 2413 void MacroAssembler::AssertFastElements(Register elements) { | |
| 2414 if (emit_debug_code()) { | |
| 2415 Factory* factory = isolate()->factory(); | |
| 2416 Label ok; | |
| 2417 cmp(FieldOperand(elements, HeapObject::kMapOffset), | |
| 2418 Immediate(factory->fixed_array_map())); | |
| 2419 j(equal, &ok); | |
| 2420 cmp(FieldOperand(elements, HeapObject::kMapOffset), | |
| 2421 Immediate(factory->fixed_double_array_map())); | |
| 2422 j(equal, &ok); | |
| 2423 cmp(FieldOperand(elements, HeapObject::kMapOffset), | |
| 2424 Immediate(factory->fixed_cow_array_map())); | |
| 2425 j(equal, &ok); | |
| 2426 Abort(kJSObjectWithFastElementsMapHasSlowElements); | |
| 2427 bind(&ok); | |
| 2428 } | |
| 2429 } | |
| 2430 | |
| 2431 | 2247 |
| 2432 void MacroAssembler::Check(Condition cc, BailoutReason reason) { | 2248 void MacroAssembler::Check(Condition cc, BailoutReason reason) { |
| 2433 Label L; | 2249 Label L; |
| 2434 j(cc, &L); | 2250 j(cc, &L); |
| 2435 Abort(reason); | 2251 Abort(reason); |
| 2436 // will not return here | 2252 // will not return here |
| 2437 bind(&L); | 2253 bind(&L); |
| 2438 } | 2254 } |
| 2439 | 2255 |
| 2440 | 2256 |
| (...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2926 mov(eax, dividend); | 2742 mov(eax, dividend); |
| 2927 shr(eax, 31); | 2743 shr(eax, 31); |
| 2928 add(edx, eax); | 2744 add(edx, eax); |
| 2929 } | 2745 } |
| 2930 | 2746 |
| 2931 | 2747 |
| 2932 } // namespace internal | 2748 } // namespace internal |
| 2933 } // namespace v8 | 2749 } // namespace v8 |
| 2934 | 2750 |
| 2935 #endif // V8_TARGET_ARCH_IA32 | 2751 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |