1 // Copyright 2012 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 #ifndef V8_MACRO_ASSEMBLER_H_ 29 #define V8_MACRO_ASSEMBLER_H_ 30 31 32 // Helper types to make boolean flag easier to read at call-site. 33 enum InvokeFlag { 34 CALL_FUNCTION, 35 JUMP_FUNCTION 36 }; 37 38 39 // Flags used for the AllocateInNewSpace functions. 40 enum AllocationFlags { 41 // No special flags. 42 NO_ALLOCATION_FLAGS = 0, 43 // Return the pointer to the allocated already tagged as a heap object. 44 TAG_OBJECT = 1 << 0, 45 // The content of the result register already contains the allocation top in 46 // new space. 47 RESULT_CONTAINS_TOP = 1 << 1, 48 // Specify that the requested size of the space to allocate is specified in 49 // words instead of bytes. 50 SIZE_IN_WORDS = 1 << 2, 51 // Align the allocation to a multiple of kDoubleSize 52 DOUBLE_ALIGNMENT = 1 << 3, 53 // Directly allocate in old pointer space 54 PRETENURE_OLD_POINTER_SPACE = 1 << 4, 55 // Directly allocate in old data space 56 PRETENURE_OLD_DATA_SPACE = 1 << 5 57 }; 58 59 60 // Invalid depth in prototype chain. 61 const int kInvalidProtoDepth = -1; 62 63 #if V8_TARGET_ARCH_IA32 64 #include "assembler.h" 65 #include "ia32/assembler-ia32.h" 66 #include "ia32/assembler-ia32-inl.h" 67 #include "code.h" // must be after assembler_*.h 68 #include "ia32/macro-assembler-ia32.h" 69 #elif V8_TARGET_ARCH_X64 70 #include "assembler.h" 71 #include "x64/assembler-x64.h" 72 #include "x64/assembler-x64-inl.h" 73 #include "code.h" // must be after assembler_*.h 74 #include "x64/macro-assembler-x64.h" 75 #elif V8_TARGET_ARCH_ARM 76 #include "arm/constants-arm.h" 77 #include "assembler.h" 78 #include "arm/assembler-arm.h" 79 #include "arm/assembler-arm-inl.h" 80 #include "code.h" // must be after assembler_*.h 81 #include "arm/macro-assembler-arm.h" 82 #elif V8_TARGET_ARCH_MIPS 83 #include "mips/constants-mips.h" 84 #include "assembler.h" 85 #include "mips/assembler-mips.h" 86 #include "mips/assembler-mips-inl.h" 87 #include "code.h" // must be after assembler_*.h 88 #include "mips/macro-assembler-mips.h" 89 #else 90 #error Unsupported target architecture. 91 #endif 92 93 namespace v8 { 94 namespace internal { 95 96 class FrameScope { 97 public: 98 explicit FrameScope(MacroAssembler* masm, StackFrame::Type type) 99 : masm_(masm), type_(type), old_has_frame_(masm->has_frame()) { 100 masm->set_has_frame(true); 101 if (type != StackFrame::MANUAL && type_ != StackFrame::NONE) { 102 masm->EnterFrame(type); 103 } 104 } 105 106 ~FrameScope() { 107 if (type_ != StackFrame::MANUAL && type_ != StackFrame::NONE) { 108 masm_->LeaveFrame(type_); 109 } 110 masm_->set_has_frame(old_has_frame_); 111 } 112 113 // Normally we generate the leave-frame code when this object goes 114 // out of scope. Sometimes we may need to generate the code somewhere else 115 // in addition. Calling this will achieve that, but the object stays in 116 // scope, the MacroAssembler is still marked as being in a frame scope, and 117 // the code will be generated again when it goes out of scope. 118 void GenerateLeaveFrame() { 119 masm_->LeaveFrame(type_); 120 } 121 122 private: 123 MacroAssembler* masm_; 124 StackFrame::Type type_; 125 bool old_has_frame_; 126 }; 127 128 129 class AllowExternalCallThatCantCauseGC: public FrameScope { 130 public: 131 explicit AllowExternalCallThatCantCauseGC(MacroAssembler* masm) 132 : FrameScope(masm, StackFrame::NONE) { } 133 }; 134 135 136 class NoCurrentFrameScope { 137 public: 138 explicit NoCurrentFrameScope(MacroAssembler* masm) 139 : masm_(masm), saved_(masm->has_frame()) { 140 masm->set_has_frame(false); 141 } 142 143 ~NoCurrentFrameScope() { 144 masm_->set_has_frame(saved_); 145 } 146 147 private: 148 MacroAssembler* masm_; 149 bool saved_; 150 }; 151 152 153 // Support for "structured" code comments. 154 #ifdef DEBUG 155 156 class Comment { 157 public: 158 Comment(MacroAssembler* masm, const char* msg); 159 ~Comment(); 160 161 private: 162 MacroAssembler* masm_; 163 const char* msg_; 164 }; 165 166 #else 167 168 class Comment { 169 public: 170 Comment(MacroAssembler*, const char*) {} 171 }; 172 173 #endif // DEBUG 174 175 176 class AllocationUtils { 177 public: 178 static ExternalReference GetAllocationTopReference( 179 Isolate* isolate, AllocationFlags flags) { 180 if ((flags & PRETENURE_OLD_POINTER_SPACE) != 0) { 181 return ExternalReference::old_pointer_space_allocation_top_address( 182 isolate); 183 } else if ((flags & PRETENURE_OLD_DATA_SPACE) != 0) { 184 return ExternalReference::old_data_space_allocation_top_address(isolate); 185 } 186 return ExternalReference::new_space_allocation_top_address(isolate); 187 } 188 189 190 static ExternalReference GetAllocationLimitReference( 191 Isolate* isolate, AllocationFlags flags) { 192 if ((flags & PRETENURE_OLD_POINTER_SPACE) != 0) { 193 return ExternalReference::old_pointer_space_allocation_limit_address( 194 isolate); 195 } else if ((flags & PRETENURE_OLD_DATA_SPACE) != 0) { 196 return ExternalReference::old_data_space_allocation_limit_address( 197 isolate); 198 } 199 return ExternalReference::new_space_allocation_limit_address(isolate); 200 } 201 }; 202 203 204 } } // namespace v8::internal 205 206 #endif // V8_MACRO_ASSEMBLER_H_ 207