Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apple Silicon support #102

Merged
merged 12 commits into from
May 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 8 additions & 3 deletions .github/workflows/native-macos.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
name: Build macOS Binaries

on:
# push:
# branches: [ master ]
# pull_request:
# branches: [ master ]
# GHA does not support building Apple am64 very well, so we disable this workflow for now.
# See https://github.com/actions/runner/issues/805
push:
branches: [ master ]
pull_request:
branches: [ master ]
branches-ignore:
- '**'

jobs:
native:
Expand Down
Binary file modified archive/jffi-Darwin.jar
Binary file not shown.
19 changes: 7 additions & 12 deletions jni/GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -164,16 +164,7 @@ endif

ifeq ($(OS), darwin)
PLATFORM = darwin
ARCHES =
ifneq ($(findstring $(CPU), i386),)
ARCHES += i386
endif
ifneq ($(findstring $(CPU), x86_64),)
ARCHES += x86_64
endif
ifneq ($(findstring $(CPU), arm64),)
ARCHES += arm64
endif
ARCHES = x86_64 arm64

XCODE=$(shell xcode-select -print-path)
CC = $(XCODE)/usr/bin/gcc
Expand All @@ -182,7 +173,7 @@ ifeq ($(OS), darwin)
CFLAGS += -isysroot $(MACSDK) -DTARGET_RT_MAC_CFM=0
CFLAGS += -I$(MACSDK)/System/Library/Frameworks/JavaVM.framework/Headers
CFLAGS += $(foreach arch, $(ARCHES),-arch $(arch))
LDFLAGS = $(foreach arch, $(ARCHES),-arch $(arch)) -dynamiclib -framework JavaVM \
LDFLAGS = $(foreach arch, $(ARCHES),-arch $(arch)) -dynamiclib \
-Wl,-syslibroot,$(MACSDK) -mmacosx-version-min=10.6
JNIEXT = jnilib
#CFLAGS += -I$(MACSDK)/System/Library/Frameworks/Kernel.framework/Versions/A/Headers
Expand Down Expand Up @@ -300,7 +291,7 @@ build_ffi = \
$(LIBFFI):
@mkdir -p $(@D)
@for arch in $(ARCHES); do $(call build_ffi,$$arch);done
# Assemble into a FAT (i386, x86_64) library
# Assemble into a FAT (x86_64, arm64) library
@mkdir -p $(BUILD_DIR)/libffi/.libs
@env MACOSX_DEPLOYMENT_TARGET=10.4 /usr/bin/libtool -static -o $@ \
$(foreach arch, $(ARCHES),$(BUILD_DIR)/libffi-darwin-$(arch)/.libs/libffi_convenience.a)
Expand All @@ -311,13 +302,17 @@ $(LIBFFI):
printf "#include \"libffi-darwin-i386/include/ffi.h\"\n"; \
printf "#elif defined(__x86_64__)\n"; \
printf "#include \"libffi-darwin-x86_64/include/ffi.h\"\n";\
printf "#elif defined(__arm64__)\n"; \
printf "#include \"libffi-darwin-arm64/include/ffi.h\"\n";\
printf "#endif\n";\
) > $(LIBFFI_BUILD_DIR)/include/ffi.h
@( \
printf "#if defined(__i386__)\n"; \
printf "#include \"libffi-darwin-i386/include/ffitarget.h\"\n"; \
printf "#elif defined(__x86_64__)\n"; \
printf "#include \"libffi-darwin-x86_64/include/ffitarget.h\"\n";\
printf "#elif defined(__arm64__)\n"; \
printf "#include \"libffi-darwin-arm64/include/ffitarget.h\"\n";\
printf "#endif\n";\
) > $(LIBFFI_BUILD_DIR)/include/ffitarget.h
else
Expand Down
74 changes: 72 additions & 2 deletions jni/jffi/ClosureMagazine.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@
#include "FaultProtect.h"
#include "com_kenai_jffi_Foreign.h"

#if (defined(__arm64__) && defined(__APPLE__))
#define USE_FFI_ALLOC 1
#else
#define USE_FFI_ALLOC 0
#endif

#define THREAD_ATTACH_THRESHOLD (1000)

struct Closure;
Expand All @@ -71,10 +77,13 @@ typedef struct Closure {
void* code; /* the code address must be the first member of this struct; used by java */
jobject javaObject;
Magazine* magazine;
void* pcl;
} Closure;

static bool closure_prep(ffi_cif* cif, void* code, Closure* closure, char* errbuf, size_t errbufsize);

#if !USE_FFI_ALLOC

JNIEXPORT jlong JNICALL
Java_com_kenai_jffi_Foreign_newClosureMagazine(JNIEnv *env, jobject self, jlong ctxAddress, jobject closureMethod,
jboolean callWithPrimitiveParameters)
Expand Down Expand Up @@ -105,6 +114,7 @@ Java_com_kenai_jffi_Foreign_newClosureMagazine(JNIEnv *env, jobject self, jlong
Closure* closure = &list[i];
closure->magazine = magazine;
closure->code = (code + (i * trampolineSize));
closure->pcl = closure->code;

if (!closure_prep(&ctx->cif, closure->code, closure, errmsg, sizeof(errmsg))) {
goto error;
Expand Down Expand Up @@ -143,6 +153,63 @@ Java_com_kenai_jffi_Foreign_newClosureMagazine(JNIEnv *env, jobject self, jlong
return 0L;
}

#else

JNIEXPORT jlong JNICALL
Java_com_kenai_jffi_Foreign_newClosureMagazine(JNIEnv *env, jobject self, jlong ctxAddress, jobject closureMethod,
jboolean callWithPrimitiveParameters)
{
CallContext* ctx = (CallContext *) j2p(ctxAddress);
Closure* closure = NULL;
Magazine* magazine = NULL;
void* code = NULL;
caddr_t pcl = NULL;
char errmsg[256];

magazine = calloc(1, sizeof(*magazine));
closure = calloc(1, sizeof(*closure));
pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);

if (magazine == NULL || closure == NULL || pcl == NULL) {
snprintf(errmsg, sizeof(errmsg), "failed to allocate a page. errno=%d (%s)", errno, strerror(errno));
goto error;
}

closure->magazine = magazine;
closure->code = code;
closure->pcl = pcl;

if (!closure_prep(&ctx->cif, closure->code, closure, errmsg, sizeof(errmsg))) {
goto error;
}

magazine->methodID = (*env)->FromReflectedMethod(env, closureMethod);
if (magazine->methodID == NULL) {
throwException(env, IllegalArgument, "could not obtain reference to closure method");
goto error;
}

/* Track the allocated page + Closure memory area */
magazine->closures = closure;
magazine->nextclosure = 0;
magazine->nclosures = 1;
magazine->code = pcl;
magazine->callWithPrimitiveParameters = callWithPrimitiveParameters;
(*env)->GetJavaVM(env, &magazine->jvm);

return p2j(magazine);

error:
free(closure);
free(magazine);
if (pcl != NULL) {
ffi_closure_free(pcl);
}
throwException(env, Runtime, errmsg);
return 0L;
}

#endif //!USE_FFI_ALLOC

/*
* Class: com_kenai_jffi_Foreign
Expand All @@ -161,11 +228,14 @@ Java_com_kenai_jffi_Foreign_freeClosureMagazine(JNIEnv *env, jobject self, jlong
}

free(magazine->closures);
#if !USE_FFI_ALLOC
jffi_freePages(magazine->code, 1);
#else
ffi_closure_free(magazine->code);
#endif
free(magazine);
}


/*
* Class: com_kenai_jffi_Foreign
* Method: closureMagazineGet
Expand Down Expand Up @@ -408,7 +478,7 @@ closure_prep(ffi_cif* cif, void* code, Closure* closure, char* errbuf, size_t er
{
ffi_status status;

status = ffi_prep_closure_loc(code, cif, closure_invoke, closure, code);
status = ffi_prep_closure_loc(closure->pcl, cif, closure_invoke, closure, code);
switch (status) {
case FFI_OK:
return true;
Expand Down
2 changes: 1 addition & 1 deletion jni/jffi/Exception.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,6 @@ const char* jffi_IllegalArgumentException = "java/lang/IllegalArgumentException"
const char* jffi_NullPointerException = "java/lang/NullPointerException";
const char* jffi_OutOfBoundsException = "java/lang/IndexOutOfBoundsException";
const char* jffi_OutOfMemoryException = "java/lang/OutOfMemoryError";
const char* jffi_RuntimeException = "java/lang/RuntimeError";
const char* jffi_RuntimeException = "java/lang/RuntimeException";
const char* jffi_UnsatisfiedLinkException = "java/lang/UnsatisfiedLinkError";

6 changes: 2 additions & 4 deletions jni/libffi/Makefile.in
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Makefile.in generated by automake 1.16.3 from Makefile.am.
# Makefile.in generated by automake 1.16.2 from Makefile.am.
# @configure_input@

# Copyright (C) 1994-2020 Free Software Foundation, Inc.
Expand Down Expand Up @@ -371,8 +371,6 @@ am__relativize = \
DIST_ARCHIVES = $(distdir).tar.gz
GZIP_ENV = --best
DIST_TARGETS = dist-gzip
# Exists only to be overridden by the user if desired.
AM_DISTCHECK_DVI_TARGET = dvi
distuninstallcheck_listfiles = find . -type f -print
am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
| sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$'
Expand Down Expand Up @@ -1621,7 +1619,7 @@ distcheck: dist
$(DISTCHECK_CONFIGURE_FLAGS) \
--srcdir=../.. --prefix="$$dc_install_base" \
&& $(MAKE) $(AM_MAKEFLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) $(AM_DISTCHECK_DVI_TARGET) \
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
&& $(MAKE) $(AM_MAKEFLAGS) check \
&& $(MAKE) $(AM_MAKEFLAGS) install \
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \
Expand Down