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_X87 | 5 #if V8_TARGET_ARCH_X87 |
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/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
313 j(not_sign, &done, Label::kNear); | 313 j(not_sign, &done, Label::kNear); |
314 ExternalReference uint32_bias = | 314 ExternalReference uint32_bias = |
315 ExternalReference::address_of_uint32_bias(); | 315 ExternalReference::address_of_uint32_bias(); |
316 fld_d(Operand::StaticVariable(uint32_bias)); | 316 fld_d(Operand::StaticVariable(uint32_bias)); |
317 faddp(1); | 317 faddp(1); |
318 bind(&done); | 318 bind(&done); |
319 add(esp, Immediate(kPointerSize)); | 319 add(esp, Immediate(kPointerSize)); |
320 } | 320 } |
321 | 321 |
322 | 322 |
323 void MacroAssembler::RecordWriteArray( | |
324 Register object, Register value, Register index, SaveFPRegsMode save_fp, | |
325 RememberedSetAction remembered_set_action, SmiCheck smi_check, | |
326 PointersToHereCheck pointers_to_here_check_for_value) { | |
327 // First, check if a write barrier is even needed. The tests below | |
328 // catch stores of Smis. | |
329 Label done; | |
330 | |
331 // Skip barrier if writing a smi. | |
332 if (smi_check == INLINE_SMI_CHECK) { | |
333 DCHECK_EQ(0, kSmiTag); | |
334 test(value, Immediate(kSmiTagMask)); | |
335 j(zero, &done); | |
336 } | |
337 | |
338 // Array access: calculate the destination address in the same manner as | |
339 // KeyedStoreIC::GenerateGeneric. Multiply a smi by 2 to get an offset | |
340 // into an array of words. | |
341 Register dst = index; | |
342 lea(dst, Operand(object, index, times_half_pointer_size, | |
343 FixedArray::kHeaderSize - kHeapObjectTag)); | |
344 | |
345 RecordWrite(object, dst, value, save_fp, remembered_set_action, | |
346 OMIT_SMI_CHECK, pointers_to_here_check_for_value); | |
347 | |
348 bind(&done); | |
349 | |
350 // Clobber clobbered input registers when running with the debug-code flag | |
351 // turned on to provoke errors. | |
352 if (emit_debug_code()) { | |
353 mov(value, Immediate(bit_cast<int32_t>(kZapValue))); | |
354 mov(index, Immediate(bit_cast<int32_t>(kZapValue))); | |
355 } | |
356 } | |
357 | |
358 | |
359 void MacroAssembler::RecordWriteField( | 323 void MacroAssembler::RecordWriteField( |
360 Register object, int offset, Register value, Register dst, | 324 Register object, int offset, Register value, Register dst, |
361 SaveFPRegsMode save_fp, RememberedSetAction remembered_set_action, | 325 SaveFPRegsMode save_fp, RememberedSetAction remembered_set_action, |
362 SmiCheck smi_check, PointersToHereCheck pointers_to_here_check_for_value) { | 326 SmiCheck smi_check, PointersToHereCheck pointers_to_here_check_for_value) { |
363 // First, check if a write barrier is even needed. The tests below | 327 // First, check if a write barrier is even needed. The tests below |
364 // catch stores of Smis. | 328 // catch stores of Smis. |
365 Label done; | 329 Label done; |
366 | 330 |
367 // Skip barrier if writing a smi. | 331 // Skip barrier if writing a smi. |
368 if (smi_check == INLINE_SMI_CHECK) { | 332 if (smi_check == INLINE_SMI_CHECK) { |
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
713 SmiCheckType smi_check_type) { | 677 SmiCheckType smi_check_type) { |
714 if (smi_check_type == DO_SMI_CHECK) { | 678 if (smi_check_type == DO_SMI_CHECK) { |
715 JumpIfSmi(obj, fail); | 679 JumpIfSmi(obj, fail); |
716 } | 680 } |
717 | 681 |
718 CompareMap(obj, map); | 682 CompareMap(obj, map); |
719 j(not_equal, fail); | 683 j(not_equal, fail); |
720 } | 684 } |
721 | 685 |
722 | 686 |
723 void MacroAssembler::DispatchWeakMap(Register obj, Register scratch1, | |
724 Register scratch2, Handle<WeakCell> cell, | |
725 Handle<Code> success, | |
726 SmiCheckType smi_check_type) { | |
727 Label fail; | |
728 if (smi_check_type == DO_SMI_CHECK) { | |
729 JumpIfSmi(obj, &fail); | |
730 } | |
731 mov(scratch1, FieldOperand(obj, HeapObject::kMapOffset)); | |
732 CmpWeakValue(scratch1, cell, scratch2); | |
733 j(equal, success); | |
734 | |
735 bind(&fail); | |
736 } | |
737 | |
738 | |
739 Condition MacroAssembler::IsObjectStringType(Register heap_object, | 687 Condition MacroAssembler::IsObjectStringType(Register heap_object, |
740 Register map, | 688 Register map, |
741 Register instance_type) { | 689 Register instance_type) { |
742 mov(map, FieldOperand(heap_object, HeapObject::kMapOffset)); | 690 mov(map, FieldOperand(heap_object, HeapObject::kMapOffset)); |
743 movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset)); | 691 movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset)); |
744 STATIC_ASSERT(kNotStringTag != 0); | 692 STATIC_ASSERT(kNotStringTag != 0); |
745 test(instance_type, Immediate(kIsNotStringMask)); | 693 test(instance_type, Immediate(kIsNotStringMask)); |
746 return zero; | 694 return zero; |
747 } | 695 } |
748 | 696 |
749 | 697 |
750 Condition MacroAssembler::IsObjectNameType(Register heap_object, | |
751 Register map, | |
752 Register instance_type) { | |
753 mov(map, FieldOperand(heap_object, HeapObject::kMapOffset)); | |
754 movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset)); | |
755 cmpb(instance_type, Immediate(LAST_NAME_TYPE)); | |
756 return below_equal; | |
757 } | |
758 | |
759 | |
760 void MacroAssembler::FCmp() { | 698 void MacroAssembler::FCmp() { |
761 fucompp(); | 699 fucompp(); |
762 push(eax); | 700 push(eax); |
763 fnstsw_ax(); | 701 fnstsw_ax(); |
764 sahf(); | 702 sahf(); |
765 pop(eax); | 703 pop(eax); |
766 } | 704 } |
767 | 705 |
768 | 706 |
769 void MacroAssembler::FXamMinusZero() { | 707 void MacroAssembler::FXamMinusZero() { |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
815 | 753 |
816 void MacroAssembler::X87SetFPUCW(int cw) { | 754 void MacroAssembler::X87SetFPUCW(int cw) { |
817 RecordComment("-- X87SetFPUCW start --"); | 755 RecordComment("-- X87SetFPUCW start --"); |
818 push(Immediate(cw)); | 756 push(Immediate(cw)); |
819 fldcw(MemOperand(esp, 0)); | 757 fldcw(MemOperand(esp, 0)); |
820 add(esp, Immediate(kPointerSize)); | 758 add(esp, Immediate(kPointerSize)); |
821 RecordComment("-- X87SetFPUCW end--"); | 759 RecordComment("-- X87SetFPUCW end--"); |
822 } | 760 } |
823 | 761 |
824 | 762 |
825 void MacroAssembler::AssertNumber(Register object) { | |
826 if (emit_debug_code()) { | |
827 Label ok; | |
828 JumpIfSmi(object, &ok); | |
829 cmp(FieldOperand(object, HeapObject::kMapOffset), | |
830 isolate()->factory()->heap_number_map()); | |
831 Check(equal, kOperandNotANumber); | |
832 bind(&ok); | |
833 } | |
834 } | |
835 | |
836 void MacroAssembler::AssertNotNumber(Register object) { | |
837 if (emit_debug_code()) { | |
838 test(object, Immediate(kSmiTagMask)); | |
839 Check(not_equal, kOperandIsANumber); | |
840 cmp(FieldOperand(object, HeapObject::kMapOffset), | |
841 isolate()->factory()->heap_number_map()); | |
842 Check(not_equal, kOperandIsANumber); | |
843 } | |
844 } | |
845 | |
846 void MacroAssembler::AssertSmi(Register object) { | 763 void MacroAssembler::AssertSmi(Register object) { |
847 if (emit_debug_code()) { | 764 if (emit_debug_code()) { |
848 test(object, Immediate(kSmiTagMask)); | 765 test(object, Immediate(kSmiTagMask)); |
849 Check(equal, kOperandIsNotASmi); | 766 Check(equal, kOperandIsNotASmi); |
850 } | 767 } |
851 } | 768 } |
852 | 769 |
853 | 770 |
854 void MacroAssembler::AssertString(Register object) { | |
855 if (emit_debug_code()) { | |
856 test(object, Immediate(kSmiTagMask)); | |
857 Check(not_equal, kOperandIsASmiAndNotAString); | |
858 push(object); | |
859 mov(object, FieldOperand(object, HeapObject::kMapOffset)); | |
860 CmpInstanceType(object, FIRST_NONSTRING_TYPE); | |
861 pop(object); | |
862 Check(below, kOperandIsNotAString); | |
863 } | |
864 } | |
865 | |
866 | |
867 void MacroAssembler::AssertName(Register object) { | |
868 if (emit_debug_code()) { | |
869 test(object, Immediate(kSmiTagMask)); | |
870 Check(not_equal, kOperandIsASmiAndNotAName); | |
871 push(object); | |
872 mov(object, FieldOperand(object, HeapObject::kMapOffset)); | |
873 CmpInstanceType(object, LAST_NAME_TYPE); | |
874 pop(object); | |
875 Check(below_equal, kOperandIsNotAName); | |
876 } | |
877 } | |
878 | |
879 | |
880 void MacroAssembler::AssertFunction(Register object) { | 771 void MacroAssembler::AssertFunction(Register object) { |
881 if (emit_debug_code()) { | 772 if (emit_debug_code()) { |
882 test(object, Immediate(kSmiTagMask)); | 773 test(object, Immediate(kSmiTagMask)); |
883 Check(not_equal, kOperandIsASmiAndNotAFunction); | 774 Check(not_equal, kOperandIsASmiAndNotAFunction); |
884 Push(object); | 775 Push(object); |
885 CmpObjectType(object, JS_FUNCTION_TYPE, object); | 776 CmpObjectType(object, JS_FUNCTION_TYPE, object); |
886 Pop(object); | 777 Pop(object); |
887 Check(equal, kOperandIsNotAFunction); | 778 Check(equal, kOperandIsNotAFunction); |
888 } | 779 } |
889 } | 780 } |
(...skipping 14 matching lines...) Expand all Loading... |
904 if (emit_debug_code()) { | 795 if (emit_debug_code()) { |
905 test(object, Immediate(kSmiTagMask)); | 796 test(object, Immediate(kSmiTagMask)); |
906 Check(not_equal, kOperandIsASmiAndNotAGeneratorObject); | 797 Check(not_equal, kOperandIsASmiAndNotAGeneratorObject); |
907 Push(object); | 798 Push(object); |
908 CmpObjectType(object, JS_GENERATOR_OBJECT_TYPE, object); | 799 CmpObjectType(object, JS_GENERATOR_OBJECT_TYPE, object); |
909 Pop(object); | 800 Pop(object); |
910 Check(equal, kOperandIsNotAGeneratorObject); | 801 Check(equal, kOperandIsNotAGeneratorObject); |
911 } | 802 } |
912 } | 803 } |
913 | 804 |
914 void MacroAssembler::AssertReceiver(Register object) { | |
915 if (emit_debug_code()) { | |
916 test(object, Immediate(kSmiTagMask)); | |
917 Check(not_equal, kOperandIsASmiAndNotAReceiver); | |
918 Push(object); | |
919 STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); | |
920 CmpObjectType(object, FIRST_JS_RECEIVER_TYPE, object); | |
921 Pop(object); | |
922 Check(above_equal, kOperandIsNotAReceiver); | |
923 } | |
924 } | |
925 | |
926 void MacroAssembler::AssertUndefinedOrAllocationSite(Register object) { | 805 void MacroAssembler::AssertUndefinedOrAllocationSite(Register object) { |
927 if (emit_debug_code()) { | 806 if (emit_debug_code()) { |
928 Label done_checking; | 807 Label done_checking; |
929 AssertNotSmi(object); | 808 AssertNotSmi(object); |
930 cmp(object, isolate()->factory()->undefined_value()); | 809 cmp(object, isolate()->factory()->undefined_value()); |
931 j(equal, &done_checking); | 810 j(equal, &done_checking); |
932 cmp(FieldOperand(object, 0), | 811 cmp(FieldOperand(object, 0), |
933 Immediate(isolate()->factory()->allocation_site_map())); | 812 Immediate(isolate()->factory()->allocation_site_map())); |
934 Assert(equal, kExpectedUndefinedOrCell); | 813 Assert(equal, kExpectedUndefinedOrCell); |
935 bind(&done_checking); | 814 bind(&done_checking); |
(...skipping 641 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1577 bit_index += kSmiTagSize + kSmiShiftSize; | 1456 bit_index += kSmiTagSize + kSmiShiftSize; |
1578 DCHECK(base::bits::IsPowerOfTwo32(kBitsPerByte)); | 1457 DCHECK(base::bits::IsPowerOfTwo32(kBitsPerByte)); |
1579 int byte_index = bit_index / kBitsPerByte; | 1458 int byte_index = bit_index / kBitsPerByte; |
1580 int byte_bit_index = bit_index & (kBitsPerByte - 1); | 1459 int byte_bit_index = bit_index & (kBitsPerByte - 1); |
1581 test_b(FieldOperand(object, field_offset + byte_index), | 1460 test_b(FieldOperand(object, field_offset + byte_index), |
1582 Immediate(1 << byte_bit_index)); | 1461 Immediate(1 << byte_bit_index)); |
1583 } | 1462 } |
1584 | 1463 |
1585 | 1464 |
1586 | 1465 |
1587 void MacroAssembler::NegativeZeroTest(Register result, | |
1588 Register op, | |
1589 Label* then_label) { | |
1590 Label ok; | |
1591 test(result, result); | |
1592 j(not_zero, &ok, Label::kNear); | |
1593 test(op, op); | |
1594 j(sign, then_label, Label::kNear); | |
1595 bind(&ok); | |
1596 } | |
1597 | |
1598 | |
1599 void MacroAssembler::NegativeZeroTest(Register result, | |
1600 Register op1, | |
1601 Register op2, | |
1602 Register scratch, | |
1603 Label* then_label) { | |
1604 Label ok; | |
1605 test(result, result); | |
1606 j(not_zero, &ok, Label::kNear); | |
1607 mov(scratch, op1); | |
1608 or_(scratch, op2); | |
1609 j(sign, then_label, Label::kNear); | |
1610 bind(&ok); | |
1611 } | |
1612 | |
1613 void MacroAssembler::CallStub(CodeStub* stub, TypeFeedbackId ast_id) { | 1466 void MacroAssembler::CallStub(CodeStub* stub, TypeFeedbackId ast_id) { |
1614 DCHECK(AllowThisStubCall(stub)); // Calls are not allowed in some stubs. | 1467 DCHECK(AllowThisStubCall(stub)); // Calls are not allowed in some stubs. |
1615 call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id); | 1468 call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id); |
1616 } | 1469 } |
1617 | 1470 |
1618 | 1471 |
1619 void MacroAssembler::TailCallStub(CodeStub* stub) { | 1472 void MacroAssembler::TailCallStub(CodeStub* stub) { |
1620 jmp(stub->GetCode(), RelocInfo::CODE_TARGET); | 1473 jmp(stub->GetCode(), RelocInfo::CODE_TARGET); |
1621 } | 1474 } |
1622 | 1475 |
1623 | 1476 |
1624 void MacroAssembler::StubReturn(int argc) { | |
1625 DCHECK(argc >= 1 && generating_stub()); | |
1626 ret((argc - 1) * kPointerSize); | |
1627 } | |
1628 | |
1629 | 1477 |
1630 bool MacroAssembler::AllowThisStubCall(CodeStub* stub) { | 1478 bool MacroAssembler::AllowThisStubCall(CodeStub* stub) { |
1631 return has_frame_ || !stub->SometimesSetsUpAFrame(); | 1479 return has_frame_ || !stub->SometimesSetsUpAFrame(); |
1632 } | 1480 } |
1633 | 1481 |
1634 void MacroAssembler::CallRuntime(const Runtime::Function* f, int num_arguments, | 1482 void MacroAssembler::CallRuntime(const Runtime::Function* f, int num_arguments, |
1635 SaveFPRegsMode save_doubles) { | 1483 SaveFPRegsMode save_doubles) { |
1636 // If the expected number of arguments of the runtime function is | 1484 // If the expected number of arguments of the runtime function is |
1637 // constant, we check that the actual number of arguments match the | 1485 // constant, we check that the actual number of arguments match the |
1638 // expectation. | 1486 // expectation. |
(...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2055 mov(result, object); | 1903 mov(result, object); |
2056 } | 1904 } |
2057 | 1905 |
2058 | 1906 |
2059 void MacroAssembler::CmpHeapObject(Register reg, Handle<HeapObject> object) { | 1907 void MacroAssembler::CmpHeapObject(Register reg, Handle<HeapObject> object) { |
2060 cmp(reg, object); | 1908 cmp(reg, object); |
2061 } | 1909 } |
2062 | 1910 |
2063 void MacroAssembler::PushHeapObject(Handle<HeapObject> object) { Push(object); } | 1911 void MacroAssembler::PushHeapObject(Handle<HeapObject> object) { Push(object); } |
2064 | 1912 |
2065 void MacroAssembler::CmpWeakValue(Register value, Handle<WeakCell> cell, | |
2066 Register scratch) { | |
2067 mov(scratch, cell); | |
2068 cmp(value, FieldOperand(scratch, WeakCell::kValueOffset)); | |
2069 } | |
2070 | |
2071 | |
2072 void MacroAssembler::GetWeakValue(Register value, Handle<WeakCell> cell) { | 1913 void MacroAssembler::GetWeakValue(Register value, Handle<WeakCell> cell) { |
2073 mov(value, cell); | 1914 mov(value, cell); |
2074 mov(value, FieldOperand(value, WeakCell::kValueOffset)); | 1915 mov(value, FieldOperand(value, WeakCell::kValueOffset)); |
2075 } | 1916 } |
2076 | 1917 |
2077 | 1918 |
2078 void MacroAssembler::LoadWeakValue(Register value, Handle<WeakCell> cell, | 1919 void MacroAssembler::LoadWeakValue(Register value, Handle<WeakCell> cell, |
2079 Label* miss) { | 1920 Label* miss) { |
2080 GetWeakValue(value, cell); | 1921 GetWeakValue(value, cell); |
2081 JumpIfSmi(value, miss); | 1922 JumpIfSmi(value, miss); |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2244 bind(&skip); | 2085 bind(&skip); |
2245 } | 2086 } |
2246 } | 2087 } |
2247 | 2088 |
2248 | 2089 |
2249 void MacroAssembler::Assert(Condition cc, BailoutReason reason) { | 2090 void MacroAssembler::Assert(Condition cc, BailoutReason reason) { |
2250 if (emit_debug_code()) Check(cc, reason); | 2091 if (emit_debug_code()) Check(cc, reason); |
2251 } | 2092 } |
2252 | 2093 |
2253 | 2094 |
2254 void MacroAssembler::AssertFastElements(Register elements) { | |
2255 if (emit_debug_code()) { | |
2256 Factory* factory = isolate()->factory(); | |
2257 Label ok; | |
2258 cmp(FieldOperand(elements, HeapObject::kMapOffset), | |
2259 Immediate(factory->fixed_array_map())); | |
2260 j(equal, &ok); | |
2261 cmp(FieldOperand(elements, HeapObject::kMapOffset), | |
2262 Immediate(factory->fixed_double_array_map())); | |
2263 j(equal, &ok); | |
2264 cmp(FieldOperand(elements, HeapObject::kMapOffset), | |
2265 Immediate(factory->fixed_cow_array_map())); | |
2266 j(equal, &ok); | |
2267 Abort(kJSObjectWithFastElementsMapHasSlowElements); | |
2268 bind(&ok); | |
2269 } | |
2270 } | |
2271 | |
2272 | 2095 |
2273 void MacroAssembler::Check(Condition cc, BailoutReason reason) { | 2096 void MacroAssembler::Check(Condition cc, BailoutReason reason) { |
2274 Label L; | 2097 Label L; |
2275 j(cc, &L); | 2098 j(cc, &L); |
2276 Abort(reason); | 2099 Abort(reason); |
2277 // will not return here | 2100 // will not return here |
2278 bind(&L); | 2101 bind(&L); |
2279 } | 2102 } |
2280 | 2103 |
2281 | 2104 |
(...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2756 mov(eax, dividend); | 2579 mov(eax, dividend); |
2757 shr(eax, 31); | 2580 shr(eax, 31); |
2758 add(edx, eax); | 2581 add(edx, eax); |
2759 } | 2582 } |
2760 | 2583 |
2761 | 2584 |
2762 } // namespace internal | 2585 } // namespace internal |
2763 } // namespace v8 | 2586 } // namespace v8 |
2764 | 2587 |
2765 #endif // V8_TARGET_ARCH_X87 | 2588 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |