Skip to content

Commit

Permalink
Partial arm64 JIT
Browse files Browse the repository at this point in the history
Summary:
It supports only a few instructions using a switch. Followups will
improve it.

Reviewed By: avp

Differential Revision: D61687434

fbshipit-source-id: 3949dd6b7c8962bb8e027765b1fe445d33debd03
  • Loading branch information
Tzvetan Mikov authored and facebook-github-bot committed Aug 27, 2024
1 parent 419a599 commit 505c9dd
Show file tree
Hide file tree
Showing 12 changed files with 531 additions and 575 deletions.
26 changes: 25 additions & 1 deletion include/hermes/VM/JIT/JIT.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,28 @@

#include "hermes/VM/JIT/Config.h"

#if HERMESVM_JIT

#if defined(__aarch64__) || defined(_M_ARM64)
#include "hermes/VM/JIT/arm64/JIT.h"
#elif defined(__x86_64__) || defined(_M_X64)
#include "hermes/VM/JIT/x86-64/JIT.h"
#endif

namespace hermes {
namespace vm {

#if defined(__aarch64__) || defined(_M_ARM64)
using arm64::JITContext;
#elif defined(__x86_64__) || defined(_M_X64)
using x86_64::JITContext;
#endif

} // namespace vm
} // namespace hermes

#else

#include "hermes/VM/CodeBlock.h"

namespace hermes {
Expand Down Expand Up @@ -60,11 +82,13 @@ class JITContext {
return false;
}

/// Whether to force jitting of all functions right away.
/// Set the flag to force jitting of all functions.
void setForceJIT(bool force) {}
};

} // namespace vm
} // namespace hermes

#endif // HERMESVM_JIT

#endif // HERMES_VM_JIT_JIT_H
111 changes: 111 additions & 0 deletions include/hermes/VM/JIT/arm64/JIT.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#ifndef HERMES_VM_JIT_ARM64_JIT_H
#define HERMES_VM_JIT_ARM64_JIT_H

#include "hermes/VM/CodeBlock.h"

namespace hermes {
namespace vm {
namespace arm64 {

/// All state related to JIT compilation.
class JITContext {
public:
/// Construct a JIT context. No executable memory is allocated before it is
/// needed.
/// \param enable whether JIT is enabled.
JITContext(bool enable);
~JITContext();

JITContext(const JITContext &) = delete;
void operator=(const JITContext &) = delete;

/// Compile a function to native code and return the native pointer. If the
/// function was previously compiled, return the existing body. If it cannot
/// be compiled, return nullptr.
inline JITCompiledFunctionPtr compile(Runtime &runtime, CodeBlock *codeBlock);

/// \return true if JIT compilation is enabled.
bool isEnabled() const {
return enabled_;
}

/// Enable or disable JIT compilation.
void setEnabled(bool enabled) {
enabled_ = enabled;
}

/// Enable or disable dumping JIT'ed Code.
void setDumpJITCode(bool dump) {
dumpJITCode_ = dump;
}

/// \return true if dumping JIT'ed Code is enabled.
bool getDumpJITCode() {
return dumpJITCode_;
}

/// Set the flag to fatally crash on JIT compilation errors.
void setCrashOnError(bool crash) {
crashOnError_ = crash;
}

/// \return true if we should fatally crash on JIT compilation errors.
bool getCrashOnError() {
return crashOnError_;
}

/// Set the flag to force jitting of all functions.
void setForceJIT(bool force) {
execThreshold_ = force ? 0 : DEFAULT_EXEC_THRESHOLD;
}

private:
/// Slow path that actually performs the compilation of the specified
/// CodeBlock.
JITCompiledFunctionPtr compileImpl(Runtime &runtime, CodeBlock *codeBlock);

private:
class Impl;
std::unique_ptr<Impl> impl_{};

/// Whether JIT compilation is enabled.
bool enabled_{false};
/// whether to dump JIT'ed code
bool dumpJITCode_{false};
/// whether to fatally crash on JIT compilation errors
bool crashOnError_{false};

/// Execution threshold before a function is compiled.
unsigned execThreshold_ = 0;

/// The JIT default threshold for function execution count
static constexpr uint32_t DEFAULT_EXEC_THRESHOLD = 0;
};

LLVM_ATTRIBUTE_ALWAYS_INLINE
inline JITCompiledFunctionPtr JITContext::compile(
Runtime &runtime,
CodeBlock *codeBlock) {
auto ptr = codeBlock->getJITCompiled();
if (LLVM_LIKELY(ptr))
return ptr;
if (LLVM_LIKELY(!enabled_))
return nullptr;
if (LLVM_LIKELY(codeBlock->getDontJIT()))
return nullptr;
if (LLVM_LIKELY(codeBlock->getExecutionCount() < DEFAULT_EXEC_THRESHOLD))
return nullptr;
return compileImpl(runtime, codeBlock);
}

} // namespace arm64
} // namespace vm
} // namespace hermes
#endif // HERMES_VM_JIT_ARM64_JIT_H
3 changes: 3 additions & 0 deletions lib/VM/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,9 @@ endif()
set(JITLIBS)
if (HERMESVM_ALLOW_JIT)
list(APPEND source_files
JIT/RuntimeOffsets.h
JIT/arm64/JitEmitter.cpp JIT/arm64/JitEmitter.h
JIT/arm64/JIT.cpp
)
set(JITLIBS asmjit)
endif ()
Expand Down
31 changes: 31 additions & 0 deletions lib/VM/JIT/RuntimeOffsets.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#ifndef HERMES_VM_JIT_X86_64_RUNTIMEOFFSETS_H
#define HERMES_VM_JIT_X86_64_RUNTIMEOFFSETS_H

#include "hermes/VM/Runtime.h"

namespace hermes {
namespace vm {

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Winvalid-offsetof"

struct RuntimeOffsets {
static constexpr uint32_t stackPointer = offsetof(Runtime, stackPointer_);
static constexpr uint32_t currentFrame = offsetof(Runtime, currentFrame_);
static constexpr uint32_t globalObject = offsetof(Runtime, global_);
static constexpr uint32_t thrownValue = offsetof(Runtime, thrownValue_);
};

#pragma GCC diagnostic pop

} // namespace vm
} // namespace hermes

#endif // HERMES_VM_JIT_X86_64_RUNTIMEOFFSETS_H
Loading

0 comments on commit 505c9dd

Please sign in to comment.