Skip to content

Commit 10bcd49

Browse files
committed
[GR-47958] Fix assertions in PolyglotWrapper host code cache lookup.
PullRequest: graal/15407
2 parents be1908a + babc773 commit 10bcd49

File tree

7 files changed

+167
-30
lines changed

7 files changed

+167
-30
lines changed
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
/*
2+
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* The Universal Permissive License (UPL), Version 1.0
6+
*
7+
* Subject to the condition set forth below, permission is hereby granted to any
8+
* person obtaining a copy of this software, associated documentation and/or
9+
* data (collectively the "Software"), free of charge and under any and all
10+
* copyright rights in the Software, and any and all patent rights owned or
11+
* freely licensable by each licensor hereunder covering either (i) the
12+
* unmodified Software as contributed to or provided by such licensor, or (ii)
13+
* the Larger Works (as defined below), to deal in both
14+
*
15+
* (a) the Software, and
16+
*
17+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
18+
* one is included with the Software each a "Larger Work" to which the Software
19+
* is contributed by such licensors),
20+
*
21+
* without restriction, including without limitation the rights to copy, create
22+
* derivative works of, display, perform, and distribute the Software and make,
23+
* use, sell, offer for sale, import, export, have made, and have sold the
24+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
25+
* either these or other terms.
26+
*
27+
* This license is subject to the following condition:
28+
*
29+
* The above copyright notice and either this complete permission notice or at a
30+
* minimum a reference to the UPL must be included in all copies or substantial
31+
* portions of the Software.
32+
*
33+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39+
* SOFTWARE.
40+
*/
41+
package com.oracle.truffle.api.test.host;
42+
43+
import java.util.List;
44+
import java.util.Map;
45+
import java.util.function.BiFunction;
46+
import java.util.stream.Collectors;
47+
48+
import org.graalvm.polyglot.Context;
49+
import org.graalvm.polyglot.HostAccess;
50+
import org.graalvm.polyglot.Value;
51+
import org.graalvm.polyglot.proxy.ProxyArray;
52+
import org.graalvm.polyglot.proxy.ProxyHashMap;
53+
import org.junit.Assert;
54+
import org.junit.Test;
55+
56+
import com.oracle.truffle.api.test.host.AsCollectionsTest.ListBasedTO;
57+
import com.oracle.truffle.api.test.host.AsCollectionsTest.MapBasedTO;
58+
59+
/**
60+
* Reproducer for https://github.com/oracle/graal/issues/7082.
61+
*/
62+
public class GR47958 {
63+
64+
@FunctionalInterface
65+
public interface GenericListConsumer {
66+
@HostAccess.Export
67+
String call(List<List<CharSequence>> arg);
68+
}
69+
70+
@FunctionalInterface
71+
public interface GenericMapConsumer {
72+
@HostAccess.Export
73+
String call(Map<String, List<CharSequence>> arg);
74+
}
75+
76+
@SuppressWarnings("static-method")
77+
private String toString(List<List<CharSequence>> arg) {
78+
return String.valueOf(arg.stream().flatMap(List<CharSequence>::stream).collect(Collectors.joining(", ")));
79+
}
80+
81+
@SuppressWarnings("static-method")
82+
private String toString(Map<String, List<CharSequence>> arg) {
83+
return String.valueOf(arg.entrySet().stream().map(e -> e.getKey() + ", " + String.join(", ", e.getValue())).collect(Collectors.joining(", ")));
84+
}
85+
86+
@Test
87+
public void testPolyglotListReproducer() {
88+
HostAccess hostAccess = HostAccess.newBuilder(HostAccess.EXPLICIT).allowAccessInheritance(true).build();
89+
try (Context context = Context.newBuilder().allowHostAccess(hostAccess).build()) {
90+
for (var invoker : List.<BiFunction<Value, Object, Value>> of(
91+
(target, array) -> target.invokeMember("call", array),
92+
(target, array) -> target.execute(array))) {
93+
Value target;
94+
Value result;
95+
Object array;
96+
97+
target = context.asValue((GenericListConsumer) this::toString);
98+
array = new ListBasedTO(List.of(new ListBasedTO(List.of("hello")), new ListBasedTO(List.of("world")), new ListBasedTO(List.of())));
99+
result = invoker.apply(target, array);
100+
Assert.assertEquals("hello, world", result.toString());
101+
102+
target = context.asValue((GenericListConsumer) this::toString);
103+
array = new ListBasedTO(List.of(new ListBasedTO(List.of("hello"))));
104+
result = invoker.apply(target, array);
105+
Assert.assertEquals("hello", result.toString());
106+
107+
target = context.asValue((GenericListConsumer) this::toString);
108+
array = ProxyArray.fromArray(ProxyArray.fromArray("hello"), ProxyArray.fromArray("world"), ProxyArray.fromArray());
109+
result = invoker.apply(target, array);
110+
Assert.assertEquals("hello, world", result.toString());
111+
112+
target = context.asValue((GenericListConsumer) this::toString);
113+
array = ProxyArray.fromArray(ProxyArray.fromArray("hello"));
114+
result = invoker.apply(target, array);
115+
Assert.assertEquals("hello", result.toString());
116+
}
117+
}
118+
}
119+
120+
@Test
121+
public void testPolyglotMapReproducer() {
122+
HostAccess hostAccess = HostAccess.newBuilder(HostAccess.EXPLICIT).allowAccessInheritance(true).build();
123+
try (Context context = Context.newBuilder().allowHostAccess(hostAccess).build()) {
124+
for (var invoker : List.<BiFunction<Value, Object, Value>> of(
125+
(target, array) -> target.invokeMember("call", array),
126+
(target, array) -> target.execute(array))) {
127+
Value target;
128+
Value result;
129+
Object map;
130+
131+
target = context.asValue((GenericMapConsumer) this::toString);
132+
map = new MapBasedTO(Map.of("hello", new ListBasedTO(List.of("world"))));
133+
result = invoker.apply(target, map);
134+
Assert.assertEquals("hello, world", result.toString());
135+
136+
target = context.asValue((GenericMapConsumer) this::toString);
137+
map = new MapBasedTO(Map.of("hi", new ListBasedTO(List.of("there"))));
138+
result = invoker.apply(target, map);
139+
Assert.assertEquals("hi, there", result.toString());
140+
141+
target = context.asValue((GenericMapConsumer) this::toString);
142+
map = ProxyHashMap.from(Map.of("hello", ProxyArray.fromList(List.of("world"))));
143+
result = invoker.apply(target, map);
144+
Assert.assertEquals("hello, world", result.toString());
145+
146+
target = context.asValue((GenericMapConsumer) this::toString);
147+
map = ProxyHashMap.from(Map.of("hi", ProxyArray.fromList(List.of("there"))));
148+
result = invoker.apply(target, map);
149+
Assert.assertEquals("hi, there", result.toString());
150+
}
151+
}
152+
}
153+
}

truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ValueHostInteropTest.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -78,7 +78,6 @@
7878
import org.graalvm.polyglot.proxy.ProxyObject;
7979
import org.hamcrest.CoreMatchers;
8080
import org.junit.Before;
81-
import org.junit.Ignore;
8281
import org.junit.Rule;
8382
import org.junit.Test;
8483
import org.junit.rules.TestName;
@@ -537,9 +536,9 @@ public void executableAsFunctionalInterface2() throws Exception {
537536
f.toString();
538537
}
539538

540-
@Ignore("Interface not accessible")
541539
@Test
542540
public void executableAsFunctionalInterface3() throws Exception {
541+
TruffleTestAssumptions.assumeNotAOT();
543542
TruffleTestAssumptions.assumeNoClassLoaderEncapsulation();
544543
TruffleObject executable = new FunctionObject();
545544
FunctionalWithDefaults f = context.asValue(executable).as(FunctionalWithDefaults.class);

truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotFunctionProxyHandler.java

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -40,9 +40,6 @@
4040
*/
4141
package com.oracle.truffle.polyglot;
4242

43-
import java.lang.invoke.MethodHandle;
44-
import java.lang.invoke.MethodHandles;
45-
import java.lang.invoke.MethodType;
4643
import java.lang.reflect.InvocationHandler;
4744
import java.lang.reflect.Method;
4845
import java.lang.reflect.Modifier;
@@ -53,7 +50,6 @@
5350
import com.oracle.truffle.api.CallTarget;
5451
import com.oracle.truffle.api.CompilerAsserts;
5552
import com.oracle.truffle.api.CompilerDirectives;
56-
import com.oracle.truffle.api.Truffle;
5753
import com.oracle.truffle.api.TruffleOptions;
5854
import com.oracle.truffle.api.dsl.Cached;
5955
import com.oracle.truffle.api.dsl.ImportStatic;
@@ -191,18 +187,7 @@ static Object invokeDefault(PolyglotWrapper host, Object proxy, Method method, O
191187
if (TruffleOptions.AOT) {
192188
throw new UnsupportedOperationException("calling default method " + method.getName() + " is not yet supported on SubstrateVM");
193189
}
194-
195-
// default method; requires Java 9 (JEP 274)
196-
Class<?> declaringClass = method.getDeclaringClass();
197-
assert declaringClass.isInterface() : declaringClass;
198-
MethodHandle mh;
199-
try {
200-
Truffle.class.getModule().addReads(declaringClass.getModule());
201-
mh = MethodHandles.lookup().findSpecial(declaringClass, method.getName(), MethodType.methodType(method.getReturnType(), method.getParameterTypes()), declaringClass);
202-
} catch (IllegalAccessException e) {
203-
throw new UnsupportedOperationException(method.getName(), e);
204-
}
205-
return mh.bindTo(proxy).invokeWithArguments(arguments);
190+
return InvocationHandler.invokeDefault(proxy, method, arguments);
206191
}
207192

208193
@ImportStatic(ProxyInvokeNode.class)

truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotIterable.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -138,7 +138,7 @@ static Cache lookup(PolyglotLanguageContext languageContext, Class<?> receiverCl
138138
}
139139
assert cache.receiverClass == receiverClass;
140140
assert cache.valueClass == valueClass;
141-
assert cache.valueType == valueType;
141+
assert Objects.equals(cache.valueType, valueType);
142142
return cache;
143143
}
144144

truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotList.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -191,7 +191,7 @@ static Cache lookup(PolyglotLanguageContext languageContext, Class<?> receiverCl
191191
}
192192
assert cache.receiverClass == receiverClass;
193193
assert cache.valueClass == valueClass;
194-
assert cache.valueType == valueType;
194+
assert Objects.equals(cache.valueType, valueType);
195195
return cache;
196196
}
197197

truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotMap.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -427,9 +427,9 @@ static Cache lookup(PolyglotLanguageContext languageContext, Class<?> receiverCl
427427
}
428428
assert cache.receiverClass == receiverClass;
429429
assert cache.keyClass == keyClass;
430-
assert cache.keyType == keyType;
430+
assert Objects.equals(cache.keyType, keyType);
431431
assert cache.valueClass == valueClass;
432-
assert cache.valueType == valueType;
432+
assert Objects.equals(cache.valueType, valueType);
433433
return cache;
434434
}
435435

truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotMapEntry.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -164,9 +164,9 @@ static PolyglotMapEntry.Cache lookup(PolyglotLanguageContext languageContext, Cl
164164
}
165165
assert cache.receiverClass == receiverClass;
166166
assert cache.keyClass == keyClass;
167-
assert cache.keyType == keyType;
167+
assert Objects.equals(cache.keyType, keyType);
168168
assert cache.valueClass == valueClass;
169-
assert cache.valueType == valueType;
169+
assert Objects.equals(cache.valueType, valueType);
170170
return cache;
171171
}
172172

0 commit comments

Comments
 (0)