| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 442 | 442 |
| 443 // Clobber clobbered registers when running with the debug-code flag | 443 // Clobber clobbered registers when running with the debug-code flag |
| 444 // turned on to provoke errors. | 444 // turned on to provoke errors. |
| 445 if (emit_debug_code()) { | 445 if (emit_debug_code()) { |
| 446 movq(address, BitCast<int64_t>(kZapValue), RelocInfo::NONE64); | 446 movq(address, BitCast<int64_t>(kZapValue), RelocInfo::NONE64); |
| 447 movq(value, BitCast<int64_t>(kZapValue), RelocInfo::NONE64); | 447 movq(value, BitCast<int64_t>(kZapValue), RelocInfo::NONE64); |
| 448 } | 448 } |
| 449 } | 449 } |
| 450 | 450 |
| 451 | 451 |
| 452 void MacroAssembler::Assert(Condition cc, const char* msg) { | 452 void MacroAssembler::Assert(Condition cc, BailoutReason reason) { |
| 453 if (emit_debug_code()) Check(cc, msg); | 453 if (emit_debug_code()) Check(cc, reason); |
| 454 } | 454 } |
| 455 | 455 |
| 456 | 456 |
| 457 void MacroAssembler::AssertFastElements(Register elements) { | 457 void MacroAssembler::AssertFastElements(Register elements) { |
| 458 if (emit_debug_code()) { | 458 if (emit_debug_code()) { |
| 459 Label ok; | 459 Label ok; |
| 460 CompareRoot(FieldOperand(elements, HeapObject::kMapOffset), | 460 CompareRoot(FieldOperand(elements, HeapObject::kMapOffset), |
| 461 Heap::kFixedArrayMapRootIndex); | 461 Heap::kFixedArrayMapRootIndex); |
| 462 j(equal, &ok, Label::kNear); | 462 j(equal, &ok, Label::kNear); |
| 463 CompareRoot(FieldOperand(elements, HeapObject::kMapOffset), | 463 CompareRoot(FieldOperand(elements, HeapObject::kMapOffset), |
| 464 Heap::kFixedDoubleArrayMapRootIndex); | 464 Heap::kFixedDoubleArrayMapRootIndex); |
| 465 j(equal, &ok, Label::kNear); | 465 j(equal, &ok, Label::kNear); |
| 466 CompareRoot(FieldOperand(elements, HeapObject::kMapOffset), | 466 CompareRoot(FieldOperand(elements, HeapObject::kMapOffset), |
| 467 Heap::kFixedCOWArrayMapRootIndex); | 467 Heap::kFixedCOWArrayMapRootIndex); |
| 468 j(equal, &ok, Label::kNear); | 468 j(equal, &ok, Label::kNear); |
| 469 Abort("JSObject with fast elements map has slow elements"); | 469 Abort(kJSObjectWithFastElementsMapHasSlowElements); |
| 470 bind(&ok); | 470 bind(&ok); |
| 471 } | 471 } |
| 472 } | 472 } |
| 473 | 473 |
| 474 | 474 |
| 475 void MacroAssembler::Check(Condition cc, const char* msg) { | 475 void MacroAssembler::Check(Condition cc, BailoutReason reason) { |
| 476 Label L; | 476 Label L; |
| 477 j(cc, &L, Label::kNear); | 477 j(cc, &L, Label::kNear); |
| 478 Abort(msg); | 478 Abort(reason); |
| 479 // Control will not return here. | 479 // Control will not return here. |
| 480 bind(&L); | 480 bind(&L); |
| 481 } | 481 } |
| 482 | 482 |
| 483 | 483 |
| 484 void MacroAssembler::CheckStackAlignment() { | 484 void MacroAssembler::CheckStackAlignment() { |
| 485 int frame_alignment = OS::ActivationFrameAlignment(); | 485 int frame_alignment = OS::ActivationFrameAlignment(); |
| 486 int frame_alignment_mask = frame_alignment - 1; | 486 int frame_alignment_mask = frame_alignment - 1; |
| 487 if (frame_alignment > kPointerSize) { | 487 if (frame_alignment > kPointerSize) { |
| 488 ASSERT(IsPowerOf2(frame_alignment)); | 488 ASSERT(IsPowerOf2(frame_alignment)); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 501 Label* then_label) { | 501 Label* then_label) { |
| 502 Label ok; | 502 Label ok; |
| 503 testl(result, result); | 503 testl(result, result); |
| 504 j(not_zero, &ok, Label::kNear); | 504 j(not_zero, &ok, Label::kNear); |
| 505 testl(op, op); | 505 testl(op, op); |
| 506 j(sign, then_label); | 506 j(sign, then_label); |
| 507 bind(&ok); | 507 bind(&ok); |
| 508 } | 508 } |
| 509 | 509 |
| 510 | 510 |
| 511 void MacroAssembler::Abort(const char* msg) { | 511 void MacroAssembler::Abort(BailoutReason reason) { |
| 512 // We want to pass the msg string like a smi to avoid GC | 512 // We want to pass the msg string like a smi to avoid GC |
| 513 // problems, however msg is not guaranteed to be aligned | 513 // problems, however msg is not guaranteed to be aligned |
| 514 // properly. Instead, we pass an aligned pointer that is | 514 // properly. Instead, we pass an aligned pointer that is |
| 515 // a proper v8 smi, but also pass the alignment difference | 515 // a proper v8 smi, but also pass the alignment difference |
| 516 // from the real pointer as a smi. | 516 // from the real pointer as a smi. |
| 517 const char* msg = GetBailoutReason(reason); |
| 517 intptr_t p1 = reinterpret_cast<intptr_t>(msg); | 518 intptr_t p1 = reinterpret_cast<intptr_t>(msg); |
| 518 intptr_t p0 = (p1 & ~kSmiTagMask) + kSmiTag; | 519 intptr_t p0 = (p1 & ~kSmiTagMask) + kSmiTag; |
| 519 // Note: p0 might not be a valid Smi _value_, but it has a valid Smi tag. | 520 // Note: p0 might not be a valid Smi _value_, but it has a valid Smi tag. |
| 520 ASSERT(reinterpret_cast<Object*>(p0)->IsSmi()); | 521 ASSERT(reinterpret_cast<Object*>(p0)->IsSmi()); |
| 521 #ifdef DEBUG | 522 #ifdef DEBUG |
| 522 if (msg != NULL) { | 523 if (msg != NULL) { |
| 523 RecordComment("Abort message: "); | 524 RecordComment("Abort message: "); |
| 524 RecordComment(msg); | 525 RecordComment(msg); |
| 525 } | 526 } |
| 526 #endif | 527 #endif |
| (...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 831 | 832 |
| 832 CompareRoot(return_value, Heap::kTrueValueRootIndex); | 833 CompareRoot(return_value, Heap::kTrueValueRootIndex); |
| 833 j(equal, &ok, Label::kNear); | 834 j(equal, &ok, Label::kNear); |
| 834 | 835 |
| 835 CompareRoot(return_value, Heap::kFalseValueRootIndex); | 836 CompareRoot(return_value, Heap::kFalseValueRootIndex); |
| 836 j(equal, &ok, Label::kNear); | 837 j(equal, &ok, Label::kNear); |
| 837 | 838 |
| 838 CompareRoot(return_value, Heap::kNullValueRootIndex); | 839 CompareRoot(return_value, Heap::kNullValueRootIndex); |
| 839 j(equal, &ok, Label::kNear); | 840 j(equal, &ok, Label::kNear); |
| 840 | 841 |
| 841 Abort("API call returned invalid object"); | 842 Abort(kAPICallReturnedInvalidObject); |
| 842 | 843 |
| 843 bind(&ok); | 844 bind(&ok); |
| 844 #endif | 845 #endif |
| 845 | 846 |
| 846 LeaveApiExitFrame(); | 847 LeaveApiExitFrame(); |
| 847 ret(stack_space * kPointerSize); | 848 ret(stack_space * kPointerSize); |
| 848 | 849 |
| 849 bind(&promote_scheduled_exception); | 850 bind(&promote_scheduled_exception); |
| 850 TailCallRuntime(Runtime::kPromoteScheduledException, 0, 1); | 851 TailCallRuntime(Runtime::kPromoteScheduledException, 0, 1); |
| 851 | 852 |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1031 } | 1032 } |
| 1032 | 1033 |
| 1033 | 1034 |
| 1034 void MacroAssembler::LoadSmiConstant(Register dst, Smi* source) { | 1035 void MacroAssembler::LoadSmiConstant(Register dst, Smi* source) { |
| 1035 if (emit_debug_code()) { | 1036 if (emit_debug_code()) { |
| 1036 movq(dst, | 1037 movq(dst, |
| 1037 reinterpret_cast<uint64_t>(Smi::FromInt(kSmiConstantRegisterValue)), | 1038 reinterpret_cast<uint64_t>(Smi::FromInt(kSmiConstantRegisterValue)), |
| 1038 RelocInfo::NONE64); | 1039 RelocInfo::NONE64); |
| 1039 cmpq(dst, kSmiConstantRegister); | 1040 cmpq(dst, kSmiConstantRegister); |
| 1040 if (allow_stub_calls()) { | 1041 if (allow_stub_calls()) { |
| 1041 Assert(equal, "Uninitialized kSmiConstantRegister"); | 1042 Assert(equal, kUninitializedKSmiConstantRegister); |
| 1042 } else { | 1043 } else { |
| 1043 Label ok; | 1044 Label ok; |
| 1044 j(equal, &ok, Label::kNear); | 1045 j(equal, &ok, Label::kNear); |
| 1045 int3(); | 1046 int3(); |
| 1046 bind(&ok); | 1047 bind(&ok); |
| 1047 } | 1048 } |
| 1048 } | 1049 } |
| 1049 int value = source->value(); | 1050 int value = source->value(); |
| 1050 if (value == 0) { | 1051 if (value == 0) { |
| 1051 xorl(dst, dst); | 1052 xorl(dst, dst); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1099 shl(dst, Immediate(kSmiShift)); | 1100 shl(dst, Immediate(kSmiShift)); |
| 1100 } | 1101 } |
| 1101 | 1102 |
| 1102 | 1103 |
| 1103 void MacroAssembler::Integer32ToSmiField(const Operand& dst, Register src) { | 1104 void MacroAssembler::Integer32ToSmiField(const Operand& dst, Register src) { |
| 1104 if (emit_debug_code()) { | 1105 if (emit_debug_code()) { |
| 1105 testb(dst, Immediate(0x01)); | 1106 testb(dst, Immediate(0x01)); |
| 1106 Label ok; | 1107 Label ok; |
| 1107 j(zero, &ok, Label::kNear); | 1108 j(zero, &ok, Label::kNear); |
| 1108 if (allow_stub_calls()) { | 1109 if (allow_stub_calls()) { |
| 1109 Abort("Integer32ToSmiField writing to non-smi location"); | 1110 Abort(kInteger32ToSmiFieldWritingToNonSmiLocation); |
| 1110 } else { | 1111 } else { |
| 1111 int3(); | 1112 int3(); |
| 1112 } | 1113 } |
| 1113 bind(&ok); | 1114 bind(&ok); |
| 1114 } | 1115 } |
| 1115 ASSERT(kSmiShift % kBitsPerByte == 0); | 1116 ASSERT(kSmiShift % kBitsPerByte == 0); |
| 1116 movl(Operand(dst, kSmiShift / kBitsPerByte), src); | 1117 movl(Operand(dst, kSmiShift / kBitsPerByte), src); |
| 1117 } | 1118 } |
| 1118 | 1119 |
| 1119 | 1120 |
| (...skipping 562 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1682 | 1683 |
| 1683 void MacroAssembler::SmiAdd(Register dst, | 1684 void MacroAssembler::SmiAdd(Register dst, |
| 1684 Register src1, | 1685 Register src1, |
| 1685 Register src2) { | 1686 Register src2) { |
| 1686 // No overflow checking. Use only when it's known that | 1687 // No overflow checking. Use only when it's known that |
| 1687 // overflowing is impossible. | 1688 // overflowing is impossible. |
| 1688 if (!dst.is(src1)) { | 1689 if (!dst.is(src1)) { |
| 1689 if (emit_debug_code()) { | 1690 if (emit_debug_code()) { |
| 1690 movq(kScratchRegister, src1); | 1691 movq(kScratchRegister, src1); |
| 1691 addq(kScratchRegister, src2); | 1692 addq(kScratchRegister, src2); |
| 1692 Check(no_overflow, "Smi addition overflow"); | 1693 Check(no_overflow, kSmiAdditionOverflow); |
| 1693 } | 1694 } |
| 1694 lea(dst, Operand(src1, src2, times_1, 0)); | 1695 lea(dst, Operand(src1, src2, times_1, 0)); |
| 1695 } else { | 1696 } else { |
| 1696 addq(dst, src2); | 1697 addq(dst, src2); |
| 1697 Assert(no_overflow, "Smi addition overflow"); | 1698 Assert(no_overflow, kSmiAdditionOverflow); |
| 1698 } | 1699 } |
| 1699 } | 1700 } |
| 1700 | 1701 |
| 1701 | 1702 |
| 1702 void MacroAssembler::SmiSub(Register dst, | 1703 void MacroAssembler::SmiSub(Register dst, |
| 1703 Register src1, | 1704 Register src1, |
| 1704 Register src2, | 1705 Register src2, |
| 1705 Label* on_not_smi_result, | 1706 Label* on_not_smi_result, |
| 1706 Label::Distance near_jump) { | 1707 Label::Distance near_jump) { |
| 1707 ASSERT_NOT_NULL(on_not_smi_result); | 1708 ASSERT_NOT_NULL(on_not_smi_result); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1719 | 1720 |
| 1720 | 1721 |
| 1721 void MacroAssembler::SmiSub(Register dst, Register src1, Register src2) { | 1722 void MacroAssembler::SmiSub(Register dst, Register src1, Register src2) { |
| 1722 // No overflow checking. Use only when it's known that | 1723 // No overflow checking. Use only when it's known that |
| 1723 // overflowing is impossible (e.g., subtracting two positive smis). | 1724 // overflowing is impossible (e.g., subtracting two positive smis). |
| 1724 ASSERT(!dst.is(src2)); | 1725 ASSERT(!dst.is(src2)); |
| 1725 if (!dst.is(src1)) { | 1726 if (!dst.is(src1)) { |
| 1726 movq(dst, src1); | 1727 movq(dst, src1); |
| 1727 } | 1728 } |
| 1728 subq(dst, src2); | 1729 subq(dst, src2); |
| 1729 Assert(no_overflow, "Smi subtraction overflow"); | 1730 Assert(no_overflow, kSmiSubtractionOverflow); |
| 1730 } | 1731 } |
| 1731 | 1732 |
| 1732 | 1733 |
| 1733 void MacroAssembler::SmiSub(Register dst, | 1734 void MacroAssembler::SmiSub(Register dst, |
| 1734 Register src1, | 1735 Register src1, |
| 1735 const Operand& src2, | 1736 const Operand& src2, |
| 1736 Label* on_not_smi_result, | 1737 Label* on_not_smi_result, |
| 1737 Label::Distance near_jump) { | 1738 Label::Distance near_jump) { |
| 1738 ASSERT_NOT_NULL(on_not_smi_result); | 1739 ASSERT_NOT_NULL(on_not_smi_result); |
| 1739 if (dst.is(src1)) { | 1740 if (dst.is(src1)) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1751 | 1752 |
| 1752 void MacroAssembler::SmiSub(Register dst, | 1753 void MacroAssembler::SmiSub(Register dst, |
| 1753 Register src1, | 1754 Register src1, |
| 1754 const Operand& src2) { | 1755 const Operand& src2) { |
| 1755 // No overflow checking. Use only when it's known that | 1756 // No overflow checking. Use only when it's known that |
| 1756 // overflowing is impossible (e.g., subtracting two positive smis). | 1757 // overflowing is impossible (e.g., subtracting two positive smis). |
| 1757 if (!dst.is(src1)) { | 1758 if (!dst.is(src1)) { |
| 1758 movq(dst, src1); | 1759 movq(dst, src1); |
| 1759 } | 1760 } |
| 1760 subq(dst, src2); | 1761 subq(dst, src2); |
| 1761 Assert(no_overflow, "Smi subtraction overflow"); | 1762 Assert(no_overflow, kSmiSubtractionOverflow); |
| 1762 } | 1763 } |
| 1763 | 1764 |
| 1764 | 1765 |
| 1765 void MacroAssembler::SmiMul(Register dst, | 1766 void MacroAssembler::SmiMul(Register dst, |
| 1766 Register src1, | 1767 Register src1, |
| 1767 Register src2, | 1768 Register src2, |
| 1768 Label* on_not_smi_result, | 1769 Label* on_not_smi_result, |
| 1769 Label::Distance near_jump) { | 1770 Label::Distance near_jump) { |
| 1770 ASSERT(!dst.is(src2)); | 1771 ASSERT(!dst.is(src2)); |
| 1771 ASSERT(!dst.is(kScratchRegister)); | 1772 ASSERT(!dst.is(kScratchRegister)); |
| (...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2148 Label::Distance near_jump) { | 2149 Label::Distance near_jump) { |
| 2149 ASSERT(!dst.is(kScratchRegister)); | 2150 ASSERT(!dst.is(kScratchRegister)); |
| 2150 ASSERT(!src1.is(kScratchRegister)); | 2151 ASSERT(!src1.is(kScratchRegister)); |
| 2151 ASSERT(!src2.is(kScratchRegister)); | 2152 ASSERT(!src2.is(kScratchRegister)); |
| 2152 ASSERT(!dst.is(src1)); | 2153 ASSERT(!dst.is(src1)); |
| 2153 ASSERT(!dst.is(src2)); | 2154 ASSERT(!dst.is(src2)); |
| 2154 // Both operands must not be smis. | 2155 // Both operands must not be smis. |
| 2155 #ifdef DEBUG | 2156 #ifdef DEBUG |
| 2156 if (allow_stub_calls()) { // Check contains a stub call. | 2157 if (allow_stub_calls()) { // Check contains a stub call. |
| 2157 Condition not_both_smis = NegateCondition(CheckBothSmi(src1, src2)); | 2158 Condition not_both_smis = NegateCondition(CheckBothSmi(src1, src2)); |
| 2158 Check(not_both_smis, "Both registers were smis in SelectNonSmi."); | 2159 Check(not_both_smis, kBothRegistersWereSmisInSelectNonSmi); |
| 2159 } | 2160 } |
| 2160 #endif | 2161 #endif |
| 2161 STATIC_ASSERT(kSmiTag == 0); | 2162 STATIC_ASSERT(kSmiTag == 0); |
| 2162 ASSERT_EQ(0, Smi::FromInt(0)); | 2163 ASSERT_EQ(0, Smi::FromInt(0)); |
| 2163 movl(kScratchRegister, Immediate(kSmiTagMask)); | 2164 movl(kScratchRegister, Immediate(kSmiTagMask)); |
| 2164 and_(kScratchRegister, src1); | 2165 and_(kScratchRegister, src1); |
| 2165 testl(kScratchRegister, src2); | 2166 testl(kScratchRegister, src2); |
| 2166 // If non-zero then both are smis. | 2167 // If non-zero then both are smis. |
| 2167 j(not_zero, on_not_smis, near_jump); | 2168 j(not_zero, on_not_smis, near_jump); |
| 2168 | 2169 |
| (...skipping 808 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2977 Set(result_reg, 255); | 2978 Set(result_reg, 255); |
| 2978 bind(&done); | 2979 bind(&done); |
| 2979 } | 2980 } |
| 2980 | 2981 |
| 2981 | 2982 |
| 2982 void MacroAssembler::LoadUint32(XMMRegister dst, | 2983 void MacroAssembler::LoadUint32(XMMRegister dst, |
| 2983 Register src, | 2984 Register src, |
| 2984 XMMRegister scratch) { | 2985 XMMRegister scratch) { |
| 2985 if (FLAG_debug_code) { | 2986 if (FLAG_debug_code) { |
| 2986 cmpq(src, Immediate(0xffffffff)); | 2987 cmpq(src, Immediate(0xffffffff)); |
| 2987 Assert(below_equal, "input GPR is expected to have upper32 cleared"); | 2988 Assert(below_equal, kInputGPRIsExpectedToHaveUpper32Cleared); |
| 2988 } | 2989 } |
| 2989 cvtqsi2sd(dst, src); | 2990 cvtqsi2sd(dst, src); |
| 2990 } | 2991 } |
| 2991 | 2992 |
| 2992 | 2993 |
| 2993 void MacroAssembler::LoadInstanceDescriptors(Register map, | 2994 void MacroAssembler::LoadInstanceDescriptors(Register map, |
| 2994 Register descriptors) { | 2995 Register descriptors) { |
| 2995 movq(descriptors, FieldOperand(map, Map::kDescriptorsOffset)); | 2996 movq(descriptors, FieldOperand(map, Map::kDescriptorsOffset)); |
| 2996 } | 2997 } |
| 2997 | 2998 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 3026 } | 3027 } |
| 3027 | 3028 |
| 3028 | 3029 |
| 3029 void MacroAssembler::AssertNumber(Register object) { | 3030 void MacroAssembler::AssertNumber(Register object) { |
| 3030 if (emit_debug_code()) { | 3031 if (emit_debug_code()) { |
| 3031 Label ok; | 3032 Label ok; |
| 3032 Condition is_smi = CheckSmi(object); | 3033 Condition is_smi = CheckSmi(object); |
| 3033 j(is_smi, &ok, Label::kNear); | 3034 j(is_smi, &ok, Label::kNear); |
| 3034 Cmp(FieldOperand(object, HeapObject::kMapOffset), | 3035 Cmp(FieldOperand(object, HeapObject::kMapOffset), |
| 3035 isolate()->factory()->heap_number_map()); | 3036 isolate()->factory()->heap_number_map()); |
| 3036 Check(equal, "Operand is not a number"); | 3037 Check(equal, kOperandIsNotANumber); |
| 3037 bind(&ok); | 3038 bind(&ok); |
| 3038 } | 3039 } |
| 3039 } | 3040 } |
| 3040 | 3041 |
| 3041 | 3042 |
| 3042 void MacroAssembler::AssertNotSmi(Register object) { | 3043 void MacroAssembler::AssertNotSmi(Register object) { |
| 3043 if (emit_debug_code()) { | 3044 if (emit_debug_code()) { |
| 3044 Condition is_smi = CheckSmi(object); | 3045 Condition is_smi = CheckSmi(object); |
| 3045 Check(NegateCondition(is_smi), "Operand is a smi"); | 3046 Check(NegateCondition(is_smi), kOperandIsASmi); |
| 3046 } | 3047 } |
| 3047 } | 3048 } |
| 3048 | 3049 |
| 3049 | 3050 |
| 3050 void MacroAssembler::AssertSmi(Register object) { | 3051 void MacroAssembler::AssertSmi(Register object) { |
| 3051 if (emit_debug_code()) { | 3052 if (emit_debug_code()) { |
| 3052 Condition is_smi = CheckSmi(object); | 3053 Condition is_smi = CheckSmi(object); |
| 3053 Check(is_smi, "Operand is not a smi"); | 3054 Check(is_smi, kOperandIsNotASmi); |
| 3054 } | 3055 } |
| 3055 } | 3056 } |
| 3056 | 3057 |
| 3057 | 3058 |
| 3058 void MacroAssembler::AssertSmi(const Operand& object) { | 3059 void MacroAssembler::AssertSmi(const Operand& object) { |
| 3059 if (emit_debug_code()) { | 3060 if (emit_debug_code()) { |
| 3060 Condition is_smi = CheckSmi(object); | 3061 Condition is_smi = CheckSmi(object); |
| 3061 Check(is_smi, "Operand is not a smi"); | 3062 Check(is_smi, kOperandIsNotASmi); |
| 3062 } | 3063 } |
| 3063 } | 3064 } |
| 3064 | 3065 |
| 3065 | 3066 |
| 3066 void MacroAssembler::AssertZeroExtended(Register int32_register) { | 3067 void MacroAssembler::AssertZeroExtended(Register int32_register) { |
| 3067 if (emit_debug_code()) { | 3068 if (emit_debug_code()) { |
| 3068 ASSERT(!int32_register.is(kScratchRegister)); | 3069 ASSERT(!int32_register.is(kScratchRegister)); |
| 3069 movq(kScratchRegister, 0x100000000l, RelocInfo::NONE64); | 3070 movq(kScratchRegister, 0x100000000l, RelocInfo::NONE64); |
| 3070 cmpq(kScratchRegister, int32_register); | 3071 cmpq(kScratchRegister, int32_register); |
| 3071 Check(above_equal, "32 bit value in register is not zero-extended"); | 3072 Check(above_equal, k32BitValueInRegisterIsNotZeroExtended); |
| 3072 } | 3073 } |
| 3073 } | 3074 } |
| 3074 | 3075 |
| 3075 | 3076 |
| 3076 void MacroAssembler::AssertString(Register object) { | 3077 void MacroAssembler::AssertString(Register object) { |
| 3077 if (emit_debug_code()) { | 3078 if (emit_debug_code()) { |
| 3078 testb(object, Immediate(kSmiTagMask)); | 3079 testb(object, Immediate(kSmiTagMask)); |
| 3079 Check(not_equal, "Operand is a smi and not a string"); | 3080 Check(not_equal, kOperandIsASmiAndNotAString); |
| 3080 push(object); | 3081 push(object); |
| 3081 movq(object, FieldOperand(object, HeapObject::kMapOffset)); | 3082 movq(object, FieldOperand(object, HeapObject::kMapOffset)); |
| 3082 CmpInstanceType(object, FIRST_NONSTRING_TYPE); | 3083 CmpInstanceType(object, FIRST_NONSTRING_TYPE); |
| 3083 pop(object); | 3084 pop(object); |
| 3084 Check(below, "Operand is not a string"); | 3085 Check(below, kOperandIsNotAString); |
| 3085 } | 3086 } |
| 3086 } | 3087 } |
| 3087 | 3088 |
| 3088 | 3089 |
| 3089 void MacroAssembler::AssertName(Register object) { | 3090 void MacroAssembler::AssertName(Register object) { |
| 3090 if (emit_debug_code()) { | 3091 if (emit_debug_code()) { |
| 3091 testb(object, Immediate(kSmiTagMask)); | 3092 testb(object, Immediate(kSmiTagMask)); |
| 3092 Check(not_equal, "Operand is a smi and not a name"); | 3093 Check(not_equal, kOperandIsASmiAndNotAName); |
| 3093 push(object); | 3094 push(object); |
| 3094 movq(object, FieldOperand(object, HeapObject::kMapOffset)); | 3095 movq(object, FieldOperand(object, HeapObject::kMapOffset)); |
| 3095 CmpInstanceType(object, LAST_NAME_TYPE); | 3096 CmpInstanceType(object, LAST_NAME_TYPE); |
| 3096 pop(object); | 3097 pop(object); |
| 3097 Check(below_equal, "Operand is not a name"); | 3098 Check(below_equal, kOperandIsNotAName); |
| 3098 } | 3099 } |
| 3099 } | 3100 } |
| 3100 | 3101 |
| 3101 | 3102 |
| 3102 void MacroAssembler::AssertRootValue(Register src, | 3103 void MacroAssembler::AssertRootValue(Register src, |
| 3103 Heap::RootListIndex root_value_index, | 3104 Heap::RootListIndex root_value_index, |
| 3104 const char* message) { | 3105 BailoutReason reason) { |
| 3105 if (emit_debug_code()) { | 3106 if (emit_debug_code()) { |
| 3106 ASSERT(!src.is(kScratchRegister)); | 3107 ASSERT(!src.is(kScratchRegister)); |
| 3107 LoadRoot(kScratchRegister, root_value_index); | 3108 LoadRoot(kScratchRegister, root_value_index); |
| 3108 cmpq(src, kScratchRegister); | 3109 cmpq(src, kScratchRegister); |
| 3109 Check(equal, message); | 3110 Check(equal, reason); |
| 3110 } | 3111 } |
| 3111 } | 3112 } |
| 3112 | 3113 |
| 3113 | 3114 |
| 3114 | 3115 |
| 3115 Condition MacroAssembler::IsObjectStringType(Register heap_object, | 3116 Condition MacroAssembler::IsObjectStringType(Register heap_object, |
| 3116 Register map, | 3117 Register map, |
| 3117 Register instance_type) { | 3118 Register instance_type) { |
| 3118 movq(map, FieldOperand(heap_object, HeapObject::kMapOffset)); | 3119 movq(map, FieldOperand(heap_object, HeapObject::kMapOffset)); |
| 3119 movzxbl(instance_type, FieldOperand(map, Map::kInstanceTypeOffset)); | 3120 movzxbl(instance_type, FieldOperand(map, Map::kInstanceTypeOffset)); |
| (...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3450 movq(rbp, rsp); | 3451 movq(rbp, rsp); |
| 3451 push(rsi); // Context. | 3452 push(rsi); // Context. |
| 3452 Push(Smi::FromInt(type)); | 3453 Push(Smi::FromInt(type)); |
| 3453 movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT); | 3454 movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT); |
| 3454 push(kScratchRegister); | 3455 push(kScratchRegister); |
| 3455 if (emit_debug_code()) { | 3456 if (emit_debug_code()) { |
| 3456 movq(kScratchRegister, | 3457 movq(kScratchRegister, |
| 3457 isolate()->factory()->undefined_value(), | 3458 isolate()->factory()->undefined_value(), |
| 3458 RelocInfo::EMBEDDED_OBJECT); | 3459 RelocInfo::EMBEDDED_OBJECT); |
| 3459 cmpq(Operand(rsp, 0), kScratchRegister); | 3460 cmpq(Operand(rsp, 0), kScratchRegister); |
| 3460 Check(not_equal, "code object not properly patched"); | 3461 Check(not_equal, kCodeObjectNotProperlyPatched); |
| 3461 } | 3462 } |
| 3462 } | 3463 } |
| 3463 | 3464 |
| 3464 | 3465 |
| 3465 void MacroAssembler::LeaveFrame(StackFrame::Type type) { | 3466 void MacroAssembler::LeaveFrame(StackFrame::Type type) { |
| 3466 if (emit_debug_code()) { | 3467 if (emit_debug_code()) { |
| 3467 Move(kScratchRegister, Smi::FromInt(type)); | 3468 Move(kScratchRegister, Smi::FromInt(type)); |
| 3468 cmpq(Operand(rbp, StandardFrameConstants::kMarkerOffset), kScratchRegister); | 3469 cmpq(Operand(rbp, StandardFrameConstants::kMarkerOffset), kScratchRegister); |
| 3469 Check(equal, "stack frame types must match"); | 3470 Check(equal, kStackFrameTypesMustMatch); |
| 3470 } | 3471 } |
| 3471 movq(rsp, rbp); | 3472 movq(rsp, rbp); |
| 3472 pop(rbp); | 3473 pop(rbp); |
| 3473 } | 3474 } |
| 3474 | 3475 |
| 3475 | 3476 |
| 3476 void MacroAssembler::EnterExitFramePrologue(bool save_rax) { | 3477 void MacroAssembler::EnterExitFramePrologue(bool save_rax) { |
| 3477 // Set up the frame structure on the stack. | 3478 // Set up the frame structure on the stack. |
| 3478 // All constants are relative to the frame pointer of the exit frame. | 3479 // All constants are relative to the frame pointer of the exit frame. |
| 3479 ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize); | 3480 ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize); |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3605 Label same_contexts; | 3606 Label same_contexts; |
| 3606 | 3607 |
| 3607 ASSERT(!holder_reg.is(scratch)); | 3608 ASSERT(!holder_reg.is(scratch)); |
| 3608 ASSERT(!scratch.is(kScratchRegister)); | 3609 ASSERT(!scratch.is(kScratchRegister)); |
| 3609 // Load current lexical context from the stack frame. | 3610 // Load current lexical context from the stack frame. |
| 3610 movq(scratch, Operand(rbp, StandardFrameConstants::kContextOffset)); | 3611 movq(scratch, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 3611 | 3612 |
| 3612 // When generating debug code, make sure the lexical context is set. | 3613 // When generating debug code, make sure the lexical context is set. |
| 3613 if (emit_debug_code()) { | 3614 if (emit_debug_code()) { |
| 3614 cmpq(scratch, Immediate(0)); | 3615 cmpq(scratch, Immediate(0)); |
| 3615 Check(not_equal, "we should not have an empty lexical context"); | 3616 Check(not_equal, kWeShouldNotHaveAnEmptyLexicalContext); |
| 3616 } | 3617 } |
| 3617 // Load the native context of the current context. | 3618 // Load the native context of the current context. |
| 3618 int offset = | 3619 int offset = |
| 3619 Context::kHeaderSize + Context::GLOBAL_OBJECT_INDEX * kPointerSize; | 3620 Context::kHeaderSize + Context::GLOBAL_OBJECT_INDEX * kPointerSize; |
| 3620 movq(scratch, FieldOperand(scratch, offset)); | 3621 movq(scratch, FieldOperand(scratch, offset)); |
| 3621 movq(scratch, FieldOperand(scratch, GlobalObject::kNativeContextOffset)); | 3622 movq(scratch, FieldOperand(scratch, GlobalObject::kNativeContextOffset)); |
| 3622 | 3623 |
| 3623 // Check the context is a native context. | 3624 // Check the context is a native context. |
| 3624 if (emit_debug_code()) { | 3625 if (emit_debug_code()) { |
| 3625 Cmp(FieldOperand(scratch, HeapObject::kMapOffset), | 3626 Cmp(FieldOperand(scratch, HeapObject::kMapOffset), |
| 3626 isolate()->factory()->native_context_map()); | 3627 isolate()->factory()->native_context_map()); |
| 3627 Check(equal, "JSGlobalObject::native_context should be a native context."); | 3628 Check(equal, kJSGlobalObjectNativeContextShouldBeANativeContext); |
| 3628 } | 3629 } |
| 3629 | 3630 |
| 3630 // Check if both contexts are the same. | 3631 // Check if both contexts are the same. |
| 3631 cmpq(scratch, FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset)); | 3632 cmpq(scratch, FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset)); |
| 3632 j(equal, &same_contexts); | 3633 j(equal, &same_contexts); |
| 3633 | 3634 |
| 3634 // Compare security tokens. | 3635 // Compare security tokens. |
| 3635 // Check that the security token in the calling global object is | 3636 // Check that the security token in the calling global object is |
| 3636 // compatible with the security token in the receiving global | 3637 // compatible with the security token in the receiving global |
| 3637 // object. | 3638 // object. |
| 3638 | 3639 |
| 3639 // Check the context is a native context. | 3640 // Check the context is a native context. |
| 3640 if (emit_debug_code()) { | 3641 if (emit_debug_code()) { |
| 3641 // Preserve original value of holder_reg. | 3642 // Preserve original value of holder_reg. |
| 3642 push(holder_reg); | 3643 push(holder_reg); |
| 3643 movq(holder_reg, | 3644 movq(holder_reg, |
| 3644 FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset)); | 3645 FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset)); |
| 3645 CompareRoot(holder_reg, Heap::kNullValueRootIndex); | 3646 CompareRoot(holder_reg, Heap::kNullValueRootIndex); |
| 3646 Check(not_equal, "JSGlobalProxy::context() should not be null."); | 3647 Check(not_equal, kJSGlobalProxyContextShouldNotBeNull); |
| 3647 | 3648 |
| 3648 // Read the first word and compare to native_context_map(), | 3649 // Read the first word and compare to native_context_map(), |
| 3649 movq(holder_reg, FieldOperand(holder_reg, HeapObject::kMapOffset)); | 3650 movq(holder_reg, FieldOperand(holder_reg, HeapObject::kMapOffset)); |
| 3650 CompareRoot(holder_reg, Heap::kNativeContextMapRootIndex); | 3651 CompareRoot(holder_reg, Heap::kNativeContextMapRootIndex); |
| 3651 Check(equal, "JSGlobalObject::native_context should be a native context."); | 3652 Check(equal, kJSGlobalObjectNativeContextShouldBeANativeContext); |
| 3652 pop(holder_reg); | 3653 pop(holder_reg); |
| 3653 } | 3654 } |
| 3654 | 3655 |
| 3655 movq(kScratchRegister, | 3656 movq(kScratchRegister, |
| 3656 FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset)); | 3657 FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset)); |
| 3657 int token_offset = | 3658 int token_offset = |
| 3658 Context::kHeaderSize + Context::SECURITY_TOKEN_INDEX * kPointerSize; | 3659 Context::kHeaderSize + Context::SECURITY_TOKEN_INDEX * kPointerSize; |
| 3659 movq(scratch, FieldOperand(scratch, token_offset)); | 3660 movq(scratch, FieldOperand(scratch, token_offset)); |
| 3660 cmpq(scratch, FieldOperand(kScratchRegister, token_offset)); | 3661 cmpq(scratch, FieldOperand(kScratchRegister, token_offset)); |
| 3661 j(not_equal, miss); | 3662 j(not_equal, miss); |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3787 AllocationUtils::GetAllocationTopReference(isolate(), flags); | 3788 AllocationUtils::GetAllocationTopReference(isolate(), flags); |
| 3788 | 3789 |
| 3789 // Just return if allocation top is already known. | 3790 // Just return if allocation top is already known. |
| 3790 if ((flags & RESULT_CONTAINS_TOP) != 0) { | 3791 if ((flags & RESULT_CONTAINS_TOP) != 0) { |
| 3791 // No use of scratch if allocation top is provided. | 3792 // No use of scratch if allocation top is provided. |
| 3792 ASSERT(!scratch.is_valid()); | 3793 ASSERT(!scratch.is_valid()); |
| 3793 #ifdef DEBUG | 3794 #ifdef DEBUG |
| 3794 // Assert that result actually contains top on entry. | 3795 // Assert that result actually contains top on entry. |
| 3795 Operand top_operand = ExternalOperand(allocation_top); | 3796 Operand top_operand = ExternalOperand(allocation_top); |
| 3796 cmpq(result, top_operand); | 3797 cmpq(result, top_operand); |
| 3797 Check(equal, "Unexpected allocation top"); | 3798 Check(equal, kUnexpectedAllocationTop); |
| 3798 #endif | 3799 #endif |
| 3799 return; | 3800 return; |
| 3800 } | 3801 } |
| 3801 | 3802 |
| 3802 // Move address of new object to result. Use scratch register if available, | 3803 // Move address of new object to result. Use scratch register if available, |
| 3803 // and keep address in scratch until call to UpdateAllocationTopHelper. | 3804 // and keep address in scratch until call to UpdateAllocationTopHelper. |
| 3804 if (scratch.is_valid()) { | 3805 if (scratch.is_valid()) { |
| 3805 LoadAddress(scratch, allocation_top); | 3806 LoadAddress(scratch, allocation_top); |
| 3806 movq(result, Operand(scratch, 0)); | 3807 movq(result, Operand(scratch, 0)); |
| 3807 } else { | 3808 } else { |
| 3808 Load(result, allocation_top); | 3809 Load(result, allocation_top); |
| 3809 } | 3810 } |
| 3810 } | 3811 } |
| 3811 | 3812 |
| 3812 | 3813 |
| 3813 void MacroAssembler::UpdateAllocationTopHelper(Register result_end, | 3814 void MacroAssembler::UpdateAllocationTopHelper(Register result_end, |
| 3814 Register scratch, | 3815 Register scratch, |
| 3815 AllocationFlags flags) { | 3816 AllocationFlags flags) { |
| 3816 if (emit_debug_code()) { | 3817 if (emit_debug_code()) { |
| 3817 testq(result_end, Immediate(kObjectAlignmentMask)); | 3818 testq(result_end, Immediate(kObjectAlignmentMask)); |
| 3818 Check(zero, "Unaligned allocation in new space"); | 3819 Check(zero, kUnalignedAllocationInNewSpace); |
| 3819 } | 3820 } |
| 3820 | 3821 |
| 3821 ExternalReference allocation_top = | 3822 ExternalReference allocation_top = |
| 3822 AllocationUtils::GetAllocationTopReference(isolate(), flags); | 3823 AllocationUtils::GetAllocationTopReference(isolate(), flags); |
| 3823 | 3824 |
| 3824 // Update new top. | 3825 // Update new top. |
| 3825 if (scratch.is_valid()) { | 3826 if (scratch.is_valid()) { |
| 3826 // Scratch already contains address of allocation top. | 3827 // Scratch already contains address of allocation top. |
| 3827 movq(Operand(scratch, 0), result_end); | 3828 movq(Operand(scratch, 0), result_end); |
| 3828 } else { | 3829 } else { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 3855 } | 3856 } |
| 3856 ASSERT(!result.is(result_end)); | 3857 ASSERT(!result.is(result_end)); |
| 3857 | 3858 |
| 3858 // Load address of new object into result. | 3859 // Load address of new object into result. |
| 3859 LoadAllocationTopHelper(result, scratch, flags); | 3860 LoadAllocationTopHelper(result, scratch, flags); |
| 3860 | 3861 |
| 3861 // Align the next allocation. Storing the filler map without checking top is | 3862 // Align the next allocation. Storing the filler map without checking top is |
| 3862 // always safe because the limit of the heap is always aligned. | 3863 // always safe because the limit of the heap is always aligned. |
| 3863 if (((flags & DOUBLE_ALIGNMENT) != 0) && FLAG_debug_code) { | 3864 if (((flags & DOUBLE_ALIGNMENT) != 0) && FLAG_debug_code) { |
| 3864 testq(result, Immediate(kDoubleAlignmentMask)); | 3865 testq(result, Immediate(kDoubleAlignmentMask)); |
| 3865 Check(zero, "Allocation is not double aligned"); | 3866 Check(zero, kAllocationIsNotDoubleAligned); |
| 3866 } | 3867 } |
| 3867 | 3868 |
| 3868 // Calculate new top and bail out if new space is exhausted. | 3869 // Calculate new top and bail out if new space is exhausted. |
| 3869 ExternalReference allocation_limit = | 3870 ExternalReference allocation_limit = |
| 3870 AllocationUtils::GetAllocationLimitReference(isolate(), flags); | 3871 AllocationUtils::GetAllocationLimitReference(isolate(), flags); |
| 3871 | 3872 |
| 3872 Register top_reg = result_end.is_valid() ? result_end : result; | 3873 Register top_reg = result_end.is_valid() ? result_end : result; |
| 3873 | 3874 |
| 3874 if (!top_reg.is(result)) { | 3875 if (!top_reg.is(result)) { |
| 3875 movq(top_reg, result); | 3876 movq(top_reg, result); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3934 } | 3935 } |
| 3935 ASSERT(!result.is(result_end)); | 3936 ASSERT(!result.is(result_end)); |
| 3936 | 3937 |
| 3937 // Load address of new object into result. | 3938 // Load address of new object into result. |
| 3938 LoadAllocationTopHelper(result, scratch, flags); | 3939 LoadAllocationTopHelper(result, scratch, flags); |
| 3939 | 3940 |
| 3940 // Align the next allocation. Storing the filler map without checking top is | 3941 // Align the next allocation. Storing the filler map without checking top is |
| 3941 // always safe because the limit of the heap is always aligned. | 3942 // always safe because the limit of the heap is always aligned. |
| 3942 if (((flags & DOUBLE_ALIGNMENT) != 0) && FLAG_debug_code) { | 3943 if (((flags & DOUBLE_ALIGNMENT) != 0) && FLAG_debug_code) { |
| 3943 testq(result, Immediate(kDoubleAlignmentMask)); | 3944 testq(result, Immediate(kDoubleAlignmentMask)); |
| 3944 Check(zero, "Allocation is not double aligned"); | 3945 Check(zero, kAllocationIsNotDoubleAligned); |
| 3945 } | 3946 } |
| 3946 | 3947 |
| 3947 // Calculate new top and bail out if new space is exhausted. | 3948 // Calculate new top and bail out if new space is exhausted. |
| 3948 ExternalReference allocation_limit = | 3949 ExternalReference allocation_limit = |
| 3949 AllocationUtils::GetAllocationLimitReference(isolate(), flags); | 3950 AllocationUtils::GetAllocationLimitReference(isolate(), flags); |
| 3950 if (!object_size.is(result_end)) { | 3951 if (!object_size.is(result_end)) { |
| 3951 movq(result_end, object_size); | 3952 movq(result_end, object_size); |
| 3952 } | 3953 } |
| 3953 addq(result_end, result); | 3954 addq(result_end, result); |
| 3954 j(carry, gc_required); | 3955 j(carry, gc_required); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 3968 | 3969 |
| 3969 void MacroAssembler::UndoAllocationInNewSpace(Register object) { | 3970 void MacroAssembler::UndoAllocationInNewSpace(Register object) { |
| 3970 ExternalReference new_space_allocation_top = | 3971 ExternalReference new_space_allocation_top = |
| 3971 ExternalReference::new_space_allocation_top_address(isolate()); | 3972 ExternalReference::new_space_allocation_top_address(isolate()); |
| 3972 | 3973 |
| 3973 // Make sure the object has no tag before resetting top. | 3974 // Make sure the object has no tag before resetting top. |
| 3974 and_(object, Immediate(~kHeapObjectTagMask)); | 3975 and_(object, Immediate(~kHeapObjectTagMask)); |
| 3975 Operand top_operand = ExternalOperand(new_space_allocation_top); | 3976 Operand top_operand = ExternalOperand(new_space_allocation_top); |
| 3976 #ifdef DEBUG | 3977 #ifdef DEBUG |
| 3977 cmpq(object, top_operand); | 3978 cmpq(object, top_operand); |
| 3978 Check(below, "Undo allocation of non allocated memory"); | 3979 Check(below, kUndoAllocationOfNonAllocatedMemory); |
| 3979 #endif | 3980 #endif |
| 3980 movq(top_operand, object); | 3981 movq(top_operand, object); |
| 3981 } | 3982 } |
| 3982 | 3983 |
| 3983 | 3984 |
| 3984 void MacroAssembler::AllocateHeapNumber(Register result, | 3985 void MacroAssembler::AllocateHeapNumber(Register result, |
| 3985 Register scratch, | 3986 Register scratch, |
| 3986 Label* gc_required) { | 3987 Label* gc_required) { |
| 3987 // Allocate heap number in new space. | 3988 // Allocate heap number in new space. |
| 3988 Allocate(HeapNumber::kSize, result, scratch, no_reg, gc_required, TAG_OBJECT); | 3989 Allocate(HeapNumber::kSize, result, scratch, no_reg, gc_required, TAG_OBJECT); |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4158 // The cld() instruction must have been emitted, to set the direction flag(), | 4159 // The cld() instruction must have been emitted, to set the direction flag(), |
| 4159 // before calling this function. | 4160 // before calling this function. |
| 4160 void MacroAssembler::CopyBytes(Register destination, | 4161 void MacroAssembler::CopyBytes(Register destination, |
| 4161 Register source, | 4162 Register source, |
| 4162 Register length, | 4163 Register length, |
| 4163 int min_length, | 4164 int min_length, |
| 4164 Register scratch) { | 4165 Register scratch) { |
| 4165 ASSERT(min_length >= 0); | 4166 ASSERT(min_length >= 0); |
| 4166 if (emit_debug_code()) { | 4167 if (emit_debug_code()) { |
| 4167 cmpl(length, Immediate(min_length)); | 4168 cmpl(length, Immediate(min_length)); |
| 4168 Assert(greater_equal, "Invalid min_length"); | 4169 Assert(greater_equal, kInvalidMinLength); |
| 4169 } | 4170 } |
| 4170 Label loop, done, short_string, short_loop; | 4171 Label loop, done, short_string, short_loop; |
| 4171 | 4172 |
| 4172 const int kLongStringLimit = 20; | 4173 const int kLongStringLimit = 20; |
| 4173 if (min_length <= kLongStringLimit) { | 4174 if (min_length <= kLongStringLimit) { |
| 4174 cmpl(length, Immediate(kLongStringLimit)); | 4175 cmpl(length, Immediate(kLongStringLimit)); |
| 4175 j(less_equal, &short_string); | 4176 j(less_equal, &short_string); |
| 4176 } | 4177 } |
| 4177 | 4178 |
| 4178 ASSERT(source.is(rsi)); | 4179 ASSERT(source.is(rsi)); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4242 movq(dst, rsi); | 4243 movq(dst, rsi); |
| 4243 } | 4244 } |
| 4244 | 4245 |
| 4245 // We should not have found a with context by walking the context | 4246 // We should not have found a with context by walking the context |
| 4246 // chain (i.e., the static scope chain and runtime context chain do | 4247 // chain (i.e., the static scope chain and runtime context chain do |
| 4247 // not agree). A variable occurring in such a scope should have | 4248 // not agree). A variable occurring in such a scope should have |
| 4248 // slot type LOOKUP and not CONTEXT. | 4249 // slot type LOOKUP and not CONTEXT. |
| 4249 if (emit_debug_code()) { | 4250 if (emit_debug_code()) { |
| 4250 CompareRoot(FieldOperand(dst, HeapObject::kMapOffset), | 4251 CompareRoot(FieldOperand(dst, HeapObject::kMapOffset), |
| 4251 Heap::kWithContextMapRootIndex); | 4252 Heap::kWithContextMapRootIndex); |
| 4252 Check(not_equal, "Variable resolved to with context."); | 4253 Check(not_equal, kVariableResolvedToWithContext); |
| 4253 } | 4254 } |
| 4254 } | 4255 } |
| 4255 | 4256 |
| 4256 | 4257 |
| 4257 void MacroAssembler::LoadTransitionedArrayMapConditional( | 4258 void MacroAssembler::LoadTransitionedArrayMapConditional( |
| 4258 ElementsKind expected_kind, | 4259 ElementsKind expected_kind, |
| 4259 ElementsKind transitioned_kind, | 4260 ElementsKind transitioned_kind, |
| 4260 Register map_in_out, | 4261 Register map_in_out, |
| 4261 Register scratch, | 4262 Register scratch, |
| 4262 Label* no_map_match) { | 4263 Label* no_map_match) { |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4333 | 4334 |
| 4334 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function, | 4335 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function, |
| 4335 Register map) { | 4336 Register map) { |
| 4336 // Load the initial map. The global functions all have initial maps. | 4337 // Load the initial map. The global functions all have initial maps. |
| 4337 movq(map, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); | 4338 movq(map, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); |
| 4338 if (emit_debug_code()) { | 4339 if (emit_debug_code()) { |
| 4339 Label ok, fail; | 4340 Label ok, fail; |
| 4340 CheckMap(map, isolate()->factory()->meta_map(), &fail, DO_SMI_CHECK); | 4341 CheckMap(map, isolate()->factory()->meta_map(), &fail, DO_SMI_CHECK); |
| 4341 jmp(&ok); | 4342 jmp(&ok); |
| 4342 bind(&fail); | 4343 bind(&fail); |
| 4343 Abort("Global functions must have initial map"); | 4344 Abort(kGlobalFunctionsMustHaveInitialMap); |
| 4344 bind(&ok); | 4345 bind(&ok); |
| 4345 } | 4346 } |
| 4346 } | 4347 } |
| 4347 | 4348 |
| 4348 | 4349 |
| 4349 int MacroAssembler::ArgumentStackSlotsForCFunctionCall(int num_arguments) { | 4350 int MacroAssembler::ArgumentStackSlotsForCFunctionCall(int num_arguments) { |
| 4350 // On Windows 64 stack slots are reserved by the caller for all arguments | 4351 // On Windows 64 stack slots are reserved by the caller for all arguments |
| 4351 // including the ones passed in registers, and space is always allocated for | 4352 // including the ones passed in registers, and space is always allocated for |
| 4352 // the four register arguments even if the function takes fewer than four | 4353 // the four register arguments even if the function takes fewer than four |
| 4353 // arguments. | 4354 // arguments. |
| (...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4694 j(greater, &no_memento_available); | 4695 j(greater, &no_memento_available); |
| 4695 CompareRoot(MemOperand(scratch_reg, -AllocationMemento::kSize), | 4696 CompareRoot(MemOperand(scratch_reg, -AllocationMemento::kSize), |
| 4696 Heap::kAllocationMementoMapRootIndex); | 4697 Heap::kAllocationMementoMapRootIndex); |
| 4697 bind(&no_memento_available); | 4698 bind(&no_memento_available); |
| 4698 } | 4699 } |
| 4699 | 4700 |
| 4700 | 4701 |
| 4701 } } // namespace v8::internal | 4702 } } // namespace v8::internal |
| 4702 | 4703 |
| 4703 #endif // V8_TARGET_ARCH_X64 | 4704 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |