summaryrefslogtreecommitdiffstats
path: root/js/src/jit/JitCode.h
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit/JitCode.h')
-rw-r--r--js/src/jit/JitCode.h171
1 files changed, 171 insertions, 0 deletions
diff --git a/js/src/jit/JitCode.h b/js/src/jit/JitCode.h
new file mode 100644
index 0000000000..5a96445c12
--- /dev/null
+++ b/js/src/jit/JitCode.h
@@ -0,0 +1,171 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: set ts=8 sts=2 et sw=2 tw=80:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef jit_JitCode_h
+#define jit_JitCode_h
+
+#include "mozilla/MemoryReporting.h" // MallocSizeOf
+
+#include <stddef.h> // size_t
+#include <stdint.h> // uint8_t, uint32_t
+
+#include "jstypes.h"
+
+#include "gc/Allocator.h" // AllowGC
+#include "gc/Cell.h" // gc::TenuredCellWithNonGCPointer
+#include "js/TraceKind.h" // JS::TraceKind
+#include "js/UbiNode.h" // ubi::{TracerConcrete, Size, CourseType}
+
+namespace js {
+namespace jit {
+
+class ExecutablePool;
+class JitCode;
+class MacroAssembler;
+
+enum class CodeKind : uint8_t;
+
+// Header at start of raw code buffer
+struct JitCodeHeader {
+ // Link back to corresponding gcthing
+ JitCode* jitCode_;
+
+ void init(JitCode* jitCode);
+
+ static JitCodeHeader* FromExecutable(uint8_t* buffer) {
+ return (JitCodeHeader*)(buffer - sizeof(JitCodeHeader));
+ }
+};
+
+class JitCode : public gc::TenuredCellWithNonGCPointer<uint8_t> {
+ friend class gc::CellAllocator;
+
+ public:
+ // Raw code pointer, stored in the cell header.
+ uint8_t* raw() const { return headerPtr(); }
+
+ protected:
+ ExecutablePool* pool_;
+ uint32_t bufferSize_; // Total buffer size. Does not include headerSize_.
+ uint32_t insnSize_; // Instruction stream size.
+ uint32_t dataSize_; // Size of the read-only data area.
+ uint32_t jumpRelocTableBytes_; // Size of the jump relocation table.
+ uint32_t dataRelocTableBytes_; // Size of the data relocation table.
+ uint8_t headerSize_ : 5; // Number of bytes allocated before codeStart.
+ uint8_t kind_ : 3; // jit::CodeKind, for the memory reporters.
+ bool invalidated_ : 1; // Whether the code object has been invalidated.
+ // This is necessary to prevent GC tracing.
+ bool hasBytecodeMap_ : 1; // Whether the code object has been registered with
+ // native=>bytecode mapping tables.
+
+ JitCode() = delete;
+ JitCode(uint8_t* code, uint32_t bufferSize, uint32_t headerSize,
+ ExecutablePool* pool, CodeKind kind)
+ : TenuredCellWithNonGCPointer(code),
+ pool_(pool),
+ bufferSize_(bufferSize),
+ insnSize_(0),
+ dataSize_(0),
+ jumpRelocTableBytes_(0),
+ dataRelocTableBytes_(0),
+ headerSize_(headerSize),
+ kind_(uint8_t(kind)),
+ invalidated_(false),
+ hasBytecodeMap_(false) {
+ MOZ_ASSERT(CodeKind(kind_) == kind);
+ MOZ_ASSERT(headerSize_ == headerSize);
+ }
+
+ uint32_t dataOffset() const { return insnSize_; }
+ uint32_t jumpRelocTableOffset() const { return dataOffset() + dataSize_; }
+ uint32_t dataRelocTableOffset() const {
+ return jumpRelocTableOffset() + jumpRelocTableBytes_;
+ }
+
+ public:
+ uint8_t* rawEnd() const { return raw() + insnSize_; }
+ bool containsNativePC(const void* addr) const {
+ const uint8_t* addr_u8 = (const uint8_t*)addr;
+ return raw() <= addr_u8 && addr_u8 < rawEnd();
+ }
+ size_t instructionsSize() const { return insnSize_; }
+ size_t bufferSize() const { return bufferSize_; }
+ size_t headerSize() const { return headerSize_; }
+
+ void traceChildren(JSTracer* trc);
+ void finalize(JS::GCContext* gcx);
+ void setInvalidated() { invalidated_ = true; }
+
+ void setHasBytecodeMap() { hasBytecodeMap_ = true; }
+
+ // If this JitCode object has been, effectively, corrupted due to
+ // invalidation patching, then we have to remember this so we don't try and
+ // trace relocation entries that may now be corrupt.
+ bool invalidated() const { return !!invalidated_; }
+
+ template <typename T>
+ T as() const {
+ return JS_DATA_TO_FUNC_PTR(T, raw());
+ }
+
+ void copyFrom(MacroAssembler& masm);
+
+ static JitCode* FromExecutable(uint8_t* buffer) {
+ JitCode* code = JitCodeHeader::FromExecutable(buffer)->jitCode_;
+ MOZ_ASSERT(code->raw() == buffer);
+ return code;
+ }
+
+ static size_t offsetOfCode() { return offsetOfHeaderPtr(); }
+
+ uint8_t* jumpRelocTable() { return raw() + jumpRelocTableOffset(); }
+
+ // Allocates a new JitCode object which will be managed by the GC. If no
+ // object can be allocated, nullptr is returned. On failure, |pool| is
+ // automatically released, so the code may be freed.
+ template <AllowGC allowGC>
+ static JitCode* New(JSContext* cx, uint8_t* code, uint32_t totalSize,
+ uint32_t headerSize, ExecutablePool* pool, CodeKind kind);
+
+ public:
+ static const JS::TraceKind TraceKind = JS::TraceKind::JitCode;
+};
+
+} // namespace jit
+} // namespace js
+
+// JS::ubi::Nodes can point to js::jit::JitCode instances; they're js::gc::Cell
+// instances with no associated compartment.
+namespace JS {
+namespace ubi {
+template <>
+class Concrete<js::jit::JitCode> : TracerConcrete<js::jit::JitCode> {
+ protected:
+ explicit Concrete(js::jit::JitCode* ptr)
+ : TracerConcrete<js::jit::JitCode>(ptr) {}
+
+ public:
+ static void construct(void* storage, js::jit::JitCode* ptr) {
+ new (storage) Concrete(ptr);
+ }
+
+ CoarseType coarseType() const final { return CoarseType::Script; }
+
+ Size size(mozilla::MallocSizeOf mallocSizeOf) const override {
+ Size size = js::gc::Arena::thingSize(get().asTenured().getAllocKind());
+ size += get().bufferSize();
+ size += get().headerSize();
+ return size;
+ }
+
+ const char16_t* typeName() const override { return concreteTypeName; }
+ static const char16_t concreteTypeName[];
+};
+
+} // namespace ubi
+} // namespace JS
+
+#endif /* jit_JitCode_h */