Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 997c2c2

Browse files
committed
[GR-71042] Espresso: Introduce --java.NativeBackend=nfi-staticlib on Darwin (default for JVM mode)
PullRequest: graal/22455
2 parents 0fc5386 + 252fdde commit 997c2c2

File tree

8 files changed

+295
-10
lines changed

8 files changed

+295
-10
lines changed

‎espresso-compiler-stub/mx.espresso-compiler-stub/mx_espresso_compiler_stub.py‎

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,15 @@ def create_ni_standalone(base_standalone_name, register_distribution):
6464
f'dependency:espresso:{base_standalone_name}/languages/java/lib/<lib:javavm>'
6565
]
6666
else:
67-
idx = layout['languages/java/lib/'].index('dependency:espresso:com.oracle.truffle.espresso.mokapot/*/<multitarget_libc_selection>/<lib:jvm>')
68-
layout['languages/java/lib/'][idx] = f'dependency:espresso:{base_standalone_name}/languages/java/lib/<lib:jvm>'
67+
idx = layout['languages/java/lib/'].index('dependency:espresso:ESPRESSO_JVM_STANDALONE_MOKAPOT_SUPPORT/*')
68+
if mx.is_darwin():
69+
layout['languages/java/lib/'][idx] = f'dependency:espresso:{base_standalone_name}/languages/java/lib/fatpot/<lib:jvm>'
70+
else:
71+
layout['languages/java/lib/'][idx] = f'dependency:espresso:{base_standalone_name}/languages/java/lib/<lib:jvm>'
72+
6973
idx = layout['bin/'].index('dependency:espresso:espresso')
7074
del layout['bin/'][idx]
75+
7176
layout['bin/<exe:espresso>'] = f'dependency:espresso:{base_standalone}/bin/<exe:espresso>'
7277
layout['bin/<exe:java>'] = 'link:<exe:espresso>'
7378
layout['./'][0]['exclude'].append("bin/<exe:java>")
@@ -86,14 +91,16 @@ def create_ni_standalone(base_standalone_name, register_distribution):
8691
if espresso_java_home.java_home != mx_sdk_vm.base_jdk(stage1=False).home:
8792
mx.abort(f"ESPRESSO_JAVA_HOME(={espresso_java_home.java_home}) must match JAVA_HOME (={mx_sdk_vm.base_jdk(stage1=True).home}) (or FINAL_STAGE_JAVA_HOME (={mx_sdk_vm.base_jdk(stage1=False).home}) if set)")
8893

94+
prefix = '*/Contents/Home/' if mx.is_darwin() else '*/'
95+
8996
# substratevm is available and ESPRESSO_JAVA_HOME is JAVA_HOME, use GraalVM
9097
layout['./'][0]['source_type'] = 'extracted-dependency'
9198
layout['./'][0]['dependency'] = get_final_graalvm_distribution().qualifiedName()
92-
layout['./'][0]['path'] = '*/*'
99+
layout['./'][0]['path'] = prefix+'*'
93100
layout['./'][0]['exclude'] += [
94-
'*/languages/elau',
95-
'*/languages/java',
96-
'*/bin/espresso'
101+
prefix+'languages/elau',
102+
prefix+'languages/java',
103+
prefix+'bin/espresso'
97104
]
98105
else:
99106
layout = None

‎espresso/docs/hacking.md‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,9 +165,14 @@ $ LD_DEBUG=unused mx espresso -cp mxbuild/dists/jdk1.8/espresso-playground.jar c
165165

166166
### macOS
167167

168-
On macOS there is nothing like `dlmopen` available, therefore `jvm-ce` does not work.
168+
Nothing like `dlmopen` is available on macOS. Instead we default to `nfi-staticlib` for the JVM mode, which statically links in (most) of the OpenJDK libraries into `libjvm.dylib`.
169+
A notable exception is `libawt.dylib` and its related libraries, which only work via dynamic loading.
170+
This means in practice only the host _or_ the guest can use AWT, but not both at the same time.
169171

170172

173+
Currently `nfi-staticlib` only works for one Espresso context. Using `nfi-staticlib` with more than one context will likely result in a SIGSEGV in `libtrufflenfi.dylib`.
174+
We are exploring how to implement support for multiple contexts (GR-71082).
175+
171176
## _Espresson_ Java-ception
172177

173178
Espresso can run itself. **Self-hosting requires a Linux distribution with an up-to-date glibc.**

‎espresso/mx.espresso/mx_espresso.py‎

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import subprocess
2929
import argparse
3030
import sys
31+
import re
3132
from abc import ABCMeta, abstractmethod
3233

3334
import mx
@@ -44,6 +45,7 @@
4445
from os.path import join, exists, dirname, relpath
4546
from import_order import verify_order, validate_format
4647
from mx_truffle import resolve_truffle_dist_names
48+
from mx_native import DefaultNativeProject
4749

4850
_suite = mx.suite('espresso')
4951

@@ -637,6 +639,74 @@ def register_espresso_runtime_resources(register_project, register_distribution,
637639
register_distribution(extra_llvm_java_home_dep)
638640
register_espresso_runtime_resource(extra_java_home_dep, extra_llvm_java_home_dep, register_project, register_distribution, suite, False)
639641

642+
class CustomLibJVMLinking(DefaultNativeProject):
643+
def __init__(self, suite, name, deps, workingSets, **kwargs):
644+
subDir = kwargs.pop('subDir')
645+
d = join(suite.dir, subDir, kwargs.pop('dir'))
646+
super(CustomLibJVMLinking, self).__init__(suite, name, subDir, [], deps, workingSets, d, 'shared_lib', **kwargs)
647+
648+
@staticmethod
649+
def _extract_loaded_by_espresso():
650+
source_path = join(_suite.dir, 'src', 'com.oracle.truffle.espresso', 'src', 'com', 'oracle', 'truffle', 'espresso', 'ffi', 'nfi', 'NFIStaticLibNativeAccess.java')
651+
with open(source_path, "r", encoding="utf-8") as f:
652+
# look for:
653+
# private static final Set<String> LOADED_BY_ESPRESSO = Set.of(...);
654+
m = re.search(r'\bLOADED_BY_ESPRESSO\s*=\s*Set\.of\s*\(([a-z",\s]*)\)', f.read())
655+
if not m:
656+
raise RuntimeError("Could not find LOADED_BY_ESPRESSO = Set.of(")
657+
658+
# collect quoted strings from Set
659+
return set(re.findall(r'\"([a-z]+)\"', m.group(1)))
660+
661+
@property
662+
def ldflags(self):
663+
platform = mx.get_os() + '-' + mx.get_arch()
664+
665+
assert mx.is_darwin(), "not supported yet: " + platform
666+
667+
# Most OpenJDK libraries are suitable for static linking, with the exception of
668+
# libawt and related libs.
669+
#
670+
# This is also the minimum set of libraries required to make this approach work, as HotSpot
671+
# always will load these and it would result into a namespace clash otherwise. Depending
672+
# on the application ran by the host (next to Espresso) and by the guest, other libraries
673+
# such as libmanagement make sense to include as well.
674+
#
675+
# As noted above, libawt only works with dynamic loading and thus only the host or the
676+
# guest will be able to use it.
677+
#
678+
# Some libraries are not included as they are VM implementation specific (e.g. libsaproc).
679+
#
680+
#
681+
# Hints for debugging on Darwin:
682+
# - --log.level=ALL: Prints the reason why a library could not be loaded.
683+
# - DYLD_PRINT_LIBRARIES=1: Verbose output of the dynamic linker, e.g. prints the full
684+
# path of libraries that are attempted to be loaded.
685+
# - breakpoint on dlopen/dlsym
686+
687+
darwin_linked_in_libs = {"attach", "extnet", "freetype", "j2gss", "j2pcsc", "j2pkcs11", "jaas",
688+
"java", "javajpeg", "jimage", "management_agent", "management_ext",
689+
"management", "mlib_image", "net", "nio", "osxkrb5", "prefs", "rmi", "sleef",
690+
"syslookup", "verify", "zip"}
691+
692+
expected_by_VM = CustomLibJVMLinking._extract_loaded_by_espresso()
693+
missing_libs = expected_by_VM - darwin_linked_in_libs
694+
assert not missing_libs, "missing libraries expected by the VM: " + str(missing_libs)
695+
696+
static_lib_dir = os.path.join(get_java_home_dep().java_home, "lib", "static", platform)
697+
ldf = []
698+
699+
for jdk_static_lib in os.listdir(static_lib_dir):
700+
if not jdk_static_lib.endswith('.a'):
701+
continue
702+
703+
if jdk_static_lib[3:-2] not in darwin_linked_in_libs:
704+
continue
705+
706+
ldf.append(f'-Wl,-force_load,{os.path.join(static_lib_dir, jdk_static_lib)}')
707+
708+
return ldf + super(CustomLibJVMLinking, self).ldflags
709+
640710

641711
def register_espresso_runtime_resource(java_home_dep, llvm_java_home_dep, register_project, register_distribution, suite, is_main):
642712
is_ee_suite = suite != _suite

‎espresso/mx.espresso/suite.py‎

Lines changed: 82 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,38 @@
405405
},
406406
},
407407

408+
# same as mokapot, but with statically linked OpenJDK libraries.
409+
"com.oracle.truffle.espresso.fatpot": {
410+
"class": "CustomLibJVMLinking",
411+
"subDir": "src",
412+
"dir": "com.oracle.truffle.espresso.mokapot",
413+
"native": "shared_lib",
414+
"deliverable": "jvm",
415+
"platformDependent": True,
416+
"os_arch": {
417+
"darwin": {
418+
"<others>": {
419+
"cflags": ["-Wall", "-Werror", "-std=c11", "-DESPRESSO_NFI_STATIC"],
420+
"ldflags": [
421+
"-Wl,-install_name,@rpath/libjvm.dylib",
422+
"-Wl,-rpath,@loader_path/.",
423+
"-Wl,-rpath,@loader_path/..",
424+
"-Wl,-current_version,1.0.0",
425+
"-Wl,-compatibility_version,1.0.0"
426+
],
427+
"multitarget": {
428+
"compiler": ["host", "*"]
429+
},
430+
},
431+
},
432+
"<others>": {
433+
"<others>": {
434+
"ignore": "GR-66340: Darwin only for now",
435+
},
436+
},
437+
},
438+
},
439+
408440
"com.oracle.truffle.espresso.shadowed.asm" : {
409441
# Shadowed ASM library (org.ow2.asm:asm)
410442
"subDir" : "src",
@@ -654,6 +686,29 @@
654686
"maven": False,
655687
},
656688

689+
"ESPRESSO_JVM_STANDALONE_MOKAPOT_SUPPORT": {
690+
"type": "dir",
691+
"platformDependent": True,
692+
"platforms": "local",
693+
"os": {
694+
"darwin": {
695+
"layout": {
696+
"./fatpot/": [
697+
"dependency:espresso:com.oracle.truffle.espresso.fatpot/*/<multitarget_libc_selection>/<lib:jvm>",
698+
]
699+
},
700+
},
701+
"<others>": {
702+
"layout": {
703+
"./": [
704+
"dependency:espresso:com.oracle.truffle.espresso.mokapot/*/<multitarget_libc_selection>/<lib:jvm>",
705+
]
706+
},
707+
},
708+
},
709+
"maven": False,
710+
},
711+
657712
"ESPRESSO_JVM_STANDALONE": {
658713
"type": "dir",
659714
"pruning_mode": "optional",
@@ -683,7 +738,7 @@
683738
],
684739
"languages/java/lib/": [
685740
# Copy of libjvm.so, accessible by Sulong via the default Truffle file system.
686-
"dependency:espresso:com.oracle.truffle.espresso.mokapot/*/<multitarget_libc_selection>/<lib:jvm>",
741+
"dependency:espresso:ESPRESSO_JVM_STANDALONE_MOKAPOT_SUPPORT/*",
687742
],
688743
"languages/java/": [
689744
{
@@ -765,11 +820,20 @@
765820
"darwin-aarch64",
766821
"windows-amd64",
767822
],
823+
"pruning_mode": "optional",
768824
"layout": {
769825
"META-INF/resources/java/espresso-libs/<os>/<arch>/lib/": [
770826
# Copy of libjvm.so, accessible by Sulong via the default Truffle file system.
771827
"dependency:espresso:com.oracle.truffle.espresso.mokapot/*/<multitarget_libc_selection>/<lib:jvm>",
772828
],
829+
"META-INF/resources/java/espresso-libs/<os>/<arch>/lib/fatpot/": [
830+
{
831+
'source_type': 'dependency',
832+
'dependency': 'espresso:com.oracle.truffle.espresso.fatpot',
833+
'path': '*/<multitarget_libc_selection>/<lib:jvm>',
834+
'optional': True,
835+
},
836+
],
773837
"META-INF/resources/java/espresso-libs/<os>/<arch>/": "dependency:espresso:ESPRESSO_SUPPORT/*",
774838
},
775839
"maven": False,
@@ -841,7 +905,15 @@
841905
"lib/": [
842906
# Copy of libjvm.so, accessible by Sulong via the default Truffle file system.
843907
"dependency:espresso:com.oracle.truffle.espresso.mokapot/*/<multitarget_libc_selection>/<lib:jvm>",
844-
]
908+
],
909+
"lib/fatpot/": [
910+
{
911+
'source_type': 'dependency',
912+
'dependency': 'espresso:com.oracle.truffle.espresso.fatpot',
913+
'path': '*/<multitarget_libc_selection>/<lib:jvm>',
914+
'optional': True,
915+
},
916+
],
845917
},
846918
"maven": False,
847919
},
@@ -854,6 +926,14 @@
854926
"truffle/": [
855927
"dependency:espresso:com.oracle.truffle.espresso.mokapot/*/<multitarget_libc_selection>/<lib:jvm>",
856928
],
929+
"truffle/fatpot/": [
930+
{
931+
'source_type': 'dependency',
932+
'dependency': 'espresso:com.oracle.truffle.espresso.fatpot',
933+
'path': '*/<multitarget_libc_selection>/<lib:jvm>',
934+
'optional': True,
935+
},
936+
],
857937
},
858938
"maven": False,
859939
},

‎espresso/src/com.oracle.truffle.espresso.mokapot/src/mokapot.c‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1730,7 +1730,11 @@ JNIEXPORT jboolean JNICALL JVM_IsForeignLinkerSupported(void) {
17301730
JNIEXPORT jboolean JNICALL
17311731
JVM_IsStaticallyLinked(void) {
17321732
IMPLEMENTED(JVM_IsStaticallyLinked);
1733+
#ifdef ESPRESSO_NFI_STATIC
1734+
return JNI_TRUE;
1735+
#else
17331736
return JNI_FALSE;
1737+
#endif
17341738
}
17351739

17361740
JNIEXPORT void JNICALL JVM_VirtualThreadStart(JNIEnv* env, jobject vthread) {

‎espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/EspressoLanguage.java‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
import com.oracle.truffle.espresso.ffi.NoNativeAccess;
7272
import com.oracle.truffle.espresso.ffi.nfi.NFIIsolatedNativeAccess;
7373
import com.oracle.truffle.espresso.ffi.nfi.NFINativeAccess;
74+
import com.oracle.truffle.espresso.ffi.nfi.NFIStaticLibNativeAccess;
7475
import com.oracle.truffle.espresso.ffi.nfi.NFISulongNativeAccess;
7576
import com.oracle.truffle.espresso.impl.EspressoType;
7677
import com.oracle.truffle.espresso.impl.SuppressFBWarnings;
@@ -345,6 +346,8 @@ private static String setNativeBackendId(final TruffleLanguage.Env env) {
345346
if (isInPreInit || !EspressoOptions.RUNNING_ON_SVM) {
346347
if (OS.getCurrent() == OS.Linux) {
347348
nativeBackend = NFIIsolatedNativeAccess.Provider.ID;
349+
} else if (OS.getCurrent() == OS.Darwin) {
350+
nativeBackend = NFIStaticLibNativeAccess.Provider.ID;
348351
} else {
349352
nativeBackend = NFISulongNativeAccess.Provider.ID;
350353
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /