From 505c9ddc6f6a9fd19b061e7dfb130e10e8fd7517 Mon Sep 17 00:00:00 2001 From: Tzvetan Mikov Date: Tue, 27 Aug 2024 09:55:03 -0700 Subject: [PATCH] Partial arm64 JIT Summary: It supports only a few instructions using a switch. Followups will improve it. Reviewed By: avp Differential Revision: D61687434 fbshipit-source-id: 3949dd6b7c8962bb8e027765b1fe445d33debd03 --- include/hermes/VM/JIT/JIT.h | 26 +- include/hermes/VM/JIT/arm64/JIT.h | 111 ++++++ lib/VM/CMakeLists.txt | 3 + lib/VM/JIT/RuntimeOffsets.h | 31 ++ lib/VM/JIT/arm64/JIT.cpp | 285 +++++++++++++++ .../VM/JIT/arm64/JitEmitter.cpp | 245 +++---------- .../expjit => lib/VM/JIT/arm64}/JitEmitter.h | 35 +- lib/VM/Runtime.cpp | 3 + tools/CMakeLists.txt | 3 - tools/expjit/CMakeLists.txt | 12 - tools/expjit/idisp-exp.c | 329 ------------------ tools/expjit/loop1-jit.h | 23 -- 12 files changed, 531 insertions(+), 575 deletions(-) create mode 100644 include/hermes/VM/JIT/arm64/JIT.h create mode 100644 lib/VM/JIT/RuntimeOffsets.h create mode 100644 lib/VM/JIT/arm64/JIT.cpp rename tools/expjit/idisp-jit.cpp => lib/VM/JIT/arm64/JitEmitter.cpp (85%) rename {tools/expjit => lib/VM/JIT/arm64}/JitEmitter.h (96%) delete mode 100644 tools/expjit/CMakeLists.txt delete mode 100644 tools/expjit/idisp-exp.c delete mode 100644 tools/expjit/loop1-jit.h diff --git a/include/hermes/VM/JIT/JIT.h b/include/hermes/VM/JIT/JIT.h index fcc63d6695b..0e14704356d 100644 --- a/include/hermes/VM/JIT/JIT.h +++ b/include/hermes/VM/JIT/JIT.h @@ -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 { @@ -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 diff --git a/include/hermes/VM/JIT/arm64/JIT.h b/include/hermes/VM/JIT/arm64/JIT.h new file mode 100644 index 00000000000..c37f4f879e2 --- /dev/null +++ b/include/hermes/VM/JIT/arm64/JIT.h @@ -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_{}; + + /// 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 diff --git a/lib/VM/CMakeLists.txt b/lib/VM/CMakeLists.txt index 2be7b721925..0fecdbec6a6 100644 --- a/lib/VM/CMakeLists.txt +++ b/lib/VM/CMakeLists.txt @@ -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 () diff --git a/lib/VM/JIT/RuntimeOffsets.h b/lib/VM/JIT/RuntimeOffsets.h new file mode 100644 index 00000000000..cdd2c6474c3 --- /dev/null +++ b/lib/VM/JIT/RuntimeOffsets.h @@ -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 diff --git a/lib/VM/JIT/arm64/JIT.cpp b/lib/VM/JIT/arm64/JIT.cpp new file mode 100644 index 00000000000..770a7b8008e --- /dev/null +++ b/lib/VM/JIT/arm64/JIT.cpp @@ -0,0 +1,285 @@ +/* + * 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. + */ + +#include "hermes/VM/JIT/Config.h" +#if HERMESVM_JIT +#include "hermes/VM/JIT/arm64/JIT.h" + +#include "JitEmitter.h" + +#include "hermes/Inst/InstDecode.h" +#include "hermes/VM/JIT/DiscoverBB.h" + +#define DEBUG_TYPE "jit" + +namespace hermes { +namespace vm { +namespace arm64 { + +class JITContext::Impl { + public: + asmjit::JitRuntime jr{}; +}; + +JITContext::JITContext(bool enable) : enabled_(enable) { + if (!enable) + return; + impl_ = std::make_unique(); +} + +JITContext::~JITContext() = default; + +// Calculate the address of the next instruction given the name of the +// current one. +#define NEXTINST(name) ((const inst::Inst *)(&ip->i##name + 1)) + +// Add an arbitrary byte offset to ip. +#define IPADD(val) ((const inst::Inst *)((const uint8_t *)ip + (val))) + +JITCompiledFunctionPtr JITContext::compileImpl( + Runtime &runtime, + CodeBlock *codeBlock) { + std::string funcName{}; + if (dumpJITCode_) { + funcName = codeBlock->getNameString(); + llvh::outs() << "\nJIT compilation of FunctionID " + << codeBlock->getFunctionID() << ", '" << funcName << "'\n"; + } + + std::vector basicBlocks{}; + llvh::DenseMap ofsToBBIndex{}; + + bool fail = false; + discoverBasicBlocks(codeBlock, basicBlocks, ofsToBBIndex); + + const char *funcStart = (const char *)codeBlock->begin(); + + if (dumpJITCode_ && !funcName.empty()) + llvh::outs() << "\n" << funcName << ":\n"; + + // TODO: is getFrameSize() the right thing to call? + Emitter em(impl_->jr, getDumpJITCode(), codeBlock->getFrameSize(), 0, 0); + std::vector labels{}; + labels.reserve(basicBlocks.size() - 1); + for (unsigned bbIndex = 0; bbIndex < basicBlocks.size() - 1; ++bbIndex) + labels.push_back(em.newPrefLabel("BB", bbIndex)); + + for (unsigned bbIndex = 0; bbIndex < basicBlocks.size() - 1; ++bbIndex) { + uint32_t startOfs = basicBlocks[bbIndex]; + uint32_t endOfs = basicBlocks[bbIndex + 1]; + + em.newBasicBlock(labels[bbIndex]); + auto *ip = reinterpret_cast(funcStart + startOfs); + auto *to = reinterpret_cast(funcStart + endOfs); + + while (ip != to) { + switch (ip->opCode) { + case inst::OpCode::LoadParam: + em.loadParam(FR(ip->iLoadParam.op1), ip->iLoadParam.op2); + ip = NEXTINST(LoadParam); + break; + case inst::OpCode::LoadConstZero: + em.loadConstUInt8(FR(ip->iLoadConstZero.op1), 0); + ip = NEXTINST(LoadConstZero); + break; + case inst::OpCode::LoadConstUInt8: + em.loadConstUInt8( + FR(ip->iLoadConstUInt8.op1), ip->iLoadConstUInt8.op2); + ip = NEXTINST(LoadConstUInt8); + break; + + case inst::OpCode::Mov: + em.mov(FR(ip->iMov.op1), FR(ip->iMov.op2)); + ip = NEXTINST(Mov); + break; + case inst::OpCode::ToNumber: + em.toNumber(FR(ip->iToNumber.op1), FR(ip->iToNumber.op2)); + ip = NEXTINST(ToNumber); + break; + + case inst::OpCode::Add: + em.add(FR(ip->iAdd.op1), FR(ip->iAdd.op2), FR(ip->iAdd.op3)); + ip = NEXTINST(Add); + break; + case inst::OpCode::AddN: + em.addN(FR(ip->iAdd.op1), FR(ip->iAdd.op2), FR(ip->iAdd.op3)); + ip = NEXTINST(Add); + break; + case inst::OpCode::Sub: + em.sub(FR(ip->iSub.op1), FR(ip->iSub.op2), FR(ip->iSub.op3)); + ip = NEXTINST(Add); + break; + case inst::OpCode::SubN: + em.subN(FR(ip->iSub.op1), FR(ip->iSub.op2), FR(ip->iSub.op3)); + ip = NEXTINST(SubN); + break; + case inst::OpCode::Mul: + em.mul(FR(ip->iMul.op1), FR(ip->iMul.op2), FR(ip->iMul.op3)); + ip = NEXTINST(Mul); + break; + case inst::OpCode::MulN: + em.mulN(FR(ip->iMul.op1), FR(ip->iMul.op2), FR(ip->iMul.op3)); + ip = NEXTINST(Mul); + break; + + case inst::OpCode::Dec: + em.dec(FR(ip->iDec.op1), FR(ip->iDec.op2)); + ip = NEXTINST(Dec); + break; + + case inst::OpCode::JGreaterEqual: + em.jGreaterEqual( + false, + labels[ofsToBBIndex + [(const char *)ip - (const char *)funcStart + + ip->iJGreaterEqual.op1]], + FR(ip->iJGreaterEqual.op2), + FR(ip->iJGreaterEqual.op3)); + ip = NEXTINST(JGreaterEqual); + break; + case inst::OpCode::JGreaterEqualN: + em.jGreaterEqualN( + false, + labels[ofsToBBIndex + [(const char *)ip - (const char *)funcStart + + ip->iJGreaterEqual.op1]], + FR(ip->iJGreaterEqual.op2), + FR(ip->iJGreaterEqual.op3)); + ip = NEXTINST(JGreaterEqual); + break; + case inst::OpCode::JNotGreaterEqual: + em.jGreaterEqual( + true, + labels[ofsToBBIndex + [(const char *)ip - (const char *)funcStart + + ip->iJNotGreaterEqual.op1]], + FR(ip->iJNotGreaterEqual.op2), + FR(ip->iJNotGreaterEqual.op3)); + ip = NEXTINST(JNotGreaterEqual); + break; + case inst::OpCode::JNotGreaterEqualN: + em.jGreaterEqualN( + true, + labels[ofsToBBIndex + [(const char *)ip - (const char *)funcStart + + ip->iJNotGreaterEqual.op1]], + FR(ip->iJNotGreaterEqual.op2), + FR(ip->iJNotGreaterEqual.op3)); + ip = NEXTINST(JNotGreaterEqual); + break; + case inst::OpCode::JGreater: + em.jGreater( + false, + labels[ofsToBBIndex + [(const char *)ip - (const char *)funcStart + + ip->iJGreater.op1]], + FR(ip->iJGreater.op2), + FR(ip->iJGreater.op3)); + ip = NEXTINST(JGreater); + break; + case inst::OpCode::JGreaterN: + em.jGreaterN( + false, + labels[ofsToBBIndex + [(const char *)ip - (const char *)funcStart + + ip->iJGreater.op1]], + FR(ip->iJGreater.op2), + FR(ip->iJGreater.op3)); + ip = NEXTINST(JGreater); + break; + case inst::OpCode::JNotGreater: + em.jGreater( + true, + labels[ofsToBBIndex + [(const char *)ip - (const char *)funcStart + + ip->iJNotGreater.op1]], + FR(ip->iJNotGreater.op2), + FR(ip->iJNotGreater.op3)); + ip = NEXTINST(JNotGreater); + break; + case inst::OpCode::JNotGreaterN: + em.jGreaterN( + true, + labels[ofsToBBIndex + [(const char *)ip - (const char *)funcStart + + ip->iJNotGreater.op1]], + FR(ip->iJNotGreater.op2), + FR(ip->iJNotGreater.op3)); + ip = NEXTINST(JNotGreater); + break; + + case inst::OpCode::Ret: + em.ret(FR(ip->iRet.op1)); + ip = NEXTINST(Ret); + break; + + default: + if (crashOnError_) { + llvh::errs() << "*** Unsupported instruction: " + << llvh::format_decimal( + (const char *)ip - (const char *)funcStart, 3) + << ": " << inst::decodeInstruction(ip) << "\n"; + hermes_fatal("jit: unsupported instruction"); + } else { + if (dumpJITCode_) { + llvh::outs() << "** Unsupported instruction: " + << llvh::format_decimal( + (const char *)ip - (const char *)funcStart, 3) + << ": " << inst::decodeInstruction(ip) << "\n"; + } else { + LLVM_DEBUG( + llvh::outs() + << "** Unsupported instruction: " + << llvh::format_decimal( + (const char *)ip - (const char *)funcStart, 3) + << ": " << inst::decodeInstruction(ip) << "\n"); + } + } + fail = true; + goto onError; + } + } + } + +onError: + if (fail) { + codeBlock->setDontJIT(true); + return nullptr; + } + + em.leave(); + codeBlock->setJITCompiled(em.addToRuntime(impl_->jr)); + + LLVM_DEBUG( + llvh::outs() << "\n Bytecode:"; + for (unsigned bbIndex = 0; bbIndex < basicBlocks.size() - 1; ++bbIndex) { + uint32_t startOfs = basicBlocks[bbIndex]; + uint32_t endOfs = basicBlocks[bbIndex + 1]; + llvh::outs() << "BB" << bbIndex << ":\n"; + auto *ip = funcStart + startOfs; + auto *to = funcStart + endOfs; + while (ip != to) { + auto di = inst::decodeInstruction((const inst::Inst *)ip); + llvh::outs() << " " << llvh::format_decimal(ip - funcStart, 3) + << ": " << di << "\n"; + ip += di.meta.size; + } + }); + + if (dumpJITCode_) { + funcName = codeBlock->getNameString(); + llvh::outs() << "\nJIT successfully compiled FunctionID " + << codeBlock->getFunctionID() << ", '" << funcName << "'\n"; + } + + return codeBlock->getJITCompiled(); +} + +} // namespace arm64 +} // namespace vm +} // namespace hermes +#endif // HERMESVM_JIT diff --git a/tools/expjit/idisp-jit.cpp b/lib/VM/JIT/arm64/JitEmitter.cpp similarity index 85% rename from tools/expjit/idisp-jit.cpp rename to lib/VM/JIT/arm64/JitEmitter.cpp index 0d4508bb5cf..94d2d3482dc 100644 --- a/tools/expjit/idisp-jit.cpp +++ b/lib/VM/JIT/arm64/JitEmitter.cpp @@ -5,15 +5,39 @@ * LICENSE file in the root directory of this source tree. */ -#include "loop1-jit.h" - +#include "hermes/VM/JIT/Config.h" +#if HERMESVM_JIT #include "JitEmitter.h" #include "hermes/Support/ErrorHandling.h" -namespace hermes::jit { +namespace hermes::vm::arm64 { + +namespace { + +class OurErrorHandler : public asmjit::ErrorHandler { + void handleError( + asmjit::Error err, + const char *message, + asmjit::BaseEmitter *origin) override { + llvh::errs() << "AsmJit error: " << err << ": " + << asmjit::DebugUtils::errorAsString(err) << ": " << message + << "\n"; + hermes_fatal("AsmJit error"); + } +}; + +class OurLogger : public asmjit::Logger { + ASMJIT_API asmjit::Error _log(const char *data, size_t size) noexcept + override { + llvh::outs() + << (size == SIZE_MAX ? llvh::StringRef(data) + : llvh::StringRef(data, size)); + return asmjit::kErrorOk; + } +}; -static asmjit::JitRuntime s_jitRT; +} // unnamed namespace /// Return true if the specified 64-bit value can be efficiently loaded on /// Arm64 with up to two integer instructions. In other words, it has at most @@ -27,37 +51,26 @@ static bool isCheapConst(uint64_t k) { return count <= 2; } -void ErrorHandler::handleError( - asmjit::Error err, - const char *message, - asmjit::BaseEmitter *origin) { - llvh::errs() << "AsmJit error: " << err << ": " - << asmjit::DebugUtils::errorAsString(err) << ": " << message - << "\n"; - hermes::hermes_fatal("AsmJit error"); -} - #define EMIT_RUNTIME_CALL(em, func) (em).call((void *)func, #func) Emitter::Emitter( asmjit::JitRuntime &jitRT, + bool dumpJitCode, uint32_t numFrameRegs, unsigned numCount, unsigned npCount) : frameRegs_(numFrameRegs) { -#ifndef NDEBUG - fileLogger_ = std::make_unique(stdout); -#endif - if (fileLogger_) - logger_ = fileLogger_.get(); - + if (dumpJitCode) + logger_ = std::unique_ptr(new OurLogger()); if (logger_) logger_->setIndentation(asmjit::FormatIndentationGroup::kCode, 4); + errorHandler_ = std::unique_ptr(new OurErrorHandler()); + code.init(jitRT.environment(), jitRT.cpuFeatures()); - code.setErrorHandler(&errorHandler_); + code.setErrorHandler(errorHandler_.get()); if (logger_) - code.setLogger(logger_); + code.setLogger(logger_.get()); code.attach(&a); roDataLabel_ = a.newNamedLabel("RO_DATA"); @@ -101,7 +114,7 @@ Emitter::Emitter( frameRegs_[frIndex].globalType = FRType::Unknown; } - frameSetup(nextGp - kGPSaved.first, nextVec - kVecSaved.first); + frameSetup(numFrameRegs, nextGp - kGPSaved.first, nextVec - kVecSaved.first); } void Emitter::comment(const char *fmt, ...) { @@ -115,14 +128,14 @@ void Emitter::comment(const char *fmt, ...) { a.comment(buf); } -JitFn Emitter::addToRuntime() { +JITCompiledFunctionPtr Emitter::addToRuntime(asmjit::JitRuntime &jr) { emitSlowPaths(); emitThunks(); emitROData(); code.detach(&a); - JitFn fn; - asmjit::Error err = s_jitRT.add(&fn, &code); + JITCompiledFunctionPtr fn; + asmjit::Error err = jr.add(&fn, &code); if (err) { llvh::errs() << "AsmJit failed: " << asmjit::DebugUtils::errorAsString(err) << "\n"; @@ -146,7 +159,10 @@ void Emitter::newBasicBlock(const asmjit::Label &label) { a.bind(label); } -void Emitter::frameSetup(unsigned gpSaveCount, unsigned vecSaveCount) { +void Emitter::frameSetup( + unsigned numFrameRegs, + unsigned gpSaveCount, + unsigned vecSaveCount) { assert( gpSaveCount <= kGPSaved.second - kGPSaved.first + 1 && "Too many callee saved GP regs"); @@ -208,7 +224,7 @@ void Emitter::frameSetup(unsigned gpSaveCount, unsigned vecSaveCount) { comment("// _sh_enter"); a.mov(a64::x0, xRuntime); a.mov(a64::x1, a64::sp); - a.mov(a64::w2, 13); + a.mov(a64::w2, numFrameRegs); EMIT_RUNTIME_CALL(*this, _sh_enter); comment("// xFrame"); a.mov(xFrame, a64::x0); @@ -264,7 +280,7 @@ void Emitter::call(void *fn, const char *name) { void Emitter::loadFrameAddr(a64::GpX dst, FR frameReg) { // FIXME: check range of frameReg * 8 - if (frameReg == FR(9)) + if (frameReg == FR(0)) a.mov(dst, xFrame); else a.add(dst, xFrame, frameReg.index() * sizeof(SHLegacyValue)); @@ -313,11 +329,11 @@ HWReg Emitter::_allocTemp(TempRegAlloc &ra) { if (auto optReg = ra.alloc(); optReg) return HWReg(*optReg, TAG{}); // Spill one register. - unsigned index = gpTemp_.leastRecentlyUsed(); + unsigned index = ra.leastRecentlyUsed(); spillTempReg(HWReg(index, TAG{})); ra.free(index); // Allocate again. This must succeed. - return HWReg(*gpTemp_.alloc(), TAG{}); + return HWReg(*ra.alloc(), TAG{}); } void Emitter::freeReg(HWReg hwReg) { @@ -1061,7 +1077,7 @@ void Emitter::jCond( slowPathLab = newSlowPathLabel(); contLab = newContLabel(); } - // Do this always, since this is the end of the BB. + // Do this always, since this could be the end of the BB. syncAllTempExcept(FR()); if (leftIsNum) { @@ -1096,12 +1112,12 @@ void Emitter::jCond( if (contLab.isValid()) a.bind(contLab); - // Do this always, since this is the end of the BB. - freeAllTempExcept(FR()); - if (!slow) return; + // Do this always, since this is the end of the BB. + freeAllTempExcept(FR()); + slowPaths_.push_back( {.slowPathLab = slowPathLab, .contLab = contLab, @@ -1124,160 +1140,13 @@ void Emitter::jCond( em.loadFrameAddr(a64::x1, sl.frInput1); em.loadFrameAddr(a64::x2, sl.frInput2); em.call(sl.slowCall, sl.slowCallName); - if (!sl.invert) { + if (!sl.invert) + em.a.cbnz(a64::w0, sl.target); + else em.a.cbz(a64::w0, sl.target); - em.a.b(sl.contLab); - } else { - em.a.cbz(a64::w0, sl.contLab); - em.a.b(sl.target); - } + em.a.b(sl.contLab); }}); } -JitFn compile_loop(void) { - Emitter em(s_jitRT, 13, 0, 0); - a64::Assembler &a = em.a; - - // LoadParam r5, 2 - em.loadParam(FR(5), 2); - // LoadParam r9, 1 - em.loadParam(FR(9), 1); - // Dec r11, r9 - em.dec(FR(11), FR(9)); - // LoadConstZero r10 - em.loadConstUInt8(FR(10), 0); - // LoadConstUInt8 r2, 1 - em.loadConstUInt8(FR(2), 1); - // LoadConstZero r7 - em.loadConstUInt8(FR(7), 0); - // LoadConstZero r9 - em.loadConstUInt8(FR(9), 0); - // JNotGreaterEqual L1, r11, r9 - auto L1 = a.newLabel(); - em.jGreaterEqual(true, L1, FR(11), FR(9)); - // L4: - auto L4 = a.newLabel(); - em.newBasicBlock(L4); - // Dec r3, r5 - em.dec(FR(3), FR(5)); - // Mov r8, r7 - em.mov(FR(8), FR(7)); - // Mov r6, r11 - em.mov(FR(6), FR(11)); - // Mov r0, r5 - em.mov(FR(0), FR(5)); - // Mov r1, r0 - em.mov(FR(1), FR(0)); - // JNotGreater L2, r3, r2 - auto L2 = a.newLabel(); - em.jGreater(true, L2, FR(3), FR(2)); - // L3: - auto L3 = a.newLabel(); - em.newBasicBlock(L3); - // Mul r0, r0, r3 - em.mul(FR(0), FR(0), FR(3)); - // Dec r3, r3 - em.dec(FR(3), FR(3)); - // Mov r1, r0 - em.mov(FR(1), FR(0)); - // JGreater L3, r3, r2 - em.jGreater(false, L3, FR(3), FR(2)); - // L2: - em.newBasicBlock(L2); - // Add r7, r8, r1 - em.add(FR(7), FR(8), FR(1)); - // Dec r11, r6 - em.dec(FR(11), FR(6)); - // Mov r9, r7 - em.mov(FR(9), FR(7)); - // JGreaterEqual L4, r11, r10 - em.jGreaterEqual(false, L4, FR(11), FR(10)); - // L1: - em.newBasicBlock(L1); - // Ret r9 - em.ret(FR(9)); - - em.leave(); - - return em.addToRuntime(); -} - -JitFn compile_loop1n(bool useRA = false) { - Emitter em(s_jitRT, 13, useRA ? 12 : 0, 0); - a64::Assembler &a = em.a; - - // LoadParam r5, 2 - em.loadParam(FR(12), 2); - em.toNumber(FR(5), FR(12)); - // LoadParam r9, 1 - em.loadParam(FR(12), 1); - em.toNumber(FR(9), FR(12)); - // LoadConstUInt8 r4, 1 - em.loadConstUInt8(FR(4), 1); - // SubN r11, r9, r4 - em.subN(FR(11), FR(9), FR(4)); - // LoadConstZero r10 - em.loadConstUInt8(FR(10), 0); - // LoadConstUInt8 r2, 1 - em.loadConstUInt8(FR(2), 1); - // LoadConstZero r7 - em.loadConstUInt8(FR(7), 0); - // LoadConstZero r9 - em.loadConstUInt8(FR(9), 0); - // JNotGreaterEqual L1, r11, r9 - auto L1 = a.newLabel(); - em.jGreaterEqualN(true, L1, FR(11), FR(9)); - // L4: - auto L4 = a.newLabel(); - em.newBasicBlock(L4); - // SubN r3, r5, r4 - em.subN(FR(3), FR(5), FR(4)); - // Mov r8, r7 - em.mov(FR(8), FR(7)); - // Mov r6, r11 - em.mov(FR(6), FR(11)); - // Mov r0, r5 - em.mov(FR(0), FR(5)); - // Mov r1, r0 - em.mov(FR(1), FR(0)); - // JNotGreater L2, r3, r2 - auto L2 = a.newLabel(); - em.jGreaterN(true, L2, FR(3), FR(2)); - // L3: - auto L3 = a.newLabel(); - em.newBasicBlock(L3); - // Mul r0, r0, r3 - em.mulN(FR(0), FR(0), FR(3)); - // SubN r3, r3, r4 - em.subN(FR(3), FR(3), FR(4)); - // Mov r1, r0 - em.mov(FR(1), FR(0)); - // JGreater L3, r3, r2 - em.jGreaterN(false, L3, FR(3), FR(2)); - // L2: - em.newBasicBlock(L2); - // Add r7, r8, r1 - em.addN(FR(7), FR(8), FR(1)); - // SubN r11, r6, r4 - em.subN(FR(11), FR(6), FR(4)); - // Mov r9, r7 - em.mov(FR(9), FR(7)); - // JGreaterEqual L4, r11, r10 - em.jGreaterEqualN(false, L4, FR(11), FR(10)); - // L1: - em.newBasicBlock(L1); - // Ret r9 - em.ret(FR(9)); - - em.leave(); - - return em.addToRuntime(); -} - -} // namespace hermes::jit - -JitFn compile_loop1(void) { - // return hermes::jit::compile_loop(); - // return hermes::jit::compile_loop1n(); - return hermes::jit::compile_loop1n(true); -} +} // namespace hermes::vm::arm64 +#endif // HERMESVM_JIT diff --git a/tools/expjit/JitEmitter.h b/lib/VM/JIT/arm64/JitEmitter.h similarity index 96% rename from tools/expjit/JitEmitter.h rename to lib/VM/JIT/arm64/JitEmitter.h index 66622fb53c0..823248b3edb 100644 --- a/tools/expjit/JitEmitter.h +++ b/lib/VM/JIT/arm64/JitEmitter.h @@ -9,17 +9,18 @@ #include "asmjit/a64.h" +#include "hermes/ADT/DenseUInt64.h" #include "hermes/ADT/SimpleLRU.h" #include "hermes/Support/OptValue.h" #include "hermes/VM/static_h.h" #include "llvh/ADT/DenseMap.h" -#include "llvh/Support/raw_ostream.h" #include -#include -namespace hermes::jit { +#include "hermes/VM/CodeBlock.h" + +namespace hermes::vm::arm64 { namespace a64 = asmjit::a64; @@ -256,18 +257,10 @@ class TempRegAlloc { private: }; -class ErrorHandler : public asmjit::ErrorHandler { - virtual void handleError( - asmjit::Error err, - const char *message, - asmjit::BaseEmitter *origin) override; -}; - class Emitter { public: - std::unique_ptr fileLogger_{}; - asmjit::FileLogger *logger_ = nullptr; - ErrorHandler errorHandler_; + std::unique_ptr logger_{}; + std::unique_ptr errorHandler_; std::vector frameRegs_; std::array hwRegs_; @@ -326,7 +319,7 @@ class Emitter { llvh::DenseMap thunkMap_{}; /// Map from the bit pattern of a double value to offset in constant pool. - std::unordered_map fp64ConstMap_{}; + llvh::DenseMap fp64ConstMap_{}; /// Label to branch to when returning from a function. Return value will be /// in x22. @@ -341,12 +334,13 @@ class Emitter { explicit Emitter( asmjit::JitRuntime &jitRT, + bool dumpJitCode, uint32_t numFrameRegs, uint32_t numCount, uint32_t npCount); /// Add the jitted function to the JIT runtime and return a pointer to it. - JitFn addToRuntime(); + JITCompiledFunctionPtr addToRuntime(asmjit::JitRuntime &jr); /// Log a comment. /// Annotated with printf-style format. @@ -444,6 +438,8 @@ class Emitter { b_ge) #undef DECL_JCOND + asmjit::Label newPrefLabel(const char *pref, size_t index); + private: /// Create an a64::Mem to a specifc frame register. static constexpr inline a64::Mem frA64Mem(FR fr) { @@ -521,9 +517,10 @@ class Emitter { } private: - void frameSetup(unsigned gpSaveCount, unsigned vecSaveCount); - - asmjit::Label newPrefLabel(const char *pref, size_t index); + void frameSetup( + unsigned numFrameRegs, + unsigned gpSaveCount, + unsigned vecSaveCount); asmjit::Label newSlowPathLabel() { return newPrefLabel("SLOW_", slowPaths_.size()); @@ -586,4 +583,4 @@ class Emitter { const char *slowCallName); }; // class Emitter -} // namespace hermes::jit +} // namespace hermes::vm::arm64 diff --git a/lib/VM/Runtime.cpp b/lib/VM/Runtime.cpp index 579ab1f323f..5e6c58e374b 100644 --- a/lib/VM/Runtime.cpp +++ b/lib/VM/Runtime.cpp @@ -418,8 +418,11 @@ Runtime::Runtime( symbolRegistry_.init(*this); codeCoverageProfiler_->disable(); + // FIXME: temporarily disable JIT for internal bytecode + jitContext_.setEnabled(false); // Execute our internal bytecode. auto jsBuiltinsObj = runInternalJavaScript(); + jitContext_.setEnabled(runtimeConfig.getEnableJIT()); codeCoverageProfiler_->restore(); // Populate JS builtins returned from internal bytecode to the builtins table. diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 65f33b93f6d..e48d13a785a 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -20,6 +20,3 @@ add_subdirectory(hermes-parser) add_subdirectory(node-hermes) add_subdirectory(shermes) add_subdirectory(synth) -if(HERMESVM_ALLOW_JIT EQUAL 2) - add_subdirectory(expjit) -endif() diff --git a/tools/expjit/CMakeLists.txt b/tools/expjit/CMakeLists.txt deleted file mode 100644 index 90817007fdb..00000000000 --- a/tools/expjit/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -enable_language(ASM) - -add_hermes_tool(idisp - idisp-exp.c loop1-jit.h - idisp-jit.cpp JitEmitter.h - LINK_LIBS shermes_console_a hermesvm_a -) diff --git a/tools/expjit/idisp-exp.c b/tools/expjit/idisp-exp.c deleted file mode 100644 index aa4dad5c15d..00000000000 --- a/tools/expjit/idisp-exp.c +++ /dev/null @@ -1,329 +0,0 @@ -/* - * 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. - */ - -#include "hermes/VM/static_h.h" - -#include -#include - -#include "loop1-jit.h" - -static uint32_t unit_index; -static inline SHSymbolID *get_symbols(SHUnit *); -static inline SHPropertyCacheEntry *get_prop_cache(SHUnit *); -static const SHSrcLoc s_source_locations[]; -static SHNativeFuncInfo s_function_info_table[]; -static SHLegacyValue _0_global(SHRuntime *shr); -static SHLegacyValue _1_bench(SHRuntime *shr); -// idisp.js:8:1 -static SHLegacyValue _0_global(SHRuntime *shr) { - _SH_MODEL(); - struct { - SHLocals head; - SHLegacyValue t0; - SHLegacyValue t1; - SHLegacyValue t2; - } locals; - _sh_check_native_stack_overflow(shr); - SHLegacyValue *frame = _sh_enter(shr, &locals.head, 12); - locals.head.count = 3; - SHUnit *shUnit = shr->units[unit_index]; - locals.t0 = _sh_ljs_undefined(); - locals.t1 = _sh_ljs_undefined(); - locals.t2 = _sh_ljs_undefined(); - SHLegacyValue np0 = _sh_ljs_undefined(); - SHLegacyValue np1 = _sh_ljs_undefined(); - SHLegacyValue np2 = _sh_ljs_undefined(); - SHLegacyValue np3 = _sh_ljs_undefined(); - SHLegacyValue np4 = _sh_ljs_undefined(); - SHLegacyValue np5 = _sh_ljs_undefined(); - -L0:; - _sh_ljs_declare_global_var(shr, get_symbols(shUnit)[1] /*bench*/); - _sh_ljs_declare_global_var(shr, get_symbols(shUnit)[2] /*start*/); - _sh_ljs_declare_global_var(shr, get_symbols(shUnit)[3] /*end*/); - locals.t0 = _sh_ljs_create_environment(shr, NULL, 0); - locals.t1 = _sh_ljs_create_closure( - shr, &locals.t0, _1_bench, &s_function_info_table[1], shUnit); - locals.t0 = _sh_ljs_get_global_object(shr); - _sh_ljs_put_by_id_strict_rjs( - shr, - &locals.t0, - get_symbols(shUnit)[1] /*bench*/, - &locals.t1, - get_prop_cache(shUnit) + 0); - np0 = _sh_ljs_undefined(); - np3 = _sh_ljs_double(1); - np2 = _sh_ljs_double(1000); - np5 = _sh_ljs_double(0); - goto L1; -L1:; - // PhiInst - frame[5] = _sh_ljs_get_by_id_rjs( - shr, - &locals.t0, - get_symbols(shUnit)[1] /*bench*/, - get_prop_cache(shUnit) + 1); - frame[6] = _sh_ljs_undefined(); - frame[4] = _sh_ljs_undefined(); - frame[3] = _sh_ljs_double(10); - frame[2] = _sh_ljs_double(10); - locals.t1 = _sh_ljs_call(shr, frame, 2); - np5 = _sh_ljs_double(_sh_ljs_get_double(np5) + _sh_ljs_get_double(np3)); - np1 = _sh_ljs_bool(_sh_ljs_get_double(np5) != _sh_ljs_get_double(np2)); - if (_sh_ljs_get_bool(np1)) - goto L1; - goto L2; - -L2:; - locals.t1 = _sh_ljs_try_get_by_id_rjs( - shr, - &locals.t0, - get_symbols(shUnit)[4] /*Date*/, - get_prop_cache(shUnit) + 2); - locals.t2 = _sh_ljs_get_by_id_rjs( - shr, - &locals.t1, - get_symbols(shUnit)[5] /*prototype*/, - get_prop_cache(shUnit) + 3); - locals.t2 = _sh_ljs_create_this(shr, &locals.t2, &locals.t1); - frame[6] = locals.t1; - frame[5] = locals.t1; - frame[4] = locals.t2; - locals.t1 = _sh_ljs_call(shr, frame, 0); - locals.t1 = _sh_ljs_is_object(locals.t1) ? locals.t1 : locals.t2; - _sh_ljs_put_by_id_strict_rjs( - shr, - &locals.t0, - get_symbols(shUnit)[2] /*start*/, - &locals.t1, - get_prop_cache(shUnit) + 4); - locals.t2 = _sh_ljs_try_get_by_id_rjs( - shr, - &locals.t0, - get_symbols(shUnit)[6] /*print*/, - get_prop_cache(shUnit) + 5); - frame[5] = _sh_ljs_get_by_id_rjs( - shr, - &locals.t0, - get_symbols(shUnit)[1] /*bench*/, - get_prop_cache(shUnit) + 6); - frame[3] = _sh_ljs_double(4000000); - frame[2] = _sh_ljs_double(100); - frame[6] = _sh_ljs_undefined(); - frame[4] = _sh_ljs_undefined(); - frame[3] = _sh_ljs_call(shr, frame, 2); - frame[6] = _sh_ljs_undefined(); - frame[5] = locals.t2; - frame[4] = _sh_ljs_undefined(); - locals.t1 = _sh_ljs_call(shr, frame, 1); - locals.t1 = _sh_ljs_try_get_by_id_rjs( - shr, - &locals.t0, - get_symbols(shUnit)[4] /*Date*/, - get_prop_cache(shUnit) + 7); - locals.t2 = _sh_ljs_get_by_id_rjs( - shr, - &locals.t1, - get_symbols(shUnit)[5] /*prototype*/, - get_prop_cache(shUnit) + 8); - locals.t2 = _sh_ljs_create_this(shr, &locals.t2, &locals.t1); - frame[6] = locals.t1; - frame[5] = locals.t1; - frame[4] = locals.t2; - locals.t1 = _sh_ljs_call(shr, frame, 0); - locals.t1 = _sh_ljs_is_object(locals.t1) ? locals.t1 : locals.t2; - _sh_ljs_put_by_id_strict_rjs( - shr, - &locals.t0, - get_symbols(shUnit)[3] /*end*/, - &locals.t1, - get_prop_cache(shUnit) + 9); - frame[5] = _sh_ljs_try_get_by_id_rjs( - shr, - &locals.t0, - get_symbols(shUnit)[6] /*print*/, - get_prop_cache(shUnit) + 10); - locals.t2 = _sh_ljs_get_by_id_rjs( - shr, - &locals.t0, - get_symbols(shUnit)[3] /*end*/, - get_prop_cache(shUnit) + 11); - locals.t0 = _sh_ljs_get_by_id_rjs( - shr, - &locals.t0, - get_symbols(shUnit)[2] /*start*/, - get_prop_cache(shUnit) + 12); - locals.t2 = _sh_ljs_sub_rjs(shr, &locals.t2, &locals.t0); - locals.t0 = _sh_ljs_get_string(shr, get_symbols(shUnit)[7] /*Time: */); - frame[3] = _sh_ljs_add_rjs(shr, &locals.t0, &locals.t2); - frame[6] = _sh_ljs_undefined(); - frame[4] = _sh_ljs_undefined(); - locals.t0 = _sh_ljs_call(shr, frame, 1); - _sh_leave(shr, &locals.head, frame); - return locals.t0; -} -// idisp.js:10:1 -static SHLegacyValue _1_bench(SHRuntime *shr) { - static JitFn s_fn = NULL; - static unsigned s_count = 0; - if (s_fn) - return (*s_fn)(shr); - if (++s_count >= 10) { - s_fn = compile_loop1(); - // exit(1); - return (*s_fn)(shr); - } - - struct { - SHLocals head; - SHLegacyValue t0; - SHLegacyValue t1; - SHLegacyValue t2; - SHLegacyValue t3; - SHLegacyValue t4; - SHLegacyValue t5; - SHLegacyValue t6; - SHLegacyValue t7; - } locals; - _sh_check_native_stack_overflow(shr); - SHLegacyValue *frame = _sh_enter(shr, &locals.head, 2); - locals.head.count = 8; - SHUnit *shUnit = shr->units[unit_index]; - locals.t0 = _sh_ljs_undefined(); - locals.t1 = _sh_ljs_undefined(); - locals.t2 = _sh_ljs_undefined(); - locals.t3 = _sh_ljs_undefined(); - locals.t4 = _sh_ljs_undefined(); - locals.t5 = _sh_ljs_undefined(); - locals.t6 = _sh_ljs_undefined(); - locals.t7 = _sh_ljs_undefined(); - SHLegacyValue np0 = _sh_ljs_undefined(); - SHLegacyValue np1 = _sh_ljs_undefined(); - -L0:; - locals.t3 = _sh_ljs_param(frame, 2); - locals.t0 = _sh_ljs_param(frame, 1); - locals.t2 = _sh_ljs_dec_rjs(shr, &locals.t0); - np1 = _sh_ljs_double(0); - np0 = _sh_ljs_double(1); - locals.t1 = _sh_ljs_double(0); - locals.t0 = _sh_ljs_double(0); - if (_sh_ljs_greater_equal_rjs(shr, &locals.t2, &locals.t0)) - goto L1; - goto L4; - -L1:; - // PhiInst - // PhiInst - locals.t6 = _sh_ljs_dec_rjs(shr, &locals.t3); - locals.t5 = locals.t3; - locals.t4 = locals.t5; - if (_sh_ljs_greater_rjs(shr, &locals.t6, &np0)) - goto L2; - goto L3; - -L2:; - // PhiInst - // PhiInst - locals.t5 = _sh_ljs_mul_rjs(shr, &locals.t5, &locals.t6); - locals.t6 = _sh_ljs_dec_rjs(shr, &locals.t6); - locals.t4 = locals.t5; - if (_sh_ljs_greater_rjs(shr, &locals.t6, &np0)) - goto L2; - goto L3; - -L3:; - // PhiInst - locals.t1 = _sh_ljs_add_rjs(shr, &locals.t1, &locals.t4); - locals.t2 = _sh_ljs_dec_rjs(shr, &locals.t2); - locals.t0 = locals.t1; - if (_sh_ljs_greater_equal_rjs(shr, &locals.t2, &np1)) - goto L1; - goto L4; - -L4:; - // PhiInst - _sh_leave(shr, &locals.head, frame); - return locals.t0; -} -static unsigned char s_literal_val_buffer[0] = {}; -static unsigned char s_obj_key_buffer[0] = {}; -static const SHShapeTableEntry s_obj_shape_table[] = {}; - -static const SHSrcLoc s_source_locations[] = { - {.filename_idx = 0, .line = 0, .column = 0}, -}; - -static SHNativeFuncInfo s_function_info_table[] = { - {.name_index = 8, .arg_count = 0, .prohibit_invoke = 2, .kind = 0}, - {.name_index = 1, .arg_count = 2, .prohibit_invoke = 2, .kind = 0}, -}; -static const char s_ascii_pool[] = { - '\0', 'b', 'e', 'n', 'c', 'h', '\0', 's', 't', 'a', 'r', 't', '\0', - 'e', 'n', 'd', '\0', 'D', 'a', 't', 'e', '\0', 'p', 'r', 'o', 't', - 'o', 't', 'y', 'p', 'e', '\0', 'p', 'r', 'i', 'n', 't', '\0', 'T', - 'i', 'm', 'e', ':', ' ', '\0', 'g', 'l', 'o', 'b', 'a', 'l', '\0', -}; -static const char16_t s_u16_pool[] = {}; -static const uint32_t s_strings[] = { - 0, 0, 0, 1, 5, 540019094, 7, 5, 2477978462, - 13, 3, 1517149248, 17, 4, 3442766438, 22, 9, 2155634493, - 32, 5, 2794059355, 38, 6, 3934850720, 45, 6, 615793799, -}; -#define CREATE_THIS_UNIT sh_export_this_unit -struct UnitData { - SHUnit unit; - SHSymbolID symbol_data[9]; - SHPropertyCacheEntry prop_cache_data[13]; - ; - SHCompressedPointer object_literal_class_cache[0]; -}; -SHUnit *CREATE_THIS_UNIT(SHRuntime *shr) { - struct UnitData *unit_data = calloc(sizeof(struct UnitData), 1); - *unit_data = (struct UnitData){ - .unit = { - .index = &unit_index, - .num_symbols = 9, - .num_prop_cache_entries = 13, - .ascii_pool = s_ascii_pool, - .u16_pool = s_u16_pool, - .strings = s_strings, - .symbols = unit_data->symbol_data, - .prop_cache = unit_data->prop_cache_data, - .obj_key_buffer = s_obj_key_buffer, - .obj_key_buffer_size = 0, - .literal_val_buffer = s_literal_val_buffer, - .literal_val_buffer_size = 0, - .obj_shape_table = s_obj_shape_table, - .obj_shape_table_count = 0, - .object_literal_class_cache = unit_data->object_literal_class_cache, - .source_locations = s_source_locations, - .source_locations_size = 1, - .unit_main = _0_global, - .unit_main_info = &s_function_info_table[0], - .unit_name = "sh_compiled"}}; - return (SHUnit *)unit_data; -} - -SHSymbolID *get_symbols(SHUnit *unit) { - return ((struct UnitData *)unit)->symbol_data; -} - -SHPropertyCacheEntry *get_prop_cache(SHUnit *unit) { - return ((struct UnitData *)unit)->prop_cache_data; -} - -void init_console_bindings(SHRuntime *shr); - -int main(int argc, char **argv) { - SHRuntime *shr = _sh_init(argc, argv); - init_console_bindings(shr); - bool success = _sh_initialize_units(shr, 1, CREATE_THIS_UNIT); - _sh_done(shr); - return success ? 0 : 1; -} diff --git a/tools/expjit/loop1-jit.h b/tools/expjit/loop1-jit.h deleted file mode 100644 index 339258f067f..00000000000 --- a/tools/expjit/loop1-jit.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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. - */ - -#pragma once - -#include "hermes/VM/sh_legacy_value.h" -#include "hermes/VM/sh_runtime.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef SHLegacyValue (*JitFn)(SHRuntime *shr); - -JitFn compile_loop1(void); - -#ifdef __cplusplus -} -#endif