# HG changeset patch # User Lukas Stadler # Date 1399307893 -7200 # Node ID 6f23b90c4129068d07cde650658f462fa4fe9e76 # Parent eb9fa3d34314aaca16dd8988367b449d9921d9b4# Parent 1a7ebcf3ae22bb040f35e0c28636843629a6b64b Merge (Truffle: fix javadoc) diff -r eb9fa3d34314 -r 6f23b90c4129 CHANGELOG.md --- 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 diff -r eb9fa3d34314 -r 6f23b90c4129 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/LazyClassLoadingTest.java --- /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 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)"; + } + } +} diff -r eb9fa3d34314 -r 6f23b90c4129 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildNodeTest.java --- 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 @@ * *

* 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()}. *

* *

diff -r eb9fa3d34314 -r 6f23b90c4129 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java --- 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[] 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 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[] insert(final T[] newChildren) { CompilerDirectives.transferToInterpreterAndInvalidate(); assert newChildren != null; diff -r eb9fa3d34314 -r 6f23b90c4129 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java --- 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 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 getImplicitTypeParamters(SpecializationData model) { + protected final List getImplicitTypeParameters(SpecializationData model) { List 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 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 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 {