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 |