changeset 22196:364e3f024643

Java objects passed into globalSymbol should be converted into something that Truffle languages can understand - e.g. TruffleObject instances.
author Jaroslav Tulach <jaroslav.tulach@oracle.com>
date Fri, 25 Sep 2015 14:06:44 +0200
parents 09d91119929f
children c8f4168061ea
files truffle/com.oracle.truffle.api.interop.java.test/src/com/oracle/truffle/api/interop/java/test/MethodMessageTest.java truffle/com.oracle.truffle.api.interop.java/src/com/oracle/truffle/api/interop/java/JavaInterop.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/GlobalSymbolTest.java truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/JavaWrapper.java truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/PolyglotEngine.java
diffstat 5 files changed, 59 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/truffle/com.oracle.truffle.api.interop.java.test/src/com/oracle/truffle/api/interop/java/test/MethodMessageTest.java	Thu Sep 24 15:50:38 2015 +0200
+++ b/truffle/com.oracle.truffle.api.interop.java.test/src/com/oracle/truffle/api/interop/java/test/MethodMessageTest.java	Fri Sep 25 14:06:44 2015 +0200
@@ -24,6 +24,7 @@
  */
 package com.oracle.truffle.api.interop.java.test;
 
+import com.oracle.truffle.api.interop.Message;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.interop.java.MethodMessage;
@@ -71,6 +72,9 @@
     public void workWithAnArray() throws Exception {
         TruffleObject arr = JavaInterop.asTruffleObject(new Object[]{1, 2, 3});
 
+        Boolean itIsAnArray = (Boolean) JavaInteropTest.message(Message.HAS_SIZE, arr);
+        assertTrue("Yes, array", itIsAnArray);
+
         MaxFunction wrap = JavaInterop.asJavaObject(MaxFunction.class, arr);
 
         assertTrue("It is an array", wrap.isArray());
--- a/truffle/com.oracle.truffle.api.interop.java/src/com/oracle/truffle/api/interop/java/JavaInterop.java	Thu Sep 24 15:50:38 2015 +0200
+++ b/truffle/com.oracle.truffle.api.interop.java/src/com/oracle/truffle/api/interop/java/JavaInterop.java	Fri Sep 25 14:06:44 2015 +0200
@@ -140,15 +140,32 @@
      *         <code>foreignObject</code>
      */
     public static <T> T asJavaObject(Class<T> type, TruffleObject foreignObject) {
-        if (type.isInstance(foreignObject)) {
-            return type.cast(foreignObject);
+        return asJavaObject(type, null, foreignObject);
+    }
+
+    private static <T> T asJavaObject(Class<T> clazz, Type type, TruffleObject foreignObject) {
+        Object obj;
+        if (clazz.isInstance(foreignObject)) {
+            obj = foreignObject;
         } else {
-            if (!type.isInterface()) {
+            if (!clazz.isInterface()) {
                 throw new IllegalArgumentException();
             }
-            Object obj = Proxy.newProxyInstance(type.getClassLoader(), new Class<?>[]{type}, new TruffleHandler(foreignObject));
-            return type.cast(obj);
+            if (clazz == List.class && Boolean.TRUE.equals(message(Message.HAS_SIZE, foreignObject))) {
+                Class<?> elementType = Object.class;
+                if (type instanceof ParameterizedType) {
+                    ParameterizedType parametrizedType = (ParameterizedType) type;
+                    final Type[] arr = parametrizedType.getActualTypeArguments();
+                    if (arr.length == 1 && arr[0] instanceof Class) {
+                        elementType = (Class<?>) arr[0];
+                    }
+                }
+                obj = TruffleList.create(elementType, foreignObject);
+            } else {
+                obj = Proxy.newProxyInstance(clazz.getClassLoader(), new Class<?>[]{clazz}, new TruffleHandler(foreignObject));
+            }
         }
+        return clazz.cast(obj);
     }
 
     /**
@@ -265,19 +282,7 @@
         if (ret instanceof TruffleObject) {
             final TruffleObject truffleObject = (TruffleObject) ret;
             if (retType.isInterface()) {
-                if (method.getReturnType() == List.class && Boolean.TRUE.equals(message(Message.HAS_SIZE, truffleObject))) {
-                    Class<?> elementType = Object.class;
-                    Type type = method.getGenericReturnType();
-                    if (type instanceof ParameterizedType) {
-                        ParameterizedType parametrizedType = (ParameterizedType) type;
-                        final Type[] arr = parametrizedType.getActualTypeArguments();
-                        if (arr.length == 1 && arr[0] instanceof Class) {
-                            elementType = (Class<?>) arr[0];
-                        }
-                    }
-                    return TruffleList.create(elementType, truffleObject);
-                }
-                return asJavaObject(retType, truffleObject);
+                return asJavaObject(retType, method.getGenericReturnType(), truffleObject);
             }
         }
         return ret;
--- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/GlobalSymbolTest.java	Thu Sep 24 15:50:38 2015 +0200
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/GlobalSymbolTest.java	Fri Sep 25 14:06:44 2015 +0200
@@ -22,13 +22,17 @@
  */
 package com.oracle.truffle.api.test.vm;
 
+import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.source.Source;
 import static com.oracle.truffle.api.test.vm.ImplicitExplicitExportTest.L3;
 import com.oracle.truffle.api.vm.PolyglotEngine;
 import java.io.IOException;
+import java.util.List;
 import java.util.concurrent.Executors;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 import org.junit.Test;
 
 public class GlobalSymbolTest {
@@ -50,4 +54,18 @@
         assertNotNull("Symbol found", ret);
         assertEquals("42", ret.get());
     }
+
+    @Test
+    public void passingArray() throws IOException {
+        PolyglotEngine vm = PolyglotEngine.buildNew().globalSymbol("arguments", new Object[]{"one", "two", "three"}).build();
+        PolyglotEngine.Value value = vm.findGlobalSymbol("arguments");
+        assertFalse("Not instance of array", value.get() instanceof Object[]);
+        assertTrue("Instance of TruffleObject", value.get() instanceof TruffleObject);
+        List<?> args = value.as(List.class);
+        assertNotNull("Can be converted to List", args);
+        assertEquals("Three items", 3, args.size());
+        assertEquals("one", args.get(0));
+        assertEquals("two", args.get(1));
+        assertEquals("three", args.get(2));
+    }
 }
--- a/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/JavaWrapper.java	Thu Sep 24 15:50:38 2015 +0200
+++ b/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/JavaWrapper.java	Fri Sep 25 14:06:44 2015 +0200
@@ -40,9 +40,13 @@
     }
 
     static <T> T create(Class<T> representation, Object wrapper, PolyglotEngine.Value value) {
-        InvocationHandler chain = Proxy.getInvocationHandler(wrapper);
-        Object instance = Proxy.newProxyInstance(representation.getClassLoader(), new Class<?>[]{representation}, new JavaWrapper(value, wrapper, chain));
-        return representation.cast(instance);
+        try {
+            InvocationHandler chain = Proxy.getInvocationHandler(wrapper);
+            Object instance = Proxy.newProxyInstance(representation.getClassLoader(), new Class<?>[]{representation}, new JavaWrapper(value, wrapper, chain));
+            return representation.cast(instance);
+        } catch (IllegalArgumentException ex) {
+            return representation.cast(wrapper);
+        }
     }
 
     @Override
--- a/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/PolyglotEngine.java	Thu Sep 24 15:50:38 2015 +0200
+++ b/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/PolyglotEngine.java	Fri Sep 25 14:06:44 2015 +0200
@@ -293,7 +293,13 @@
          * @see PolyglotEngine#findGlobalSymbol(java.lang.String)
          */
         public Builder globalSymbol(String name, Object obj) {
-            globals.put(name, obj);
+            final Object truffleReady;
+            if (obj instanceof Number || obj instanceof String || obj instanceof Character || obj instanceof Boolean) {
+                truffleReady = obj;
+            } else {
+                truffleReady = JavaInterop.asTruffleObject(obj);
+            }
+            globals.put(name, truffleReady);
             return this;
         }