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

Premature initialization of SVM encodings #8795

Open
sgammon opened this issue Apr 17, 2024 · 2 comments
Open

Premature initialization of SVM encodings #8795

sgammon opened this issue Apr 17, 2024 · 2 comments

Comments

@sgammon
Copy link

sgammon commented Apr 17, 2024

Describe the issue

When building a Truffle-enabled native-image with a certain combination of Feature implementations on the classpath, initialization of registered encodings for TruffleString may occur before the full suite of Truffle languages has loaded; this causes an invalid state which causes TruffleRuby to crash later, at runtime.

Truffle decides whether to enable JCodings based on a simple condition:

if (TruffleOptions.AOT && !TStringAccessor.getNeedsAllEncodings()) {

TStringAccessor delegates to the engine:

static boolean getNeedsAllEncodings() {
return ENGINE.getNeedsAllEncodings();
}

Which delegates to EngineAccessor:

@Override
public boolean getNeedsAllEncodings() {
return LanguageCache.getNeedsAllEncodings();
}

Which ultimately calls into the LanguageCache:

public static boolean getNeedsAllEncodings() {
for (LanguageCache cache : languages().values()) {
if (cache.isNeedsAllEncodings()) {
return true;
}
}
return false;

... which then queries the registered Truffle languages to determine if all codings are needed.

However, at this stage of execution, it is not guaranteed that Truffle languages have loaded yet via TruffleBaseFeature:

invokeStaticMethod("com.oracle.truffle.api.impl.Accessor", "getTVMCI", Collections.emptyList());
invokeStaticMethod("com.oracle.truffle.polyglot.InternalResourceCache", "initializeNativeImageState",
Collections.singletonList(ClassLoader.class), imageClassLoader);
invokeStaticMethod("com.oracle.truffle.polyglot.LanguageCache", "initializeNativeImageState",
Collections.singletonList(ClassLoader.class), imageClassLoader);
invokeStaticMethod("com.oracle.truffle.polyglot.InstrumentCache", "initializeNativeImageState",
Collections.singletonList(ClassLoader.class), imageClassLoader);
invokeStaticMethod("com.oracle.truffle.api.impl.TruffleLocator", "initializeNativeImageState",
Collections.emptyList());

TruffleRuby at latest release happens to depend on all encodings. As a result, the native-image created under these conditions either breaks immediately at runtime, with:

Caused by: java.lang.IllegalArgumentException: unknown encoding: "ASCII-8BIT"
        at org.graalvm.truffle/com.oracle.truffle.api.strings.InternalErrors.illegalArgument(InternalErrors.java:76)
        at org.graalvm.truffle/com.oracle.truffle.api.strings.InternalErrors.unknownEncoding(InternalErrors.java:96)
        at org.graalvm.truffle/com.oracle.truffle.api.strings.TruffleString$Encoding.fromJCodingName(TruffleString.java:1094)
        at org.truffleruby.core.encoding.TStringUtils.jcodingToTEncoding(TStringUtils.java:43)
        at org.truffleruby.core.encoding.RubyEncoding.<init>(RubyEncoding.java:57)
        at org.truffleruby.core.encoding.Encodings.initializeRubyEncodings(Encodings.java:95)
        at org.truffleruby.core.encoding.Encodings.<clinit>(Encodings.java:43)

... or at build time with the same exception, if --initialize-at-build-time=org.truffleruby.core.encoding.Encodings is passed.

Steps to reproduce the issue

In our case (Elide), we are building against latest (24.0.1) native-image, with GraalPython, TruffleRuby, and GraalJs.

GraalPython triggers the early initialization of TruffleString encodings via a handful of calls in the BouncyCastleFeature and JNIFeature classes. In both cases, there are checks against PythonOptions static fields; for example here. It is the class initialization of PythonOptions which initializes encodings with TruffleString literals used at class-init time.

  1. git clone git@github.com:elide-dev/elide.git -b main
  2. cd elide && ./gradlew build -x test -x check
  3. vim ./packages/cli/build.gradle.kts
  4. Change enableRuby to true
  5. ./gradlew :packages:cli:nativeCompile
  6. ./packages/cli/build/native/nativeCompile/elide.debug shell --language=RUBY

Describe GraalVM and your environment:

  • GraalVM version (latest snapshot builds can be found here), or commit id if built from source: 24.0.1
  • JDK major version: 22.0.1
  • OS: macOS Sonoma 14.3.1
  • Architecture: M-series (aarch64)
@fernando-valdez
Copy link
Member

Thanks for reporting this. I will take a look at it

sgammon added a commit to elide-dev/elide that referenced this issue Apr 18, 2024
- chore: release bump → `1.0.0-alpha8`
- chore: issue new packaging and install script versions
- chore: doc for issue with gvm/ruby
- chore: readme updates; language compat, new versions
- chore: use short test names in console reporting
- chore: rebuild docs
- chore: fix slsa provenance
- chore: strict ci hardening

Fixes and closes #789

Relates-To: oracle/graal#8795
Signed-off-by: Sam Gammon <sam@elide.ventures>
@eregon
Copy link
Member

eregon commented Apr 18, 2024

This specific code changed on master, compare
24.0: https://github.com/oracle/graal/blob/release/graal-vm/24.0/truffle/src/com.oracle.truffle.api.strings/src/com/oracle/truffle/api/strings/TruffleString.java#L1049-L1051
master:

static TruffleString.Encoding fromJCodingsName(String jCodingsName) {

Could you try with master too?
There are dev builds at https://github.com/graalvm/graalvm-ce-dev-builds and https://github.com/graalvm/oracle-graalvm-ea-builds/releases.
I suspect no error or a different error on master.
The logic to detect if all encoding are needed also changed, which might have fixed this.
cc @woess

@eregon eregon added the truffle label Apr 18, 2024
sgammon added a commit to elide-dev/elide that referenced this issue Apr 18, 2024
- chore: release bump → `1.0.0-alpha8`
- chore: issue new packaging and install script versions
- chore: doc for issue with gvm/ruby
- chore: readme updates; language compat, new versions
- chore: use short test names in console reporting
- chore: rebuild docs
- chore: fix slsa provenance
- chore: strict ci hardening

Fixes and closes #789

Relates-To: oracle/graal#8795
Signed-off-by: Sam Gammon <sam@elide.ventures>
sgammon added a commit to elide-dev/elide that referenced this issue Apr 26, 2024
Prepares the `alpha8` release of Elide.

- feat: extended language tooling
- feat(dev): add support for rust
- feat(dev): add new `graalvm-ts` module for typescript
- feat(model): model for dependencies in project config
- feat(model): model for tooling configurations and support
- feat(node): node native std module structures
- feat(node): implement `path` module
- feat(node): implement `process` module
- fix: build deprecations, ability to override kotlin + jvm targets
- fix: detect `Throwable` instances as provided to logging calls
- fix: generate stacktrace and include in place of exception
- fix: ci audit for build, unused imports/fmt
- fix: version alignment for netty and kotlin
- fix(cli): duplicate print with commands via repl
- fix(cli): language selector logic
- fix(cli): missing libffi dependency
- fix(cli): static native library registration
- fix(cli): jline output style
- fix(cli): support for `elide srcfile.<js|py|rb>`
- fix(cli): language/action selection from root entrypoint
- fix(cli): ability to detect language by file extension
- fix(cli): command prefix should override language selection
- fix(dev): detekt version and conventions
- fix(js): cis and esm imports
- fix(js): js bindings in newer testing framework
- fix(js): latest language declaration for `ES2023`
- fix(vfs): short-read bug in vfs layer
- fix(vfs): vfs access during testing
- chore: release bump → `1.0.0-alpha8`
- chore: issue new packaging and install script versions
- chore: doc for issue with gvm/ruby
- chore: readme updates; language compat, new versions
- chore: use short test names in console reporting
- chore: rebuild docs
- chore: fix slsa provenance
- chore: strict ci hardening
- chore: update pgo profiles
- chore: remove superfluous deps from native image
- chore: enable embedded sbom
- chore: enable pgo
- chore: enable context pre-init (non-experimental)
- chore(model): language support updates to embedded vm info
- chore(tooling): add `pkl` module
- chore(tooling): add `esbuild` module
- chore(tooling): add `ruff` module
- chore(tooling): add `uv` module
- chore(tooling): add third_party root
- chore(cli): re-enable native lib features
- chore(cli): add `umbrella` native lib for tooling bridge
- chore(cli): add new `cli-bridge` module for JNI access to umbrella lib
- chore(js): recompile polyfills and runtime facade
- chore(js): cleanup old experimental esbuild entry point

Fixes and closes #789
Fixes and closes #210

Relates-To: oracle/graal#8795
Signed-off-by: Sam Gammon <sam@elide.ventures>
sgammon added a commit to elide-dev/elide that referenced this issue Apr 26, 2024
Prepares the `alpha8` release of Elide.

- feat: extended language tooling
- feat(dev): add support for rust
- feat(dev): add new `graalvm-ts` module for typescript
- feat(model): model for dependencies in project config
- feat(model): model for tooling configurations and support
- feat(node): node native std module structures
- feat(node): implement `path` module
- feat(node): implement `process` module
- fix: build deprecations, ability to override kotlin + jvm targets
- fix: detect `Throwable` instances as provided to logging calls
- fix: generate stacktrace and include in place of exception
- fix: ci audit for build, unused imports/fmt
- fix: version alignment for netty and kotlin
- fix(cli): duplicate print with commands via repl
- fix(cli): language selector logic
- fix(cli): missing libffi dependency
- fix(cli): static native library registration
- fix(cli): jline output style
- fix(cli): support for `elide srcfile.<js|py|rb>`
- fix(cli): language/action selection from root entrypoint
- fix(cli): ability to detect language by file extension
- fix(cli): command prefix should override language selection
- fix(dev): detekt version and conventions
- fix(js): cis and esm imports
- fix(js): js bindings in newer testing framework
- fix(js): latest language declaration for `ES2023`
- fix(vfs): short-read bug in vfs layer
- fix(vfs): vfs access during testing
- chore: release bump → `1.0.0-alpha8`
- chore: issue new packaging and install script versions
- chore: doc for issue with gvm/ruby
- chore: readme updates; language compat, new versions
- chore: use short test names in console reporting
- chore: rebuild docs
- chore: fix slsa provenance
- chore: strict ci hardening
- chore: update pgo profiles
- chore: remove superfluous deps from native image
- chore: enable embedded sbom
- chore: enable pgo
- chore: enable context pre-init (non-experimental)
- chore(model): language support updates to embedded vm info
- chore(tooling): add `pkl` module
- chore(tooling): add `esbuild` module
- chore(tooling): add `ruff` module
- chore(tooling): add `uv` module
- chore(tooling): add third_party root
- chore(cli): re-enable native lib features
- chore(cli): add `umbrella` native lib for tooling bridge
- chore(cli): add new `cli-bridge` module for JNI access to umbrella lib
- chore(js): recompile polyfills and runtime facade
- chore(js): cleanup old experimental esbuild entry point

Fixes and closes #789
Fixes and closes #210

Relates-To: oracle/graal#8795
Signed-off-by: Sam Gammon <sam@elide.ventures>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants