JitCode.h (6163B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef jit_JitCode_h 8 #define jit_JitCode_h 9 10 #include "mozilla/MemoryReporting.h" // MallocSizeOf 11 12 #include <stddef.h> // size_t 13 #include <stdint.h> // uint8_t, uint32_t 14 15 #include "jstypes.h" 16 17 #include "gc/Cell.h" // gc::TenuredCellWithNonGCPointer 18 #include "gc/GCEnum.h" // AllowGC 19 #include "js/TraceKind.h" // JS::TraceKind 20 #include "js/UbiNode.h" // ubi::{TracerConcrete, Size, CourseType} 21 22 namespace js { 23 namespace jit { 24 25 class ExecutablePool; 26 class JitCode; 27 class MacroAssembler; 28 29 enum class CodeKind : uint8_t; 30 31 // Header at start of raw code buffer 32 struct JitCodeHeader { 33 // Link back to corresponding gcthing 34 JitCode* jitCode_; 35 36 void init(JitCode* jitCode); 37 38 static JitCodeHeader* FromExecutable(uint8_t* buffer) { 39 return (JitCodeHeader*)(buffer - sizeof(JitCodeHeader)); 40 } 41 }; 42 43 class JitCode : public gc::TenuredCellWithNonGCPointer<uint8_t> { 44 friend class gc::CellAllocator; 45 46 public: 47 // Raw code pointer, stored in the cell header. 48 uint8_t* raw() const { return headerPtr(); } 49 50 // Raw pointer to the allocated memory to be able to modify the JitCodePointer 51 // which is stored above the code. 52 uint8_t* allocatedMemory() const { return headerPtr() - headerSize_; } 53 54 protected: 55 ExecutablePool* pool_; 56 uint32_t bufferSize_; // Total buffer size. Does not include headerSize_. 57 uint32_t insnSize_; // Instruction stream size. 58 uint32_t dataSize_; // Size of the read-only data area. 59 uint32_t jumpRelocTableBytes_; // Size of the jump relocation table. 60 uint32_t dataRelocTableBytes_; // Size of the data relocation table. 61 uint8_t headerSize_ : 5; // Number of bytes allocated before codeStart. 62 uint8_t kind_ : 3; // jit::CodeKind, for the memory reporters. 63 bool invalidated_ : 1; // Whether the code object has been invalidated. 64 // This is necessary to prevent GC tracing. 65 bool hasBytecodeMap_ : 1; // Whether the code object has been registered with 66 // native=>bytecode mapping tables. 67 uint8_t localTracingSlots_; 68 69 JitCode() = delete; 70 JitCode(uint8_t* code, uint32_t bufferSize, uint32_t headerSize, 71 ExecutablePool* pool, CodeKind kind) 72 : TenuredCellWithNonGCPointer(code), 73 pool_(pool), 74 bufferSize_(bufferSize), 75 insnSize_(0), 76 dataSize_(0), 77 jumpRelocTableBytes_(0), 78 dataRelocTableBytes_(0), 79 headerSize_(headerSize), 80 kind_(uint8_t(kind)), 81 invalidated_(false), 82 hasBytecodeMap_(false), 83 localTracingSlots_(0) { 84 MOZ_ASSERT(CodeKind(kind_) == kind); 85 MOZ_ASSERT(headerSize_ == headerSize); 86 } 87 88 uint32_t dataOffset() const { return insnSize_; } 89 uint32_t jumpRelocTableOffset() const { return dataOffset() + dataSize_; } 90 uint32_t dataRelocTableOffset() const { 91 return jumpRelocTableOffset() + jumpRelocTableBytes_; 92 } 93 94 public: 95 uint8_t* rawEnd() const { return raw() + insnSize_; } 96 bool containsNativePC(const void* addr) const { 97 const uint8_t* addr_u8 = (const uint8_t*)addr; 98 return raw() <= addr_u8 && addr_u8 < rawEnd(); 99 } 100 size_t instructionsSize() const { return insnSize_; } 101 size_t bufferSize() const { return bufferSize_; } 102 size_t headerSize() const { return headerSize_; } 103 size_t allocatedSize() const { return bufferSize_ + headerSize_; } 104 105 void traceChildren(JSTracer* trc); 106 void finalize(JS::GCContext* gcx); 107 void setInvalidated() { invalidated_ = true; } 108 109 void setHasBytecodeMap() { hasBytecodeMap_ = true; } 110 111 void setLocalTracingSlots(uint8_t localTracingSlots) { 112 localTracingSlots_ = localTracingSlots; 113 } 114 115 uint8_t localTracingSlots() { return localTracingSlots_; } 116 117 // If this JitCode object has been, effectively, corrupted due to 118 // invalidation patching, then we have to remember this so we don't try and 119 // trace relocation entries that may now be corrupt. 120 bool invalidated() const { return !!invalidated_; } 121 122 template <typename T> 123 T as() const { 124 return JS_DATA_TO_FUNC_PTR(T, raw()); 125 } 126 127 void copyFrom(MacroAssembler& masm); 128 129 static JitCode* FromExecutable(uint8_t* buffer) { 130 JitCode* code = JitCodeHeader::FromExecutable(buffer)->jitCode_; 131 MOZ_ASSERT(code->raw() == buffer); 132 return code; 133 } 134 135 static size_t offsetOfCode() { return offsetOfHeaderPtr(); } 136 137 uint8_t* jumpRelocTable() { return raw() + jumpRelocTableOffset(); } 138 139 // Allocates a new JitCode object which will be managed by the GC. If no 140 // object can be allocated, nullptr is returned. On failure, |pool| is 141 // automatically released, so the code may be freed. 142 template <AllowGC allowGC> 143 static JitCode* New(JSContext* cx, uint8_t* code, uint32_t totalSize, 144 uint32_t headerSize, ExecutablePool* pool, CodeKind kind); 145 146 public: 147 static const JS::TraceKind TraceKind = JS::TraceKind::JitCode; 148 }; 149 150 } // namespace jit 151 } // namespace js 152 153 // JS::ubi::Nodes can point to js::jit::JitCode instances; they're js::gc::Cell 154 // instances with no associated compartment. 155 namespace JS { 156 namespace ubi { 157 template <> 158 class Concrete<js::jit::JitCode> : TracerConcrete<js::jit::JitCode> { 159 protected: 160 explicit Concrete(js::jit::JitCode* ptr) 161 : TracerConcrete<js::jit::JitCode>(ptr) {} 162 163 public: 164 static void construct(void* storage, js::jit::JitCode* ptr) { 165 new (storage) Concrete(ptr); 166 } 167 168 CoarseType coarseType() const final { return CoarseType::Script; } 169 170 Size size(mozilla::MallocSizeOf mallocSizeOf) const override { 171 Size size = js::gc::Arena::thingSize(get().asTenured().getAllocKind()); 172 size += get().bufferSize(); 173 size += get().headerSize(); 174 return size; 175 } 176 177 const char16_t* typeName() const override { return concreteTypeName; } 178 static const char16_t concreteTypeName[]; 179 }; 180 181 } // namespace ubi 182 } // namespace JS 183 184 #endif /* jit_JitCode_h */