# HG changeset patch # User Thomas Wuerthinger # Date 1339798008 -7200 # Node ID 26a060cc58caf40d17435d44fb85816bb64cf110 # Parent 65bf69eb147c35b014c2235f7b45c3e96ec874e3 Initial implementation of closed world analysis by iteratively expanding the universe starting at method entry points. diff -r 65bf69eb147c -r 26a060cc58ca graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaField.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaField.java Thu Jun 14 18:03:43 2012 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaField.java Sat Jun 16 00:06:48 2012 +0200 @@ -47,6 +47,13 @@ Constant constantValue(Constant receiver); /** + * Gets the current value of the field if available. + * @param receiver object from which this field's value is to be read. This value is ignored if this field is static. + * @return the value of this field or {@code null} if the value is not available (e.g., because the field holder is not yet initialized). + */ + Constant getValue(Constant receiver); + + /** * Gets the holder of this field as a compiler-runtime interface type. * @return the holder of this field */ diff -r 65bf69eb147c -r 26a060cc58ca graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/HelloWorldTest.java --- a/graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/HelloWorldTest.java Thu Jun 14 18:03:43 2012 +0200 +++ b/graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/HelloWorldTest.java Sat Jun 16 00:06:48 2012 +0200 @@ -29,6 +29,6 @@ public static void main(String[] args) { BootImageGenerator generator = new BootImageGenerator(); generator.addEntryMethod(HelloWorldTestProgram.class, "main", String[].class); - generator.logState(); + generator.printState(); } } diff -r 65bf69eb147c -r 26a060cc58ca graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/test/helloworld/HelloWorldTestProgram.java --- a/graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/test/helloworld/HelloWorldTestProgram.java Thu Jun 14 18:03:43 2012 +0200 +++ b/graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/test/helloworld/HelloWorldTestProgram.java Sat Jun 16 00:06:48 2012 +0200 @@ -22,7 +22,6 @@ */ package com.oracle.graal.boot.test.helloworld; - public class HelloWorldTestProgram { public static void main(String[] args) { System.out.println("Hello world!"); diff -r 65bf69eb147c -r 26a060cc58ca graal/com.oracle.graal.boot/src/com/oracle/graal/boot/BigBang.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/BigBang.java Sat Jun 16 00:06:48 2012 +0200 @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2012, 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.graal.boot; + +import java.lang.reflect.*; +import java.util.*; +import java.util.concurrent.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.boot.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.java.*; + +public class BigBang { + + private static final int THREADS = 1; + + private MetaAccessProvider metaAccessProvider; + private int postedOperationCount; + + // Mappings from Graal IR and Graal meta-data to element instances. + private Map sinkMap = new IdentityHashMap<>(); + private Map fieldMap = new IdentityHashMap<>(); + private Map methodMap = new IdentityHashMap<>(); + private Map arrayTypeMap = new IdentityHashMap<>(); + + // Processing queue. + private ThreadPoolExecutor executor = new ThreadPoolExecutor(THREADS, THREADS, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), Executors.defaultThreadFactory()); + + public BigBang(MetaAccessProvider metaAccessProvider) { + this.metaAccessProvider = metaAccessProvider; + } + + public synchronized FieldElement getProcessedField(ResolvedJavaField field) { + assert field != null; + if (!fieldMap.containsKey(field)) { + fieldMap.put(field, new FieldElement(field)); + } + return fieldMap.get(field); + } + + public synchronized MethodElement getProcessedMethod(ResolvedJavaMethod method) { + assert method != null; + if (!methodMap.containsKey(method)) { + methodMap.put(method, new MethodElement(method)); + } + return methodMap.get(method); + } + + public synchronized ArrayTypeElement getProcessedArrayType(ResolvedJavaType type) { + assert type != null; + if (!arrayTypeMap.containsKey(type)) { + arrayTypeMap.put(type, new ArrayTypeElement(type)); + } + return arrayTypeMap.get(type); + } + + public synchronized Element getSinkElement(Node node, Node sourceNode) { + if (!sinkMap.containsKey(node)) { + Element resultElement = Element.BLACK_HOLE; + if (node instanceof PhiNode) { + PhiNode phiNode = (PhiNode) node; + resultElement = new PhiElement(phiNode); + } else if (node instanceof StoreFieldNode) { + StoreFieldNode storeFieldNode = (StoreFieldNode) node; + resultElement = getProcessedField(storeFieldNode.field()); + } else if (node instanceof StoreIndexedNode) { + StoreIndexedNode storeIndexedNode = (StoreIndexedNode) node; + if (storeIndexedNode.elementKind() == Kind.Object) { + resultElement = getProcessedArrayType(storeIndexedNode.array().stamp().declaredType()); + } + } else if (node instanceof ReturnNode) { + ReturnNode returnNode = (ReturnNode) node; + ResolvedJavaMethod method = ((StructuredGraph) returnNode.graph()).method(); + resultElement = getProcessedMethod(method); + } else { + if (node instanceof FrameState || node instanceof MonitorEnterNode || node instanceof MonitorExitNode || node instanceof LoadFieldNode || node instanceof IsNullNode) { + // OK. + } else { + System.out.println("Unknown sink - black hole? " + node); + } + } + + sinkMap.put(node, resultElement); + } + + if (node instanceof StoreIndexedNode) { + StoreIndexedNode storeIndexedNode = (StoreIndexedNode) node; + if (storeIndexedNode.value() != sourceNode) { + return Element.BLACK_HOLE; + } + } + + if (node instanceof StoreFieldNode) { + StoreFieldNode storeFieldNode = (StoreFieldNode) node; + if (storeFieldNode.value() != sourceNode) { + return Element.BLACK_HOLE; + } + } + return sinkMap.get(node); + } + + public synchronized void registerSourceCallTargetNode(MethodCallTargetNode methodCallTargetNode) { + sinkMap.put(methodCallTargetNode, new InvokeElement(methodCallTargetNode)); + } + + public synchronized void registerSourceNode(Node node) { + Element resultElement = null; + if (node instanceof LoadFieldNode) { + LoadFieldNode loadFieldNode = (LoadFieldNode) node; + resultElement = getProcessedField(loadFieldNode.field()); + } else if (node instanceof LoadIndexedNode) { + LoadIndexedNode loadIndexedNode = (LoadIndexedNode) node; + resultElement = getProcessedArrayType(loadIndexedNode.array().stamp().declaredType()); + } else if (node instanceof LocalNode) { + LocalNode localNode = (LocalNode) node; + if (localNode.kind() == Kind.Object) { + ResolvedJavaMethod method = ((StructuredGraph) localNode.graph()).method(); + resultElement = getProcessedMethod(method).getParameter(localNode.index()); + System.out.println("resultElement = " + resultElement + " index= " + localNode.index() + ", node=" + node); + } + } + + if (resultElement != null) { + resultElement.postAddUsage(this, node); + } + } + + public synchronized void postOperation(UniverseExpansionOp operation) { + System.out.println("posting operation " + operation); + executor.execute(operation); + postedOperationCount++; + } + + public MetaAccessProvider getMetaAccess() { + return metaAccessProvider; + } + + public void finish() { + while (true) { + try { + Thread.sleep(10); + boolean terminated; + int oldPostedOperationCount; + synchronized (this) { + terminated = (executor.getCompletedTaskCount() == postedOperationCount); + oldPostedOperationCount = postedOperationCount; + } + + if (terminated) { + checkObjectGraph(); + synchronized (this) { + if (postedOperationCount == oldPostedOperationCount) { + System.out.printf("Big bang simulation completed in %d operations.\n", postedOperationCount); + executor.shutdown(); + break; + } + } + } + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + } + + private void checkObjectGraph() { + List originalRoots = new ArrayList<>(); + synchronized (this) { + for (FieldElement field : fieldMap.values()) { + if (field.isStatic()) { + originalRoots.add(field); + } + } + } + + Map scannedObjects = new IdentityHashMap<>(); + for (FieldElement field : originalRoots) { + assert field.isStatic(); + if (field.getUsageCount() > 0 && field.getJavaField().kind() == Kind.Object) { + Object value = field.getJavaField().getValue(null).asObject(); + System.out.printf("Root field %s: %s\n", field, value); + scanField(scannedObjects, field, value); + } + } + } + + private void scanField(Map scannedObjects, FieldElement field, Object value) { + if (value != null && field.getUsageCount() > 0) { + field.registerNewValue(this, value); + scan(scannedObjects, value); + } + } + + private void scan(Map scannedObjects, Object value) { + assert value != null; + if (scannedObjects.containsKey(value)) { + return; + } + + scannedObjects.put(value, Boolean.TRUE); + ResolvedJavaType type = getMetaAccess().getResolvedJavaType(value.getClass()); + scan(scannedObjects, value, type); + } + + private void scan(Map scannedObjects, Object value, ResolvedJavaType type) { + if (type.superType() != null) { + scan(scannedObjects, value, type.superType()); + } + + ResolvedJavaField[] declaredFields = type.declaredFields(); + for (ResolvedJavaField field : declaredFields) { + if (field.kind() == Kind.Object) { + FieldElement fieldElement = getProcessedField(field); + Object fieldValue = field.getValue(Constant.forObject(value)).asObject(); + scanField(scannedObjects, fieldElement, fieldValue); + } + } + + } + + public synchronized void printState() { + + int nativeMethodCount = 0; + for (MethodElement methodElement : methodMap.values()) { + if (methodElement.hasGraph()) { + if (Modifier.isNative(methodElement.getResolvedJavaMethod().accessFlags())) { + System.out.println("Included native method: " + methodElement.getResolvedJavaMethod()); + nativeMethodCount++; + } + } + } + + int methodCount = 0; + for (MethodElement methodElement : methodMap.values()) { + if (methodElement.hasGraph()) { + if (!Modifier.isNative(methodElement.getResolvedJavaMethod().accessFlags())) { + System.out.println("Included method: " + methodElement.getResolvedJavaMethod()); + methodCount++; + } + } + } + + Set includedTypes = new HashSet<>(); + int fieldCount = 0; + for (FieldElement fieldElement : fieldMap.values()) { + if (fieldElement.getUsageCount() > 0) { + System.out.println("Included field: " + fieldElement.getJavaField()); + fieldCount++; + includedTypes.add(fieldElement.getJavaField().holder()); + } + } + + for (ResolvedJavaType type : includedTypes) { + System.out.println("Included type: " + type); + } + + System.out.println("Number of included native methods: " + nativeMethodCount); + System.out.println("Number of included method: " + methodCount); + System.out.println("Number of included fields: " + fieldCount); + System.out.println("Number of included types: " + includedTypes.size()); + } +} diff -r 65bf69eb147c -r 26a060cc58ca graal/com.oracle.graal.boot/src/com/oracle/graal/boot/BootImageGenerator.java --- a/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/BootImageGenerator.java Thu Jun 14 18:03:43 2012 +0200 +++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/BootImageGenerator.java Sat Jun 16 00:06:48 2012 +0200 @@ -26,13 +26,14 @@ import com.oracle.graal.api.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.debug.*; +import com.oracle.graal.boot.meta.*; public class BootImageGenerator { private final BootImageClassLoader classLoader = new BootImageClassLoader(); private final MetaAccessProvider metaAccess = Graal.getRequiredCapability(MetaAccessProvider.class); + private final BigBang bigbang = new BigBang(metaAccess); public void addEntryMethod(Class clazz, String name, Class ... parameterTypes) { Class convertedClass = classLoader.convert(clazz); @@ -42,17 +43,20 @@ } catch (NoSuchMethodException | SecurityException e) { throw new RuntimeException("Could not find method " + name + " with parameter types " + parameterTypes + " in class " + convertedClass.getCanonicalName()); } - Debug.log("Adding method %s.%s to the boot image", method.getClass().getName(), method.getName()); + System.out.printf("Adding method %s.%s to the boot image\n", method.getDeclaringClass().getName(), method.getName()); addEntryMethod(metaAccess.getResolvedJavaMethod(method)); } private void addEntryMethod(ResolvedJavaMethod javaMethod) { - + MethodElement methodElement = bigbang.getProcessedMethod(javaMethod); + methodElement.postParseGraph(bigbang); + bigbang.finish(); } - public void logState() { - Debug.log("State"); + public void printState() { + System.out.println("State of boot image generation"); + bigbang.printState(); } } diff -r 65bf69eb147c -r 26a060cc58ca graal/com.oracle.graal.boot/src/com/oracle/graal/boot/UniverseExpansionOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/UniverseExpansionOp.java Sat Jun 16 00:06:48 2012 +0200 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2012, 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.graal.boot; + +import com.oracle.graal.boot.*; + + + +public abstract class UniverseExpansionOp implements Runnable { + + public void post(BigBang store) { + store.postOperation(this); + } + + @Override + public void run() { + expand(); + } + + protected abstract void expand(); +} diff -r 65bf69eb147c -r 26a060cc58ca graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/ArrayTypeElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/ArrayTypeElement.java Sat Jun 16 00:06:48 2012 +0200 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2012, 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.graal.boot.meta; + +import com.oracle.graal.api.meta.*; + + +public class ArrayTypeElement extends Element { + + private ResolvedJavaType javaType; + + public ArrayTypeElement(ResolvedJavaType javaType) { + super(javaType.componentType()); + this.javaType = javaType; + } + + @Override + public String toString() { + return javaType + super.toString(); + } +} diff -r 65bf69eb147c -r 26a060cc58ca graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/Element.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/Element.java Sat Jun 16 00:06:48 2012 +0200 @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2011, 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.graal.boot.meta; + +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.boot.*; +import com.oracle.graal.graph.*; + + +public class Element { + + public static final Element BLACK_HOLE = new Element(null); + + protected List usages = new ArrayList<>(4); + protected Set seenTypes = new HashSet<>(); + private ResolvedJavaType declaredType; + + protected Element(ResolvedJavaType declaredType) { + this.declaredType = declaredType; + } + + public void postUnionTypes(final BigBang bb, final Node sourceNode, final Set newSeenTypes) { + new UniverseExpansionOp() { + @Override + protected void expand() { + unionTypes(bb, sourceNode, newSeenTypes); + } + + @Override + public String toString() { + return String.format("Add new seen types %s from source node %s to element %s", newSeenTypes, sourceNode, Element.this); + } + }.post(bb); + } + + public void postAddUsage(final BigBang bb, final Node usage) { + new UniverseExpansionOp() { + @Override + protected void expand() { + addUsage(bb, usage); + } + + @Override + public String toString() { + return String.format("Add usage %s to element %s", usage, Element.this); + } + }.post(bb); + } + + protected synchronized void unionTypes(BigBang bb, @SuppressWarnings("unused") Node sourceNode, Set newSeenTypes) { + if (!seenTypes.containsAll(newSeenTypes)) { + if (declaredType != null) { + for (ResolvedJavaType seenType : newSeenTypes) { + if (!seenType.isSubtypeOf(declaredType)) { + System.out.println("Wrong type found " + seenType + " where declared type of element " + this + " is " + declaredType); + System.exit(-1); + } + } + } + seenTypes.addAll(newSeenTypes); + propagateTypes(bb, newSeenTypes); + } + } + + protected synchronized void propagateTypes(BigBang bb, Set newSeenTypes) { + for (Node n : usages) { + propagateTypes(bb, n, newSeenTypes); + } + } + + public synchronized int getUsageCount() { + return usages.size(); + } + + protected synchronized void addUsage(BigBang bb, Node usage) { + if (!usages.contains(usage)) { + usages.add(usage); + propagateTypes(bb, usage, seenTypes); + } + } + + public static void propagateTypes(BigBang bb, Node n, Set types) { + if (types.size() != 0) { + Set newSet = new HashSet<>(types); + for (Node use : n.usages()) { + Element element = bb.getSinkElement(use, n); + assert element != null; + if (element != BLACK_HOLE) { + element.postUnionTypes(bb, n, newSet); + } + } + } + } +} diff -r 65bf69eb147c -r 26a060cc58ca graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/FieldElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/FieldElement.java Sat Jun 16 00:06:48 2012 +0200 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2012, 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.graal.boot.meta; + +import java.lang.reflect.*; +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.boot.*; + + +public class FieldElement extends Element { + + protected ResolvedJavaField javaField; + + public FieldElement(ResolvedJavaField javaField) { + super(javaField.type().resolve(javaField.holder())); + this.javaField = javaField; + } + + public boolean isStatic() { + return Modifier.isStatic(javaField.accessFlags()); + } + + public ResolvedJavaField getJavaField() { + return javaField; + } + + @Override + public String toString() { + return "Field[" + javaField + "]"; + } + + public synchronized void registerNewValue(BigBang bb, Object value) { + if (value != null) { + Class clazz = value.getClass(); + ResolvedJavaType resolvedType = bb.getMetaAccess().getResolvedJavaType(clazz); + if (seenTypes.add(resolvedType)) { + Set newSeenTypes = new HashSet<>(); + newSeenTypes.add(resolvedType); + super.propagateTypes(bb, newSeenTypes); + } + } + } +} diff -r 65bf69eb147c -r 26a060cc58ca graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/InvokeElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/InvokeElement.java Sat Jun 16 00:06:48 2012 +0200 @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2012, 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.graal.boot.meta; + +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.boot.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; + + +public class InvokeElement extends Element { + + private MethodCallTargetNode methodCallTarget; + private Set concreteTargets = new HashSet<>(); + private Set[] parameterTypes; + + @SuppressWarnings("unchecked") + public InvokeElement(MethodCallTargetNode methodCallTarget) { + super(methodCallTarget.isStatic() ? null : methodCallTarget.targetMethod().holder()); + this.methodCallTarget = methodCallTarget; + parameterTypes = new Set[methodCallTarget.arguments().size()]; + } + + @Override + protected synchronized void unionTypes(BigBang bb, Node sourceNode, Set newSeenTypes) { + + System.out.println("union invoke element " + this); + int index = 0; + for (Node arg : methodCallTarget.arguments()) { + if (arg == sourceNode) { + System.out.println("source node " + sourceNode + " is at index " + index + " declaredType=" + ((ValueNode) sourceNode).stamp().declaredType()); + unionTypes(bb, sourceNode, newSeenTypes, index); + } + ++index; + } + } + + @Override + public String toString() { + return "Invoke[bci=" + methodCallTarget.invoke().stateAfter().method() + "," + methodCallTarget.targetMethod() + "]"; + } + + private void unionTypes(BigBang bb, @SuppressWarnings("unused") Node sourceNode, Set newSeenTypes, int index) { + if (index == 0 && !methodCallTarget.isStatic()) { + for (ResolvedJavaType type : newSeenTypes) { + if (seenTypes.add(type)) { + // There is a new receiver type! + ResolvedJavaMethod method = type.resolveMethodImpl(methodCallTarget.targetMethod()); + if (method == null) { + System.out.println("!!! type = " + type + " / " + methodCallTarget.targetMethod()); + } + if (!concreteTargets.contains(method)) { + concreteTargets.add(method); + // New concrete method. + MethodElement processedMethod = bb.getProcessedMethod(method); + processedMethod.postParseGraph(bb); + // Propagate types that were previously found for the parameters. + for (int i = 0; i < parameterTypes.length; ++i) { + if (parameterTypes[i] != null) { + HashSet newSeenTypesTemp = new HashSet<>(parameterTypes[i]); + bb.getProcessedMethod(method).getParameter(i).postUnionTypes(bb, null, newSeenTypesTemp); + } + } + } + + // Register new type for receiver. + HashSet newSeenTypesTemp = new HashSet<>(); + newSeenTypesTemp.add(type); + bb.getProcessedMethod(method).getParameter(index).postUnionTypes(bb, null, newSeenTypesTemp); + } + } + } else { + if (parameterTypes[index] == null) { + parameterTypes[index] = new HashSet<>(); + } + if (parameterTypes[index].addAll(newSeenTypes)) { + for (ResolvedJavaMethod method : concreteTargets) { + HashSet newSeenTypesTemp = new HashSet<>(newSeenTypes); + bb.getProcessedMethod(method).getParameter(index).postUnionTypes(bb, null, newSeenTypesTemp); + } + } + } + } +} diff -r 65bf69eb147c -r 26a060cc58ca graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/MethodElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/MethodElement.java Sat Jun 16 00:06:48 2012 +0200 @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2012, 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.graal.boot.meta; + +import java.lang.reflect.*; +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.boot.*; +import com.oracle.graal.compiler.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.java.*; +import com.oracle.graal.java.GraphBuilderConfiguration.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; + + +public class MethodElement extends Element { + + private ParameterElement[] parameters; + private Graph graph; + private ResolvedJavaMethod resolvedJavaMethod; + + public MethodElement(ResolvedJavaMethod javaMethod) { + super(javaMethod.signature().returnType(javaMethod.holder()).resolve(javaMethod.holder())); + assert javaMethod != null; + this.resolvedJavaMethod = javaMethod; + int parameterCount = resolvedJavaMethod.signature().argumentCount(!Modifier.isStatic(resolvedJavaMethod.accessFlags())); + parameters = new ParameterElement[parameterCount]; + for (int i = 0; i < parameters.length; ++i) { + parameters[i] = new ParameterElement(resolvedJavaMethod, i); + } + } + + public ParameterElement getParameter(int index) { + return parameters[index]; + } + + public synchronized boolean hasGraph() { + return graph != null; + } + + public void postParseGraph(final BigBang bb) { + synchronized (this) { + if (graph != null) { + return; + } + } + new UniverseExpansionOp() { + @Override + protected void expand() { + parseGraph(bb); + } + + @Override + public String toString() { + return String.format("Parsing method %s", resolvedJavaMethod); + } + }.post(bb); + } + + protected synchronized void parseGraph(final BigBang bb) { + if (graph != null) { + // Graph already exists => quit operation. + return; + } + StructuredGraph newGraph = new StructuredGraph(resolvedJavaMethod); + this.graph = newGraph; + if (Modifier.isNative(resolvedJavaMethod.accessFlags())) { + System.out.println("NATIVE METHOD " + resolvedJavaMethod); + return; + } + + System.out.println("parsing graph " + resolvedJavaMethod + ", locals=" + resolvedJavaMethod.maxLocals()); + GraphBuilderConfiguration config = new GraphBuilderConfiguration(ResolvePolicy.Eager, null); + GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(bb.getMetaAccess(), config, OptimisticOptimizations.NONE); + graphBuilderPhase.apply(newGraph); + for (MethodCallTargetNode callTargetNode : newGraph.getNodes(MethodCallTargetNode.class)) { + bb.registerSourceCallTargetNode(callTargetNode); + } + + for (Node node : newGraph.getNodes()) { + bb.registerSourceNode(node); + } + + for (NewInstanceNode newInstance : newGraph.getNodes(NewInstanceNode.class)) { + Set types = new HashSet<>(); + types.add(newInstance.instanceClass()); + System.out.println("propagate new instance " + newInstance + ", " + newInstance.instanceClass()); + Element.propagateTypes(bb, newInstance, types); + } + } + + public ResolvedJavaMethod getResolvedJavaMethod() { + return resolvedJavaMethod; + } +} diff -r 65bf69eb147c -r 26a060cc58ca graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/ParameterElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/ParameterElement.java Sat Jun 16 00:06:48 2012 +0200 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2012, 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.graal.boot.meta; + +import java.lang.reflect.*; + +import com.oracle.graal.api.meta.*; + + +public class ParameterElement extends Element { + + private int index; + private ResolvedJavaMethod method; + + public ParameterElement(ResolvedJavaMethod method, int index) { + super(calculateDeclaredType(method, index)); + this.method = method; + this.index = index; + } + + private static ResolvedJavaType calculateDeclaredType(ResolvedJavaMethod m, int i) { + if (Modifier.isStatic(m.accessFlags())) { + return m.signature().argumentTypeAt(i, m.holder()).resolve(m.holder()); + } else { + if (i == 0) { + return m.holder(); + } + return m.signature().argumentTypeAt(i - 1, m.holder()).resolve(m.holder()); + } + } + + @Override + public String toString() { + return "[Parameter, index= " + index + " of method " + method + "]"; + } + +} diff -r 65bf69eb147c -r 26a060cc58ca graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/PhiElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/PhiElement.java Sat Jun 16 00:06:48 2012 +0200 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2012, 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.graal.boot.meta; + +import com.oracle.graal.nodes.*; + + +public class PhiElement extends Element { + + private PhiNode phi; + + public PhiElement(PhiNode phi) { + super(null); + this.phi = phi; + } + + @Override + public String toString() { + return "phi " + phi + super.toString(); + } +} diff -r 65bf69eb147c -r 26a060cc58ca graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Thu Jun 14 18:03:43 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Sat Jun 16 00:06:48 2012 +0200 @@ -204,7 +204,7 @@ @SuppressWarnings("unchecked") @Override public T getCapability(Class clazz) { - if (clazz == ExtendedRiRuntime.class) { + if (clazz == ExtendedRiRuntime.class || clazz == MetaAccessProvider.class) { return (T) getRuntime(); } if (clazz == GraalCompiler.class) { diff -r 65bf69eb147c -r 26a060cc58ca graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java Thu Jun 14 18:03:43 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java Sat Jun 16 00:06:48 2012 +0200 @@ -66,8 +66,7 @@ if (constant == null) { if (holder.isInitialized() && holder.toJava() != System.class) { if (Modifier.isFinal(accessFlags()) || assumeStaticFieldsFinal(holder.toJava())) { - Constant encoding = holder.getEncoding(Representation.StaticFields); - constant = this.kind().readUnsafeConstant(encoding.asObject(), offset); + constant = getValue(receiver); } } } @@ -76,12 +75,27 @@ assert !Modifier.isStatic(accessFlags); // TODO (chaeubl) HotSpot does not trust final non-static fields (see ciField.cpp) if (Modifier.isFinal(accessFlags())) { - return this.kind().readUnsafeConstant(receiver.asObject(), offset); + return getValue(receiver); } } return null; } + @Override + public Constant getValue(Constant receiver) { + if (receiver == null) { + assert Modifier.isStatic(accessFlags); + if (holder.isInitialized()) { + Constant encoding = holder.getEncoding(Representation.StaticFields); + return this.kind().readUnsafeConstant(encoding.asObject(), offset); + } + return null; + } else { + assert !Modifier.isStatic(accessFlags); + return this.kind().readUnsafeConstant(receiver.asObject(), offset); + } + } + private static boolean assumeStaticFieldsFinal(Class< ? > clazz) { return clazz == GraalOptions.class; } diff -r 65bf69eb147c -r 26a060cc58ca graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java Thu Jun 14 18:03:43 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java Sat Jun 16 00:06:48 2012 +0200 @@ -121,6 +121,7 @@ case StaticFields: return Constant.forObject(javaMirror); default: + assert false : "Should not reach here."; return null; } } diff -r 65bf69eb147c -r 26a060cc58ca graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Thu Jun 14 18:03:43 2012 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Sat Jun 16 00:06:48 2012 +0200 @@ -68,7 +68,7 @@ private StructuredGraph currentGraph; - private final CodeCacheProvider runtime; + private final MetaAccessProvider runtime; private ConstantPool constantPool; private ResolvedJavaMethod method; private ProfilingInfo profilingInfo; @@ -104,11 +104,12 @@ private Block[] loopHeaders; - public GraphBuilderPhase(CodeCacheProvider runtime, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts) { + public GraphBuilderPhase(MetaAccessProvider runtime, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts) { this.graphBuilderConfig = graphBuilderConfig; this.optimisticOpts = optimisticOpts; this.runtime = runtime; this.log = GraalOptions.TraceBytecodeParserLevel > 0 ? new LogStream(TTY.out()) : null; + assert runtime != null; } @Override @@ -1097,6 +1098,7 @@ } private ConstantNode appendConstant(Constant constant) { + assert constant != null; return ConstantNode.forConstant(constant, runtime, currentGraph); } diff -r 65bf69eb147c -r 26a060cc58ca graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java Thu Jun 14 18:03:43 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java Sat Jun 16 00:06:48 2012 +0200 @@ -22,7 +22,6 @@ */ package com.oracle.graal.nodes; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.iterators.*; @@ -47,7 +46,7 @@ * Constructs a new ConstantNode representing the specified constant. * @param value the constant */ - protected ConstantNode(Constant value, CodeCacheProvider runtime) { + protected ConstantNode(Constant value, MetaAccessProvider runtime) { super(StampFactory.forConstant(value, runtime)); this.value = value; } @@ -65,7 +64,7 @@ return usages().filter(NodePredicates.isNotA(FrameState.class)).isEmpty(); } - public static ConstantNode forConstant(Constant constant, CodeCacheProvider runtime, Graph graph) { + public static ConstantNode forConstant(Constant constant, MetaAccessProvider runtime, Graph graph) { if (constant.kind == Kind.Object) { return graph.unique(new ConstantNode(constant, runtime)); } else { @@ -169,7 +168,7 @@ * @param graph * @return a node representing the object */ - public static ConstantNode forObject(Object o, CodeCacheProvider runtime, Graph graph) { + public static ConstantNode forObject(Object o, MetaAccessProvider runtime, Graph graph) { return graph.unique(new ConstantNode(Constant.forObject(o), runtime)); } diff -r 65bf69eb147c -r 26a060cc58ca graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java Thu Jun 14 18:03:43 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java Sat Jun 16 00:06:48 2012 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.nodes.java; -import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; @@ -36,7 +36,7 @@ /** * Constructs a new ExceptionObject instruction. */ - public ExceptionObjectNode(CodeCacheProvider runtime) { + public ExceptionObjectNode(MetaAccessProvider runtime) { super(StampFactory.declared(runtime.getResolvedJavaType(Throwable.class))); } diff -r 65bf69eb147c -r 26a060cc58ca graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java Thu Jun 14 18:03:43 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java Sat Jun 16 00:06:48 2012 +0200 @@ -24,7 +24,6 @@ import java.util.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.type.GenericStamp.GenericStampType; @@ -119,7 +118,7 @@ } } - public static Stamp forConstant(Constant value, CodeCacheProvider runtime) { + public static Stamp forConstant(Constant value, MetaAccessProvider runtime) { assert value.kind == Kind.Object; if (value.kind == Kind.Object) { ResolvedJavaType type = value.isNull() ? null : runtime.getTypeOf(value); diff -r 65bf69eb147c -r 26a060cc58ca mx/projects --- a/mx/projects Thu Jun 14 18:03:43 2012 +0200 +++ b/mx/projects Sat Jun 16 00:06:48 2012 +0200 @@ -147,7 +147,7 @@ # graal.boot project@com.oracle.graal.boot@subDir=graal project@com.oracle.graal.boot@sourceDirs=src -project@com.oracle.graal.boot@dependencies=com.oracle.graal.compiler,com.oracle.graal.api +project@com.oracle.graal.boot@dependencies=com.oracle.graal.compiler,com.oracle.graal.java,com.oracle.graal.api project@com.oracle.graal.boot@checkstyle=com.oracle.graal.graph project@com.oracle.graal.boot@javaCompliance=1.7