Bug 1874684 - Part 31: Correctly reject invalid durations in some RoundDuration calls...
[gecko.git] / js / src / jit / JitCode.h
blob58968a469c77cc887c4cd23be6577a2d4d8ee75f
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/. */
7 #ifndef jit_JitCode_h
8 #define jit_JitCode_h
10 #include "mozilla/MemoryReporting.h" // MallocSizeOf
12 #include <stddef.h> // size_t
13 #include <stdint.h> // uint8_t, uint32_t
15 #include "jstypes.h"
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}
22 namespace js {
23 namespace jit {
25 class ExecutablePool;
26 class JitCode;
27 class MacroAssembler;
29 enum class CodeKind : uint8_t;
31 // Header at start of raw code buffer
32 struct JitCodeHeader {
33 // Link back to corresponding gcthing
34 JitCode* jitCode_;
36 void init(JitCode* jitCode);
38 static JitCodeHeader* FromExecutable(uint8_t* buffer) {
39 return (JitCodeHeader*)(buffer - sizeof(JitCodeHeader));
43 class JitCode : public gc::TenuredCellWithNonGCPointer<uint8_t> {
44 friend class gc::CellAllocator;
46 public:
47 // Raw code pointer, stored in the cell header.
48 uint8_t* raw() const { return headerPtr(); }
50 protected:
51 ExecutablePool* pool_;
52 uint32_t bufferSize_; // Total buffer size. Does not include headerSize_.
53 uint32_t insnSize_; // Instruction stream size.
54 uint32_t dataSize_; // Size of the read-only data area.
55 uint32_t jumpRelocTableBytes_; // Size of the jump relocation table.
56 uint32_t dataRelocTableBytes_; // Size of the data relocation table.
57 uint8_t headerSize_ : 5; // Number of bytes allocated before codeStart.
58 uint8_t kind_ : 3; // jit::CodeKind, for the memory reporters.
59 bool invalidated_ : 1; // Whether the code object has been invalidated.
60 // This is necessary to prevent GC tracing.
61 bool hasBytecodeMap_ : 1; // Whether the code object has been registered with
62 // native=>bytecode mapping tables.
63 uint8_t localTracingSlots_;
65 JitCode() = delete;
66 JitCode(uint8_t* code, uint32_t bufferSize, uint32_t headerSize,
67 ExecutablePool* pool, CodeKind kind)
68 : TenuredCellWithNonGCPointer(code),
69 pool_(pool),
70 bufferSize_(bufferSize),
71 insnSize_(0),
72 dataSize_(0),
73 jumpRelocTableBytes_(0),
74 dataRelocTableBytes_(0),
75 headerSize_(headerSize),
76 kind_(uint8_t(kind)),
77 invalidated_(false),
78 hasBytecodeMap_(false),
79 localTracingSlots_(0) {
80 MOZ_ASSERT(CodeKind(kind_) == kind);
81 MOZ_ASSERT(headerSize_ == headerSize);
84 uint32_t dataOffset() const { return insnSize_; }
85 uint32_t jumpRelocTableOffset() const { return dataOffset() + dataSize_; }
86 uint32_t dataRelocTableOffset() const {
87 return jumpRelocTableOffset() + jumpRelocTableBytes_;
90 public:
91 uint8_t* rawEnd() const { return raw() + insnSize_; }
92 bool containsNativePC(const void* addr) const {
93 const uint8_t* addr_u8 = (const uint8_t*)addr;
94 return raw() <= addr_u8 && addr_u8 < rawEnd();
96 size_t instructionsSize() const { return insnSize_; }
97 size_t bufferSize() const { return bufferSize_; }
98 size_t headerSize() const { return headerSize_; }
100 void traceChildren(JSTracer* trc);
101 void finalize(JS::GCContext* gcx);
102 void setInvalidated() { invalidated_ = true; }
104 void setHasBytecodeMap() { hasBytecodeMap_ = true; }
106 void setLocalTracingSlots(uint8_t localTracingSlots) {
107 localTracingSlots_ = localTracingSlots;
110 uint8_t localTracingSlots() { return localTracingSlots_; }
112 // If this JitCode object has been, effectively, corrupted due to
113 // invalidation patching, then we have to remember this so we don't try and
114 // trace relocation entries that may now be corrupt.
115 bool invalidated() const { return !!invalidated_; }
117 template <typename T>
118 T as() const {
119 return JS_DATA_TO_FUNC_PTR(T, raw());
122 void copyFrom(MacroAssembler& masm);
124 static JitCode* FromExecutable(uint8_t* buffer) {
125 JitCode* code = JitCodeHeader::FromExecutable(buffer)->jitCode_;
126 MOZ_ASSERT(code->raw() == buffer);
127 return code;
130 static size_t offsetOfCode() { return offsetOfHeaderPtr(); }
132 uint8_t* jumpRelocTable() { return raw() + jumpRelocTableOffset(); }
134 // Allocates a new JitCode object which will be managed by the GC. If no
135 // object can be allocated, nullptr is returned. On failure, |pool| is
136 // automatically released, so the code may be freed.
137 template <AllowGC allowGC>
138 static JitCode* New(JSContext* cx, uint8_t* code, uint32_t totalSize,
139 uint32_t headerSize, ExecutablePool* pool, CodeKind kind);
141 public:
142 static const JS::TraceKind TraceKind = JS::TraceKind::JitCode;
145 } // namespace jit
146 } // namespace js
148 // JS::ubi::Nodes can point to js::jit::JitCode instances; they're js::gc::Cell
149 // instances with no associated compartment.
150 namespace JS {
151 namespace ubi {
152 template <>
153 class Concrete<js::jit::JitCode> : TracerConcrete<js::jit::JitCode> {
154 protected:
155 explicit Concrete(js::jit::JitCode* ptr)
156 : TracerConcrete<js::jit::JitCode>(ptr) {}
158 public:
159 static void construct(void* storage, js::jit::JitCode* ptr) {
160 new (storage) Concrete(ptr);
163 CoarseType coarseType() const final { return CoarseType::Script; }
165 Size size(mozilla::MallocSizeOf mallocSizeOf) const override {
166 Size size = js::gc::Arena::thingSize(get().asTenured().getAllocKind());
167 size += get().bufferSize();
168 size += get().headerSize();
169 return size;
172 const char16_t* typeName() const override { return concreteTypeName; }
173 static const char16_t concreteTypeName[];
176 } // namespace ubi
177 } // namespace JS
179 #endif /* jit_JitCode_h */