| 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 29 matching lines...) Expand all Loading... |
| 41 TAG_OBJECT = 1 << 0, | 41 TAG_OBJECT = 1 << 0, |
| 42 // The content of the result register already contains the allocation top in | 42 // The content of the result register already contains the allocation top in |
| 43 // new space. | 43 // new space. |
| 44 RESULT_CONTAINS_TOP = 1 << 1 | 44 RESULT_CONTAINS_TOP = 1 << 1 |
| 45 }; | 45 }; |
| 46 | 46 |
| 47 // Default scratch register used by MacroAssembler (and other code that needs | 47 // Default scratch register used by MacroAssembler (and other code that needs |
| 48 // a spare register). The register isn't callee save, and not used by the | 48 // a spare register). The register isn't callee save, and not used by the |
| 49 // function calling convention. | 49 // function calling convention. |
| 50 static const Register kScratchRegister = { 10 }; // r10. | 50 static const Register kScratchRegister = { 10 }; // r10. |
| 51 static const Register kSmiConstantRegister = { 15 }; // r15 (callee save). | 51 static const Register kSmiConstantRegister = { 12 }; // r12 (callee save). |
| 52 static const Register kRootRegister = { 13 }; // r13 (callee save). | 52 static const Register kRootRegister = { 13 }; // r13 (callee save). |
| 53 // Value of smi in kSmiConstantRegister. | 53 // Value of smi in kSmiConstantRegister. |
| 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 |
| 56 // to take advantage of negitive 8-bit displacement values. |
| 57 static const int kRootRegisterBias = 128; |
| 55 | 58 |
| 56 // Convenience for platform-independent signatures. | 59 // Convenience for platform-independent signatures. |
| 57 typedef Operand MemOperand; | 60 typedef Operand MemOperand; |
| 58 | 61 |
| 59 // Forward declaration. | 62 // Forward declaration. |
| 60 class JumpTarget; | 63 class JumpTarget; |
| 64 class CallWrapper; |
| 61 | 65 |
| 62 struct SmiIndex { | 66 struct SmiIndex { |
| 63 SmiIndex(Register index_register, ScaleFactor scale) | 67 SmiIndex(Register index_register, ScaleFactor scale) |
| 64 : reg(index_register), | 68 : reg(index_register), |
| 65 scale(scale) {} | 69 scale(scale) {} |
| 66 Register reg; | 70 Register reg; |
| 67 ScaleFactor scale; | 71 ScaleFactor scale; |
| 68 }; | 72 }; |
| 69 | 73 |
| 70 // MacroAssembler implements a collection of frequently used macros. | 74 // MacroAssembler implements a collection of frequently used macros. |
| 71 class MacroAssembler: public Assembler { | 75 class MacroAssembler: public Assembler { |
| 72 public: | 76 public: |
| 73 MacroAssembler(void* buffer, int size); | 77 MacroAssembler(void* buffer, int size); |
| 74 | 78 |
| 75 void LoadRoot(Register destination, Heap::RootListIndex index); | 79 void LoadRoot(Register destination, Heap::RootListIndex index); |
| 80 // Load a root value where the index (or part of it) is variable. |
| 81 // The variable_offset register is added to the fixed_offset value |
| 82 // to get the index into the root-array. |
| 83 void LoadRootIndexed(Register destination, |
| 84 Register variable_offset, |
| 85 int fixed_offset); |
| 76 void CompareRoot(Register with, Heap::RootListIndex index); | 86 void CompareRoot(Register with, Heap::RootListIndex index); |
| 77 void CompareRoot(const Operand& with, Heap::RootListIndex index); | 87 void CompareRoot(const Operand& with, Heap::RootListIndex index); |
| 78 void PushRoot(Heap::RootListIndex index); | 88 void PushRoot(Heap::RootListIndex index); |
| 79 void StoreRoot(Register source, Heap::RootListIndex index); | 89 void StoreRoot(Register source, Heap::RootListIndex index); |
| 80 | 90 |
| 81 // --------------------------------------------------------------------------- | 91 // --------------------------------------------------------------------------- |
| 82 // GC Support | 92 // GC Support |
| 83 | 93 |
| 84 // For page containing |object| mark region covering |addr| dirty. | 94 // For page containing |object| mark region covering |addr| dirty. |
| 85 // RecordWriteHelper only works if the object is not in new | 95 // RecordWriteHelper only works if the object is not in new |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 167 // argument in register rsi. | 177 // argument in register rsi. |
| 168 void LeaveExitFrame(bool save_doubles = false); | 178 void LeaveExitFrame(bool save_doubles = false); |
| 169 | 179 |
| 170 // Leave the current exit frame. Expects/provides the return value in | 180 // Leave the current exit frame. Expects/provides the return value in |
| 171 // register rax (untouched). | 181 // register rax (untouched). |
| 172 void LeaveApiExitFrame(); | 182 void LeaveApiExitFrame(); |
| 173 | 183 |
| 174 // Push and pop the registers that can hold pointers. | 184 // Push and pop the registers that can hold pointers. |
| 175 void PushSafepointRegisters() { Pushad(); } | 185 void PushSafepointRegisters() { Pushad(); } |
| 176 void PopSafepointRegisters() { Popad(); } | 186 void PopSafepointRegisters() { Popad(); } |
| 177 static int SafepointRegisterStackIndex(int reg_code) { | 187 // Store the value in register src in the safepoint register stack |
| 178 return kNumSafepointRegisters - 1 - | 188 // slot for register dst. |
| 179 kSafepointPushRegisterIndices[reg_code]; | 189 void StoreToSafepointRegisterSlot(Register dst, Register src); |
| 190 void LoadFromSafepointRegisterSlot(Register dst, Register src); |
| 191 |
| 192 void InitializeRootRegister() { |
| 193 ExternalReference roots_address = ExternalReference::roots_address(); |
| 194 movq(kRootRegister, roots_address); |
| 195 addq(kRootRegister, Immediate(kRootRegisterBias)); |
| 180 } | 196 } |
| 181 | 197 |
| 182 | |
| 183 // --------------------------------------------------------------------------- | 198 // --------------------------------------------------------------------------- |
| 184 // JavaScript invokes | 199 // JavaScript invokes |
| 185 | 200 |
| 186 // Invoke the JavaScript function code by either calling or jumping. | 201 // Invoke the JavaScript function code by either calling or jumping. |
| 187 void InvokeCode(Register code, | 202 void InvokeCode(Register code, |
| 188 const ParameterCount& expected, | 203 const ParameterCount& expected, |
| 189 const ParameterCount& actual, | 204 const ParameterCount& actual, |
| 190 InvokeFlag flag); | 205 InvokeFlag flag, |
| 206 CallWrapper* call_wrapper = NULL); |
| 191 | 207 |
| 192 void InvokeCode(Handle<Code> code, | 208 void InvokeCode(Handle<Code> code, |
| 193 const ParameterCount& expected, | 209 const ParameterCount& expected, |
| 194 const ParameterCount& actual, | 210 const ParameterCount& actual, |
| 195 RelocInfo::Mode rmode, | 211 RelocInfo::Mode rmode, |
| 196 InvokeFlag flag); | 212 InvokeFlag flag, |
| 213 CallWrapper* call_wrapper = NULL); |
| 197 | 214 |
| 198 // Invoke the JavaScript function in the given register. Changes the | 215 // Invoke the JavaScript function in the given register. Changes the |
| 199 // current context to the context in the function before invoking. | 216 // current context to the context in the function before invoking. |
| 200 void InvokeFunction(Register function, | 217 void InvokeFunction(Register function, |
| 201 const ParameterCount& actual, | 218 const ParameterCount& actual, |
| 202 InvokeFlag flag); | 219 InvokeFlag flag, |
| 220 CallWrapper* call_wrapper = NULL); |
| 203 | 221 |
| 204 void InvokeFunction(JSFunction* function, | 222 void InvokeFunction(JSFunction* function, |
| 205 const ParameterCount& actual, | 223 const ParameterCount& actual, |
| 206 InvokeFlag flag); | 224 InvokeFlag flag, |
| 225 CallWrapper* call_wrapper = NULL); |
| 207 | 226 |
| 208 // Invoke specified builtin JavaScript function. Adds an entry to | 227 // Invoke specified builtin JavaScript function. Adds an entry to |
| 209 // the unresolved list if the name does not resolve. | 228 // the unresolved list if the name does not resolve. |
| 210 void InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag); | 229 void InvokeBuiltin(Builtins::JavaScript id, |
| 230 InvokeFlag flag, |
| 231 CallWrapper* call_wrapper = NULL); |
| 211 | 232 |
| 212 // Store the function for the given builtin in the target register. | 233 // Store the function for the given builtin in the target register. |
| 213 void GetBuiltinFunction(Register target, Builtins::JavaScript id); | 234 void GetBuiltinFunction(Register target, Builtins::JavaScript id); |
| 214 | 235 |
| 215 // Store the code object for the given builtin in the target register. | 236 // Store the code object for the given builtin in the target register. |
| 216 void GetBuiltinEntry(Register target, Builtins::JavaScript id); | 237 void GetBuiltinEntry(Register target, Builtins::JavaScript id); |
| 217 | 238 |
| 218 | 239 |
| 219 // --------------------------------------------------------------------------- | 240 // --------------------------------------------------------------------------- |
| 220 // Smi tagging, untagging and operations on tagged smis. | 241 // Smi tagging, untagging and operations on tagged smis. |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 254 Register src, | 275 Register src, |
| 255 int power); | 276 int power); |
| 256 | 277 |
| 257 // Divide a positive smi's integer value by a power of two. | 278 // Divide a positive smi's integer value by a power of two. |
| 258 // Provides result as 32-bit integer value. | 279 // Provides result as 32-bit integer value. |
| 259 void PositiveSmiDivPowerOfTwoToInteger32(Register dst, | 280 void PositiveSmiDivPowerOfTwoToInteger32(Register dst, |
| 260 Register src, | 281 Register src, |
| 261 int power); | 282 int power); |
| 262 | 283 |
| 263 | 284 |
| 264 // Simple comparison of smis. | 285 // Simple comparison of smis. Both sides must be known smis to use these, |
| 265 void SmiCompare(Register dst, Register src); | 286 // otherwise use Cmp. |
| 287 void SmiCompare(Register smi1, Register smi2); |
| 266 void SmiCompare(Register dst, Smi* src); | 288 void SmiCompare(Register dst, Smi* src); |
| 267 void SmiCompare(Register dst, const Operand& src); | 289 void SmiCompare(Register dst, const Operand& src); |
| 268 void SmiCompare(const Operand& dst, Register src); | 290 void SmiCompare(const Operand& dst, Register src); |
| 269 void SmiCompare(const Operand& dst, Smi* src); | 291 void SmiCompare(const Operand& dst, Smi* src); |
| 270 // Compare the int32 in src register to the value of the smi stored at dst. | 292 // Compare the int32 in src register to the value of the smi stored at dst. |
| 271 void SmiCompareInteger32(const Operand& dst, Register src); | 293 void SmiCompareInteger32(const Operand& dst, Register src); |
| 272 // Sets sign and zero flags depending on value of smi in register. | 294 // Sets sign and zero flags depending on value of smi in register. |
| 273 void SmiTest(Register src); | 295 void SmiTest(Register src); |
| 274 | 296 |
| 275 // Functions performing a check on a known or potential smi. Returns | 297 // Functions performing a check on a known or potential smi. Returns |
| (...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 585 void Set(const Operand& dst, int64_t x); | 607 void Set(const Operand& dst, int64_t x); |
| 586 | 608 |
| 587 // Move if the registers are not identical. | 609 // Move if the registers are not identical. |
| 588 void Move(Register target, Register source); | 610 void Move(Register target, Register source); |
| 589 | 611 |
| 590 // Handle support | 612 // Handle support |
| 591 void Move(Register dst, Handle<Object> source); | 613 void Move(Register dst, Handle<Object> source); |
| 592 void Move(const Operand& dst, Handle<Object> source); | 614 void Move(const Operand& dst, Handle<Object> source); |
| 593 void Cmp(Register dst, Handle<Object> source); | 615 void Cmp(Register dst, Handle<Object> source); |
| 594 void Cmp(const Operand& dst, Handle<Object> source); | 616 void Cmp(const Operand& dst, Handle<Object> source); |
| 617 void Cmp(Register dst, Smi* src); |
| 618 void Cmp(const Operand& dst, Smi* src); |
| 595 void Push(Handle<Object> source); | 619 void Push(Handle<Object> source); |
| 596 | 620 |
| 597 // Emit code to discard a non-negative number of pointer-sized elements | 621 // Emit code to discard a non-negative number of pointer-sized elements |
| 598 // from the stack, clobbering only the rsp register. | 622 // from the stack, clobbering only the rsp register. |
| 599 void Drop(int stack_elements); | 623 void Drop(int stack_elements); |
| 600 | 624 |
| 601 void Call(Label* target) { call(target); } | 625 void Call(Label* target) { call(target); } |
| 602 | 626 |
| 603 // Control Flow | 627 // Control Flow |
| 604 void Jump(Address destination, RelocInfo::Mode rmode); | 628 void Jump(Address destination, RelocInfo::Mode rmode); |
| 605 void Jump(ExternalReference ext); | 629 void Jump(ExternalReference ext); |
| 606 void Jump(Handle<Code> code_object, RelocInfo::Mode rmode); | 630 void Jump(Handle<Code> code_object, RelocInfo::Mode rmode); |
| 607 | 631 |
| 608 void Call(Address destination, RelocInfo::Mode rmode); | 632 void Call(Address destination, RelocInfo::Mode rmode); |
| 609 void Call(ExternalReference ext); | 633 void Call(ExternalReference ext); |
| 610 void Call(Handle<Code> code_object, RelocInfo::Mode rmode); | 634 void Call(Handle<Code> code_object, RelocInfo::Mode rmode); |
| 611 | 635 |
| 636 // The size of the code generated for different call instructions. |
| 637 int CallSize(Address destination, RelocInfo::Mode rmode) { |
| 638 return kCallInstructionLength; |
| 639 } |
| 640 int CallSize(ExternalReference ext) { |
| 641 return kCallInstructionLength; |
| 642 } |
| 643 int CallSize(Handle<Code> code_object) { |
| 644 // Code calls use 32-bit relative addressing. |
| 645 return kShortCallInstructionLength; |
| 646 } |
| 647 int CallSize(Register target) { |
| 648 // Opcode: REX_opt FF /2 m64 |
| 649 return (target.high_bit() != 0) ? 3 : 2; |
| 650 } |
| 651 int CallSize(const Operand& target) { |
| 652 // Opcode: REX_opt FF /2 m64 |
| 653 return (target.requires_rex() ? 2 : 1) + target.operand_size(); |
| 654 } |
| 655 |
| 612 // Emit call to the code we are currently generating. | 656 // Emit call to the code we are currently generating. |
| 613 void CallSelf() { | 657 void CallSelf() { |
| 614 Handle<Code> self(reinterpret_cast<Code**>(CodeObject().location())); | 658 Handle<Code> self(reinterpret_cast<Code**>(CodeObject().location())); |
| 615 Call(self, RelocInfo::CODE_TARGET); | 659 Call(self, RelocInfo::CODE_TARGET); |
| 616 } | 660 } |
| 617 | 661 |
| 618 // Non-x64 instructions. | 662 // Non-x64 instructions. |
| 619 // Push/pop all general purpose registers. | 663 // Push/pop all general purpose registers. |
| 620 // Does not push rsp/rbp nor any of the assembler's special purpose registers | 664 // Does not push rsp/rbp nor any of the assembler's special purpose registers |
| 621 // (kScratchRegister, kSmiConstantRegister, kRootRegister). | 665 // (kScratchRegister, kSmiConstantRegister, kRootRegister). |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 658 void FCmp(); | 702 void FCmp(); |
| 659 | 703 |
| 660 // Abort execution if argument is not a number. Used in debug code. | 704 // Abort execution if argument is not a number. Used in debug code. |
| 661 void AbortIfNotNumber(Register object); | 705 void AbortIfNotNumber(Register object); |
| 662 | 706 |
| 663 // Abort execution if argument is a smi. Used in debug code. | 707 // Abort execution if argument is a smi. Used in debug code. |
| 664 void AbortIfSmi(Register object); | 708 void AbortIfSmi(Register object); |
| 665 | 709 |
| 666 // Abort execution if argument is not a smi. Used in debug code. | 710 // Abort execution if argument is not a smi. Used in debug code. |
| 667 void AbortIfNotSmi(Register object); | 711 void AbortIfNotSmi(Register object); |
| 712 void AbortIfNotSmi(const Operand& object); |
| 668 | 713 |
| 669 // Abort execution if argument is a string. Used in debug code. | 714 // Abort execution if argument is a string. Used in debug code. |
| 670 void AbortIfNotString(Register object); | 715 void AbortIfNotString(Register object); |
| 671 | 716 |
| 672 // Abort execution if argument is not the root value with the given index. | 717 // Abort execution if argument is not the root value with the given index. |
| 673 void AbortIfNotRootValue(Register src, | 718 void AbortIfNotRootValue(Register src, |
| 674 Heap::RootListIndex root_value_index, | 719 Heap::RootListIndex root_value_index, |
| 675 const char* message); | 720 const char* message); |
| 676 | 721 |
| 677 // --------------------------------------------------------------------------- | 722 // --------------------------------------------------------------------------- |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 897 | 942 |
| 898 // Prepares stack to put arguments (aligns and so on). | 943 // Prepares stack to put arguments (aligns and so on). |
| 899 // WIN64 calling convention requires to put the pointer to the return value | 944 // WIN64 calling convention requires to put the pointer to the return value |
| 900 // slot into rcx (rcx must be preserverd until TryCallApiFunctionAndReturn). | 945 // slot into rcx (rcx must be preserverd until TryCallApiFunctionAndReturn). |
| 901 // Saves context (rsi). Clobbers rax. Allocates arg_stack_space * kPointerSize | 946 // Saves context (rsi). Clobbers rax. Allocates arg_stack_space * kPointerSize |
| 902 // inside the exit frame (not GCed) accessible via StackSpaceOperand. | 947 // inside the exit frame (not GCed) accessible via StackSpaceOperand. |
| 903 void PrepareCallApiFunction(int arg_stack_space); | 948 void PrepareCallApiFunction(int arg_stack_space); |
| 904 | 949 |
| 905 // Calls an API function. Allocates HandleScope, extracts | 950 // Calls an API function. Allocates HandleScope, extracts |
| 906 // returned value from handle and propagates exceptions. | 951 // returned value from handle and propagates exceptions. |
| 907 // Clobbers r12, r14, rbx and caller-save registers. Restores context. | 952 // Clobbers r14, r15, rbx and caller-save registers. Restores context. |
| 908 // On return removes stack_space * kPointerSize (GCed). | 953 // On return removes stack_space * kPointerSize (GCed). |
| 909 MUST_USE_RESULT MaybeObject* TryCallApiFunctionAndReturn( | 954 MUST_USE_RESULT MaybeObject* TryCallApiFunctionAndReturn( |
| 910 ApiFunction* function, int stack_space); | 955 ApiFunction* function, int stack_space); |
| 911 | 956 |
| 912 // Before calling a C-function from generated code, align arguments on stack. | 957 // Before calling a C-function from generated code, align arguments on stack. |
| 913 // After aligning the frame, arguments must be stored in esp[0], esp[4], | 958 // After aligning the frame, arguments must be stored in esp[0], esp[4], |
| 914 // etc., not pushed. The argument count assumes all arguments are word sized. | 959 // etc., not pushed. The argument count assumes all arguments are word sized. |
| 915 // The number of slots reserved for arguments depends on platform. On Windows | 960 // The number of slots reserved for arguments depends on platform. On Windows |
| 916 // stack slots are reserved for the arguments passed in registers. On other | 961 // stack slots are reserved for the arguments passed in registers. On other |
| 917 // platforms stack slots are only reserved for the arguments actually passed | 962 // platforms stack slots are only reserved for the arguments actually passed |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 969 void CheckStackAlignment(); | 1014 void CheckStackAlignment(); |
| 970 | 1015 |
| 971 // Verify restrictions about code generated in stubs. | 1016 // Verify restrictions about code generated in stubs. |
| 972 void set_generating_stub(bool value) { generating_stub_ = value; } | 1017 void set_generating_stub(bool value) { generating_stub_ = value; } |
| 973 bool generating_stub() { return generating_stub_; } | 1018 bool generating_stub() { return generating_stub_; } |
| 974 void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; } | 1019 void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; } |
| 975 bool allow_stub_calls() { return allow_stub_calls_; } | 1020 bool allow_stub_calls() { return allow_stub_calls_; } |
| 976 | 1021 |
| 977 private: | 1022 private: |
| 978 // Order general registers are pushed by Pushad. | 1023 // Order general registers are pushed by Pushad. |
| 979 // rax, rcx, rdx, rbx, rsi, rdi, r8, r9, r11, r12, r14. | 1024 // rax, rcx, rdx, rbx, rsi, rdi, r8, r9, r11, r14, r15. |
| 980 static int kSafepointPushRegisterIndices[Register::kNumRegisters]; | 1025 static int kSafepointPushRegisterIndices[Register::kNumRegisters]; |
| 981 static const int kNumSafepointSavedRegisters = 11; | 1026 static const int kNumSafepointSavedRegisters = 11; |
| 982 | 1027 |
| 983 bool generating_stub_; | 1028 bool generating_stub_; |
| 984 bool allow_stub_calls_; | 1029 bool allow_stub_calls_; |
| 985 | 1030 |
| 986 // Returns a register holding the smi value. The register MUST NOT be | 1031 // Returns a register holding the smi value. The register MUST NOT be |
| 987 // modified. It may be the "smi 1 constant" register. | 1032 // modified. It may be the "smi 1 constant" register. |
| 988 Register GetSmiConstant(Smi* value); | 1033 Register GetSmiConstant(Smi* value); |
| 989 | 1034 |
| 990 // Moves the smi value to the destination register. | 1035 // Moves the smi value to the destination register. |
| 991 void LoadSmiConstant(Register dst, Smi* value); | 1036 void LoadSmiConstant(Register dst, Smi* value); |
| 992 | 1037 |
| 993 // This handle will be patched with the code object on installation. | 1038 // This handle will be patched with the code object on installation. |
| 994 Handle<Object> code_object_; | 1039 Handle<Object> code_object_; |
| 995 | 1040 |
| 996 // Helper functions for generating invokes. | 1041 // Helper functions for generating invokes. |
| 997 template <typename LabelType> | 1042 template <typename LabelType> |
| 998 void InvokePrologue(const ParameterCount& expected, | 1043 void InvokePrologue(const ParameterCount& expected, |
| 999 const ParameterCount& actual, | 1044 const ParameterCount& actual, |
| 1000 Handle<Code> code_constant, | 1045 Handle<Code> code_constant, |
| 1001 Register code_register, | 1046 Register code_register, |
| 1002 LabelType* done, | 1047 LabelType* done, |
| 1003 InvokeFlag flag); | 1048 InvokeFlag flag, |
| 1049 CallWrapper* call_wrapper); |
| 1004 | 1050 |
| 1005 // Activation support. | 1051 // Activation support. |
| 1006 void EnterFrame(StackFrame::Type type); | 1052 void EnterFrame(StackFrame::Type type); |
| 1007 void LeaveFrame(StackFrame::Type type); | 1053 void LeaveFrame(StackFrame::Type type); |
| 1008 | 1054 |
| 1009 void EnterExitFramePrologue(bool save_rax); | 1055 void EnterExitFramePrologue(bool save_rax); |
| 1010 | 1056 |
| 1011 // Allocates arg_stack_space * kPointerSize memory (not GCed) on the stack | 1057 // Allocates arg_stack_space * kPointerSize memory (not GCed) on the stack |
| 1012 // accessible via StackSpaceOperand. | 1058 // accessible via StackSpaceOperand. |
| 1013 void EnterExitFrameEpilogue(int arg_stack_space, bool save_doubles); | 1059 void EnterExitFrameEpilogue(int arg_stack_space, bool save_doubles); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1024 // Update allocation top with value in result_end register. | 1070 // Update allocation top with value in result_end register. |
| 1025 // If scratch is valid, it contains the address of the allocation top. | 1071 // If scratch is valid, it contains the address of the allocation top. |
| 1026 void UpdateAllocationTopHelper(Register result_end, Register scratch); | 1072 void UpdateAllocationTopHelper(Register result_end, Register scratch); |
| 1027 | 1073 |
| 1028 // Helper for PopHandleScope. Allowed to perform a GC and returns | 1074 // Helper for PopHandleScope. Allowed to perform a GC and returns |
| 1029 // NULL if gc_allowed. Does not perform a GC if !gc_allowed, and | 1075 // NULL if gc_allowed. Does not perform a GC if !gc_allowed, and |
| 1030 // possibly returns a failure object indicating an allocation failure. | 1076 // possibly returns a failure object indicating an allocation failure. |
| 1031 Object* PopHandleScopeHelper(Register saved, | 1077 Object* PopHandleScopeHelper(Register saved, |
| 1032 Register scratch, | 1078 Register scratch, |
| 1033 bool gc_allowed); | 1079 bool gc_allowed); |
| 1080 |
| 1081 |
| 1082 // Compute memory operands for safepoint stack slots. |
| 1083 Operand SafepointRegisterSlot(Register reg); |
| 1084 static int SafepointRegisterStackIndex(int reg_code) { |
| 1085 return kNumSafepointRegisters - kSafepointPushRegisterIndices[reg_code] - 1; |
| 1086 } |
| 1087 |
| 1088 // Needs access to SafepointRegisterStackIndex for optimized frame |
| 1089 // traversal. |
| 1090 friend class OptimizedFrame; |
| 1034 }; | 1091 }; |
| 1035 | 1092 |
| 1036 | 1093 |
| 1037 // The code patcher is used to patch (typically) small parts of code e.g. for | 1094 // The code patcher is used to patch (typically) small parts of code e.g. for |
| 1038 // debugging and other types of instrumentation. When using the code patcher | 1095 // debugging and other types of instrumentation. When using the code patcher |
| 1039 // the exact number of bytes specified must be emitted. Is not legal to emit | 1096 // the exact number of bytes specified must be emitted. Is not legal to emit |
| 1040 // relocation information. If any of these constraints are violated it causes | 1097 // relocation information. If any of these constraints are violated it causes |
| 1041 // an assertion. | 1098 // an assertion. |
| 1042 class CodePatcher { | 1099 class CodePatcher { |
| 1043 public: | 1100 public: |
| 1044 CodePatcher(byte* address, int size); | 1101 CodePatcher(byte* address, int size); |
| 1045 virtual ~CodePatcher(); | 1102 virtual ~CodePatcher(); |
| 1046 | 1103 |
| 1047 // Macro assembler to emit code. | 1104 // Macro assembler to emit code. |
| 1048 MacroAssembler* masm() { return &masm_; } | 1105 MacroAssembler* masm() { return &masm_; } |
| 1049 | 1106 |
| 1050 private: | 1107 private: |
| 1051 byte* address_; // The address of the code being patched. | 1108 byte* address_; // The address of the code being patched. |
| 1052 int size_; // Number of bytes of the expected patch size. | 1109 int size_; // Number of bytes of the expected patch size. |
| 1053 MacroAssembler masm_; // Macro assembler used to generate the code. | 1110 MacroAssembler masm_; // Macro assembler used to generate the code. |
| 1054 }; | 1111 }; |
| 1055 | 1112 |
| 1056 | 1113 |
| 1114 // Helper class for generating code or data associated with the code |
| 1115 // right before or after a call instruction. As an example this can be used to |
| 1116 // generate safepoint data after calls for crankshaft. |
| 1117 class CallWrapper { |
| 1118 public: |
| 1119 CallWrapper() { } |
| 1120 virtual ~CallWrapper() { } |
| 1121 // Called just before emitting a call. Argument is the size of the generated |
| 1122 // call code. |
| 1123 virtual void BeforeCall(int call_size) = 0; |
| 1124 // Called just after emitting a call, i.e., at the return site for the call. |
| 1125 virtual void AfterCall() = 0; |
| 1126 }; |
| 1127 |
| 1128 |
| 1057 // ----------------------------------------------------------------------------- | 1129 // ----------------------------------------------------------------------------- |
| 1058 // Static helper functions. | 1130 // Static helper functions. |
| 1059 | 1131 |
| 1060 // Generate an Operand for loading a field from an object. | 1132 // Generate an Operand for loading a field from an object. |
| 1061 static inline Operand FieldOperand(Register object, int offset) { | 1133 static inline Operand FieldOperand(Register object, int offset) { |
| 1062 return Operand(object, offset - kHeapObjectTag); | 1134 return Operand(object, offset - kHeapObjectTag); |
| 1063 } | 1135 } |
| 1064 | 1136 |
| 1065 | 1137 |
| 1066 // Generate an Operand for loading an indexed field from an object. | 1138 // Generate an Operand for loading an indexed field from an object. |
| (...skipping 686 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1753 } | 1825 } |
| 1754 } | 1826 } |
| 1755 | 1827 |
| 1756 | 1828 |
| 1757 template <typename LabelType> | 1829 template <typename LabelType> |
| 1758 void MacroAssembler::InvokePrologue(const ParameterCount& expected, | 1830 void MacroAssembler::InvokePrologue(const ParameterCount& expected, |
| 1759 const ParameterCount& actual, | 1831 const ParameterCount& actual, |
| 1760 Handle<Code> code_constant, | 1832 Handle<Code> code_constant, |
| 1761 Register code_register, | 1833 Register code_register, |
| 1762 LabelType* done, | 1834 LabelType* done, |
| 1763 InvokeFlag flag) { | 1835 InvokeFlag flag, |
| 1836 CallWrapper* call_wrapper) { |
| 1764 bool definitely_matches = false; | 1837 bool definitely_matches = false; |
| 1765 NearLabel invoke; | 1838 NearLabel invoke; |
| 1766 if (expected.is_immediate()) { | 1839 if (expected.is_immediate()) { |
| 1767 ASSERT(actual.is_immediate()); | 1840 ASSERT(actual.is_immediate()); |
| 1768 if (expected.immediate() == actual.immediate()) { | 1841 if (expected.immediate() == actual.immediate()) { |
| 1769 definitely_matches = true; | 1842 definitely_matches = true; |
| 1770 } else { | 1843 } else { |
| 1771 Set(rax, actual.immediate()); | 1844 Set(rax, actual.immediate()); |
| 1772 if (expected.immediate() == | 1845 if (expected.immediate() == |
| 1773 SharedFunctionInfo::kDontAdaptArgumentsSentinel) { | 1846 SharedFunctionInfo::kDontAdaptArgumentsSentinel) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1803 Handle<Code> adaptor = | 1876 Handle<Code> adaptor = |
| 1804 Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)); | 1877 Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)); |
| 1805 if (!code_constant.is_null()) { | 1878 if (!code_constant.is_null()) { |
| 1806 movq(rdx, code_constant, RelocInfo::EMBEDDED_OBJECT); | 1879 movq(rdx, code_constant, RelocInfo::EMBEDDED_OBJECT); |
| 1807 addq(rdx, Immediate(Code::kHeaderSize - kHeapObjectTag)); | 1880 addq(rdx, Immediate(Code::kHeaderSize - kHeapObjectTag)); |
| 1808 } else if (!code_register.is(rdx)) { | 1881 } else if (!code_register.is(rdx)) { |
| 1809 movq(rdx, code_register); | 1882 movq(rdx, code_register); |
| 1810 } | 1883 } |
| 1811 | 1884 |
| 1812 if (flag == CALL_FUNCTION) { | 1885 if (flag == CALL_FUNCTION) { |
| 1886 if (call_wrapper != NULL) call_wrapper->BeforeCall(CallSize(adaptor)); |
| 1813 Call(adaptor, RelocInfo::CODE_TARGET); | 1887 Call(adaptor, RelocInfo::CODE_TARGET); |
| 1888 if (call_wrapper != NULL) call_wrapper->AfterCall(); |
| 1814 jmp(done); | 1889 jmp(done); |
| 1815 } else { | 1890 } else { |
| 1816 Jump(adaptor, RelocInfo::CODE_TARGET); | 1891 Jump(adaptor, RelocInfo::CODE_TARGET); |
| 1817 } | 1892 } |
| 1818 bind(&invoke); | 1893 bind(&invoke); |
| 1819 } | 1894 } |
| 1820 } | 1895 } |
| 1821 | 1896 |
| 1822 | 1897 |
| 1823 } } // namespace v8::internal | 1898 } } // namespace v8::internal |
| 1824 | 1899 |
| 1825 #endif // V8_X64_MACRO_ASSEMBLER_X64_H_ | 1900 #endif // V8_X64_MACRO_ASSEMBLER_X64_H_ |
| OLD | NEW |