changeset 15509:6f23b90c4129

Merge (Truffle: fix javadoc)
author Lukas Stadler <lukas.stadler@oracle.com>
date Mon, 05 May 2014 18:38:13 +0200
parents eb9fa3d34314 (current diff) 1a7ebcf3ae22 (diff)
children a900caddcd60
files
diffstat 5 files changed, 151 insertions(+), 45 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGELOG.md	Mon May 05 18:37:27 2014 +0200
+++ b/CHANGELOG.md	Mon May 05 18:38:13 2014 +0200
@@ -12,13 +12,14 @@
 * ...
 
 ### Truffle
-* The method CallTarget#call takes now a variable number of Object arguments.
+* The method `CallTarget#call` takes now a variable number of Object arguments.
 * Support for collecting stack traces and for accessing the current frame in slow paths.
-* Renamed CallNode to DirectCallNode.
-* Renamed TruffleRuntime#createCallNode to TruffleRuntime#createDirectCallNode.
-* Added IndirectCallNode for calls with a changing CallTarget. 
-* Added TruffleRuntime#createIndirectCallNode to create an IndirectCallNode.
-* DirectCallNode#inline was renamed to DirectCallNode#forceInlining().
+* Renamed `CallNode` to `DirectCallNode`.
+* Renamed `TruffleRuntime#createCallNode` to `TruffleRuntime#createDirectCallNode`.
+* Added `IndirectCallNode` for calls with a changing `CallTarget`.
+* Added `TruffleRuntime#createIndirectCallNode` to create an `IndirectCallNode`.
+* `DirectCallNode#inline` was renamed to `DirectCallNode#forceInlining()`.
+* Removed deprecated `Node#adoptChild`.
 * ...
 
 ## Version 0.2
@@ -45,7 +46,7 @@
 * New API to declare the cost of a Node for use in runtime environment specific heuristics. See `NodeCost`, `Node#getCost` and `NodeInfo#cost`.
 * Removed old API for `NodeInfo#Kind` and `NodeInfo#kind`. As a replacement the new `NodeCost` API can be used.
 * Changed `Node#replace` reason parameter type to `CharSequence` (to enable lazy string building)
-* Deprecated `Node#adoptChild` and `Node#adoptChild`, no longer needed in node constructor
+* Deprecated `Node#adoptChild` and `Node#adoptChildren`, no longer needed in node constructor
 * New `Node#insert` method for inserting new nodes into the tree (formerly `adoptChild`)
 * New `Node#adoptChildren` helper method that adopts all (direct and indirect) children of a node
 * New API `Node#atomic` for atomic tree operations
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/LazyClassLoadingTest.java	Mon May 05 18:38:13 2014 +0200
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import java.lang.reflect.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.LazyClassLoadingTestFactory.TestNodeFactory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+
+public class LazyClassLoadingTest {
+    @Test
+    public void test() {
+        String testClassName = getClass().getName();
+        String factoryClassName = testClassName + "Factory";
+        String nodeFactoryClassName = factoryClassName + "$TestNodeFactory";
+
+        Assert.assertFalse(isLoaded(factoryClassName + "$TestNode"));
+        Assert.assertFalse(isLoaded(nodeFactoryClassName));
+
+        NodeFactory<TestNode> factory = TestNodeFactory.getInstance();
+
+        Assert.assertTrue(isLoaded(nodeFactoryClassName));
+        Assert.assertFalse(isLoaded(nodeFactoryClassName + "$TestBaseNode"));
+
+        TestHelper.createRoot(factory);
+
+        Assert.assertTrue(isLoaded(nodeFactoryClassName + "$TestBaseNode"));
+        Assert.assertTrue(isLoaded(nodeFactoryClassName + "$TestUninitializedNode"));
+        Assert.assertFalse(isLoaded(nodeFactoryClassName + "$TestGenericNode"));
+    }
+
+    private boolean isLoaded(String className) {
+        ClassLoader classLoader = getClass().getClassLoader();
+        Method m;
+        try {
+            m = ClassLoader.class.getDeclaredMethod("findLoadedClass", String.class);
+            m.setAccessible(true);
+            return m.invoke(classLoader, className) != null;
+        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @SuppressWarnings("unused")
+    @NodeChildren({@NodeChild("left"), @NodeChild("right")})
+    abstract static class TestNode extends ValueNode {
+        @Specialization(order = 1)
+        int add(int left, int right) {
+            return 42;
+        }
+
+        @Specialization(order = 2)
+        int add(boolean left, boolean right) {
+            return 21;
+        }
+
+        @Specialization(order = 4)
+        String add(boolean left, int right) {
+            return "(boolean,int)";
+        }
+    }
+}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildNodeTest.java	Mon May 05 18:37:27 2014 +0200
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildNodeTest.java	Mon May 05 18:38:13 2014 +0200
@@ -36,10 +36,8 @@
  *
  * <p>
  * Child nodes are stored in the class of the parent node in fields that are marked with the
- * {@link Child} annotation. Before such a field is assigned, {@link Node#adoptChild} must be
- * called. This method automatically establishes a link from the child to the parent. The
- * {@link Node#getParent()} method allows access to this field. Every node also provides the ability
- * to iterate over its children using {@link Node#getChildren()}.
+ * {@link Child} annotation. The {@link Node#getParent()} method allows access to this field. Every
+ * node also provides the ability to iterate over its children using {@link Node#getChildren()}.
  * </p>
  *
  * <p>
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Mon May 05 18:37:27 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Mon May 05 18:38:13 2014 +0200
@@ -134,31 +134,6 @@
      * @param newChildren the array of new children whose parent should be updated
      * @return the array of new children
      */
-    @SuppressWarnings("static-method")
-    @Deprecated
-    protected final <T extends Node> T[] adoptChildren(final T[] newChildren) {
-        return newChildren;
-    }
-
-    /**
-     * Method that updates the link to the parent in the specified new child node to this node.
-     *
-     * @param newChild the new child whose parent should be updated
-     * @return the new child
-     */
-    @SuppressWarnings("static-method")
-    @Deprecated
-    protected final <T extends Node> T adoptChild(final T newChild) {
-        return newChild;
-    }
-
-    /**
-     * Method that updates the link to the parent in the array of specified new child nodes to this
-     * node.
-     *
-     * @param newChildren the array of new children whose parent should be updated
-     * @return the array of new children
-     */
     protected final <T extends Node> T[] insert(final T[] newChildren) {
         CompilerDirectives.transferToInterpreterAndInvalidate();
         assert newChildren != null;
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Mon May 05 18:37:27 2014 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Mon May 05 18:38:13 2014 +0200
@@ -49,6 +49,8 @@
     private static final String EXECUTE_POLYMORPHIC_NAME = "executePolymorphic0";
 
     private static final String UPDATE_TYPES_NAME = "updateTypes";
+    private static final String COPY_WITH_CONSTRUCTOR_NAME = "copyWithConstructor";
+    private static final String CREATE_SPECIALIZATION_NAME = "createSpecialization";
 
     public NodeCodeGenerator(ProcessorContext context) {
         super(context);
@@ -834,7 +836,7 @@
             if (node.getSpecializations().isEmpty()) {
                 body.nullLiteral();
             } else {
-                body.startNew(nodeSpecializationClassName(node.getSpecializations().get(0)));
+                body.startCall(nodeSpecializationClassName(node.getSpecializations().get(0)), CREATE_SPECIALIZATION_NAME);
                 for (VariableElement var : method.getParameters()) {
                     body.string(var.getSimpleName().toString());
                 }
@@ -865,7 +867,7 @@
             if (found == null) {
                 body.startThrow().startNew(getContext().getType(UnsupportedOperationException.class)).end().end();
             } else {
-                body.startReturn().startNew(nodeSpecializationClassName(found)).startGroup().cast(baseClassName(node)).string(THIS_NODE_LOCAL_VAR_NAME).end().end().end();
+                body.startReturn().startCall(nodeSpecializationClassName(found), CREATE_SPECIALIZATION_NAME).startGroup().string(THIS_NODE_LOCAL_VAR_NAME).end().end().end();
             }
             return method;
         }
@@ -952,7 +954,6 @@
             if (node.getGenericSpecialization() != null && node.getGenericSpecialization().isReachable()) {
                 clazz.add(createGenericExecute(node, rootGroup));
             }
-
         }
 
         protected boolean needsInvokeCopyConstructorMethod() {
@@ -960,7 +961,7 @@
         }
 
         protected CodeExecutableElement createCopy(TypeMirror baseType, SpecializationData specialization) {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), baseType, "copyWithConstructor");
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), baseType, COPY_WITH_CONSTRUCTOR_NAME);
             if (specialization == null) {
                 method.getModifiers().add(ABSTRACT);
             } else {
@@ -968,7 +969,7 @@
                 builder.startReturn();
                 builder.startNew(getElement().asType());
                 builder.string("this");
-                for (ActualParameter param : getImplicitTypeParamters(specialization)) {
+                for (ActualParameter param : getImplicitTypeParameters(specialization)) {
                     builder.string(implicitTypeName(param));
                 }
                 builder.end().end();
@@ -1738,7 +1739,7 @@
             } else {
                 replaceCall.startCall("replace");
             }
-            replaceCall.startGroup().startNew(className).string(source);
+            replaceCall.startGroup().cast(baseClassName(current.getNode())).startCall(className, CREATE_SPECIALIZATION_NAME).string(source);
             for (ActualParameter param : current.getSignatureParameters()) {
                 NodeChildData child = param.getSpecification().getExecution().getChild();
                 List<TypeData> types = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType());
@@ -1762,7 +1763,7 @@
             String uninitializedName = nodeSpecializationClassName(node.getUninitializedSpecialization());
             CodeTreeBuilder builder = parent.create();
 
-            builder.declaration(getElement().asType(), "currentCopy", currentNode + ".copyWithConstructor()");
+            builder.declaration(getElement().asType(), "currentCopy", currentNode + "." + COPY_WITH_CONSTRUCTOR_NAME + "()");
             for (ActualParameter param : getModel().getSignatureParameters()) {
                 NodeExecutionData execution = param.getSpecification().getExecution();
                 builder.startStatement().tree(createAccessChild(execution, "currentCopy")).string(" = ").nullLiteral().end();
@@ -1928,7 +1929,7 @@
             }
         }
 
-        protected final List<ActualParameter> getImplicitTypeParamters(SpecializationData model) {
+        protected final List<ActualParameter> getImplicitTypeParameters(SpecializationData model) {
             List<ActualParameter> parameter = new ArrayList<>();
             for (ActualParameter param : model.getSignatureParameters()) {
                 NodeChildData child = param.getSpecification().getExecution().getChild();
@@ -2546,6 +2547,18 @@
             if (needsInvokeCopyConstructorMethod()) {
                 clazz.add(createCopy(nodeGen.asType(), specialization));
             }
+
+            if (!specialization.isUninitialized() && specialization.getNode().needsRewrites(context)) {
+                clazz.add(createCopyConstructorFactoryMethod(nodeGen.asType(), specialization));
+            } else {
+                for (ExecutableElement constructor : ElementFilter.constructorsIn(clazz.getEnclosedElements())) {
+                    if (constructor.getParameters().size() == 1 && ((CodeVariableElement) constructor.getParameters().get(0)).getType().equals(nodeGen.asType())) {
+                        // skip copy constructor - not used
+                        continue;
+                    }
+                    clazz.add(createConstructorFactoryMethod(specialization, constructor));
+                }
+            }
         }
 
         protected void createConstructors(CodeTypeElement clazz) {
@@ -2579,7 +2592,7 @@
                     }
                 }
                 if (superConstructor != null) {
-                    for (ActualParameter param : getImplicitTypeParamters(getModel())) {
+                    for (ActualParameter param : getImplicitTypeParameters(getModel())) {
                         clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), getContext().getType(Class.class), implicitTypeName(param)));
                         superConstructor.getParameters().add(new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(param)));
 
@@ -2911,6 +2924,40 @@
             return builder.getRoot();
         }
 
+        protected CodeExecutableElement createCopyConstructorFactoryMethod(TypeMirror baseType, SpecializationData specialization) {
+            List<ActualParameter> implicitTypeParams = getImplicitTypeParameters(specialization);
+            CodeVariableElement[] parameters = new CodeVariableElement[implicitTypeParams.size() + 1];
+            int i = 0;
+            String baseName = "current";
+            parameters[i++] = new CodeVariableElement(specialization.getNode().getNodeType(), baseName);
+            for (ActualParameter implicitTypeParam : implicitTypeParams) {
+                parameters[i++] = new CodeVariableElement(getContext().getType(Class.class), implicitTypeName(implicitTypeParam));
+            }
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(STATIC), specialization.getNode().getNodeType(), CREATE_SPECIALIZATION_NAME, parameters);
+            CodeTreeBuilder builder = method.createBuilder();
+            builder.startReturn();
+            builder.startNew(getElement().asType());
+            builder.startGroup().cast(baseType, CodeTreeBuilder.singleString(baseName)).end();
+            for (ActualParameter param : implicitTypeParams) {
+                builder.string(implicitTypeName(param));
+            }
+            builder.end().end();
+            return method;
+        }
+
+        protected CodeExecutableElement createConstructorFactoryMethod(SpecializationData specialization, ExecutableElement constructor) {
+            List<? extends VariableElement> parameters = constructor.getParameters();
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(STATIC), specialization.getNode().getNodeType(), CREATE_SPECIALIZATION_NAME,
+                            parameters.toArray(new CodeVariableElement[parameters.size()]));
+            CodeTreeBuilder builder = method.createBuilder();
+            builder.startReturn();
+            builder.startNew(getElement().asType());
+            for (VariableElement param : parameters) {
+                builder.string(((CodeVariableElement) param).getName());
+            }
+            builder.end().end();
+            return method;
+        }
     }
 
     private interface CodeBlock<T> {