-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
HostObject interop with wrapping TruffleObject #4916
HostObject interop with wrapping TruffleObject #4916
Conversation
Thank you for your pull request and welcome to our community! To contribute, please sign the Oracle Contributor Agreement (OCA).
To sign the OCA, please create an Oracle account and sign the OCA in Oracle's Contributor Agreement Application. When singing the OCA, please provide your GitHub username. After signing the OCA and getting an OCA approval from Oracle, this PR will be automatically updated. |
Value wrapFive = WrapObject.wrap(five); | ||
|
||
Value wrapPlus = four.invokeMember("add", wrapFive); | ||
assertEquals(444L + 555L, wrapPlus.invokeMember("longValue").asLong()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When the test is executed on 21.3 branch, it fails with:
1) com.oracle.truffle.api.test.polyglot.HostObjectWrappedTest#testHostInteropWithWrapper
java.lang.IllegalArgumentException: Invalid argument when invoking 'add' on '444'(language: Java, type: java.math.BigInteger). Cannot convert '555'(language: Java, type: java.math.BigInteger) to Java type 'java.math.BigInteger': Unsupported target type.Provided arguments: ['555'(language: Java, type: java.math.BigInteger)].
at com.oracle.truffle.polyglot.PolyglotEngineException.illegalArgument(PolyglotEngineException.java:125)
at com.oracle.truffle.polyglot.PolyglotValueDispatch.invalidInvokeArgumentType(PolyglotValueDispatch.java:1432)
Are you using WrapObject.wrap in production code, if so why? I agree the kind of refactoring sketched in 6b9dfae would roughly do the trick. We cannot however just use uncached everywhere, that would lead to a performance regression. We would need to create cached libraries and use them where appropriate. We also have some dependent EE code we would need to fix on our side for this. |
No, that's just for the test. The production code has |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We cannot however just use uncached everywhere, that would lead to a performance regression
Whenever there is a Node
"somewhere", the patch uses cached version. The goal is to use uncached only when behind @TruffleBoundary
or in an @Override
method (overridden methods are usually not subject to PE, right?). Also when there already is InteropLibrary.getUncached()
or etc., it is OK to use HostLibrary.getUncached()
.
truffle/src/com.oracle.truffle.host/src/com/oracle/truffle/host/HostExecuteNode.java
Show resolved
Hide resolved
@@ -152,7 +152,7 @@ private boolean validHostValue(Object hostValue, HostContext context) { | |||
|
|||
@Override | |||
public boolean isHostValue(Object value) { | |||
Object obj = HostLanguage.unwrapIfScoped(language, value); | |||
Object obj = HostLanguage.unwrapIfScoped(language, HostLibrary.getUncached(), value); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using HostLibrary.getUncached()
as isHostValue()
is an @Override
method. Overridden methods are (usually) not subject to PE.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is not true. Such a rule does not exist and does particularly not apply for most of the truffle.polyglot and truffle.host code. The only important thing is that the virtual call can be devirtualized reliably during PE otherwise it would cause a performance warning during compilation. This is generally true for all objects rooted in the PolyglotEngineImpl class like AbstractPolyglotHostService as the engine is always a constant in PE paths.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that AbstractPolyglotHostService exists for polyglot isolates, as all host operations need to be handled differently there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The @Override
claim, was just a (wrong) guess. I know PE doesn't like overwritten methods, but if it resolves to a single method, then it of course works fine.
Update on Sep 19:
The Old Blocklisted method check does no longer work after updating to 22.x master
branch. Using new trick: let's add neverPartOfCompilation()
to HostLibrary.getUncached()
: 77254c3 - then @tzezula suggested me to run following tests:
graal/compiler$ mx unittest --verbose com.oracle.truffle
Obviously they failed on compilations. Fixed by 72e0162 - plus I've added two sets of @TruffleBoundary
annotations:
Fixing those two would require changes in the API. I Hope this is good enough base for future work that can be adopted by Truffle team lands in GraalVM soonish.
Old Blocklisted method check:
To compensate for my erroneous judgment, I suggest following check: Modify the unwrapIfScoped
method to reference some blacklisted method:
graal/vm$ git diff
diff --git a/truffle/src/com.oracle.truffle.host/src/com/oracle/truffle/host/HostLanguage.java b/truffle/src/com.oracle.truffle.host/src/com/oracle/truffle/host/HostLanguage.java
index 9706e5f5e56..a045c0ce7b0 100644
--- a/truffle/src/com.oracle.truffle.host/src/com/oracle/truffle/host/HostLanguage.java
+++ b/truffle/src/com.oracle.truffle.host/src/com/oracle/truffle/host/HostLanguage.java
@@ -61,6 +61,7 @@ import com.oracle.truffle.api.interop.UnsupportedMessageException;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.nodes.RootNode;
import com.oracle.truffle.host.HostMethodScope.ScopedObject;
+import java.io.File;
/*
* Java host language implementation.
@@ -94,6 +95,7 @@ final class HostLanguage extends TruffleLanguage<HostContext> {
}
static Object unwrapIfScoped(HostLanguage language, HostLibrary library, Object o) {
+ if (!new File(".").exists()) throw new IllegalStateException();
HostInstance host = library.asHostInstance(o);
if (language == null || !language.methodScopingEnabled) {
return host;
and then compile js
with native image. It gives seven violations like:
graal/vm$ mx --native-image=js --java-home ~/bin/labs-11/ --dy=/graal-js,/espresso --env ni-ce build
=== Found 7 compilation blocklist violations ===
Blocklisted method
java.io.UnixFileSystem.getBooleanAttributes0(File)
called from
java.io.UnixFileSystem.getBooleanAttributes(UnixFileSystem.java:248)
java.io.File.exists(File.java:831)
com.oracle.truffle.host.HostLanguage.unwrapIfScoped(HostLanguage.java:98)
com.oracle.truffle.host.HostObject.isInstance(HostObject.java:147) -> com.oracle.truffle.host.HostLanguageService.isHostObject(HostLanguageService.java:203)
com.oracle.truffle.polyglot.EngineAccessor$EngineImpl.isHostObject(EngineAccessor.java:1080)
com.oracle.truffle.api.TruffleLanguage$Env.isHostObject(TruffleLanguage.java:2116)
com.oracle.truffle.js.builtins.ConstructorBuiltins$ConstructJavaImporterNode.constructJavaImporter(ConstructorBuiltins.java:2233)
com.oracle.truffle.js.builtins.ConstructorBuiltinsFactory$ConstructJavaImporterNodeGen.execute(ConstructorBuiltinsFactory.java:4490)
com.oracle.truffle.js.nodes.control.TopLevelAwaitModuleBodyNode$TopLevelAwaitModuleRootNode.execute(TopLevelAwaitModuleBodyNode.java:106)
org.graalvm.compiler.truffle.runtime.OptimizedCallTarget.executeRootNode(OptimizedCallTarget.java:650)
org.graalvm.compiler.truffle.runtime.OptimizedCallTarget.profiledPERoot(OptimizedCallTarget.java:622)
All of them go thru com.oracle.truffle.api.TruffleLanguage$Env.isHostObject
.
truffle/src/com.oracle.truffle.host/src/com/oracle/truffle/host/HostObject.java
Show resolved
Hide resolved
truffle/src/com.oracle.truffle.host/src/com/oracle/truffle/host/HostTargetMappingNode.java
Show resolved
Hide resolved
truffle/src/com.oracle.truffle.host/src/com/oracle/truffle/host/HostToTypeNode.java
Show resolved
Hide resolved
… HostObject interop
…to HostObject and co.
629d3df
to
4be5fe5
Compare
|
||
/** Marker interface to recognize all host objects. | ||
*/ | ||
interface HostInstance { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is the purpose of this?
} | ||
|
||
public HostInstance asHostInstance(Object obj) { | ||
return obj instanceof HostInstance ? (HostInstance) obj : null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interface type checks are very expensive. Any reason why there is not a isHostInstance and asHostInstance?
The first returns true|false whether it is a host object. And the second returns not the HostObject wrapper but the underlying real host object. asHostInstance then could fail with an UnsupportedMessageException if it is used with the wrong implementation.
We should let ScopedObject implement HostLibrary as well that significantly improves other code such that we can get rid of HostLanguage.unwrapIfScoped.
@JaroslavTulach has now signed an OCA. |
I have to put this PR on hold as I don't have time to finish it right now. |
Enso language supports values with warnings. They are implemented as a
TruffleObject
that wraps original object, holds the warnings and delegates all messages viaReflectionLibrary
to the original object. Find more details in the implementation.This PR provides a test showing the use-case and demonstrating the failure as the first commit. Additional commits follow showing possible implementation making the test work: 629d3df