Home | History | Annotate | Download | only in src
      1 // Copyright 2018 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef V8_TURBO_ASSEMBLER_H_
      6 #define V8_TURBO_ASSEMBLER_H_
      7 
      8 #include "src/assembler-arch.h"
      9 #include "src/base/template-utils.h"
     10 #include "src/heap/heap.h"
     11 
     12 namespace v8 {
     13 namespace internal {
     14 
     15 // Common base class for platform-specific TurboAssemblers containing
     16 // platform-independent bits.
     17 class V8_EXPORT_PRIVATE TurboAssemblerBase : public Assembler {
     18  public:
     19   Isolate* isolate() const { return isolate_; }
     20 
     21   Handle<HeapObject> CodeObject() const {
     22     DCHECK(!code_object_.is_null());
     23     return code_object_;
     24   }
     25 
     26   bool root_array_available() const { return root_array_available_; }
     27   void set_root_array_available(bool v) { root_array_available_ = v; }
     28 
     29   bool trap_on_abort() const { return trap_on_abort_; }
     30 
     31   bool should_abort_hard() const { return hard_abort_; }
     32   void set_abort_hard(bool v) { hard_abort_ = v; }
     33 
     34   void set_builtin_index(int i) { maybe_builtin_index_ = i; }
     35 
     36   void set_has_frame(bool v) { has_frame_ = v; }
     37   bool has_frame() const { return has_frame_; }
     38 
     39   // Loads the given constant or external reference without embedding its direct
     40   // pointer. The produced code is isolate-independent.
     41   void IndirectLoadConstant(Register destination, Handle<HeapObject> object);
     42   void IndirectLoadExternalReference(Register destination,
     43                                      ExternalReference reference);
     44 
     45   virtual void LoadFromConstantsTable(Register destination,
     46                                       int constant_index) = 0;
     47 
     48   virtual void LoadRootRegisterOffset(Register destination,
     49                                       intptr_t offset) = 0;
     50   virtual void LoadRootRelative(Register destination, int32_t offset) = 0;
     51 
     52   virtual void LoadRoot(Register destination, Heap::RootListIndex index) = 0;
     53 
     54   static int32_t RootRegisterOffset(Heap::RootListIndex root_index);
     55   static int32_t RootRegisterOffsetForExternalReferenceIndex(
     56       int reference_index);
     57 
     58   static int32_t RootRegisterOffsetForBuiltinIndex(int builtin_index);
     59 
     60   static intptr_t RootRegisterOffsetForExternalReference(
     61       Isolate* isolate, const ExternalReference& reference);
     62 
     63   // An address is addressable through kRootRegister if it is located within
     64   // [isolate, roots_ + root_register_addressable_end_offset[.
     65   static bool IsAddressableThroughRootRegister(
     66       Isolate* isolate, const ExternalReference& reference);
     67 
     68  protected:
     69   TurboAssemblerBase(Isolate* isolate, const AssemblerOptions& options,
     70                      void* buffer, int buffer_size,
     71                      CodeObjectRequired create_code_object);
     72 
     73   void RecordCommentForOffHeapTrampoline(int builtin_index);
     74 
     75   Isolate* const isolate_ = nullptr;
     76 
     77   // This handle will be patched with the code object on installation.
     78   Handle<HeapObject> code_object_;
     79 
     80   // Whether kRootRegister has been initialized.
     81   bool root_array_available_ = true;
     82 
     83   // Immediately trap instead of calling {Abort} when debug code fails.
     84   bool trap_on_abort_ = FLAG_trap_on_abort;
     85 
     86   // Emit a C call to abort instead of a runtime call.
     87   bool hard_abort_ = false;
     88 
     89   // May be set while generating builtins.
     90   int maybe_builtin_index_ = Builtins::kNoBuiltinId;
     91 
     92   bool has_frame_ = false;
     93 
     94   DISALLOW_IMPLICIT_CONSTRUCTORS(TurboAssemblerBase);
     95 };
     96 
     97 // Avoids emitting calls to the {Builtins::kAbort} builtin when emitting debug
     98 // code during the lifetime of this scope object. For disabling debug code
     99 // entirely use the {DontEmitDebugCodeScope} instead.
    100 class HardAbortScope BASE_EMBEDDED {
    101  public:
    102   explicit HardAbortScope(TurboAssemblerBase* assembler)
    103       : assembler_(assembler), old_value_(assembler->should_abort_hard()) {
    104     assembler_->set_abort_hard(true);
    105   }
    106   ~HardAbortScope() { assembler_->set_abort_hard(old_value_); }
    107 
    108  private:
    109   TurboAssemblerBase* assembler_;
    110   bool old_value_;
    111 };
    112 
    113 // Helper stubs can be called in different ways depending on where the target
    114 // code is located and how the call sequence is expected to look like:
    115 //  - JavaScript: Call on-heap {Code} object via {RelocInfo::CODE_TARGET}.
    116 //  - WebAssembly: Call native {WasmCode} stub via {RelocInfo::WASM_STUB_CALL}.
    117 enum class StubCallMode { kCallOnHeapBuiltin, kCallWasmRuntimeStub };
    118 
    119 #ifdef DEBUG
    120 template <typename RegType, typename... RegTypes,
    121           // All arguments must be either Register or DoubleRegister.
    122           typename = typename std::enable_if<
    123               base::is_same<Register, RegType, RegTypes...>::value ||
    124               base::is_same<DoubleRegister, RegType, RegTypes...>::value>::type>
    125 inline bool AreAliased(RegType first_reg, RegTypes... regs) {
    126   int num_different_regs = NumRegs(RegType::ListOf(first_reg, regs...));
    127   int num_given_regs = sizeof...(regs) + 1;
    128   return num_different_regs < num_given_regs;
    129 }
    130 #endif
    131 
    132 }  // namespace internal
    133 }  // namespace v8
    134 
    135 #endif  // V8_TURBO_ASSEMBLER_H_
    136