| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 |
| 11 // with the distribution. | 11 // with the distribution. |
| (...skipping 30 matching lines...) Expand all Loading... |
| 42 | 42 |
| 43 MacroAssembler::MacroAssembler(void* buffer, int size) | 43 MacroAssembler::MacroAssembler(void* buffer, int size) |
| 44 : Assembler(buffer, size), | 44 : Assembler(buffer, size), |
| 45 generating_stub_(false), | 45 generating_stub_(false), |
| 46 allow_stub_calls_(true), | 46 allow_stub_calls_(true), |
| 47 code_object_(Heap::undefined_value()) { | 47 code_object_(Heap::undefined_value()) { |
| 48 } | 48 } |
| 49 | 49 |
| 50 | 50 |
| 51 void MacroAssembler::LoadRoot(Register destination, Heap::RootListIndex index) { | 51 void MacroAssembler::LoadRoot(Register destination, Heap::RootListIndex index) { |
| 52 movq(destination, Operand(kRootRegister, index << kPointerSizeLog2)); | 52 movq(destination, Operand(kRootRegister, |
| 53 (index << kPointerSizeLog2) - kRootRegisterBias)); |
| 54 } |
| 55 |
| 56 |
| 57 void MacroAssembler::LoadRootIndexed(Register destination, |
| 58 Register variable_offset, |
| 59 int fixed_offset) { |
| 60 movq(destination, |
| 61 Operand(kRootRegister, |
| 62 variable_offset, times_pointer_size, |
| 63 (fixed_offset << kPointerSizeLog2) - kRootRegisterBias)); |
| 53 } | 64 } |
| 54 | 65 |
| 55 | 66 |
| 56 void MacroAssembler::StoreRoot(Register source, Heap::RootListIndex index) { | 67 void MacroAssembler::StoreRoot(Register source, Heap::RootListIndex index) { |
| 57 movq(Operand(kRootRegister, index << kPointerSizeLog2), source); | 68 movq(Operand(kRootRegister, (index << kPointerSizeLog2) - kRootRegisterBias), |
| 69 source); |
| 58 } | 70 } |
| 59 | 71 |
| 60 | 72 |
| 61 void MacroAssembler::PushRoot(Heap::RootListIndex index) { | 73 void MacroAssembler::PushRoot(Heap::RootListIndex index) { |
| 62 push(Operand(kRootRegister, index << kPointerSizeLog2)); | 74 push(Operand(kRootRegister, (index << kPointerSizeLog2) - kRootRegisterBias)); |
| 63 } | 75 } |
| 64 | 76 |
| 65 | 77 |
| 66 void MacroAssembler::CompareRoot(Register with, Heap::RootListIndex index) { | 78 void MacroAssembler::CompareRoot(Register with, Heap::RootListIndex index) { |
| 67 cmpq(with, Operand(kRootRegister, index << kPointerSizeLog2)); | 79 cmpq(with, Operand(kRootRegister, |
| 80 (index << kPointerSizeLog2) - kRootRegisterBias)); |
| 68 } | 81 } |
| 69 | 82 |
| 70 | 83 |
| 71 void MacroAssembler::CompareRoot(const Operand& with, | 84 void MacroAssembler::CompareRoot(const Operand& with, |
| 72 Heap::RootListIndex index) { | 85 Heap::RootListIndex index) { |
| 73 ASSERT(!with.AddressUsesRegister(kScratchRegister)); | 86 ASSERT(!with.AddressUsesRegister(kScratchRegister)); |
| 74 LoadRoot(kScratchRegister, index); | 87 LoadRoot(kScratchRegister, index); |
| 75 cmpq(with, kScratchRegister); | 88 cmpq(with, kScratchRegister); |
| 76 } | 89 } |
| 77 | 90 |
| 78 | 91 |
| 79 void MacroAssembler::RecordWriteHelper(Register object, | 92 void MacroAssembler::RecordWriteHelper(Register object, |
| 80 Register addr, | 93 Register addr, |
| 81 Register scratch, | 94 Register scratch, |
| 82 SaveFPRegsMode save_fp) { | 95 SaveFPRegsMode save_fp) { |
| 83 if (FLAG_debug_code) { | 96 if (emit_debug_code()) { |
| 84 // Check that the object is not in new space. | 97 // Check that the object is not in new space. |
| 85 NearLabel not_in_new_space; | 98 NearLabel not_in_new_space; |
| 86 InNewSpace(object, scratch, not_equal, ¬_in_new_space); | 99 InNewSpace(object, scratch, not_equal, ¬_in_new_space); |
| 87 Abort("new-space object passed to RecordWriteHelper"); | 100 Abort("new-space object passed to RecordWriteHelper"); |
| 88 bind(¬_in_new_space); | 101 bind(¬_in_new_space); |
| 89 } | 102 } |
| 90 | 103 |
| 91 // Load store buffer top. | 104 // Load store buffer top. |
| 92 LoadRoot(scratch, Heap::kStoreBufferTopRootIndex); | 105 LoadRoot(scratch, Heap::kStoreBufferTopRootIndex); |
| 93 // Store pointer to buffer. | 106 // Store pointer to buffer. |
| (...skipping 18 matching lines...) Expand all Loading... |
| 112 int offset, | 125 int offset, |
| 113 Register value, | 126 Register value, |
| 114 Register index, | 127 Register index, |
| 115 SaveFPRegsMode save_fp) { | 128 SaveFPRegsMode save_fp) { |
| 116 // The compiled code assumes that record write doesn't change the | 129 // The compiled code assumes that record write doesn't change the |
| 117 // context register, so we check that none of the clobbered | 130 // context register, so we check that none of the clobbered |
| 118 // registers are rsi. | 131 // registers are rsi. |
| 119 ASSERT(!object.is(rsi) && !value.is(rsi) && !index.is(rsi)); | 132 ASSERT(!object.is(rsi) && !value.is(rsi) && !index.is(rsi)); |
| 120 | 133 |
| 121 // First, check if a write barrier is even needed. The tests below | 134 // First, check if a write barrier is even needed. The tests below |
| 122 // catch stores of Smis and stores into young gen. | 135 // catch stores of smis and stores into the young generation. |
| 123 Label done; | 136 Label done; |
| 124 JumpIfSmi(value, &done); | 137 JumpIfSmi(value, &done); |
| 125 | 138 |
| 126 RecordWriteNonSmi(object, offset, value, index, save_fp); | 139 RecordWriteNonSmi(object, offset, value, index, save_fp); |
| 127 bind(&done); | 140 bind(&done); |
| 128 | 141 |
| 129 // Clobber all input registers when running with the debug-code flag | 142 // Clobber all input registers when running with the debug-code flag |
| 130 // turned on to provoke errors. This clobbering repeats the | 143 // turned on to provoke errors. This clobbering repeats the |
| 131 // clobbering done inside RecordWriteNonSmi but it's necessary to | 144 // clobbering done inside RecordWriteNonSmi but it's necessary to |
| 132 // avoid having the fast case for smis leave the registers | 145 // avoid having the fast case for smis leave the registers |
| 133 // unchanged. | 146 // unchanged. |
| 134 if (FLAG_debug_code) { | 147 if (emit_debug_code()) { |
| 135 movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE); | 148 movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE); |
| 136 movq(value, BitCast<int64_t>(kZapValue), RelocInfo::NONE); | 149 movq(value, BitCast<int64_t>(kZapValue), RelocInfo::NONE); |
| 137 movq(index, BitCast<int64_t>(kZapValue), RelocInfo::NONE); | 150 movq(index, BitCast<int64_t>(kZapValue), RelocInfo::NONE); |
| 138 } | 151 } |
| 139 } | 152 } |
| 140 | 153 |
| 141 | 154 |
| 142 void MacroAssembler::RecordWrite(Register object, | 155 void MacroAssembler::RecordWrite(Register object, |
| 143 Register address, | 156 Register address, |
| 144 Register value, | 157 Register value, |
| 145 SaveFPRegsMode save_fp) { | 158 SaveFPRegsMode save_fp) { |
| 146 // The compiled code assumes that record write doesn't change the | 159 // The compiled code assumes that record write doesn't change the |
| 147 // context register, so we check that none of the clobbered | 160 // context register, so we check that none of the clobbered |
| 148 // registers are esi. | 161 // registers are rsi. |
| 149 ASSERT(!object.is(rsi) && !value.is(rsi) && !address.is(rsi)); | 162 ASSERT(!object.is(rsi) && !value.is(rsi) && !address.is(rsi)); |
| 150 | 163 |
| 151 // First, check if a write barrier is even needed. The tests below | 164 // First, check if a write barrier is even needed. The tests below |
| 152 // catch stores of Smis and stores into young gen. | 165 // catch stores of smis and stores into the young generation. |
| 153 Label done; | 166 Label done; |
| 154 JumpIfSmi(value, &done); | 167 JumpIfSmi(value, &done); |
| 155 | 168 |
| 156 InNewSpace(object, value, equal, &done); | 169 InNewSpace(object, value, equal, &done); |
| 157 | 170 |
| 158 RecordWriteHelper(object, address, value, save_fp); | 171 RecordWriteHelper(object, address, value, save_fp); |
| 159 | 172 |
| 160 bind(&done); | 173 bind(&done); |
| 161 | 174 |
| 162 // Clobber all input registers when running with the debug-code flag | 175 // Clobber all input registers when running with the debug-code flag |
| 163 // turned on to provoke errors. | 176 // turned on to provoke errors. |
| 164 if (FLAG_debug_code) { | 177 if (emit_debug_code()) { |
| 165 movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE); | 178 movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE); |
| 166 movq(address, BitCast<int64_t>(kZapValue), RelocInfo::NONE); | 179 movq(address, BitCast<int64_t>(kZapValue), RelocInfo::NONE); |
| 167 movq(value, BitCast<int64_t>(kZapValue), RelocInfo::NONE); | 180 movq(value, BitCast<int64_t>(kZapValue), RelocInfo::NONE); |
| 168 } | 181 } |
| 169 } | 182 } |
| 170 | 183 |
| 171 | 184 |
| 172 void MacroAssembler::RecordWriteNonSmi(Register object, | 185 void MacroAssembler::RecordWriteNonSmi(Register object, |
| 173 int offset, | 186 int offset, |
| 174 Register scratch, | 187 Register scratch, |
| 175 Register index, | 188 Register index, |
| 176 SaveFPRegsMode save_fp) { | 189 SaveFPRegsMode save_fp) { |
| 177 Label done; | 190 Label done; |
| 178 | 191 |
| 179 if (FLAG_debug_code) { | 192 if (emit_debug_code()) { |
| 180 NearLabel okay; | 193 NearLabel okay; |
| 181 JumpIfNotSmi(object, &okay); | 194 JumpIfNotSmi(object, &okay); |
| 182 Abort("MacroAssembler::RecordWriteNonSmi cannot deal with smis"); | 195 Abort("MacroAssembler::RecordWriteNonSmi cannot deal with smis"); |
| 183 bind(&okay); | 196 bind(&okay); |
| 184 | 197 |
| 185 if (offset == 0) { | 198 if (offset == 0) { |
| 186 // index must be int32. | 199 // index must be int32. |
| 187 Register tmp = index.is(rax) ? rbx : rax; | 200 Register tmp = index.is(rax) ? rbx : rax; |
| 188 push(tmp); | 201 push(tmp); |
| 189 movl(tmp, index); | 202 movl(tmp, index); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 213 index, | 226 index, |
| 214 times_pointer_size, | 227 times_pointer_size, |
| 215 FixedArray::kHeaderSize)); | 228 FixedArray::kHeaderSize)); |
| 216 } | 229 } |
| 217 RecordWriteHelper(object, dst, scratch, save_fp); | 230 RecordWriteHelper(object, dst, scratch, save_fp); |
| 218 | 231 |
| 219 bind(&done); | 232 bind(&done); |
| 220 | 233 |
| 221 // Clobber all input registers when running with the debug-code flag | 234 // Clobber all input registers when running with the debug-code flag |
| 222 // turned on to provoke errors. | 235 // turned on to provoke errors. |
| 223 if (FLAG_debug_code) { | 236 if (emit_debug_code()) { |
| 224 movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE); | 237 movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE); |
| 225 movq(scratch, BitCast<int64_t>(kZapValue), RelocInfo::NONE); | 238 movq(scratch, BitCast<int64_t>(kZapValue), RelocInfo::NONE); |
| 226 movq(index, BitCast<int64_t>(kZapValue), RelocInfo::NONE); | 239 movq(index, BitCast<int64_t>(kZapValue), RelocInfo::NONE); |
| 227 } | 240 } |
| 228 } | 241 } |
| 229 | 242 |
| 230 | 243 |
| 231 void MacroAssembler::Assert(Condition cc, const char* msg) { | 244 void MacroAssembler::Assert(Condition cc, const char* msg) { |
| 232 if (FLAG_debug_code) Check(cc, msg); | 245 if (emit_debug_code()) Check(cc, msg); |
| 233 } | 246 } |
| 234 | 247 |
| 235 | 248 |
| 236 void MacroAssembler::AssertFastElements(Register elements) { | 249 void MacroAssembler::AssertFastElements(Register elements) { |
| 237 if (FLAG_debug_code) { | 250 if (emit_debug_code()) { |
| 238 NearLabel ok; | 251 NearLabel ok; |
| 239 CompareRoot(FieldOperand(elements, HeapObject::kMapOffset), | 252 CompareRoot(FieldOperand(elements, HeapObject::kMapOffset), |
| 240 Heap::kFixedArrayMapRootIndex); | 253 Heap::kFixedArrayMapRootIndex); |
| 241 j(equal, &ok); | 254 j(equal, &ok); |
| 242 CompareRoot(FieldOperand(elements, HeapObject::kMapOffset), | 255 CompareRoot(FieldOperand(elements, HeapObject::kMapOffset), |
| 243 Heap::kFixedCOWArrayMapRootIndex); | 256 Heap::kFixedCOWArrayMapRootIndex); |
| 244 j(equal, &ok); | 257 j(equal, &ok); |
| 245 Abort("JSObject with fast elements map has slow elements"); | 258 Abort("JSObject with fast elements map has slow elements"); |
| 246 bind(&ok); | 259 bind(&ok); |
| 247 } | 260 } |
| (...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 546 next_address); | 559 next_address); |
| 547 const int kLevelOffset = Offset( | 560 const int kLevelOffset = Offset( |
| 548 ExternalReference::handle_scope_level_address(), | 561 ExternalReference::handle_scope_level_address(), |
| 549 next_address); | 562 next_address); |
| 550 ExternalReference scheduled_exception_address = | 563 ExternalReference scheduled_exception_address = |
| 551 ExternalReference::scheduled_exception_address(); | 564 ExternalReference::scheduled_exception_address(); |
| 552 | 565 |
| 553 // Allocate HandleScope in callee-save registers. | 566 // Allocate HandleScope in callee-save registers. |
| 554 Register prev_next_address_reg = r14; | 567 Register prev_next_address_reg = r14; |
| 555 Register prev_limit_reg = rbx; | 568 Register prev_limit_reg = rbx; |
| 556 Register base_reg = r12; | 569 Register base_reg = r15; |
| 557 movq(base_reg, next_address); | 570 movq(base_reg, next_address); |
| 558 movq(prev_next_address_reg, Operand(base_reg, kNextOffset)); | 571 movq(prev_next_address_reg, Operand(base_reg, kNextOffset)); |
| 559 movq(prev_limit_reg, Operand(base_reg, kLimitOffset)); | 572 movq(prev_limit_reg, Operand(base_reg, kLimitOffset)); |
| 560 addl(Operand(base_reg, kLevelOffset), Immediate(1)); | 573 addl(Operand(base_reg, kLevelOffset), Immediate(1)); |
| 561 // Call the api function! | 574 // Call the api function! |
| 562 movq(rax, | 575 movq(rax, |
| 563 reinterpret_cast<int64_t>(function->address()), | 576 reinterpret_cast<int64_t>(function->address()), |
| 564 RelocInfo::RUNTIME_ENTRY); | 577 RelocInfo::RUNTIME_ENTRY); |
| 565 call(rax); | 578 call(rax); |
| 566 | 579 |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 627 | 640 |
| 628 MaybeObject* MacroAssembler::TryJumpToExternalReference( | 641 MaybeObject* MacroAssembler::TryJumpToExternalReference( |
| 629 const ExternalReference& ext, int result_size) { | 642 const ExternalReference& ext, int result_size) { |
| 630 // Set the entry point and jump to the C entry runtime stub. | 643 // Set the entry point and jump to the C entry runtime stub. |
| 631 movq(rbx, ext); | 644 movq(rbx, ext); |
| 632 CEntryStub ces(result_size); | 645 CEntryStub ces(result_size); |
| 633 return TryTailCallStub(&ces); | 646 return TryTailCallStub(&ces); |
| 634 } | 647 } |
| 635 | 648 |
| 636 | 649 |
| 637 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag) { | 650 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, |
| 651 InvokeFlag flag, |
| 652 CallWrapper* call_wrapper) { |
| 638 // Calls are not allowed in some stubs. | 653 // Calls are not allowed in some stubs. |
| 639 ASSERT(flag == JUMP_FUNCTION || allow_stub_calls()); | 654 ASSERT(flag == JUMP_FUNCTION || allow_stub_calls()); |
| 640 | 655 |
| 641 // Rely on the assertion to check that the number of provided | 656 // Rely on the assertion to check that the number of provided |
| 642 // arguments match the expected number of arguments. Fake a | 657 // arguments match the expected number of arguments. Fake a |
| 643 // parameter count to avoid emitting code to do the check. | 658 // parameter count to avoid emitting code to do the check. |
| 644 ParameterCount expected(0); | 659 ParameterCount expected(0); |
| 645 GetBuiltinEntry(rdx, id); | 660 GetBuiltinEntry(rdx, id); |
| 646 InvokeCode(rdx, expected, expected, flag); | 661 InvokeCode(rdx, expected, expected, flag, call_wrapper); |
| 647 } | 662 } |
| 648 | 663 |
| 649 | 664 |
| 650 void MacroAssembler::GetBuiltinFunction(Register target, | 665 void MacroAssembler::GetBuiltinFunction(Register target, |
| 651 Builtins::JavaScript id) { | 666 Builtins::JavaScript id) { |
| 652 // Load the builtins object into target register. | 667 // Load the builtins object into target register. |
| 653 movq(target, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); | 668 movq(target, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| 654 movq(target, FieldOperand(target, GlobalObject::kBuiltinsOffset)); | 669 movq(target, FieldOperand(target, GlobalObject::kBuiltinsOffset)); |
| 655 movq(target, FieldOperand(target, | 670 movq(target, FieldOperand(target, |
| 656 JSBuiltinsObject::OffsetOfFunctionWithId(id))); | 671 JSBuiltinsObject::OffsetOfFunctionWithId(id))); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 696 return kScratchRegister; | 711 return kScratchRegister; |
| 697 } | 712 } |
| 698 if (value == 1) { | 713 if (value == 1) { |
| 699 return kSmiConstantRegister; | 714 return kSmiConstantRegister; |
| 700 } | 715 } |
| 701 LoadSmiConstant(kScratchRegister, source); | 716 LoadSmiConstant(kScratchRegister, source); |
| 702 return kScratchRegister; | 717 return kScratchRegister; |
| 703 } | 718 } |
| 704 | 719 |
| 705 void MacroAssembler::LoadSmiConstant(Register dst, Smi* source) { | 720 void MacroAssembler::LoadSmiConstant(Register dst, Smi* source) { |
| 706 if (FLAG_debug_code) { | 721 if (emit_debug_code()) { |
| 707 movq(dst, | 722 movq(dst, |
| 708 reinterpret_cast<uint64_t>(Smi::FromInt(kSmiConstantRegisterValue)), | 723 reinterpret_cast<uint64_t>(Smi::FromInt(kSmiConstantRegisterValue)), |
| 709 RelocInfo::NONE); | 724 RelocInfo::NONE); |
| 710 cmpq(dst, kSmiConstantRegister); | 725 cmpq(dst, kSmiConstantRegister); |
| 711 if (allow_stub_calls()) { | 726 if (allow_stub_calls()) { |
| 712 Assert(equal, "Uninitialized kSmiConstantRegister"); | 727 Assert(equal, "Uninitialized kSmiConstantRegister"); |
| 713 } else { | 728 } else { |
| 714 NearLabel ok; | 729 NearLabel ok; |
| 715 j(equal, &ok); | 730 j(equal, &ok); |
| 716 int3(); | 731 int3(); |
| 717 bind(&ok); | 732 bind(&ok); |
| 718 } | 733 } |
| 719 } | 734 } |
| 720 if (source->value() == 0) { | 735 int value = source->value(); |
| 736 if (value == 0) { |
| 721 xorl(dst, dst); | 737 xorl(dst, dst); |
| 722 return; | 738 return; |
| 723 } | 739 } |
| 724 int value = source->value(); | |
| 725 bool negative = value < 0; | 740 bool negative = value < 0; |
| 726 unsigned int uvalue = negative ? -value : value; | 741 unsigned int uvalue = negative ? -value : value; |
| 727 | 742 |
| 728 switch (uvalue) { | 743 switch (uvalue) { |
| 729 case 9: | 744 case 9: |
| 730 lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_8, 0)); | 745 lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_8, 0)); |
| 731 break; | 746 break; |
| 732 case 8: | 747 case 8: |
| 733 xorl(dst, dst); | 748 xorl(dst, dst); |
| 734 lea(dst, Operand(dst, kSmiConstantRegister, times_8, 0)); | 749 lea(dst, Operand(dst, kSmiConstantRegister, times_8, 0)); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 765 void MacroAssembler::Integer32ToSmi(Register dst, Register src) { | 780 void MacroAssembler::Integer32ToSmi(Register dst, Register src) { |
| 766 ASSERT_EQ(0, kSmiTag); | 781 ASSERT_EQ(0, kSmiTag); |
| 767 if (!dst.is(src)) { | 782 if (!dst.is(src)) { |
| 768 movl(dst, src); | 783 movl(dst, src); |
| 769 } | 784 } |
| 770 shl(dst, Immediate(kSmiShift)); | 785 shl(dst, Immediate(kSmiShift)); |
| 771 } | 786 } |
| 772 | 787 |
| 773 | 788 |
| 774 void MacroAssembler::Integer32ToSmiField(const Operand& dst, Register src) { | 789 void MacroAssembler::Integer32ToSmiField(const Operand& dst, Register src) { |
| 775 if (FLAG_debug_code) { | 790 if (emit_debug_code()) { |
| 776 testb(dst, Immediate(0x01)); | 791 testb(dst, Immediate(0x01)); |
| 777 NearLabel ok; | 792 NearLabel ok; |
| 778 j(zero, &ok); | 793 j(zero, &ok); |
| 779 if (allow_stub_calls()) { | 794 if (allow_stub_calls()) { |
| 780 Abort("Integer32ToSmiField writing to non-smi location"); | 795 Abort("Integer32ToSmiField writing to non-smi location"); |
| 781 } else { | 796 } else { |
| 782 int3(); | 797 int3(); |
| 783 } | 798 } |
| 784 bind(&ok); | 799 bind(&ok); |
| 785 } | 800 } |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 826 void MacroAssembler::SmiToInteger64(Register dst, const Operand& src) { | 841 void MacroAssembler::SmiToInteger64(Register dst, const Operand& src) { |
| 827 movsxlq(dst, Operand(src, kSmiShift / kBitsPerByte)); | 842 movsxlq(dst, Operand(src, kSmiShift / kBitsPerByte)); |
| 828 } | 843 } |
| 829 | 844 |
| 830 | 845 |
| 831 void MacroAssembler::SmiTest(Register src) { | 846 void MacroAssembler::SmiTest(Register src) { |
| 832 testq(src, src); | 847 testq(src, src); |
| 833 } | 848 } |
| 834 | 849 |
| 835 | 850 |
| 836 void MacroAssembler::SmiCompare(Register dst, Register src) { | 851 void MacroAssembler::SmiCompare(Register smi1, Register smi2) { |
| 837 cmpq(dst, src); | 852 if (emit_debug_code()) { |
| 853 AbortIfNotSmi(smi1); |
| 854 AbortIfNotSmi(smi2); |
| 855 } |
| 856 cmpq(smi1, smi2); |
| 838 } | 857 } |
| 839 | 858 |
| 840 | 859 |
| 841 void MacroAssembler::SmiCompare(Register dst, Smi* src) { | 860 void MacroAssembler::SmiCompare(Register dst, Smi* src) { |
| 861 if (emit_debug_code()) { |
| 862 AbortIfNotSmi(dst); |
| 863 } |
| 864 Cmp(dst, src); |
| 865 } |
| 866 |
| 867 |
| 868 void MacroAssembler::Cmp(Register dst, Smi* src) { |
| 842 ASSERT(!dst.is(kScratchRegister)); | 869 ASSERT(!dst.is(kScratchRegister)); |
| 843 if (src->value() == 0) { | 870 if (src->value() == 0) { |
| 844 testq(dst, dst); | 871 testq(dst, dst); |
| 845 } else { | 872 } else { |
| 846 Register constant_reg = GetSmiConstant(src); | 873 Register constant_reg = GetSmiConstant(src); |
| 847 cmpq(dst, constant_reg); | 874 cmpq(dst, constant_reg); |
| 848 } | 875 } |
| 849 } | 876 } |
| 850 | 877 |
| 851 | 878 |
| 852 void MacroAssembler::SmiCompare(Register dst, const Operand& src) { | 879 void MacroAssembler::SmiCompare(Register dst, const Operand& src) { |
| 880 if (emit_debug_code()) { |
| 881 AbortIfNotSmi(dst); |
| 882 AbortIfNotSmi(src); |
| 883 } |
| 853 cmpq(dst, src); | 884 cmpq(dst, src); |
| 854 } | 885 } |
| 855 | 886 |
| 856 | 887 |
| 857 void MacroAssembler::SmiCompare(const Operand& dst, Register src) { | 888 void MacroAssembler::SmiCompare(const Operand& dst, Register src) { |
| 889 if (emit_debug_code()) { |
| 890 AbortIfNotSmi(dst); |
| 891 AbortIfNotSmi(src); |
| 892 } |
| 858 cmpq(dst, src); | 893 cmpq(dst, src); |
| 859 } | 894 } |
| 860 | 895 |
| 861 | 896 |
| 862 void MacroAssembler::SmiCompare(const Operand& dst, Smi* src) { | 897 void MacroAssembler::SmiCompare(const Operand& dst, Smi* src) { |
| 898 if (emit_debug_code()) { |
| 899 AbortIfNotSmi(dst); |
| 900 } |
| 863 cmpl(Operand(dst, kSmiShift / kBitsPerByte), Immediate(src->value())); | 901 cmpl(Operand(dst, kSmiShift / kBitsPerByte), Immediate(src->value())); |
| 864 } | 902 } |
| 865 | 903 |
| 866 | 904 |
| 905 void MacroAssembler::Cmp(const Operand& dst, Smi* src) { |
| 906 // The Operand cannot use the smi register. |
| 907 Register smi_reg = GetSmiConstant(src); |
| 908 ASSERT(!dst.AddressUsesRegister(smi_reg)); |
| 909 cmpq(dst, smi_reg); |
| 910 } |
| 911 |
| 912 |
| 867 void MacroAssembler::SmiCompareInteger32(const Operand& dst, Register src) { | 913 void MacroAssembler::SmiCompareInteger32(const Operand& dst, Register src) { |
| 868 cmpl(Operand(dst, kSmiShift / kBitsPerByte), src); | 914 cmpl(Operand(dst, kSmiShift / kBitsPerByte), src); |
| 869 } | 915 } |
| 870 | 916 |
| 871 | 917 |
| 872 void MacroAssembler::PositiveSmiTimesPowerOfTwoToInteger64(Register dst, | 918 void MacroAssembler::PositiveSmiTimesPowerOfTwoToInteger64(Register dst, |
| 873 Register src, | 919 Register src, |
| 874 int power) { | 920 int power) { |
| 875 ASSERT(power >= 0); | 921 ASSERT(power >= 0); |
| 876 ASSERT(power < 64); | 922 ASSERT(power < 64); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 910 | 956 |
| 911 Condition MacroAssembler::CheckSmi(const Operand& src) { | 957 Condition MacroAssembler::CheckSmi(const Operand& src) { |
| 912 ASSERT_EQ(0, kSmiTag); | 958 ASSERT_EQ(0, kSmiTag); |
| 913 testb(src, Immediate(kSmiTagMask)); | 959 testb(src, Immediate(kSmiTagMask)); |
| 914 return zero; | 960 return zero; |
| 915 } | 961 } |
| 916 | 962 |
| 917 | 963 |
| 918 Condition MacroAssembler::CheckNonNegativeSmi(Register src) { | 964 Condition MacroAssembler::CheckNonNegativeSmi(Register src) { |
| 919 ASSERT_EQ(0, kSmiTag); | 965 ASSERT_EQ(0, kSmiTag); |
| 920 // Make mask 0x8000000000000001 and test that both bits are zero. | 966 // Test that both bits of the mask 0x8000000000000001 are zero. |
| 921 movq(kScratchRegister, src); | 967 movq(kScratchRegister, src); |
| 922 rol(kScratchRegister, Immediate(1)); | 968 rol(kScratchRegister, Immediate(1)); |
| 923 testb(kScratchRegister, Immediate(3)); | 969 testb(kScratchRegister, Immediate(3)); |
| 924 return zero; | 970 return zero; |
| 925 } | 971 } |
| 926 | 972 |
| 927 | 973 |
| 928 Condition MacroAssembler::CheckBothSmi(Register first, Register second) { | 974 Condition MacroAssembler::CheckBothSmi(Register first, Register second) { |
| 929 if (first.is(second)) { | 975 if (first.is(second)) { |
| 930 return CheckSmi(first); | 976 return CheckSmi(first); |
| (...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1341 Move(dst, Smi::cast(*source)); | 1387 Move(dst, Smi::cast(*source)); |
| 1342 } else { | 1388 } else { |
| 1343 movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT); | 1389 movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT); |
| 1344 movq(dst, kScratchRegister); | 1390 movq(dst, kScratchRegister); |
| 1345 } | 1391 } |
| 1346 } | 1392 } |
| 1347 | 1393 |
| 1348 | 1394 |
| 1349 void MacroAssembler::Cmp(Register dst, Handle<Object> source) { | 1395 void MacroAssembler::Cmp(Register dst, Handle<Object> source) { |
| 1350 if (source->IsSmi()) { | 1396 if (source->IsSmi()) { |
| 1351 SmiCompare(dst, Smi::cast(*source)); | 1397 Cmp(dst, Smi::cast(*source)); |
| 1352 } else { | 1398 } else { |
| 1353 Move(kScratchRegister, source); | 1399 Move(kScratchRegister, source); |
| 1354 cmpq(dst, kScratchRegister); | 1400 cmpq(dst, kScratchRegister); |
| 1355 } | 1401 } |
| 1356 } | 1402 } |
| 1357 | 1403 |
| 1358 | 1404 |
| 1359 void MacroAssembler::Cmp(const Operand& dst, Handle<Object> source) { | 1405 void MacroAssembler::Cmp(const Operand& dst, Handle<Object> source) { |
| 1360 if (source->IsSmi()) { | 1406 if (source->IsSmi()) { |
| 1361 SmiCompare(dst, Smi::cast(*source)); | 1407 Cmp(dst, Smi::cast(*source)); |
| 1362 } else { | 1408 } else { |
| 1363 ASSERT(source->IsHeapObject()); | 1409 ASSERT(source->IsHeapObject()); |
| 1364 movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT); | 1410 movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT); |
| 1365 cmpq(dst, kScratchRegister); | 1411 cmpq(dst, kScratchRegister); |
| 1366 } | 1412 } |
| 1367 } | 1413 } |
| 1368 | 1414 |
| 1369 | 1415 |
| 1370 void MacroAssembler::Push(Handle<Object> source) { | 1416 void MacroAssembler::Push(Handle<Object> source) { |
| 1371 if (source->IsSmi()) { | 1417 if (source->IsSmi()) { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1413 } | 1459 } |
| 1414 | 1460 |
| 1415 | 1461 |
| 1416 void MacroAssembler::Jump(Handle<Code> code_object, RelocInfo::Mode rmode) { | 1462 void MacroAssembler::Jump(Handle<Code> code_object, RelocInfo::Mode rmode) { |
| 1417 // TODO(X64): Inline this | 1463 // TODO(X64): Inline this |
| 1418 jmp(code_object, rmode); | 1464 jmp(code_object, rmode); |
| 1419 } | 1465 } |
| 1420 | 1466 |
| 1421 | 1467 |
| 1422 void MacroAssembler::Call(ExternalReference ext) { | 1468 void MacroAssembler::Call(ExternalReference ext) { |
| 1469 #ifdef DEBUG |
| 1470 int pre_position = pc_offset(); |
| 1471 #endif |
| 1423 movq(kScratchRegister, ext); | 1472 movq(kScratchRegister, ext); |
| 1424 call(kScratchRegister); | 1473 call(kScratchRegister); |
| 1474 #ifdef DEBUG |
| 1475 int post_position = pc_offset(); |
| 1476 CHECK_EQ(pre_position + CallSize(ext), post_position); |
| 1477 #endif |
| 1425 } | 1478 } |
| 1426 | 1479 |
| 1427 | 1480 |
| 1428 void MacroAssembler::Call(Address destination, RelocInfo::Mode rmode) { | 1481 void MacroAssembler::Call(Address destination, RelocInfo::Mode rmode) { |
| 1482 #ifdef DEBUG |
| 1483 int pre_position = pc_offset(); |
| 1484 #endif |
| 1429 movq(kScratchRegister, destination, rmode); | 1485 movq(kScratchRegister, destination, rmode); |
| 1430 call(kScratchRegister); | 1486 call(kScratchRegister); |
| 1487 #ifdef DEBUG |
| 1488 int post_position = pc_offset(); |
| 1489 CHECK_EQ(pre_position + CallSize(destination, rmode), post_position); |
| 1490 #endif |
| 1431 } | 1491 } |
| 1432 | 1492 |
| 1433 | 1493 |
| 1434 void MacroAssembler::Call(Handle<Code> code_object, RelocInfo::Mode rmode) { | 1494 void MacroAssembler::Call(Handle<Code> code_object, RelocInfo::Mode rmode) { |
| 1495 #ifdef DEBUG |
| 1496 int pre_position = pc_offset(); |
| 1497 #endif |
| 1435 ASSERT(RelocInfo::IsCodeTarget(rmode)); | 1498 ASSERT(RelocInfo::IsCodeTarget(rmode)); |
| 1436 call(code_object, rmode); | 1499 call(code_object, rmode); |
| 1500 #ifdef DEBUG |
| 1501 int post_position = pc_offset(); |
| 1502 CHECK_EQ(pre_position + CallSize(code_object), post_position); |
| 1503 #endif |
| 1437 } | 1504 } |
| 1438 | 1505 |
| 1439 | 1506 |
| 1440 void MacroAssembler::Pushad() { | 1507 void MacroAssembler::Pushad() { |
| 1441 push(rax); | 1508 push(rax); |
| 1442 push(rcx); | 1509 push(rcx); |
| 1443 push(rdx); | 1510 push(rdx); |
| 1444 push(rbx); | 1511 push(rbx); |
| 1445 // Not pushing rsp or rbp. | 1512 // Not pushing rsp or rbp. |
| 1446 push(rsi); | 1513 push(rsi); |
| 1447 push(rdi); | 1514 push(rdi); |
| 1448 push(r8); | 1515 push(r8); |
| 1449 push(r9); | 1516 push(r9); |
| 1450 // r10 is kScratchRegister. | 1517 // r10 is kScratchRegister. |
| 1451 push(r11); | 1518 push(r11); |
| 1452 push(r12); | 1519 // r12 is kSmiConstantRegister. |
| 1453 // r13 is kRootRegister. | 1520 // r13 is kRootRegister. |
| 1454 push(r14); | 1521 push(r14); |
| 1455 // r15 is kSmiConstantRegister | 1522 push(r15); |
| 1456 STATIC_ASSERT(11 == kNumSafepointSavedRegisters); | 1523 STATIC_ASSERT(11 == kNumSafepointSavedRegisters); |
| 1457 // Use lea for symmetry with Popad. | 1524 // Use lea for symmetry with Popad. |
| 1458 lea(rsp, Operand(rsp, | 1525 int sp_delta = |
| 1459 -(kNumSafepointRegisters-kNumSafepointSavedRegisters) * kPointerSize)); | 1526 (kNumSafepointRegisters - kNumSafepointSavedRegisters) * kPointerSize; |
| 1527 lea(rsp, Operand(rsp, -sp_delta)); |
| 1460 } | 1528 } |
| 1461 | 1529 |
| 1462 | 1530 |
| 1463 void MacroAssembler::Popad() { | 1531 void MacroAssembler::Popad() { |
| 1464 // Popad must not change the flags, so use lea instead of addq. | 1532 // Popad must not change the flags, so use lea instead of addq. |
| 1465 lea(rsp, Operand(rsp, | 1533 int sp_delta = |
| 1466 (kNumSafepointRegisters-kNumSafepointSavedRegisters) * kPointerSize)); | 1534 (kNumSafepointRegisters - kNumSafepointSavedRegisters) * kPointerSize; |
| 1535 lea(rsp, Operand(rsp, sp_delta)); |
| 1536 pop(r15); |
| 1467 pop(r14); | 1537 pop(r14); |
| 1468 pop(r12); | |
| 1469 pop(r11); | 1538 pop(r11); |
| 1470 pop(r9); | 1539 pop(r9); |
| 1471 pop(r8); | 1540 pop(r8); |
| 1472 pop(rdi); | 1541 pop(rdi); |
| 1473 pop(rsi); | 1542 pop(rsi); |
| 1474 pop(rbx); | 1543 pop(rbx); |
| 1475 pop(rdx); | 1544 pop(rdx); |
| 1476 pop(rcx); | 1545 pop(rcx); |
| 1477 pop(rax); | 1546 pop(rax); |
| 1478 } | 1547 } |
| 1479 | 1548 |
| 1480 | 1549 |
| 1481 void MacroAssembler::Dropad() { | 1550 void MacroAssembler::Dropad() { |
| 1482 addq(rsp, Immediate(kNumSafepointRegisters * kPointerSize)); | 1551 addq(rsp, Immediate(kNumSafepointRegisters * kPointerSize)); |
| 1483 } | 1552 } |
| 1484 | 1553 |
| 1485 | 1554 |
| 1486 // Order general registers are pushed by Pushad: | 1555 // Order general registers are pushed by Pushad: |
| 1487 // rax, rcx, rdx, rbx, rsi, rdi, r8, r9, r11, r12, r14. | 1556 // rax, rcx, rdx, rbx, rsi, rdi, r8, r9, r11, r14, r15. |
| 1488 int MacroAssembler::kSafepointPushRegisterIndices[Register::kNumRegisters] = { | 1557 int MacroAssembler::kSafepointPushRegisterIndices[Register::kNumRegisters] = { |
| 1489 0, | 1558 0, |
| 1490 1, | 1559 1, |
| 1491 2, | 1560 2, |
| 1492 3, | 1561 3, |
| 1493 -1, | 1562 -1, |
| 1494 -1, | 1563 -1, |
| 1495 4, | 1564 4, |
| 1496 5, | 1565 5, |
| 1497 6, | 1566 6, |
| 1498 7, | 1567 7, |
| 1499 -1, | 1568 -1, |
| 1500 8, | 1569 8, |
| 1570 -1, |
| 1571 -1, |
| 1501 9, | 1572 9, |
| 1502 -1, | 1573 10 |
| 1503 10, | |
| 1504 -1 | |
| 1505 }; | 1574 }; |
| 1506 | 1575 |
| 1507 | 1576 |
| 1577 void MacroAssembler::StoreToSafepointRegisterSlot(Register dst, Register src) { |
| 1578 movq(SafepointRegisterSlot(dst), src); |
| 1579 } |
| 1580 |
| 1581 |
| 1582 void MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) { |
| 1583 movq(dst, SafepointRegisterSlot(src)); |
| 1584 } |
| 1585 |
| 1586 |
| 1587 Operand MacroAssembler::SafepointRegisterSlot(Register reg) { |
| 1588 return Operand(rsp, SafepointRegisterStackIndex(reg.code()) * kPointerSize); |
| 1589 } |
| 1590 |
| 1591 |
| 1508 void MacroAssembler::PushTryHandler(CodeLocation try_location, | 1592 void MacroAssembler::PushTryHandler(CodeLocation try_location, |
| 1509 HandlerType type) { | 1593 HandlerType type) { |
| 1510 // Adjust this code if not the case. | 1594 // Adjust this code if not the case. |
| 1511 ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); | 1595 ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); |
| 1512 | 1596 |
| 1513 // The pc (return address) is already on TOS. This code pushes state, | 1597 // The pc (return address) is already on TOS. This code pushes state, |
| 1514 // frame pointer and current handler. Check that they are expected | 1598 // frame pointer and current handler. Check that they are expected |
| 1515 // next on the stack, in that order. | 1599 // next on the stack, in that order. |
| 1516 ASSERT_EQ(StackHandlerConstants::kStateOffset, | 1600 ASSERT_EQ(StackHandlerConstants::kStateOffset, |
| 1517 StackHandlerConstants::kPCOffset - kPointerSize); | 1601 StackHandlerConstants::kPCOffset - kPointerSize); |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1704 | 1788 |
| 1705 | 1789 |
| 1706 void MacroAssembler::AbortIfSmi(Register object) { | 1790 void MacroAssembler::AbortIfSmi(Register object) { |
| 1707 NearLabel ok; | 1791 NearLabel ok; |
| 1708 Condition is_smi = CheckSmi(object); | 1792 Condition is_smi = CheckSmi(object); |
| 1709 Assert(NegateCondition(is_smi), "Operand is a smi"); | 1793 Assert(NegateCondition(is_smi), "Operand is a smi"); |
| 1710 } | 1794 } |
| 1711 | 1795 |
| 1712 | 1796 |
| 1713 void MacroAssembler::AbortIfNotSmi(Register object) { | 1797 void MacroAssembler::AbortIfNotSmi(Register object) { |
| 1714 NearLabel ok; | 1798 Condition is_smi = CheckSmi(object); |
| 1799 Assert(is_smi, "Operand is not a smi"); |
| 1800 } |
| 1801 |
| 1802 |
| 1803 void MacroAssembler::AbortIfNotSmi(const Operand& object) { |
| 1715 Condition is_smi = CheckSmi(object); | 1804 Condition is_smi = CheckSmi(object); |
| 1716 Assert(is_smi, "Operand is not a smi"); | 1805 Assert(is_smi, "Operand is not a smi"); |
| 1717 } | 1806 } |
| 1718 | 1807 |
| 1719 | 1808 |
| 1720 void MacroAssembler::AbortIfNotString(Register object) { | 1809 void MacroAssembler::AbortIfNotString(Register object) { |
| 1721 testb(object, Immediate(kSmiTagMask)); | 1810 testb(object, Immediate(kSmiTagMask)); |
| 1722 Assert(not_equal, "Operand is not a string"); | 1811 Assert(not_equal, "Operand is not a string"); |
| 1723 push(object); | 1812 push(object); |
| 1724 movq(object, FieldOperand(object, HeapObject::kMapOffset)); | 1813 movq(object, FieldOperand(object, HeapObject::kMapOffset)); |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1839 movq(rbx, ExternalReference(Runtime::kDebugBreak)); | 1928 movq(rbx, ExternalReference(Runtime::kDebugBreak)); |
| 1840 CEntryStub ces(1); | 1929 CEntryStub ces(1); |
| 1841 Call(ces.GetCode(), RelocInfo::DEBUG_BREAK); | 1930 Call(ces.GetCode(), RelocInfo::DEBUG_BREAK); |
| 1842 } | 1931 } |
| 1843 #endif // ENABLE_DEBUGGER_SUPPORT | 1932 #endif // ENABLE_DEBUGGER_SUPPORT |
| 1844 | 1933 |
| 1845 | 1934 |
| 1846 void MacroAssembler::InvokeCode(Register code, | 1935 void MacroAssembler::InvokeCode(Register code, |
| 1847 const ParameterCount& expected, | 1936 const ParameterCount& expected, |
| 1848 const ParameterCount& actual, | 1937 const ParameterCount& actual, |
| 1849 InvokeFlag flag) { | 1938 InvokeFlag flag, |
| 1939 CallWrapper* call_wrapper) { |
| 1850 NearLabel done; | 1940 NearLabel done; |
| 1851 InvokePrologue(expected, actual, Handle<Code>::null(), code, &done, flag); | 1941 InvokePrologue(expected, |
| 1942 actual, |
| 1943 Handle<Code>::null(), |
| 1944 code, |
| 1945 &done, |
| 1946 flag, |
| 1947 call_wrapper); |
| 1852 if (flag == CALL_FUNCTION) { | 1948 if (flag == CALL_FUNCTION) { |
| 1949 if (call_wrapper != NULL) call_wrapper->BeforeCall(CallSize(code)); |
| 1853 call(code); | 1950 call(code); |
| 1951 if (call_wrapper != NULL) call_wrapper->AfterCall(); |
| 1854 } else { | 1952 } else { |
| 1855 ASSERT(flag == JUMP_FUNCTION); | 1953 ASSERT(flag == JUMP_FUNCTION); |
| 1856 jmp(code); | 1954 jmp(code); |
| 1857 } | 1955 } |
| 1858 bind(&done); | 1956 bind(&done); |
| 1859 } | 1957 } |
| 1860 | 1958 |
| 1861 | 1959 |
| 1862 void MacroAssembler::InvokeCode(Handle<Code> code, | 1960 void MacroAssembler::InvokeCode(Handle<Code> code, |
| 1863 const ParameterCount& expected, | 1961 const ParameterCount& expected, |
| 1864 const ParameterCount& actual, | 1962 const ParameterCount& actual, |
| 1865 RelocInfo::Mode rmode, | 1963 RelocInfo::Mode rmode, |
| 1866 InvokeFlag flag) { | 1964 InvokeFlag flag, |
| 1965 CallWrapper* call_wrapper) { |
| 1867 NearLabel done; | 1966 NearLabel done; |
| 1868 Register dummy = rax; | 1967 Register dummy = rax; |
| 1869 InvokePrologue(expected, actual, code, dummy, &done, flag); | 1968 InvokePrologue(expected, |
| 1969 actual, |
| 1970 code, |
| 1971 dummy, |
| 1972 &done, |
| 1973 flag, |
| 1974 call_wrapper); |
| 1870 if (flag == CALL_FUNCTION) { | 1975 if (flag == CALL_FUNCTION) { |
| 1976 if (call_wrapper != NULL) call_wrapper->BeforeCall(CallSize(code)); |
| 1871 Call(code, rmode); | 1977 Call(code, rmode); |
| 1978 if (call_wrapper != NULL) call_wrapper->AfterCall(); |
| 1872 } else { | 1979 } else { |
| 1873 ASSERT(flag == JUMP_FUNCTION); | 1980 ASSERT(flag == JUMP_FUNCTION); |
| 1874 Jump(code, rmode); | 1981 Jump(code, rmode); |
| 1875 } | 1982 } |
| 1876 bind(&done); | 1983 bind(&done); |
| 1877 } | 1984 } |
| 1878 | 1985 |
| 1879 | 1986 |
| 1880 void MacroAssembler::InvokeFunction(Register function, | 1987 void MacroAssembler::InvokeFunction(Register function, |
| 1881 const ParameterCount& actual, | 1988 const ParameterCount& actual, |
| 1882 InvokeFlag flag) { | 1989 InvokeFlag flag, |
| 1990 CallWrapper* call_wrapper) { |
| 1883 ASSERT(function.is(rdi)); | 1991 ASSERT(function.is(rdi)); |
| 1884 movq(rdx, FieldOperand(function, JSFunction::kSharedFunctionInfoOffset)); | 1992 movq(rdx, FieldOperand(function, JSFunction::kSharedFunctionInfoOffset)); |
| 1885 movq(rsi, FieldOperand(function, JSFunction::kContextOffset)); | 1993 movq(rsi, FieldOperand(function, JSFunction::kContextOffset)); |
| 1886 movsxlq(rbx, | 1994 movsxlq(rbx, |
| 1887 FieldOperand(rdx, SharedFunctionInfo::kFormalParameterCountOffset)); | 1995 FieldOperand(rdx, SharedFunctionInfo::kFormalParameterCountOffset)); |
| 1888 // Advances rdx to the end of the Code object header, to the start of | 1996 // Advances rdx to the end of the Code object header, to the start of |
| 1889 // the executable code. | 1997 // the executable code. |
| 1890 movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); | 1998 movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); |
| 1891 | 1999 |
| 1892 ParameterCount expected(rbx); | 2000 ParameterCount expected(rbx); |
| 1893 InvokeCode(rdx, expected, actual, flag); | 2001 InvokeCode(rdx, expected, actual, flag, call_wrapper); |
| 1894 } | 2002 } |
| 1895 | 2003 |
| 1896 | 2004 |
| 1897 void MacroAssembler::InvokeFunction(JSFunction* function, | 2005 void MacroAssembler::InvokeFunction(JSFunction* function, |
| 1898 const ParameterCount& actual, | 2006 const ParameterCount& actual, |
| 1899 InvokeFlag flag) { | 2007 InvokeFlag flag, |
| 2008 CallWrapper* call_wrapper) { |
| 1900 ASSERT(function->is_compiled()); | 2009 ASSERT(function->is_compiled()); |
| 1901 // Get the function and setup the context. | 2010 // Get the function and setup the context. |
| 1902 Move(rdi, Handle<JSFunction>(function)); | 2011 Move(rdi, Handle<JSFunction>(function)); |
| 1903 movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); | 2012 movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); |
| 1904 | 2013 |
| 1905 if (V8::UseCrankshaft()) { | 2014 if (V8::UseCrankshaft()) { |
| 1906 // Since Crankshaft can recompile a function, we need to load | 2015 // Since Crankshaft can recompile a function, we need to load |
| 1907 // the Code object every time we call the function. | 2016 // the Code object every time we call the function. |
| 1908 movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); | 2017 movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); |
| 1909 ParameterCount expected(function->shared()->formal_parameter_count()); | 2018 ParameterCount expected(function->shared()->formal_parameter_count()); |
| 1910 InvokeCode(rdx, expected, actual, flag); | 2019 InvokeCode(rdx, expected, actual, flag, call_wrapper); |
| 1911 } else { | 2020 } else { |
| 1912 // Invoke the cached code. | 2021 // Invoke the cached code. |
| 1913 Handle<Code> code(function->code()); | 2022 Handle<Code> code(function->code()); |
| 1914 ParameterCount expected(function->shared()->formal_parameter_count()); | 2023 ParameterCount expected(function->shared()->formal_parameter_count()); |
| 1915 InvokeCode(code, expected, actual, RelocInfo::CODE_TARGET, flag); | 2024 InvokeCode(code, |
| 2025 expected, |
| 2026 actual, |
| 2027 RelocInfo::CODE_TARGET, |
| 2028 flag, |
| 2029 call_wrapper); |
| 1916 } | 2030 } |
| 1917 } | 2031 } |
| 1918 | 2032 |
| 1919 | 2033 |
| 1920 void MacroAssembler::EnterFrame(StackFrame::Type type) { | 2034 void MacroAssembler::EnterFrame(StackFrame::Type type) { |
| 1921 push(rbp); | 2035 push(rbp); |
| 1922 movq(rbp, rsp); | 2036 movq(rbp, rsp); |
| 1923 push(rsi); // Context. | 2037 push(rsi); // Context. |
| 1924 Push(Smi::FromInt(type)); | 2038 Push(Smi::FromInt(type)); |
| 1925 movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT); | 2039 movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT); |
| 1926 push(kScratchRegister); | 2040 push(kScratchRegister); |
| 1927 if (FLAG_debug_code) { | 2041 if (emit_debug_code()) { |
| 1928 movq(kScratchRegister, | 2042 movq(kScratchRegister, |
| 1929 Factory::undefined_value(), | 2043 Factory::undefined_value(), |
| 1930 RelocInfo::EMBEDDED_OBJECT); | 2044 RelocInfo::EMBEDDED_OBJECT); |
| 1931 cmpq(Operand(rsp, 0), kScratchRegister); | 2045 cmpq(Operand(rsp, 0), kScratchRegister); |
| 1932 Check(not_equal, "code object not properly patched"); | 2046 Check(not_equal, "code object not properly patched"); |
| 1933 } | 2047 } |
| 1934 } | 2048 } |
| 1935 | 2049 |
| 1936 | 2050 |
| 1937 void MacroAssembler::LeaveFrame(StackFrame::Type type) { | 2051 void MacroAssembler::LeaveFrame(StackFrame::Type type) { |
| 1938 if (FLAG_debug_code) { | 2052 if (emit_debug_code()) { |
| 1939 Move(kScratchRegister, Smi::FromInt(type)); | 2053 Move(kScratchRegister, Smi::FromInt(type)); |
| 1940 cmpq(Operand(rbp, StandardFrameConstants::kMarkerOffset), kScratchRegister); | 2054 cmpq(Operand(rbp, StandardFrameConstants::kMarkerOffset), kScratchRegister); |
| 1941 Check(equal, "stack frame types must match"); | 2055 Check(equal, "stack frame types must match"); |
| 1942 } | 2056 } |
| 1943 movq(rsp, rbp); | 2057 movq(rsp, rbp); |
| 1944 pop(rbp); | 2058 pop(rbp); |
| 1945 } | 2059 } |
| 1946 | 2060 |
| 1947 | 2061 |
| 1948 void MacroAssembler::EnterExitFramePrologue(bool save_rax) { | 2062 void MacroAssembler::EnterExitFramePrologue(bool save_rax) { |
| 1949 // Setup the frame structure on the stack. | 2063 // Setup the frame structure on the stack. |
| 1950 // All constants are relative to the frame pointer of the exit frame. | 2064 // All constants are relative to the frame pointer of the exit frame. |
| 1951 ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize); | 2065 ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize); |
| 1952 ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize); | 2066 ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize); |
| 1953 ASSERT(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize); | 2067 ASSERT(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize); |
| 1954 push(rbp); | 2068 push(rbp); |
| 1955 movq(rbp, rsp); | 2069 movq(rbp, rsp); |
| 1956 | 2070 |
| 1957 // Reserve room for entry stack pointer and push the code object. | 2071 // Reserve room for entry stack pointer and push the code object. |
| 1958 ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize); | 2072 ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize); |
| 1959 push(Immediate(0)); // Saved entry sp, patched before call. | 2073 push(Immediate(0)); // Saved entry sp, patched before call. |
| 1960 movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT); | 2074 movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT); |
| 1961 push(kScratchRegister); // Accessed from EditFrame::code_slot. | 2075 push(kScratchRegister); // Accessed from EditFrame::code_slot. |
| 1962 | 2076 |
| 1963 // Save the frame pointer and the context in top. | 2077 // Save the frame pointer and the context in top. |
| 1964 ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address); | |
| 1965 ExternalReference context_address(Top::k_context_address); | |
| 1966 if (save_rax) { | 2078 if (save_rax) { |
| 1967 movq(r14, rax); // Backup rax before we use it. | 2079 movq(r14, rax); // Backup rax in callee-save register. |
| 1968 } | 2080 } |
| 1969 | 2081 |
| 1970 movq(rax, rbp); | 2082 movq(kScratchRegister, ExternalReference(Top::k_c_entry_fp_address)); |
| 1971 store_rax(c_entry_fp_address); | 2083 movq(Operand(kScratchRegister, 0), rbp); |
| 1972 movq(rax, rsi); | 2084 |
| 1973 store_rax(context_address); | 2085 movq(kScratchRegister, ExternalReference(Top::k_context_address)); |
| 2086 movq(Operand(kScratchRegister, 0), rsi); |
| 1974 } | 2087 } |
| 1975 | 2088 |
| 1976 | 2089 |
| 1977 void MacroAssembler::EnterExitFrameEpilogue(int arg_stack_space, | 2090 void MacroAssembler::EnterExitFrameEpilogue(int arg_stack_space, |
| 1978 bool save_doubles) { | 2091 bool save_doubles) { |
| 1979 #ifdef _WIN64 | 2092 #ifdef _WIN64 |
| 1980 const int kShadowSpace = 4; | 2093 const int kShadowSpace = 4; |
| 1981 arg_stack_space += kShadowSpace; | 2094 arg_stack_space += kShadowSpace; |
| 1982 #endif | 2095 #endif |
| 1983 // Optionally save all XMM registers. | 2096 // Optionally save all XMM registers. |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2004 } | 2117 } |
| 2005 | 2118 |
| 2006 // Patch the saved entry sp. | 2119 // Patch the saved entry sp. |
| 2007 movq(Operand(rbp, ExitFrameConstants::kSPOffset), rsp); | 2120 movq(Operand(rbp, ExitFrameConstants::kSPOffset), rsp); |
| 2008 } | 2121 } |
| 2009 | 2122 |
| 2010 | 2123 |
| 2011 void MacroAssembler::EnterExitFrame(int arg_stack_space, bool save_doubles) { | 2124 void MacroAssembler::EnterExitFrame(int arg_stack_space, bool save_doubles) { |
| 2012 EnterExitFramePrologue(true); | 2125 EnterExitFramePrologue(true); |
| 2013 | 2126 |
| 2014 // Setup argv in callee-saved register r12. It is reused in LeaveExitFrame, | 2127 // Setup argv in callee-saved register r15. It is reused in LeaveExitFrame, |
| 2015 // so it must be retained across the C-call. | 2128 // so it must be retained across the C-call. |
| 2016 int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize; | 2129 int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize; |
| 2017 lea(r12, Operand(rbp, r14, times_pointer_size, offset)); | 2130 lea(r15, Operand(rbp, r14, times_pointer_size, offset)); |
| 2018 | 2131 |
| 2019 EnterExitFrameEpilogue(arg_stack_space, save_doubles); | 2132 EnterExitFrameEpilogue(arg_stack_space, save_doubles); |
| 2020 } | 2133 } |
| 2021 | 2134 |
| 2022 | 2135 |
| 2023 void MacroAssembler::EnterApiExitFrame(int arg_stack_space) { | 2136 void MacroAssembler::EnterApiExitFrame(int arg_stack_space) { |
| 2024 EnterExitFramePrologue(false); | 2137 EnterExitFramePrologue(false); |
| 2025 EnterExitFrameEpilogue(arg_stack_space, false); | 2138 EnterExitFrameEpilogue(arg_stack_space, false); |
| 2026 } | 2139 } |
| 2027 | 2140 |
| 2028 | 2141 |
| 2029 void MacroAssembler::LeaveExitFrame(bool save_doubles) { | 2142 void MacroAssembler::LeaveExitFrame(bool save_doubles) { |
| 2030 // Registers: | 2143 // Registers: |
| 2031 // r12 : argv | 2144 // r15 : argv |
| 2032 if (save_doubles) { | 2145 if (save_doubles) { |
| 2033 int offset = -2 * kPointerSize; | 2146 int offset = -2 * kPointerSize; |
| 2034 for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; i++) { | 2147 for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; i++) { |
| 2035 XMMRegister reg = XMMRegister::FromAllocationIndex(i); | 2148 XMMRegister reg = XMMRegister::FromAllocationIndex(i); |
| 2036 movsd(reg, Operand(rbp, offset - ((i + 1) * kDoubleSize))); | 2149 movsd(reg, Operand(rbp, offset - ((i + 1) * kDoubleSize))); |
| 2037 } | 2150 } |
| 2038 } | 2151 } |
| 2039 // Get the return address from the stack and restore the frame pointer. | 2152 // Get the return address from the stack and restore the frame pointer. |
| 2040 movq(rcx, Operand(rbp, 1 * kPointerSize)); | 2153 movq(rcx, Operand(rbp, 1 * kPointerSize)); |
| 2041 movq(rbp, Operand(rbp, 0 * kPointerSize)); | 2154 movq(rbp, Operand(rbp, 0 * kPointerSize)); |
| 2042 | 2155 |
| 2043 // Drop everything up to and including the arguments and the receiver | 2156 // Drop everything up to and including the arguments and the receiver |
| 2044 // from the caller stack. | 2157 // from the caller stack. |
| 2045 lea(rsp, Operand(r12, 1 * kPointerSize)); | 2158 lea(rsp, Operand(r15, 1 * kPointerSize)); |
| 2046 | 2159 |
| 2047 // Push the return address to get ready to return. | 2160 // Push the return address to get ready to return. |
| 2048 push(rcx); | 2161 push(rcx); |
| 2049 | 2162 |
| 2050 LeaveExitFrameEpilogue(); | 2163 LeaveExitFrameEpilogue(); |
| 2051 } | 2164 } |
| 2052 | 2165 |
| 2053 | 2166 |
| 2054 void MacroAssembler::LeaveApiExitFrame() { | 2167 void MacroAssembler::LeaveApiExitFrame() { |
| 2055 movq(rsp, rbp); | 2168 movq(rsp, rbp); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2079 Register scratch, | 2192 Register scratch, |
| 2080 Label* miss) { | 2193 Label* miss) { |
| 2081 Label same_contexts; | 2194 Label same_contexts; |
| 2082 | 2195 |
| 2083 ASSERT(!holder_reg.is(scratch)); | 2196 ASSERT(!holder_reg.is(scratch)); |
| 2084 ASSERT(!scratch.is(kScratchRegister)); | 2197 ASSERT(!scratch.is(kScratchRegister)); |
| 2085 // Load current lexical context from the stack frame. | 2198 // Load current lexical context from the stack frame. |
| 2086 movq(scratch, Operand(rbp, StandardFrameConstants::kContextOffset)); | 2199 movq(scratch, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 2087 | 2200 |
| 2088 // When generating debug code, make sure the lexical context is set. | 2201 // When generating debug code, make sure the lexical context is set. |
| 2089 if (FLAG_debug_code) { | 2202 if (emit_debug_code()) { |
| 2090 cmpq(scratch, Immediate(0)); | 2203 cmpq(scratch, Immediate(0)); |
| 2091 Check(not_equal, "we should not have an empty lexical context"); | 2204 Check(not_equal, "we should not have an empty lexical context"); |
| 2092 } | 2205 } |
| 2093 // Load the global context of the current context. | 2206 // Load the global context of the current context. |
| 2094 int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; | 2207 int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; |
| 2095 movq(scratch, FieldOperand(scratch, offset)); | 2208 movq(scratch, FieldOperand(scratch, offset)); |
| 2096 movq(scratch, FieldOperand(scratch, GlobalObject::kGlobalContextOffset)); | 2209 movq(scratch, FieldOperand(scratch, GlobalObject::kGlobalContextOffset)); |
| 2097 | 2210 |
| 2098 // Check the context is a global context. | 2211 // Check the context is a global context. |
| 2099 if (FLAG_debug_code) { | 2212 if (emit_debug_code()) { |
| 2100 Cmp(FieldOperand(scratch, HeapObject::kMapOffset), | 2213 Cmp(FieldOperand(scratch, HeapObject::kMapOffset), |
| 2101 Factory::global_context_map()); | 2214 Factory::global_context_map()); |
| 2102 Check(equal, "JSGlobalObject::global_context should be a global context."); | 2215 Check(equal, "JSGlobalObject::global_context should be a global context."); |
| 2103 } | 2216 } |
| 2104 | 2217 |
| 2105 // Check if both contexts are the same. | 2218 // Check if both contexts are the same. |
| 2106 cmpq(scratch, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); | 2219 cmpq(scratch, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); |
| 2107 j(equal, &same_contexts); | 2220 j(equal, &same_contexts); |
| 2108 | 2221 |
| 2109 // Compare security tokens. | 2222 // Compare security tokens. |
| 2110 // Check that the security token in the calling global object is | 2223 // Check that the security token in the calling global object is |
| 2111 // compatible with the security token in the receiving global | 2224 // compatible with the security token in the receiving global |
| 2112 // object. | 2225 // object. |
| 2113 | 2226 |
| 2114 // Check the context is a global context. | 2227 // Check the context is a global context. |
| 2115 if (FLAG_debug_code) { | 2228 if (emit_debug_code()) { |
| 2116 // Preserve original value of holder_reg. | 2229 // Preserve original value of holder_reg. |
| 2117 push(holder_reg); | 2230 push(holder_reg); |
| 2118 movq(holder_reg, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); | 2231 movq(holder_reg, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); |
| 2119 CompareRoot(holder_reg, Heap::kNullValueRootIndex); | 2232 CompareRoot(holder_reg, Heap::kNullValueRootIndex); |
| 2120 Check(not_equal, "JSGlobalProxy::context() should not be null."); | 2233 Check(not_equal, "JSGlobalProxy::context() should not be null."); |
| 2121 | 2234 |
| 2122 // Read the first word and compare to global_context_map(), | 2235 // Read the first word and compare to global_context_map(), |
| 2123 movq(holder_reg, FieldOperand(holder_reg, HeapObject::kMapOffset)); | 2236 movq(holder_reg, FieldOperand(holder_reg, HeapObject::kMapOffset)); |
| 2124 CompareRoot(holder_reg, Heap::kGlobalContextMapRootIndex); | 2237 CompareRoot(holder_reg, Heap::kGlobalContextMapRootIndex); |
| 2125 Check(equal, "JSGlobalObject::global_context should be a global context."); | 2238 Check(equal, "JSGlobalObject::global_context should be a global context."); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2166 load_rax(new_space_allocation_top); | 2279 load_rax(new_space_allocation_top); |
| 2167 } else { | 2280 } else { |
| 2168 movq(kScratchRegister, new_space_allocation_top); | 2281 movq(kScratchRegister, new_space_allocation_top); |
| 2169 movq(result, Operand(kScratchRegister, 0)); | 2282 movq(result, Operand(kScratchRegister, 0)); |
| 2170 } | 2283 } |
| 2171 } | 2284 } |
| 2172 | 2285 |
| 2173 | 2286 |
| 2174 void MacroAssembler::UpdateAllocationTopHelper(Register result_end, | 2287 void MacroAssembler::UpdateAllocationTopHelper(Register result_end, |
| 2175 Register scratch) { | 2288 Register scratch) { |
| 2176 if (FLAG_debug_code) { | 2289 if (emit_debug_code()) { |
| 2177 testq(result_end, Immediate(kObjectAlignmentMask)); | 2290 testq(result_end, Immediate(kObjectAlignmentMask)); |
| 2178 Check(zero, "Unaligned allocation in new space"); | 2291 Check(zero, "Unaligned allocation in new space"); |
| 2179 } | 2292 } |
| 2180 | 2293 |
| 2181 ExternalReference new_space_allocation_top = | 2294 ExternalReference new_space_allocation_top = |
| 2182 ExternalReference::new_space_allocation_top_address(); | 2295 ExternalReference::new_space_allocation_top_address(); |
| 2183 | 2296 |
| 2184 // Update new top. | 2297 // Update new top. |
| 2185 if (result_end.is(rax)) { | 2298 if (result_end.is(rax)) { |
| 2186 // rax can be stored directly to a memory location. | 2299 // rax can be stored directly to a memory location. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2197 } | 2310 } |
| 2198 | 2311 |
| 2199 | 2312 |
| 2200 void MacroAssembler::AllocateInNewSpace(int object_size, | 2313 void MacroAssembler::AllocateInNewSpace(int object_size, |
| 2201 Register result, | 2314 Register result, |
| 2202 Register result_end, | 2315 Register result_end, |
| 2203 Register scratch, | 2316 Register scratch, |
| 2204 Label* gc_required, | 2317 Label* gc_required, |
| 2205 AllocationFlags flags) { | 2318 AllocationFlags flags) { |
| 2206 if (!FLAG_inline_new) { | 2319 if (!FLAG_inline_new) { |
| 2207 if (FLAG_debug_code) { | 2320 if (emit_debug_code()) { |
| 2208 // Trash the registers to simulate an allocation failure. | 2321 // Trash the registers to simulate an allocation failure. |
| 2209 movl(result, Immediate(0x7091)); | 2322 movl(result, Immediate(0x7091)); |
| 2210 if (result_end.is_valid()) { | 2323 if (result_end.is_valid()) { |
| 2211 movl(result_end, Immediate(0x7191)); | 2324 movl(result_end, Immediate(0x7191)); |
| 2212 } | 2325 } |
| 2213 if (scratch.is_valid()) { | 2326 if (scratch.is_valid()) { |
| 2214 movl(scratch, Immediate(0x7291)); | 2327 movl(scratch, Immediate(0x7291)); |
| 2215 } | 2328 } |
| 2216 } | 2329 } |
| 2217 jmp(gc_required); | 2330 jmp(gc_required); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2255 | 2368 |
| 2256 void MacroAssembler::AllocateInNewSpace(int header_size, | 2369 void MacroAssembler::AllocateInNewSpace(int header_size, |
| 2257 ScaleFactor element_size, | 2370 ScaleFactor element_size, |
| 2258 Register element_count, | 2371 Register element_count, |
| 2259 Register result, | 2372 Register result, |
| 2260 Register result_end, | 2373 Register result_end, |
| 2261 Register scratch, | 2374 Register scratch, |
| 2262 Label* gc_required, | 2375 Label* gc_required, |
| 2263 AllocationFlags flags) { | 2376 AllocationFlags flags) { |
| 2264 if (!FLAG_inline_new) { | 2377 if (!FLAG_inline_new) { |
| 2265 if (FLAG_debug_code) { | 2378 if (emit_debug_code()) { |
| 2266 // Trash the registers to simulate an allocation failure. | 2379 // Trash the registers to simulate an allocation failure. |
| 2267 movl(result, Immediate(0x7091)); | 2380 movl(result, Immediate(0x7091)); |
| 2268 movl(result_end, Immediate(0x7191)); | 2381 movl(result_end, Immediate(0x7191)); |
| 2269 if (scratch.is_valid()) { | 2382 if (scratch.is_valid()) { |
| 2270 movl(scratch, Immediate(0x7291)); | 2383 movl(scratch, Immediate(0x7291)); |
| 2271 } | 2384 } |
| 2272 // Register element_count is not modified by the function. | 2385 // Register element_count is not modified by the function. |
| 2273 } | 2386 } |
| 2274 jmp(gc_required); | 2387 jmp(gc_required); |
| 2275 return; | 2388 return; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2302 } | 2415 } |
| 2303 | 2416 |
| 2304 | 2417 |
| 2305 void MacroAssembler::AllocateInNewSpace(Register object_size, | 2418 void MacroAssembler::AllocateInNewSpace(Register object_size, |
| 2306 Register result, | 2419 Register result, |
| 2307 Register result_end, | 2420 Register result_end, |
| 2308 Register scratch, | 2421 Register scratch, |
| 2309 Label* gc_required, | 2422 Label* gc_required, |
| 2310 AllocationFlags flags) { | 2423 AllocationFlags flags) { |
| 2311 if (!FLAG_inline_new) { | 2424 if (!FLAG_inline_new) { |
| 2312 if (FLAG_debug_code) { | 2425 if (emit_debug_code()) { |
| 2313 // Trash the registers to simulate an allocation failure. | 2426 // Trash the registers to simulate an allocation failure. |
| 2314 movl(result, Immediate(0x7091)); | 2427 movl(result, Immediate(0x7091)); |
| 2315 movl(result_end, Immediate(0x7191)); | 2428 movl(result_end, Immediate(0x7191)); |
| 2316 if (scratch.is_valid()) { | 2429 if (scratch.is_valid()) { |
| 2317 movl(scratch, Immediate(0x7291)); | 2430 movl(scratch, Immediate(0x7291)); |
| 2318 } | 2431 } |
| 2319 // object_size is left unchanged by this function. | 2432 // object_size is left unchanged by this function. |
| 2320 } | 2433 } |
| 2321 jmp(gc_required); | 2434 jmp(gc_required); |
| 2322 return; | 2435 return; |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2498 // Move up the chain of contexts to the context containing the slot. | 2611 // Move up the chain of contexts to the context containing the slot. |
| 2499 movq(dst, Operand(rsi, Context::SlotOffset(Context::CLOSURE_INDEX))); | 2612 movq(dst, Operand(rsi, Context::SlotOffset(Context::CLOSURE_INDEX))); |
| 2500 // Load the function context (which is the incoming, outer context). | 2613 // Load the function context (which is the incoming, outer context). |
| 2501 movq(dst, FieldOperand(dst, JSFunction::kContextOffset)); | 2614 movq(dst, FieldOperand(dst, JSFunction::kContextOffset)); |
| 2502 for (int i = 1; i < context_chain_length; i++) { | 2615 for (int i = 1; i < context_chain_length; i++) { |
| 2503 movq(dst, Operand(dst, Context::SlotOffset(Context::CLOSURE_INDEX))); | 2616 movq(dst, Operand(dst, Context::SlotOffset(Context::CLOSURE_INDEX))); |
| 2504 movq(dst, FieldOperand(dst, JSFunction::kContextOffset)); | 2617 movq(dst, FieldOperand(dst, JSFunction::kContextOffset)); |
| 2505 } | 2618 } |
| 2506 // The context may be an intermediate context, not a function context. | 2619 // The context may be an intermediate context, not a function context. |
| 2507 movq(dst, Operand(dst, Context::SlotOffset(Context::FCONTEXT_INDEX))); | 2620 movq(dst, Operand(dst, Context::SlotOffset(Context::FCONTEXT_INDEX))); |
| 2508 } else { // context is the current function context. | 2621 } else { |
| 2509 // The context may be an intermediate context, not a function context. | 2622 // Slot is in the current function context. Move it into the |
| 2510 movq(dst, Operand(rsi, Context::SlotOffset(Context::FCONTEXT_INDEX))); | 2623 // destination register in case we store into it (the write barrier |
| 2624 // cannot be allowed to destroy the context in rsi). |
| 2625 movq(dst, rsi); |
| 2626 } |
| 2627 |
| 2628 // We should not have found a 'with' context by walking the context chain |
| 2629 // (i.e., the static scope chain and runtime context chain do not agree). |
| 2630 // A variable occurring in such a scope should have slot type LOOKUP and |
| 2631 // not CONTEXT. |
| 2632 if (emit_debug_code()) { |
| 2633 cmpq(dst, Operand(dst, Context::SlotOffset(Context::FCONTEXT_INDEX))); |
| 2634 Check(equal, "Yo dawg, I heard you liked function contexts " |
| 2635 "so I put function contexts in all your contexts"); |
| 2511 } | 2636 } |
| 2512 } | 2637 } |
| 2513 | 2638 |
| 2514 | 2639 |
| 2515 void MacroAssembler::LoadGlobalFunction(int index, Register function) { | 2640 void MacroAssembler::LoadGlobalFunction(int index, Register function) { |
| 2516 // Load the global or builtins object from the current context. | 2641 // Load the global or builtins object from the current context. |
| 2517 movq(function, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); | 2642 movq(function, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| 2518 // Load the global context from the global or builtins object. | 2643 // Load the global context from the global or builtins object. |
| 2519 movq(function, FieldOperand(function, GlobalObject::kGlobalContextOffset)); | 2644 movq(function, FieldOperand(function, GlobalObject::kGlobalContextOffset)); |
| 2520 // Load the function from the global context. | 2645 // Load the function from the global context. |
| 2521 movq(function, Operand(function, Context::SlotOffset(index))); | 2646 movq(function, Operand(function, Context::SlotOffset(index))); |
| 2522 } | 2647 } |
| 2523 | 2648 |
| 2524 | 2649 |
| 2525 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function, | 2650 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function, |
| 2526 Register map) { | 2651 Register map) { |
| 2527 // Load the initial map. The global functions all have initial maps. | 2652 // Load the initial map. The global functions all have initial maps. |
| 2528 movq(map, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); | 2653 movq(map, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); |
| 2529 if (FLAG_debug_code) { | 2654 if (emit_debug_code()) { |
| 2530 Label ok, fail; | 2655 Label ok, fail; |
| 2531 CheckMap(map, Factory::meta_map(), &fail, false); | 2656 CheckMap(map, Factory::meta_map(), &fail, false); |
| 2532 jmp(&ok); | 2657 jmp(&ok); |
| 2533 bind(&fail); | 2658 bind(&fail); |
| 2534 Abort("Global functions must have initial map"); | 2659 Abort("Global functions must have initial map"); |
| 2535 bind(&ok); | 2660 bind(&ok); |
| 2536 } | 2661 } |
| 2537 } | 2662 } |
| 2538 | 2663 |
| 2539 | 2664 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2574 | 2699 |
| 2575 void MacroAssembler::CallCFunction(ExternalReference function, | 2700 void MacroAssembler::CallCFunction(ExternalReference function, |
| 2576 int num_arguments) { | 2701 int num_arguments) { |
| 2577 movq(rax, function); | 2702 movq(rax, function); |
| 2578 CallCFunction(rax, num_arguments); | 2703 CallCFunction(rax, num_arguments); |
| 2579 } | 2704 } |
| 2580 | 2705 |
| 2581 | 2706 |
| 2582 void MacroAssembler::CallCFunction(Register function, int num_arguments) { | 2707 void MacroAssembler::CallCFunction(Register function, int num_arguments) { |
| 2583 // Check stack alignment. | 2708 // Check stack alignment. |
| 2584 if (FLAG_debug_code) { | 2709 if (emit_debug_code()) { |
| 2585 CheckStackAlignment(); | 2710 CheckStackAlignment(); |
| 2586 } | 2711 } |
| 2587 | 2712 |
| 2588 call(function); | 2713 call(function); |
| 2589 ASSERT(OS::ActivationFrameAlignment() != 0); | 2714 ASSERT(OS::ActivationFrameAlignment() != 0); |
| 2590 ASSERT(num_arguments >= 0); | 2715 ASSERT(num_arguments >= 0); |
| 2591 int argument_slots_on_stack = | 2716 int argument_slots_on_stack = |
| 2592 ArgumentStackSlotsForCFunctionCall(num_arguments); | 2717 ArgumentStackSlotsForCFunctionCall(num_arguments); |
| 2593 movq(rsp, Operand(rsp, argument_slots_on_stack * kPointerSize)); | 2718 movq(rsp, Operand(rsp, argument_slots_on_stack * kPointerSize)); |
| 2594 } | 2719 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2608 CPU::FlushICache(address_, size_); | 2733 CPU::FlushICache(address_, size_); |
| 2609 | 2734 |
| 2610 // Check that the code was patched as expected. | 2735 // Check that the code was patched as expected. |
| 2611 ASSERT(masm_.pc_ == address_ + size_); | 2736 ASSERT(masm_.pc_ == address_ + size_); |
| 2612 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); | 2737 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); |
| 2613 } | 2738 } |
| 2614 | 2739 |
| 2615 } } // namespace v8::internal | 2740 } } // namespace v8::internal |
| 2616 | 2741 |
| 2617 #endif // V8_TARGET_ARCH_X64 | 2742 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |