OLD | NEW |
1 // Copyright 2011 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 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
54 static const int kSmiConstantRegisterValue = 1; | 54 static const int kSmiConstantRegisterValue = 1; |
55 // Actual value of root register is offset from the root array's start | 55 // Actual value of root register is offset from the root array's start |
56 // to take advantage of negitive 8-bit displacement values. | 56 // to take advantage of negitive 8-bit displacement values. |
57 static const int kRootRegisterBias = 128; | 57 static const int kRootRegisterBias = 128; |
58 | 58 |
59 // Convenience for platform-independent signatures. | 59 // Convenience for platform-independent signatures. |
60 typedef Operand MemOperand; | 60 typedef Operand MemOperand; |
61 | 61 |
62 // Forward declaration. | 62 // Forward declaration. |
63 class JumpTarget; | 63 class JumpTarget; |
64 class PostCallGenerator; | 64 class CallWrapper; |
65 | 65 |
66 struct SmiIndex { | 66 struct SmiIndex { |
67 SmiIndex(Register index_register, ScaleFactor scale) | 67 SmiIndex(Register index_register, ScaleFactor scale) |
68 : reg(index_register), | 68 : reg(index_register), |
69 scale(scale) {} | 69 scale(scale) {} |
70 Register reg; | 70 Register reg; |
71 ScaleFactor scale; | 71 ScaleFactor scale; |
72 }; | 72 }; |
73 | 73 |
74 // MacroAssembler implements a collection of frequently used macros. | 74 // MacroAssembler implements a collection of frequently used macros. |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 } | 192 } |
193 | 193 |
194 // --------------------------------------------------------------------------- | 194 // --------------------------------------------------------------------------- |
195 // JavaScript invokes | 195 // JavaScript invokes |
196 | 196 |
197 // Invoke the JavaScript function code by either calling or jumping. | 197 // Invoke the JavaScript function code by either calling or jumping. |
198 void InvokeCode(Register code, | 198 void InvokeCode(Register code, |
199 const ParameterCount& expected, | 199 const ParameterCount& expected, |
200 const ParameterCount& actual, | 200 const ParameterCount& actual, |
201 InvokeFlag flag, | 201 InvokeFlag flag, |
202 PostCallGenerator* post_call_generator = NULL); | 202 CallWrapper* call_wrapper = NULL); |
203 | 203 |
204 void InvokeCode(Handle<Code> code, | 204 void InvokeCode(Handle<Code> code, |
205 const ParameterCount& expected, | 205 const ParameterCount& expected, |
206 const ParameterCount& actual, | 206 const ParameterCount& actual, |
207 RelocInfo::Mode rmode, | 207 RelocInfo::Mode rmode, |
208 InvokeFlag flag, | 208 InvokeFlag flag, |
209 PostCallGenerator* post_call_generator = NULL); | 209 CallWrapper* call_wrapper = NULL); |
210 | 210 |
211 // Invoke the JavaScript function in the given register. Changes the | 211 // Invoke the JavaScript function in the given register. Changes the |
212 // current context to the context in the function before invoking. | 212 // current context to the context in the function before invoking. |
213 void InvokeFunction(Register function, | 213 void InvokeFunction(Register function, |
214 const ParameterCount& actual, | 214 const ParameterCount& actual, |
215 InvokeFlag flag, | 215 InvokeFlag flag, |
216 PostCallGenerator* post_call_generator = NULL); | 216 CallWrapper* call_wrapper = NULL); |
217 | 217 |
218 void InvokeFunction(JSFunction* function, | 218 void InvokeFunction(JSFunction* function, |
219 const ParameterCount& actual, | 219 const ParameterCount& actual, |
220 InvokeFlag flag, | 220 InvokeFlag flag, |
221 PostCallGenerator* post_call_generator = NULL); | 221 CallWrapper* call_wrapper = NULL); |
222 | 222 |
223 // Invoke specified builtin JavaScript function. Adds an entry to | 223 // Invoke specified builtin JavaScript function. Adds an entry to |
224 // the unresolved list if the name does not resolve. | 224 // the unresolved list if the name does not resolve. |
225 void InvokeBuiltin(Builtins::JavaScript id, | 225 void InvokeBuiltin(Builtins::JavaScript id, |
226 InvokeFlag flag, | 226 InvokeFlag flag, |
227 PostCallGenerator* post_call_generator = NULL); | 227 CallWrapper* call_wrapper = NULL); |
228 | 228 |
229 // Store the function for the given builtin in the target register. | 229 // Store the function for the given builtin in the target register. |
230 void GetBuiltinFunction(Register target, Builtins::JavaScript id); | 230 void GetBuiltinFunction(Register target, Builtins::JavaScript id); |
231 | 231 |
232 // Store the code object for the given builtin in the target register. | 232 // Store the code object for the given builtin in the target register. |
233 void GetBuiltinEntry(Register target, Builtins::JavaScript id); | 233 void GetBuiltinEntry(Register target, Builtins::JavaScript id); |
234 | 234 |
235 | 235 |
236 // --------------------------------------------------------------------------- | 236 // --------------------------------------------------------------------------- |
237 // Smi tagging, untagging and operations on tagged smis. | 237 // Smi tagging, untagging and operations on tagged smis. |
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
619 | 619 |
620 // Control Flow | 620 // Control Flow |
621 void Jump(Address destination, RelocInfo::Mode rmode); | 621 void Jump(Address destination, RelocInfo::Mode rmode); |
622 void Jump(ExternalReference ext); | 622 void Jump(ExternalReference ext); |
623 void Jump(Handle<Code> code_object, RelocInfo::Mode rmode); | 623 void Jump(Handle<Code> code_object, RelocInfo::Mode rmode); |
624 | 624 |
625 void Call(Address destination, RelocInfo::Mode rmode); | 625 void Call(Address destination, RelocInfo::Mode rmode); |
626 void Call(ExternalReference ext); | 626 void Call(ExternalReference ext); |
627 void Call(Handle<Code> code_object, RelocInfo::Mode rmode); | 627 void Call(Handle<Code> code_object, RelocInfo::Mode rmode); |
628 | 628 |
| 629 // The size of the code generated for different call instructions. |
| 630 int CallSize(Address destination, RelocInfo::Mode rmode) { |
| 631 return kCallInstructionLength; |
| 632 } |
| 633 int CallSize(ExternalReference ext) { |
| 634 return kCallInstructionLength; |
| 635 } |
| 636 int CallSize(Handle<Code> code_object) { |
| 637 // Code calls use 32-bit relative addressing. |
| 638 return kShortCallInstructionLength; |
| 639 } |
| 640 int CallSize(Register target) { |
| 641 // Opcode: REX_opt FF /2 m64 |
| 642 return (target.high_bit() != 0) ? 3 : 2; |
| 643 } |
| 644 int CallSize(const Operand& target) { |
| 645 // Opcode: REX_opt FF /2 m64 |
| 646 return (target.requires_rex() ? 2 : 1) + target.operand_size(); |
| 647 } |
| 648 |
629 // Emit call to the code we are currently generating. | 649 // Emit call to the code we are currently generating. |
630 void CallSelf() { | 650 void CallSelf() { |
631 Handle<Code> self(reinterpret_cast<Code**>(CodeObject().location())); | 651 Handle<Code> self(reinterpret_cast<Code**>(CodeObject().location())); |
632 Call(self, RelocInfo::CODE_TARGET); | 652 Call(self, RelocInfo::CODE_TARGET); |
633 } | 653 } |
634 | 654 |
635 // Non-x64 instructions. | 655 // Non-x64 instructions. |
636 // Push/pop all general purpose registers. | 656 // Push/pop all general purpose registers. |
637 // Does not push rsp/rbp nor any of the assembler's special purpose registers | 657 // Does not push rsp/rbp nor any of the assembler's special purpose registers |
638 // (kScratchRegister, kSmiConstantRegister, kRootRegister). | 658 // (kScratchRegister, kSmiConstantRegister, kRootRegister). |
(...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1011 Handle<Object> code_object_; | 1031 Handle<Object> code_object_; |
1012 | 1032 |
1013 // Helper functions for generating invokes. | 1033 // Helper functions for generating invokes. |
1014 template <typename LabelType> | 1034 template <typename LabelType> |
1015 void InvokePrologue(const ParameterCount& expected, | 1035 void InvokePrologue(const ParameterCount& expected, |
1016 const ParameterCount& actual, | 1036 const ParameterCount& actual, |
1017 Handle<Code> code_constant, | 1037 Handle<Code> code_constant, |
1018 Register code_register, | 1038 Register code_register, |
1019 LabelType* done, | 1039 LabelType* done, |
1020 InvokeFlag flag, | 1040 InvokeFlag flag, |
1021 PostCallGenerator* post_call_generator); | 1041 CallWrapper* call_wrapper); |
1022 | 1042 |
1023 // Activation support. | 1043 // Activation support. |
1024 void EnterFrame(StackFrame::Type type); | 1044 void EnterFrame(StackFrame::Type type); |
1025 void LeaveFrame(StackFrame::Type type); | 1045 void LeaveFrame(StackFrame::Type type); |
1026 | 1046 |
1027 void EnterExitFramePrologue(bool save_rax); | 1047 void EnterExitFramePrologue(bool save_rax); |
1028 | 1048 |
1029 // Allocates arg_stack_space * kPointerSize memory (not GCed) on the stack | 1049 // Allocates arg_stack_space * kPointerSize memory (not GCed) on the stack |
1030 // accessible via StackSpaceOperand. | 1050 // accessible via StackSpaceOperand. |
1031 void EnterExitFrameEpilogue(int arg_stack_space, bool save_doubles); | 1051 void EnterExitFrameEpilogue(int arg_stack_space, bool save_doubles); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1077 MacroAssembler* masm() { return &masm_; } | 1097 MacroAssembler* masm() { return &masm_; } |
1078 | 1098 |
1079 private: | 1099 private: |
1080 byte* address_; // The address of the code being patched. | 1100 byte* address_; // The address of the code being patched. |
1081 int size_; // Number of bytes of the expected patch size. | 1101 int size_; // Number of bytes of the expected patch size. |
1082 MacroAssembler masm_; // Macro assembler used to generate the code. | 1102 MacroAssembler masm_; // Macro assembler used to generate the code. |
1083 }; | 1103 }; |
1084 | 1104 |
1085 | 1105 |
1086 // Helper class for generating code or data associated with the code | 1106 // Helper class for generating code or data associated with the code |
1087 // right after a call instruction. As an example this can be used to | 1107 // right before or after a call instruction. As an example this can be used to |
1088 // generate safepoint data after calls for crankshaft. | 1108 // generate safepoint data after calls for crankshaft. |
1089 class PostCallGenerator { | 1109 class CallWrapper { |
1090 public: | 1110 public: |
1091 PostCallGenerator() { } | 1111 CallWrapper() { } |
1092 virtual ~PostCallGenerator() { } | 1112 virtual ~CallWrapper() { } |
1093 virtual void Generate() = 0; | 1113 // Called just before emitting a call. Argument is the size of the generated |
| 1114 // call code. |
| 1115 virtual void BeforeCall(int call_size) = 0; |
| 1116 // Called just after emitting a call, i.e., at the return site for the call. |
| 1117 virtual void AfterCall() = 0; |
1094 }; | 1118 }; |
1095 | 1119 |
1096 | 1120 |
1097 // ----------------------------------------------------------------------------- | 1121 // ----------------------------------------------------------------------------- |
1098 // Static helper functions. | 1122 // Static helper functions. |
1099 | 1123 |
1100 // Generate an Operand for loading a field from an object. | 1124 // Generate an Operand for loading a field from an object. |
1101 static inline Operand FieldOperand(Register object, int offset) { | 1125 static inline Operand FieldOperand(Register object, int offset) { |
1102 return Operand(object, offset - kHeapObjectTag); | 1126 return Operand(object, offset - kHeapObjectTag); |
1103 } | 1127 } |
(...skipping 690 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1794 } | 1818 } |
1795 | 1819 |
1796 | 1820 |
1797 template <typename LabelType> | 1821 template <typename LabelType> |
1798 void MacroAssembler::InvokePrologue(const ParameterCount& expected, | 1822 void MacroAssembler::InvokePrologue(const ParameterCount& expected, |
1799 const ParameterCount& actual, | 1823 const ParameterCount& actual, |
1800 Handle<Code> code_constant, | 1824 Handle<Code> code_constant, |
1801 Register code_register, | 1825 Register code_register, |
1802 LabelType* done, | 1826 LabelType* done, |
1803 InvokeFlag flag, | 1827 InvokeFlag flag, |
1804 PostCallGenerator* post_call_generator) { | 1828 CallWrapper* call_wrapper) { |
1805 bool definitely_matches = false; | 1829 bool definitely_matches = false; |
1806 NearLabel invoke; | 1830 NearLabel invoke; |
1807 if (expected.is_immediate()) { | 1831 if (expected.is_immediate()) { |
1808 ASSERT(actual.is_immediate()); | 1832 ASSERT(actual.is_immediate()); |
1809 if (expected.immediate() == actual.immediate()) { | 1833 if (expected.immediate() == actual.immediate()) { |
1810 definitely_matches = true; | 1834 definitely_matches = true; |
1811 } else { | 1835 } else { |
1812 Set(rax, actual.immediate()); | 1836 Set(rax, actual.immediate()); |
1813 if (expected.immediate() == | 1837 if (expected.immediate() == |
1814 SharedFunctionInfo::kDontAdaptArgumentsSentinel) { | 1838 SharedFunctionInfo::kDontAdaptArgumentsSentinel) { |
(...skipping 29 matching lines...) Expand all Loading... |
1844 Handle<Code> adaptor = | 1868 Handle<Code> adaptor = |
1845 Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)); | 1869 Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)); |
1846 if (!code_constant.is_null()) { | 1870 if (!code_constant.is_null()) { |
1847 movq(rdx, code_constant, RelocInfo::EMBEDDED_OBJECT); | 1871 movq(rdx, code_constant, RelocInfo::EMBEDDED_OBJECT); |
1848 addq(rdx, Immediate(Code::kHeaderSize - kHeapObjectTag)); | 1872 addq(rdx, Immediate(Code::kHeaderSize - kHeapObjectTag)); |
1849 } else if (!code_register.is(rdx)) { | 1873 } else if (!code_register.is(rdx)) { |
1850 movq(rdx, code_register); | 1874 movq(rdx, code_register); |
1851 } | 1875 } |
1852 | 1876 |
1853 if (flag == CALL_FUNCTION) { | 1877 if (flag == CALL_FUNCTION) { |
| 1878 if (call_wrapper != NULL) call_wrapper->BeforeCall(CallSize(adaptor)); |
1854 Call(adaptor, RelocInfo::CODE_TARGET); | 1879 Call(adaptor, RelocInfo::CODE_TARGET); |
1855 if (post_call_generator != NULL) post_call_generator->Generate(); | 1880 if (call_wrapper != NULL) call_wrapper->AfterCall(); |
1856 jmp(done); | 1881 jmp(done); |
1857 } else { | 1882 } else { |
1858 Jump(adaptor, RelocInfo::CODE_TARGET); | 1883 Jump(adaptor, RelocInfo::CODE_TARGET); |
1859 } | 1884 } |
1860 bind(&invoke); | 1885 bind(&invoke); |
1861 } | 1886 } |
1862 } | 1887 } |
1863 | 1888 |
1864 | 1889 |
1865 } } // namespace v8::internal | 1890 } } // namespace v8::internal |
1866 | 1891 |
1867 #endif // V8_X64_MACRO_ASSEMBLER_X64_H_ | 1892 #endif // V8_X64_MACRO_ASSEMBLER_X64_H_ |
OLD | NEW |