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. 33enum InvokeFlag { 34 CALL_FUNCTION, 35 JUMP_FUNCTION 36}; 37 38 39// Flags used for the AllocateInNewSpace functions. 40enum 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. 61const 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 93namespace v8 { 94namespace internal { 95 96class 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 129class AllowExternalCallThatCantCauseGC: public FrameScope { 130 public: 131 explicit AllowExternalCallThatCantCauseGC(MacroAssembler* masm) 132 : FrameScope(masm, StackFrame::NONE) { } 133}; 134 135 136class 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 156class 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 168class Comment { 169 public: 170 Comment(MacroAssembler*, const char*) {} 171}; 172 173#endif // DEBUG 174 175 176class 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