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