macro-assembler.h 8.25 KB
Newer Older
1
// Copyright 2012 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
4 5 6 7

#ifndef V8_MACRO_ASSEMBLER_H_
#define V8_MACRO_ASSEMBLER_H_

8 9 10 11 12 13 14 15

// Helper types to make boolean flag easier to read at call-site.
enum InvokeFlag {
  CALL_FUNCTION,
  JUMP_FUNCTION
};


16 17 18 19 20 21 22 23 24 25 26 27 28
// Flags used for the AllocateInNewSpace functions.
enum AllocationFlags {
  // No special flags.
  NO_ALLOCATION_FLAGS = 0,
  // Return the pointer to the allocated already tagged as a heap object.
  TAG_OBJECT = 1 << 0,
  // The content of the result register already contains the allocation top in
  // new space.
  RESULT_CONTAINS_TOP = 1 << 1,
  // Specify that the requested size of the space to allocate is specified in
  // words instead of bytes.
  SIZE_IN_WORDS = 1 << 2,
  // Align the allocation to a multiple of kDoubleSize
29 30
  DOUBLE_ALIGNMENT = 1 << 3,
  // Directly allocate in old pointer space
31 32 33
  PRETENURE_OLD_POINTER_SPACE = 1 << 4,
  // Directly allocate in old data space
  PRETENURE_OLD_DATA_SPACE = 1 << 5
34 35 36
};


37 38
// Invalid depth in prototype chain.
const int kInvalidProtoDepth = -1;
39

40
#if V8_TARGET_ARCH_IA32
41 42 43
#include "src/assembler.h"
#include "src/ia32/assembler-ia32.h"
#include "src/ia32/assembler-ia32-inl.h"
44
#include "src/code.h"  // NOLINT, must be after assembler_*.h
45
#include "src/ia32/macro-assembler-ia32.h"
46
#elif V8_TARGET_ARCH_X64
47 48 49
#include "src/assembler.h"
#include "src/x64/assembler-x64.h"
#include "src/x64/assembler-x64-inl.h"
50
#include "src/code.h"  // NOLINT, must be after assembler_*.h
51
#include "src/x64/macro-assembler-x64.h"
52
#elif V8_TARGET_ARCH_ARM64
53 54
#include "src/arm64/constants-arm64.h"
#include "src/assembler.h"
55
#include "src/arm64/assembler-arm64.h"  // NOLINT
56
#include "src/arm64/assembler-arm64-inl.h"
57 58
#include "src/code.h"  // NOLINT, must be after assembler_*.h
#include "src/arm64/macro-assembler-arm64.h"  // NOLINT
59
#include "src/arm64/macro-assembler-arm64-inl.h"
60
#elif V8_TARGET_ARCH_ARM
61 62
#include "src/arm/constants-arm.h"
#include "src/assembler.h"
63
#include "src/arm/assembler-arm.h"  // NOLINT
64
#include "src/arm/assembler-arm-inl.h"
65 66
#include "src/code.h"                     // NOLINT, must be after assembler_*.h
#include "src/arm/macro-assembler-arm.h"  // NOLINT
67
#elif V8_TARGET_ARCH_MIPS
68
#include "src/mips/constants-mips.h"
69
#include "src/assembler.h"            // NOLINT
70
#include "src/mips/assembler-mips.h"  // NOLINT
71
#include "src/mips/assembler-mips-inl.h"
72
#include "src/code.h"  // NOLINT, must be after assembler_*.h
73
#include "src/mips/macro-assembler-mips.h"
74 75
#elif V8_TARGET_ARCH_MIPS64
#include "src/mips64/constants-mips64.h"
76
#include "src/assembler.h"                // NOLINT
77 78
#include "src/mips64/assembler-mips64.h"  // NOLINT
#include "src/mips64/assembler-mips64-inl.h"
79
#include "src/code.h"  // NOLINT, must be after assembler_*.h
80
#include "src/mips64/macro-assembler-mips64.h"
danno@chromium.org's avatar
danno@chromium.org committed
81
#elif V8_TARGET_ARCH_X87
82 83 84
#include "src/assembler.h"
#include "src/x87/assembler-x87.h"
#include "src/x87/assembler-x87-inl.h"
85
#include "src/code.h"  // NOLINT, must be after assembler_*.h
86
#include "src/x87/macro-assembler-x87.h"
87 88
#else
#error Unsupported target architecture.
89 90
#endif

91 92 93
namespace v8 {
namespace internal {

94 95 96
class FrameScope {
 public:
  explicit FrameScope(MacroAssembler* masm, StackFrame::Type type)
97
      : masm_(masm), type_(type), old_has_frame_(masm->has_frame()) {
98 99 100 101 102 103 104 105 106 107
    masm->set_has_frame(true);
    if (type != StackFrame::MANUAL && type_ != StackFrame::NONE) {
      masm->EnterFrame(type);
    }
  }

  ~FrameScope() {
    if (type_ != StackFrame::MANUAL && type_ != StackFrame::NONE) {
      masm_->LeaveFrame(type_);
    }
108
    masm_->set_has_frame(old_has_frame_);
109 110 111 112 113 114 115 116
  }

  // Normally we generate the leave-frame code when this object goes
  // out of scope.  Sometimes we may need to generate the code somewhere else
  // in addition.  Calling this will achieve that, but the object stays in
  // scope, the MacroAssembler is still marked as being in a frame scope, and
  // the code will be generated again when it goes out of scope.
  void GenerateLeaveFrame() {
117
    DCHECK(type_ != StackFrame::MANUAL && type_ != StackFrame::NONE);
118 119 120 121 122 123
    masm_->LeaveFrame(type_);
  }

 private:
  MacroAssembler* masm_;
  StackFrame::Type type_;
124
  bool old_has_frame_;
125 126
};

127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
class FrameAndConstantPoolScope {
 public:
  FrameAndConstantPoolScope(MacroAssembler* masm, StackFrame::Type type)
      : masm_(masm),
        type_(type),
        old_has_frame_(masm->has_frame()),
        old_constant_pool_available_(FLAG_enable_ool_constant_pool &&
                                     masm->is_ool_constant_pool_available()) {
    masm->set_has_frame(true);
    if (FLAG_enable_ool_constant_pool) {
      masm->set_ool_constant_pool_available(true);
    }
    if (type_ != StackFrame::MANUAL && type_ != StackFrame::NONE) {
      masm->EnterFrame(type, !old_constant_pool_available_);
    }
  }

  ~FrameAndConstantPoolScope() {
    masm_->LeaveFrame(type_);
    masm_->set_has_frame(old_has_frame_);
    if (FLAG_enable_ool_constant_pool) {
      masm_->set_ool_constant_pool_available(old_constant_pool_available_);
    }
  }

  // Normally we generate the leave-frame code when this object goes
  // out of scope.  Sometimes we may need to generate the code somewhere else
  // in addition.  Calling this will achieve that, but the object stays in
  // scope, the MacroAssembler is still marked as being in a frame scope, and
  // the code will be generated again when it goes out of scope.
  void GenerateLeaveFrame() {
    DCHECK(type_ != StackFrame::MANUAL && type_ != StackFrame::NONE);
    masm_->LeaveFrame(type_);
  }

 private:
  MacroAssembler* masm_;
  StackFrame::Type type_;
  bool old_has_frame_;
  bool old_constant_pool_available_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(FrameAndConstantPoolScope);
};

// Class for scoping the the unavailability of constant pool access.
class ConstantPoolUnavailableScope {
 public:
  explicit ConstantPoolUnavailableScope(MacroAssembler* masm)
      : masm_(masm),
        old_constant_pool_available_(FLAG_enable_ool_constant_pool &&
                                     masm->is_ool_constant_pool_available()) {
    if (FLAG_enable_ool_constant_pool) {
      masm_->set_ool_constant_pool_available(false);
    }
  }
  ~ConstantPoolUnavailableScope() {
    if (FLAG_enable_ool_constant_pool) {
      masm_->set_ool_constant_pool_available(old_constant_pool_available_);
    }
  }

 private:
  MacroAssembler* masm_;
  int old_constant_pool_available_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(ConstantPoolUnavailableScope);
};

195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219

class AllowExternalCallThatCantCauseGC: public FrameScope {
 public:
  explicit AllowExternalCallThatCantCauseGC(MacroAssembler* masm)
      : FrameScope(masm, StackFrame::NONE) { }
};


class NoCurrentFrameScope {
 public:
  explicit NoCurrentFrameScope(MacroAssembler* masm)
      : masm_(masm), saved_(masm->has_frame()) {
    masm->set_has_frame(false);
  }

  ~NoCurrentFrameScope() {
    masm_->set_has_frame(saved_);
  }

 private:
  MacroAssembler* masm_;
  bool saved_;
};


220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
// Support for "structured" code comments.
#ifdef DEBUG

class Comment {
 public:
  Comment(MacroAssembler* masm, const char* msg);
  ~Comment();

 private:
  MacroAssembler* masm_;
  const char* msg_;
};

#else

class Comment {
 public:
  Comment(MacroAssembler*, const char*)  {}
};

#endif  // DEBUG

242 243 244 245 246

class AllocationUtils {
 public:
  static ExternalReference GetAllocationTopReference(
      Isolate* isolate, AllocationFlags flags) {
247 248 249 250 251 252 253
    if ((flags & PRETENURE_OLD_POINTER_SPACE) != 0) {
      return ExternalReference::old_pointer_space_allocation_top_address(
          isolate);
    } else if ((flags & PRETENURE_OLD_DATA_SPACE) != 0) {
      return ExternalReference::old_data_space_allocation_top_address(isolate);
    }
    return ExternalReference::new_space_allocation_top_address(isolate);
254 255 256 257 258
  }


  static ExternalReference GetAllocationLimitReference(
      Isolate* isolate, AllocationFlags flags) {
259 260 261 262 263 264 265 266
    if ((flags & PRETENURE_OLD_POINTER_SPACE) != 0) {
      return ExternalReference::old_pointer_space_allocation_limit_address(
          isolate);
    } else if ((flags & PRETENURE_OLD_DATA_SPACE) != 0) {
      return ExternalReference::old_data_space_allocation_limit_address(
          isolate);
    }
    return ExternalReference::new_space_allocation_limit_address(isolate);
267 268 269 270
  }
};


271 272
} }  // namespace v8::internal

273
#endif  // V8_MACRO_ASSEMBLER_H_