Skip to content

Commit

Permalink
Merge pull request #43664 from dnadlinger/aarch64-darwin
Browse files Browse the repository at this point in the history
Switch aarch64-darwin codegen to JITLink (ObjectLinkingLayer) and small code model
  • Loading branch information
vtjnash authored Jan 19, 2022
2 parents ef23d6d + 955d427 commit 487f0b4
Show file tree
Hide file tree
Showing 5 changed files with 403 additions and 157 deletions.
18 changes: 12 additions & 6 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,6 @@ extern void _chkstk(void);
#endif
}

// llvm state
extern JITEventListener *CreateJuliaJITEventListener();

// for image reloading
bool imaging_mode = false;

Expand Down Expand Up @@ -8142,7 +8139,12 @@ extern "C" void jl_init_llvm(void)
}
// Allocate a target...
Optional<CodeModel::Model> codemodel =
#ifdef _P64
#if defined(JL_USE_JITLINK)
// JITLink can patch up relocations between far objects so we can use the
// small code model – which is good, as the large code model is unmaintained
// on MachO/AArch64.
CodeModel::Small;
#elif defined(_P64)
// Make sure we are using the large code model on 64bit
// Let LLVM pick a default suitable for jitting on 32bit
CodeModel::Large;
Expand Down Expand Up @@ -8183,13 +8185,15 @@ extern "C" void jl_init_llvm(void)
}
#endif
if (jl_using_gdb_jitevents)
jl_ExecutionEngine->RegisterJITEventListener(JITEventListener::createGDBRegistrationListener());
jl_ExecutionEngine->enableJITDebuggingSupport();

#if defined(JL_USE_INTEL_JITEVENTS) || \
defined(JL_USE_OPROFILE_JITEVENTS) || \
defined(JL_USE_PERF_JITEVENTS)
#ifdef JL_USE_JITLINK
#error "JIT profiling support (JL_USE_*_JITEVENTS) not yet available on platforms that use JITLink"
#else
const char *jit_profiling = getenv("ENABLE_JITPROFILING");
#endif

#if defined(JL_USE_INTEL_JITEVENTS)
if (jit_profiling && atoi(jit_profiling)) {
Expand Down Expand Up @@ -8222,6 +8226,8 @@ extern "C" void jl_init_llvm(void)
#ifdef JL_USE_PERF_JITEVENTS
if (jl_using_perf_jitevents)
jl_ExecutionEngine->RegisterJITEventListener(JITEventListener::createPerfJITEventListener());
#endif
#endif
#endif

cl::PrintOptionValues();
Expand Down
104 changes: 28 additions & 76 deletions src/debuginfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
#include "platform.h"

#include "llvm-version.h"
#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/ExecutionEngine/JITEventListener.h>
#include <llvm/DebugInfo/DIContext.h>
#include <llvm/DebugInfo/DWARF/DWARFContext.h>
#include <llvm/Object/SymbolSize.h>
Expand All @@ -15,6 +13,7 @@
#include <llvm/IR/DebugInfo.h>
#include <llvm/IR/DataLayout.h>
#include <llvm/IR/Mangler.h>
#include <llvm/ExecutionEngine/RTDyldMemoryManager.h>
#include <llvm/ExecutionEngine/RuntimeDyld.h>
#include <llvm/BinaryFormat/Magic.h>
#include <llvm/Object/MachO.h>
Expand Down Expand Up @@ -114,12 +113,6 @@ void jl_add_code_in_flight(StringRef name, jl_code_instance_t *codeinst, const D
}


#ifdef _OS_WINDOWS_
#if defined(_CPU_X86_64_)
void *lookupWriteAddressFor(RTDyldMemoryManager *memmgr, void *rt_addr);
#endif
#endif

#if defined(_OS_WINDOWS_)
static void create_PRUNTIME_FUNCTION(uint8_t *Code, size_t Size, StringRef fnname,
uint8_t *Section, size_t Allocated, uint8_t *UnwindData)
Expand Down Expand Up @@ -177,15 +170,20 @@ struct revcomp {
{ return lhs>rhs; }
};

class JuliaJITEventListener: public JITEventListener

// Central registry for resolving function addresses to `jl_method_instance_t`s and
// originating `ObjectFile`s (for the DWARF debug info).
//
// A global singleton instance is notified by the JIT whenever a new object is emitted,
// and later queried by the various function info APIs. We also use the chance to handle
// some platform-specific unwind info registration (which is unrelated to the query
// functionality).
class JITObjectRegistry
{
std::map<size_t, ObjectInfo, revcomp> objectmap;
std::map<size_t, std::pair<size_t, jl_method_instance_t *>, revcomp> linfomap;

public:
JuliaJITEventListener(){}
virtual ~JuliaJITEventListener() {}

jl_method_instance_t *lookupLinfo(size_t pointer) JL_NOTSAFEPOINT
{
uv_rwlock_rdlock(&threadsafe);
Expand All @@ -197,50 +195,16 @@ class JuliaJITEventListener: public JITEventListener
return linfo;
}

virtual void NotifyObjectEmitted(const object::ObjectFile &Object,
const RuntimeDyld::LoadedObjectInfo &L)
{
return _NotifyObjectEmitted(Object, L, nullptr);
}

virtual void _NotifyObjectEmitted(const object::ObjectFile &Object,
const RuntimeDyld::LoadedObjectInfo &L,
RTDyldMemoryManager *memmgr)
void registerJITObject(const object::ObjectFile &Object,
std::function<uint64_t(const StringRef &)> getLoadAddress,
std::function<void*(void*)> lookupWriteAddress)
{
jl_ptls_t ptls = jl_current_task->ptls;
// This function modify codeinst->fptr in GC safe region.
// This should be fine since the GC won't scan this field.
int8_t gc_state = jl_gc_safe_enter(ptls);

auto SavedObject = L.getObjectForDebug(Object).takeBinary();
// If the debug object is unavailable, save (a copy of) the original object
// for our backtraces.
// This copy seems unfortunate, but there doesn't seem to be a way to take
// ownership of the original buffer.
if (!SavedObject.first) {
auto NewBuffer = MemoryBuffer::getMemBufferCopy(
Object.getData(), Object.getFileName());
auto NewObj = cantFail(object::ObjectFile::createObjectFile(NewBuffer->getMemBufferRef()));
SavedObject = std::make_pair(std::move(NewObj), std::move(NewBuffer));
}
const object::ObjectFile &debugObj = *SavedObject.first.release();
SavedObject.second.release();

object::section_iterator EndSection = debugObj.section_end();
StringMap<object::SectionRef> loadedSections;
for (const object::SectionRef &lSection: Object.sections()) {
auto sName = lSection.getName();
if (sName) {
bool inserted = loadedSections.insert(std::make_pair(*sName, lSection)).second;
assert(inserted); (void)inserted;
}
}
auto getLoadAddress = [&] (const StringRef &sName) -> uint64_t {
auto search = loadedSections.find(sName);
if (search == loadedSections.end())
return 0;
return L.getSectionLoadAddress(search->second);
};
object::section_iterator EndSection = Object.section_end();

#ifdef _CPU_ARM_
// ARM does not have/use .eh_frame
Expand Down Expand Up @@ -299,7 +263,7 @@ class JuliaJITEventListener: public JITEventListener
uint8_t *UnwindData = NULL;
#if defined(_CPU_X86_64_)
uint8_t *catchjmp = NULL;
for (const object::SymbolRef &sym_iter : debugObj.symbols()) {
for (const object::SymbolRef &sym_iter : Object.symbols()) {
StringRef sName = cantFail(sym_iter.getName());
uint8_t **pAddr = NULL;
if (sName.equals("__UnwindData")) {
Expand All @@ -322,9 +286,8 @@ class JuliaJITEventListener: public JITEventListener
SectionAddrCheck = SectionAddr;
SectionLoadCheck = SectionLoadAddr;
SectionWriteCheck = SectionLoadAddr;
if (memmgr)
SectionWriteCheck = (uintptr_t)lookupWriteAddressFor(memmgr,
(void*)SectionLoadAddr);
if (lookupWriteAddress)
SectionWriteCheck = (uintptr_t)lookupWriteAddress((void*)SectionLoadAddr);
Addr += SectionWriteCheck - SectionLoadAddr;
*pAddr = (uint8_t*)Addr;
}
Expand Down Expand Up @@ -352,7 +315,7 @@ class JuliaJITEventListener: public JITEventListener
#endif // defined(_OS_X86_64_)
#endif // defined(_OS_WINDOWS_)

auto symbols = object::computeSymbolSizes(debugObj);
auto symbols = object::computeSymbolSizes(Object);
bool first = true;
for (const auto &sym_size : symbols) {
const object::SymbolRef &sym_iter = sym_size.first;
Expand Down Expand Up @@ -389,7 +352,7 @@ class JuliaJITEventListener: public JITEventListener
if (codeinst)
linfomap[Addr] = std::make_pair(Size, codeinst->def);
if (first) {
ObjectInfo tmp = {&debugObj,
ObjectInfo tmp = {&Object,
(size_t)SectionSize,
(ptrdiff_t)(SectionAddr - SectionLoadAddr),
*Section,
Expand All @@ -403,22 +366,18 @@ class JuliaJITEventListener: public JITEventListener
jl_gc_safe_leave(ptls, gc_state);
}

// must implement if we ever start freeing code
// virtual void NotifyFreeingObject(const ObjectImage &Object) {}
// virtual void NotifyFreeingObject(const object::ObjectFile &Obj) {}

std::map<size_t, ObjectInfo, revcomp>& getObjectMap() JL_NOTSAFEPOINT
{
return objectmap;
}
};

JL_DLLEXPORT void ORCNotifyObjectEmitted(JITEventListener *Listener,
const object::ObjectFile &Object,
const RuntimeDyld::LoadedObjectInfo &L,
RTDyldMemoryManager *memmgr)
static JITObjectRegistry jl_jit_object_registry;
void jl_register_jit_object(const object::ObjectFile &Object,
std::function<uint64_t(const StringRef &)> getLoadAddress,
std::function<void *(void *)> lookupWriteAddress)
{
((JuliaJITEventListener*)Listener)->_NotifyObjectEmitted(Object, L, memmgr);
jl_jit_object_registry.registerJITObject(Object, getLoadAddress, lookupWriteAddress);
}

// TODO: convert the safe names from aotcomile.cpp:makeSafeName back into symbols
Expand Down Expand Up @@ -454,13 +413,6 @@ static std::pair<char *, bool> jl_demangle(const char *name) JL_NOTSAFEPOINT
return std::make_pair(strdup(name), false);
}

static JuliaJITEventListener *jl_jit_events;
JITEventListener *CreateJuliaJITEventListener(void)
{
jl_jit_events = new JuliaJITEventListener();
return jl_jit_events;
}

// *frames is a one element array containing whatever we could come up
// with for the current frame. here we'll try to expand it using debug info
// func_name and file_name are either NULL or malloc'd pointers
Expand Down Expand Up @@ -1194,7 +1146,7 @@ int jl_DI_for_fptr(uint64_t fptr, uint64_t *symsize, int64_t *slide,
{
int found = 0;
uv_rwlock_wrlock(&threadsafe);
std::map<size_t, ObjectInfo, revcomp> &objmap = jl_jit_events->getObjectMap();
std::map<size_t, ObjectInfo, revcomp> &objmap = jl_jit_object_registry.getObjectMap();
std::map<size_t, ObjectInfo, revcomp>::iterator fit = objmap.lower_bound(fptr);

if (symsize)
Expand Down Expand Up @@ -1228,7 +1180,7 @@ extern "C" JL_DLLEXPORT int jl_getFunctionInfo_impl(jl_frame_t **frames_out, siz
int64_t slide;
uint64_t symsize;
if (jl_DI_for_fptr(pointer, &symsize, &slide, &Section, &context)) {
frames[0].linfo = jl_jit_events->lookupLinfo(pointer);
frames[0].linfo = jl_jit_object_registry.lookupLinfo(pointer);
int nf = lookup_pointer(Section, context, frames_out, pointer, slide, true, noInline);
return nf;
}
Expand All @@ -1237,7 +1189,7 @@ extern "C" JL_DLLEXPORT int jl_getFunctionInfo_impl(jl_frame_t **frames_out, siz

extern "C" jl_method_instance_t *jl_gdblookuplinfo(void *p) JL_NOTSAFEPOINT
{
return jl_jit_events->lookupLinfo((size_t)p);
return jl_jit_object_registry.lookupLinfo((size_t)p);
}

#if (defined(_OS_LINUX_) || defined(_OS_FREEBSD_) || (defined(_OS_DARWIN_) && defined(LLVM_SHLIB)))
Expand Down Expand Up @@ -1659,7 +1611,7 @@ uint64_t jl_getUnwindInfo_impl(uint64_t dwAddr)
{
// Might be called from unmanaged thread
uv_rwlock_rdlock(&threadsafe);
std::map<size_t, ObjectInfo, revcomp> &objmap = jl_jit_events->getObjectMap();
std::map<size_t, ObjectInfo, revcomp> &objmap = jl_jit_object_registry.getObjectMap();
std::map<size_t, ObjectInfo, revcomp>::iterator it = objmap.lower_bound(dwAddr);
uint64_t ipstart = 0; // ip of the start of the section (if found)
if (it != objmap.end() && dwAddr < it->first + it->second.SectionSize) {
Expand Down
1 change: 0 additions & 1 deletion src/disasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@
#include <llvm/BinaryFormat/MachO.h>
#include <llvm/DebugInfo/DIContext.h>
#include <llvm/DebugInfo/DWARF/DWARFContext.h>
#include <llvm/ExecutionEngine/JITEventListener.h>
#include <llvm/IR/AssemblyAnnotationWriter.h>
#include <llvm/IR/DebugInfo.h>
#include <llvm/IR/Function.h>
Expand Down
Loading

3 comments on commit 487f0b4

@nanosoldier
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Executing the daily package evaluation, I will reply here when finished:

@nanosoldier runtests(ALL, isdaily = true)

@nanosoldier
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something went wrong when running your job:

NanosoldierError: failed to run tests: TaskFailedException

    nested task error: IOError: mktempdir("/tmp"): no space left on device (ENOSPC)
    Stacktrace:
      [1] uv_error
        @ ./libuv.jl:97 [inlined]
      [2] #mktempdir#26
        @ ./file.jl:699
      [3] mktempdir
        @ ./file.jl:685 [inlined]
      [4] build_executor_command
        @ /storage/pkgeval/depot/packages/Sandbox/aUsDe/src/UserNamespaces.jl:145
      [5] #run#64
        @ /storage/pkgeval/depot/packages/Sandbox/aUsDe/src/Sandbox.jl:123
      [6] #run_sandboxed_julia#37
        @ /storage/pkgeval/depot/packages/PkgEval/rd3Bb/src/run.jl:59
      [7] #run_sandboxed_script#45
        @ /storage/pkgeval/depot/packages/PkgEval/rd3Bb/src/run.jl:221
      [8] #run_sandboxed_test#58
        @ /storage/pkgeval/depot/packages/PkgEval/rd3Bb/src/run.jl:368
      [9] macro expansion
        @ /storage/pkgeval/depot/packages/PkgEval/rd3Bb/src/run.jl:686 [inlined]
     [10] #63
        @ ./task.jl:423

Logs and partial data can be found here
cc @maleadt

@maleadt
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.