# HG changeset patch # User Lukas Stadler # Date 1340006853 -7200 # Node ID 731789427441496342f3d67098b6034aab724030 # Parent 8e098bf83c9510cfce7d6b9fbedda4844e8a7bcb# Parent a82376ebaaa99d01355e0ea8d979fc1fba44449c Merge. diff -r 8e098bf83c95 -r 731789427441 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 Fri Jun 15 15:59:43 2012 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaField.java Mon Jun 18 10:07:33 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 8e098bf83c95 -r 731789427441 graal/com.oracle.graal.api/src/com/oracle/graal/api/Graal.java --- a/graal/com.oracle.graal.api/src/com/oracle/graal/api/Graal.java Fri Jun 15 15:59:43 2012 +0200 +++ b/graal/com.oracle.graal.api/src/com/oracle/graal/api/Graal.java Mon Jun 18 10:07:33 2012 +0200 @@ -22,7 +22,6 @@ */ package com.oracle.graal.api; - public class Graal { private static GraalRuntime runtime; @@ -49,4 +48,12 @@ }; } } + + public static T getRequiredCapability(Class clazz) { + T t = getRuntime().getCapability(clazz); + if (t == null) { + throw new IllegalAccessError("Runtime does not expose required capability " + clazz.getName()); + } + return t; + } } diff -r 8e098bf83c95 -r 731789427441 graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/BigBangTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/BigBangTest.java Mon Jun 18 10:07:33 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; + +import org.junit.*; + +public class BigBangTest { + + @Test + public void helloWorldTest() { + BootImageGenerator generator = new BootImageGenerator(); + generator.addEntryMethod(TestPrograms.class, "helloWorldTest"); + Assert.assertArrayEquals(generator.getBigBang().printState(), new int[]{3, 118, 58, 21}); + } + + @Test + public void formattedOutputTest() { + BootImageGenerator generator = new BootImageGenerator(); + generator.addEntryMethod(TestPrograms.class, "formattedOutputTest"); + Assert.assertArrayEquals(generator.getBigBang().printState(), new int[]{15, 979, 346, 98}); + } + + + @Test + public void newTest() { + BootImageGenerator generator = new BootImageGenerator(); + generator.addEntryMethod(TestPrograms.class, "newTest"); + Assert.assertArrayEquals(generator.getBigBang().printState(), new int[]{0, 3, 0, 0}); + } + + + @Test + public void arraycopyTest() { + BootImageGenerator generator = new BootImageGenerator(); + generator.addEntryMethod(TestPrograms.class, "arraycopyTest"); + Assert.assertArrayEquals(generator.getBigBang().printState(), new int[]{2, 6, 0, 0}); + } + + @Test + public void arrayListTest() { + BootImageGenerator generator = new BootImageGenerator(); + generator.addEntryMethod(TestPrograms.class, "arrayListTest"); + Assert.assertArrayEquals(generator.getBigBang().printState(), new int[]{2, 20, 3, 2}); + } +} diff -r 8e098bf83c95 -r 731789427441 graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/BootImageClassLoaderTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/BootImageClassLoaderTest.java Mon Jun 18 10:07:33 2012 +0200 @@ -0,0 +1,79 @@ +/* + * 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 org.junit.*; + + +public class BootImageClassLoaderTest { + + @Test + public void test() throws ClassNotFoundException, IllegalArgumentException, IllegalAccessException, SecurityException { + + TestClassB.x = 1; + BootImageClassLoader l = new BootImageClassLoader(); + + // Assert that the class definition is really duplicated. + Class bClass = Class.forName(TestClassB.class.getCanonicalName(), true, l); + Assert.assertNotSame(TestClassB.class, bClass); + + // Assert that the class definition is not duplicated more than once. + Assert.assertSame(bClass, l.convert(TestClassB.class)); + + // Set field x such that it is used by the subsequent static initializer for TestClassA. + Field bField = bClass.getFields()[0]; + bField.setAccessible(true); + bField.set(null, 2); + + // Assert that the class definition is duplicated. + Class aClass = l.convert(TestClassA.class); + Assert.assertNotSame(TestClassA.class, aClass); + + // Assert that the original version of TestClassA was initialized correctly. + Assert.assertEquals(1, TestClassA.x); + + // Assert that the duplicated version of TestClassA was initialized correctly. + Field aField = aClass.getFields()[0]; + aField.setAccessible(true); + Assert.assertEquals(2, aField.getInt(null)); + + // Assert that system classes are not duplicated. + Assert.assertSame(Object.class, l.convert(Object.class)); + Assert.assertSame(Object.class, Class.forName(Object.class.getCanonicalName(), true, l)); + } + +} + +class TestClassA { + public static int x; + + static { + x = TestClassB.x; + } +} + +class TestClassB { + public static int x; +} diff -r 8e098bf83c95 -r 731789427441 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 Fri Jun 15 15:59:43 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -/* - * 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; - - -public class HelloWorldTest { - -} diff -r 8e098bf83c95 -r 731789427441 graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/TestPrograms.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/TestPrograms.java Mon Jun 18 10:07:33 2012 +0200 @@ -0,0 +1,60 @@ +/* + * 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.util.*; + +public class TestPrograms { + public static void helloWorldTest() { + System.out.println("Hello world!"); + } + + public static void formattedOutputTest() { + System.out.printf("%s %s!", "Hello", "world"); + } + + @SuppressWarnings("unused") + public static void newTest() { + Integer x = new Integer(5); + } + + public static void arraycopyTest() { + Object[] arr = new Object[1]; + arr[0] = new TestObject(); + TestObject[] newArr = Arrays.copyOf(arr, 1, TestObject[].class); + newArr[0].testMethod(); + } + + @SuppressWarnings("unchecked") + public static void arrayListTest() { + ArrayList list = new ArrayList(); + list.add(new TestObject()); + TestObject[] newArr = (TestObject[]) list.toArray(new TestObject[0]); + newArr[0].testMethod(); + } + + public static class TestObject { + public void testMethod() { + } + } +} diff -r 8e098bf83c95 -r 731789427441 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 Fri Jun 15 15:59:43 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -/* - * 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.test.helloworld; - - -public class HelloWorldTestProgram { - public static void main(String[] args) { - System.out.println("Hello world!"); - } -} diff -r 8e098bf83c95 -r 731789427441 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 Mon Jun 18 10:07:33 2012 +0200 @@ -0,0 +1,297 @@ +/* + * 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 = 4; + + 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 CheckCastNode) { + CheckCastNode checkCastNode = (CheckCastNode) node; + resultElement = new CastElement(checkCastNode); + } else if (node instanceof ValueProxyNode) { + ValueProxyNode proxyNode = (ValueProxyNode) node; + resultElement = new ProxyElement(proxyNode); + } 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(metaAccessProvider.getResolvedJavaType(Object[].class)); + } + } 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 || node instanceof InstanceOfNode) { + // 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) { + InvokeElement invokeElement = new InvokeElement(methodCallTargetNode); + sinkMap.put(methodCallTargetNode, invokeElement); + invokeElement.expandStaticMethod(this); + } + + 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; + if (loadIndexedNode.kind() == Kind.Object) { + resultElement = getProcessedArrayType(metaAccessProvider.getResolvedJavaType(Object[].class)); + } + } 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 int[] 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.print("Included field: " + fieldElement.getJavaField() + " / "); + fieldElement.printSeenTypes(); + System.out.println(); + 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()); + return new int[]{nativeMethodCount, methodCount, fieldCount, includedTypes.size()}; + } +} diff -r 8e098bf83c95 -r 731789427441 graal/com.oracle.graal.boot/src/com/oracle/graal/boot/BootImageClassLoader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/BootImageClassLoader.java Mon Jun 18 10:07:33 2012 +0200 @@ -0,0 +1,74 @@ +/* + * 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.io.*; + +public class BootImageClassLoader extends ClassLoader { + + @Override + protected java.lang.Class< ? > loadClass(String name, boolean resolve) throws ClassNotFoundException { + synchronized (getClassLoadingLock(name)) { + Class< ? > result = findLoadedClass(name); + if (result == null) { + result = super.loadClass(name, resolve); + assert result.getName().equals(name); + return duplicate(result); + } + return result; + } + } + + private Class< ? > duplicate(Class< ? > result) { + // This is a class in the bootclasspath => share. + if (result.getClassLoader() == null) { + return result; + } + + // Duplicate class definition. + InputStream inputStream = result.getClassLoader().getResourceAsStream(result.getName().replace('.', '/').concat(".class")); + try { + byte[] byteCodes = new byte[inputStream.available()]; + inputStream.read(byteCodes); + return this.defineClass(result.getName(), byteCodes, 0, byteCodes.length); + } catch (IOException e) { + throw new RuntimeException("Could not access class bytes for " + result.getName()); + } + } + + public Class< ? > convert(Class< ? > clazz) { + synchronized (getClassLoadingLock(clazz.getCanonicalName())) { + // This class has this class loader => no conversion necessary. + if (clazz.getClassLoader() == this) { + return clazz; + } + + Class< ? > thisClazz = findLoadedClass(clazz.getName()); + if (thisClazz != null) { + return thisClazz; + } + + return duplicate(clazz); + } + } +} diff -r 8e098bf83c95 -r 731789427441 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 Fri Jun 15 15:59:43 2012 +0200 +++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/BootImageGenerator.java Mon Jun 18 10:07:33 2012 +0200 @@ -22,7 +22,39 @@ */ package com.oracle.graal.boot; +import java.lang.reflect.*; + +import com.oracle.graal.api.*; +import com.oracle.graal.api.meta.*; +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); + Method method; + try { + method = convertedClass.getDeclaredMethod(name, parameterTypes); + } catch (NoSuchMethodException | SecurityException e) { + throw new RuntimeException("Could not find method " + name + " with parameter types " + parameterTypes + " in class " + convertedClass.getCanonicalName()); + } + 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 BigBang getBigBang() { + return bigbang; + } } diff -r 8e098bf83c95 -r 731789427441 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 Mon Jun 18 10:07:33 2012 +0200 @@ -0,0 +1,38 @@ +/* + * 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; + + +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 8e098bf83c95 -r 731789427441 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 Mon Jun 18 10:07:33 2012 +0200 @@ -0,0 +1,69 @@ +/* + * 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 ArrayTypeElement extends Element { + + private ResolvedJavaType javaType; + + public ArrayTypeElement(ResolvedJavaType javaType) { + super(javaType.componentType()); + this.javaType = javaType; + } + + @Override + public String toString() { + return "arrayTypeElement: " + javaType; + } + + @Override + protected void propagateTypesToUsage(BigBang bb, Node use, Set set, Element element) { + LoadIndexedNode load = (LoadIndexedNode) use; + ResolvedJavaType declaredType = load.array().stamp().declaredType(); + if (declaredType == null) { + System.out.println("FATAL error: Array access without declared type!"); + System.out.println(load.array()); + System.out.println(((StructuredGraph) load.graph()).method()); + System.exit(-1); + } + ResolvedJavaType componentType = declaredType.componentType(); + Set newSet = new HashSet<>(); + for (ResolvedJavaType myType : set) { + if (myType.isSubtypeOf(componentType)) { + newSet.add(myType); + } + } + if (newSet.size() > 0) { + super.propagateTypesToUsage(bb, use, newSet, element); + } + } +} diff -r 8e098bf83c95 -r 731789427441 graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/CastElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/CastElement.java Mon Jun 18 10:07:33 2012 +0200 @@ -0,0 +1,61 @@ +/* + * 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.java.*; + + +public class CastElement extends Element { + + private CheckCastNode checkCastNode; + + public CastElement(CheckCastNode checkCastNode) { + super(checkCastNode.targetClass()); + this.checkCastNode = checkCastNode; + this.usages.add(checkCastNode); + } + + @Override + protected synchronized void unionTypes(BigBang bb, Node sourceNode, Set newSeenTypes) { + Set newSet = new HashSet<>(); + // Filter through checkcast. + for (ResolvedJavaType type : newSeenTypes) { + if (type.isSubtypeOf(checkCastNode.targetClass())) { + newSet.add(type); + } else { + System.out.println("filtering " + type + " vs " + checkCastNode.targetClass()); + } + } + super.unionTypes(bb, sourceNode, newSet); + } + + @Override + public String toString() { + return "cast " + checkCastNode.targetClass(); + } +} diff -r 8e098bf83c95 -r 731789427441 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 Mon Jun 18 10:07:33 2012 +0200 @@ -0,0 +1,127 @@ +/* + * 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 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) { + propagateTypesToUsage(bb, n, newSet, element); + } + } + } + } + + protected void propagateTypesToUsage(BigBang bb, Node use, Set newSet, Element element) { + element.postUnionTypes(bb, use, newSet); + } + + + public synchronized void printSeenTypes() { + for (ResolvedJavaType type : seenTypes) { + System.out.print(type.name() + " "); + } + } +} diff -r 8e098bf83c95 -r 731789427441 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 Mon Jun 18 10:07:33 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 8e098bf83c95 -r 731789427441 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 Mon Jun 18 10:07:33 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.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 + " new types = " + newSeenTypes + " sourceNode= " + sourceNode); + 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() + "]"; + } + + public synchronized void expandStaticMethod(BigBang bb) { + if (methodCallTarget.isStatic()) { + ResolvedJavaMethod method = methodCallTarget.targetMethod(); + concreteTargets.add(method); + MethodElement processedMethod = bb.getProcessedMethod(method); + processedMethod.postParseGraph(bb); + } + } + + 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()); + System.out.println("resolved method " + method + " for type " + type + " and method " + 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 8e098bf83c95 -r 731789427441 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 Mon Jun 18 10:07:33 2012 +0200 @@ -0,0 +1,130 @@ +/* + * 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.compiler.phases.*; +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 void parseGraph(final BigBang bb) { + StructuredGraph newGraph = null; + synchronized (this) { + if (graph != null) { + // Graph already exists => quit operation. + return; + } + 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); + new PhiStampPhase().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()); + for (Node use : newInstance.usages()) { + Element element = bb.getSinkElement(use, newInstance); + assert element != null; + if (element != BLACK_HOLE) { + element.postUnionTypes(bb, newInstance, types); + } + } + } + } + + public ResolvedJavaMethod getResolvedJavaMethod() { + return resolvedJavaMethod; + } +} diff -r 8e098bf83c95 -r 731789427441 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 Mon Jun 18 10:07:33 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 8e098bf83c95 -r 731789427441 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 Mon Jun 18 10:07:33 2012 +0200 @@ -0,0 +1,42 @@ +/* + * 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; + usages.add(phi); + } + + @Override + public String toString() { + return "phi " + phi; + } +} diff -r 8e098bf83c95 -r 731789427441 graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/ProxyElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/ProxyElement.java Mon Jun 18 10:07:33 2012 +0200 @@ -0,0 +1,42 @@ +/* + * 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 ProxyElement extends Element { + + private ValueProxyNode proxy; + + public ProxyElement(ValueProxyNode proxy) { + super(null); + this.proxy = proxy; + usages.add(proxy); + } + + @Override + public String toString() { + return "value proxy " + proxy; + } +} diff -r 8e098bf83c95 -r 731789427441 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java Fri Jun 15 15:59:43 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java Mon Jun 18 10:07:33 2012 +0200 @@ -261,7 +261,7 @@ * Only instructions in methods whose fully qualified name contains this option will be HIR lowered. */ public static String HIRLowerCheckcast = ""; - public static String HIRLowerNewInstance = "NewInstanceTest"; + public static String HIRLowerNewInstance = "NewInstanceTest.new"; /** * The profiling info cache directory. diff -r 8e098bf83c95 -r 731789427441 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/FloatingReadPhase.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/FloatingReadPhase.java Fri Jun 15 15:59:43 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/FloatingReadPhase.java Mon Jun 18 10:07:33 2012 +0200 @@ -138,6 +138,9 @@ } public void processWrite(WriteNode writeNode) { + if (writeNode.location().locationIdentity() == LocationNode.ANY_LOCATION) { + map.clear(); + } map.put(writeNode.location().locationIdentity(), writeNode); } diff -r 8e098bf83c95 -r 731789427441 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 Fri Jun 15 15:59:43 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Mon Jun 18 10:07:33 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 8e098bf83c95 -r 731789427441 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Fri Jun 15 15:59:43 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Mon Jun 18 10:07:33 2012 +0200 @@ -37,7 +37,7 @@ // os information, register layout, code generation, ... public boolean windowsOs; public int codeEntryAlignment; - public boolean verifyPointers; + public boolean verifyOops; public boolean useFastLocking; public boolean useFastNewObjectArray; public boolean useFastNewTypeArray; @@ -103,7 +103,7 @@ public long monitorExitStub; public long fastMonitorEnterStub; public long fastMonitorExitStub; - public long verifyPointerStub; + public long verifyOopStub; public void check() { assert vmPageSize >= 16; diff -r 8e098bf83c95 -r 731789427441 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 Fri Jun 15 15:59:43 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java Mon Jun 18 10:07:33 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 8e098bf83c95 -r 731789427441 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 Fri Jun 15 15:59:43 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java Mon Jun 18 10:07:33 2012 +0200 @@ -121,6 +121,7 @@ case StaticFields: return Constant.forObject(javaMirror); default: + assert false : "Should not reach here."; return null; } } diff -r 8e098bf83c95 -r 731789427441 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java Fri Jun 15 15:59:43 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java Mon Jun 18 10:07:33 2012 +0200 @@ -48,9 +48,9 @@ @Override public void generate(LIRGenerator gen) { Variable result = gen.newVariable(Kind.Object); - gen.emitMove(gen.operand(hub), AMD64.rdx.asValue()); + gen.emitMove(gen.operand(hub), AMD64.rdx.asValue(Kind.Object)); LIRDebugInfo info = gen.state(); - AMD64NewInstanceStubCallOp op = new AMD64NewInstanceStubCallOp(result, AMD64.rdx.asValue(), info); + AMD64NewInstanceStubCallOp op = new AMD64NewInstanceStubCallOp(result, AMD64.rdx.asValue(Kind.Object), info); gen.append(op); gen.setResult(this, result); } diff -r 8e098bf83c95 -r 731789427441 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java Mon Jun 18 10:07:33 2012 +0200 @@ -0,0 +1,58 @@ +/* + * 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.hotspot.nodes; + +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.target.*; +import com.oracle.graal.hotspot.target.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.type.*; + +/** + * Node implementing a call to HotSpot's object pointer verification stub. + * + * @see AMD64VerifyOopStubCallOp + */ +public class VerifyOopStubCall extends FixedWithNextNode implements LIRGenLowerable { + + @Input private final ValueNode object; + + public VerifyOopStubCall(ValueNode object) { + super(StampFactory.objectNonNull()); + this.object = object; + } + + @Override + public void generate(LIRGenerator gen) { + LIRDebugInfo info = gen.state(); + AMD64VerifyOopStubCallOp op = new AMD64VerifyOopStubCallOp(gen.operand(object), info); + gen.append(op); + } + + @SuppressWarnings("unused") + @NodeIntrinsic + public static Object call(Object object) { + throw new UnsupportedOperationException(); + } +} diff -r 8e098bf83c95 -r 731789427441 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewInstanceSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewInstanceSnippets.java Fri Jun 15 15:59:43 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewInstanceSnippets.java Mon Jun 18 10:07:33 2012 +0200 @@ -72,7 +72,7 @@ Log.print(logType); Log.println(" - uninit alloc"); } - return NewInstanceStubCall.call(hub); + return verifyOop(NewInstanceStubCall.call(hub)); } } @@ -90,7 +90,7 @@ Log.print(" - fast alloc at "); Log.printlnAddress(instance); } - return instance; + return verifyOop(instance); } } @@ -98,7 +98,14 @@ Log.print(logType); Log.println(" - slow alloc"); } - return NewInstanceStubCall.call(hub); + return verifyOop(NewInstanceStubCall.call(hub)); + } + + private static Object verifyOop(Object object) { + if (verifyOops()) { + VerifyOopStubCall.call(object); + } + return object; } private static Word asWord(Object object) { @@ -123,6 +130,11 @@ } @Fold + private static boolean verifyOops() { + return HotSpotGraalRuntime.getInstance().getConfig().verifyOops; + } + + @Fold private static int klassStateOffset() { return HotSpotGraalRuntime.getInstance().getConfig().klassStateOffset; } @@ -196,6 +208,7 @@ SnippetTemplate template = cache.get(key); Debug.log("Lowering newInstance in %s: node=%s, template=%s, arguments=%s", graph, newInstanceNode, template, arguments); //System.out.printf("Lowering newInstance in %s: node=%s, template=%s, arguments=%s%n", graph, newInstanceNode, template, arguments); + //DebugScope.getConfig().addToContext(graph.method()); template.instantiate(runtime, newInstanceNode, newInstanceNode, arguments); new DeadCodeEliminationPhase().apply(graph); } diff -r 8e098bf83c95 -r 731789427441 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64NewInstanceStubCallOp.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64NewInstanceStubCallOp.java Fri Jun 15 15:59:43 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64NewInstanceStubCallOp.java Mon Jun 18 10:07:33 2012 +0200 @@ -40,7 +40,7 @@ */ public class AMD64NewInstanceStubCallOp extends AMD64LIRInstruction { public AMD64NewInstanceStubCallOp(Value result, Value hub, LIRDebugInfo info) { - super("NEW_INSTANCE", new Value[] {result}, info, new Value[] {hub}, NO_OPERANDS, NO_OPERANDS); + super("NEW_INSTANCE", new Value[] {result}, info, new Value[] {hub}, NO_OPERANDS, new Value[]{AMD64.rax.asValue(Kind.Object)}); } @Override @@ -63,6 +63,8 @@ return EnumSet.of(OperandFlag.Register); } else if (mode == OperandMode.Output) { return EnumSet.of(OperandFlag.Register); + } else if (mode == OperandMode.Temp) { + return EnumSet.of(OperandFlag.Register); } throw GraalInternalError.shouldNotReachHere(); } diff -r 8e098bf83c95 -r 731789427441 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64VerifyOopStubCallOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64VerifyOopStubCallOp.java Mon Jun 18 10:07:33 2012 +0200 @@ -0,0 +1,67 @@ +/* + * 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.hotspot.target; + +import static com.oracle.graal.api.code.ValueUtil.*; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.amd64.*; +import com.oracle.graal.lir.asm.*; +import com.oracle.max.asm.target.amd64.*; + +/** + * A call to HotSpot's object pointer verification stub. + */ +public class AMD64VerifyOopStubCallOp extends AMD64LIRInstruction { + public AMD64VerifyOopStubCallOp(Value object, LIRDebugInfo info) { + super("VERIFY_OOP", LIRInstruction.NO_OPERANDS, info, new Value[] {object}, NO_OPERANDS, NO_OPERANDS); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + Register object = asRegister(input(0)); + // r13: (in) object + if (object != AMD64.r13) { + masm.push(AMD64.r13); + masm.movl(AMD64.r13, object); + } + AMD64Call.directCall(tasm, masm, HotSpotGraalRuntime.getInstance().getConfig().verifyOopStub, info); + if (object != AMD64.r13) { + masm.pop(AMD64.r13); + } + } + + @Override + protected EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input) { + return EnumSet.of(OperandFlag.Register); + } + throw GraalInternalError.shouldNotReachHere(); + } +} diff -r 8e098bf83c95 -r 731789427441 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 Fri Jun 15 15:59:43 2012 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Mon Jun 18 10:07:33 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); } @@ -1394,10 +1396,16 @@ ConstantNode typeInstruction = genTypeOrDeopt(JavaType.Representation.ObjectHub, catchType, initialized); if (typeInstruction != null) { Block nextBlock = block.successors.size() == 1 ? unwindBlock(block.deoptBci) : block.successors.get(1); + ValueNode exception = frameState.stackAt(0); + CheckCastNode checkCast = currentGraph.add(new CheckCastNode(typeInstruction, (ResolvedJavaType) catchType, exception)); + frameState.apop(); + frameState.push(Kind.Object, checkCast); FixedNode catchSuccessor = createTarget(block.successors.get(0), frameState); + frameState.apop(); + frameState.push(Kind.Object, exception); FixedNode nextDispatch = createTarget(nextBlock, frameState); - ValueNode exception = frameState.stackAt(0); - IfNode ifNode = currentGraph.add(new IfNode(currentGraph.unique(new InstanceOfNode(typeInstruction, (ResolvedJavaType) catchType, exception)), catchSuccessor, nextDispatch, 0.5)); + checkCast.setNext(catchSuccessor); + IfNode ifNode = currentGraph.add(new IfNode(currentGraph.unique(new InstanceOfNode(typeInstruction, (ResolvedJavaType) catchType, exception)), checkCast, nextDispatch, 0.5)); append(ifNode); } } diff -r 8e098bf83c95 -r 731789427441 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ReassociateConstants.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ReassociateConstants.java Mon Jun 18 10:07:33 2012 +0200 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2012, 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.jtt.optimize; + +import org.junit.*; + + +public class ReassociateConstants { + public static int rnd = (int) (Math.random() * 100); + @Test + public void run0() throws Throwable { + Assert.assertEquals(rnd + 3, 1 + (rnd + 2)); + Assert.assertEquals(rnd + 3, (rnd + 2) + 1); + Assert.assertEquals(rnd + 3, 1 + (2 + rnd)); + Assert.assertEquals(rnd + 3, (2 + rnd) + 1); + + Assert.assertEquals(-1 - rnd, 1 - (rnd + 2)); + Assert.assertEquals(rnd + 1, (rnd + 2) - 1); + Assert.assertEquals(-1 - rnd, 1 - (2 + rnd)); + Assert.assertEquals(rnd + 1, (2 + rnd) - 1); + + Assert.assertEquals(rnd - 1, 1 + (rnd - 2)); + Assert.assertEquals(rnd - 1, (rnd - 2) + 1); + Assert.assertEquals(-rnd + 3, 1 + (2 - rnd)); + Assert.assertEquals(-rnd + 3, (2 - rnd) + 1); + + Assert.assertEquals(-rnd + 3, 1 - (rnd - 2)); + Assert.assertEquals(rnd - 3, (rnd - 2) - 1); + Assert.assertEquals(rnd + -1, 1 - (2 - rnd)); + Assert.assertEquals(-rnd + 1, (2 - rnd) - 1); + } +} diff -r 8e098bf83c95 -r 731789427441 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 Fri Jun 15 15:59:43 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java Mon Jun 18 10:07:33 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 8e098bf83c95 -r 731789427441 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java Fri Jun 15 15:59:43 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java Mon Jun 18 10:07:33 2012 +0200 @@ -26,6 +26,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; +import com.oracle.graal.graph.iterators.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.type.GenericStamp.*; import com.oracle.graal.nodes.util.*; @@ -89,6 +90,17 @@ return this instanceof ConstantNode; } + private static final NodePredicate IS_CONSTANT = new NodePredicate() { + @Override + public boolean apply(Node n) { + return n instanceof ValueNode && ((ValueNode) n).isConstant(); + } + }; + + public static NodePredicate isConstantPredicate() { + return IS_CONSTANT; + } + /** * Checks whether this value represents the null constant. * @return {@code true} if this value represents the null constant diff -r 8e098bf83c95 -r 731789427441 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueProxyNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueProxyNode.java Fri Jun 15 15:59:43 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueProxyNode.java Mon Jun 18 10:07:33 2012 +0200 @@ -26,6 +26,7 @@ import com.oracle.graal.graph.Node.*; import com.oracle.graal.nodes.PhiNode.PhiType; import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.type.*; /** * A value proxy that is inserted in the frame state of a loop exit for any value that is @@ -49,6 +50,11 @@ return value; } + @Override + public Stamp stamp() { + return value.stamp(); + } + public BeginNode proxyPoint() { return proxyPoint; } diff -r 8e098bf83c95 -r 731789427441 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java Fri Jun 15 15:59:43 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java Mon Jun 18 10:07:33 2012 +0200 @@ -68,6 +68,7 @@ return ConstantNode.forLong(0, graph()); } } + return BinaryNode.reassociate(this, ValueNode.isConstantPredicate()); } return this; } diff -r 8e098bf83c95 -r 731789427441 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java Fri Jun 15 15:59:43 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java Mon Jun 18 10:07:33 2012 +0200 @@ -23,6 +23,8 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.iterators.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.type.*; @@ -53,4 +55,135 @@ this.x = x; this.y = y; } + + public enum ReassociateMatch { + x, + y; + + public ValueNode getValue(BinaryNode binary) { + switch(this) { + case x: + return binary.x(); + case y: + return binary.y(); + default: throw GraalInternalError.shouldNotReachHere(); + } + } + + public ValueNode getOtherValue(BinaryNode binary) { + switch(this) { + case x: + return binary.y(); + case y: + return binary.x(); + default: throw GraalInternalError.shouldNotReachHere(); + } + } + } + + public static boolean canTryReassociate(BinaryNode node) { + return node instanceof IntegerAddNode || node instanceof IntegerSubNode || node instanceof IntegerMulNode + || node instanceof AndNode || node instanceof OrNode || node instanceof XorNode; + } + + public static ReassociateMatch findReassociate(BinaryNode binary, NodePredicate criterion) { + boolean resultX = criterion.apply(binary.x()); + boolean resultY = criterion.apply(binary.y()); + if (resultX && !resultY) { + return ReassociateMatch.x; + } + if (!resultX && resultY) { + return ReassociateMatch.y; + } + return null; + } + + /* In reassociate, complexity comes from the handling of IntegerSub (non commutative) which can be mixed with IntegerAdd. + * if first tries to find m1, m2 which match the criterion : + * (a o m2) o m1 + * (m2 o a) o m1 + * m1 o (a o m2) + * m1 o (m2 o a) + * It then produces 4 boolean for the -/+ case + * invertA : should the final expression be like *-a (rather than a+*) + * aSub : should the final expression be like a-* (rather than a+*) + * invertM1 : should the final expression contain -m1 + * invertM2 : should the final expression contain -m2 + */ + /** + * Tries to re-associate values which satisfy the criterion. + * For example with a constantness criterion : (a + 2) + 1 => a + (1 + 2)
+ * This method accepts only reassociable operations (see {@linkplain #canTryReassociate(BinaryNode)}) such as +, -, *, &, | and ^ + */ + public static BinaryNode reassociate(BinaryNode node, NodePredicate criterion) { + assert canTryReassociate(node); + ReassociateMatch match1 = findReassociate(node, criterion); + if (match1 == null) { + return node; + } + ValueNode otherValue = match1.getOtherValue(node); + boolean addSub = false; + boolean subAdd = false; + if (otherValue.getClass() != node.getClass()) { + if (node instanceof IntegerAddNode && otherValue instanceof IntegerSubNode) { + addSub = true; + } else if (node instanceof IntegerSubNode && otherValue instanceof IntegerAddNode) { + subAdd = true; + } else { + return node; + } + } + BinaryNode other = (BinaryNode) otherValue; + ReassociateMatch match2 = findReassociate(other, criterion); + if (match2 == null) { + return node; + } + boolean invertA = false; + boolean aSub = false; + boolean invertM1 = false; + boolean invertM2 = false; + if (addSub) { + invertM2 = match2 == ReassociateMatch.y; + invertA = !invertM2; + } else if (subAdd) { + invertA = invertM2 = match1 == ReassociateMatch.x; + invertM1 = !invertM2; + } else if (node instanceof IntegerSubNode && other instanceof IntegerSubNode) { + invertA = match1 == ReassociateMatch.x ^ match2 == ReassociateMatch.x; + aSub = match1 == ReassociateMatch.y && match2 == ReassociateMatch.y; + invertM1 = match1 == ReassociateMatch.y && match2 == ReassociateMatch.x; + invertM2 = match1 == ReassociateMatch.x && match2 == ReassociateMatch.x; + } + assert !(invertM1 && invertM2) && !(invertA && aSub); + ValueNode m1 = match1.getValue(node); + ValueNode m2 = match2.getValue(other); + ValueNode a = match2.getOtherValue(other); + if (node instanceof IntegerAddNode || node instanceof IntegerSubNode) { + BinaryNode associated; + if (invertM1) { + associated = IntegerArithmeticNode.sub(m2, m1); + } else if (invertM2) { + associated = IntegerArithmeticNode.sub(m1, m2); + } else { + associated = IntegerArithmeticNode.add(m1, m2); + } + if (invertA) { + return IntegerArithmeticNode.sub(associated, a); + } + if (aSub) { + return IntegerArithmeticNode.sub(a, associated); + } + return IntegerArithmeticNode.add(a, associated); + } else if (node instanceof IntegerMulNode) { + return IntegerArithmeticNode.mul(a, IntegerAddNode.mul(m1, m2)); + } else if (node instanceof AndNode) { + return LogicNode.and(a, LogicNode.and(m1, m2)); + } else if (node instanceof OrNode) { + return LogicNode.or(a, LogicNode.or(m1, m2)); + } else if (node instanceof XorNode) { + return LogicNode.xor(a, LogicNode.xor(m1, m2)); + } else { + throw GraalInternalError.shouldNotReachHere(); + } + } } diff -r 8e098bf83c95 -r 731789427441 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java Fri Jun 15 15:59:43 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java Mon Jun 18 10:07:33 2012 +0200 @@ -48,33 +48,27 @@ return ConstantNode.forLong(x().asConstant().asLong() + y().asConstant().asLong(), graph()); } } else if (y().isConstant()) { - if (kind() == Kind.Int) { - int c = y().asConstant().asInt(); - if (c == 0) { - return x(); - } - } else { - assert kind() == Kind.Long; - long c = y().asConstant().asLong(); - if (c == 0) { - return x(); - } + long c = y().asConstant().asLong(); + if (c == 0) { + return x(); } // canonicalize expressions like "(a + 1) + 2" - if (x() instanceof IntegerAddNode) { - IntegerAddNode other = (IntegerAddNode) x(); - if (other.y().isConstant()) { - ConstantNode sum; - if (kind() == Kind.Int) { - sum = ConstantNode.forInt(y().asConstant().asInt() + other.y().asConstant().asInt(), graph()); - } else { - assert kind() == Kind.Long; - sum = ConstantNode.forLong(y().asConstant().asLong() + other.y().asConstant().asLong(), graph()); - } - return graph().unique(new IntegerAddNode(kind(), other.x(), sum)); + BinaryNode reassociated = BinaryNode.reassociate(this, ValueNode.isConstantPredicate()); + if (reassociated != this) { + return reassociated; + } + if (c < 0) { + if (kind() == Kind.Int) { + return IntegerArithmeticNode.sub(x(), ConstantNode.forInt((int) -c, graph())); + } else { + assert kind() == Kind.Long; + return IntegerArithmeticNode.sub(x(), ConstantNode.forLong(-c, graph())); } } } + if (x() instanceof NegateNode) { + return IntegerArithmeticNode.sub(y(), ((NegateNode) x()).x()); + } return this; } diff -r 8e098bf83c95 -r 731789427441 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerArithmeticNode.java diff -r 8e098bf83c95 -r 731789427441 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java Fri Jun 15 15:59:43 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java Mon Jun 18 10:07:33 2012 +0200 @@ -59,19 +59,7 @@ return graph().unique(new LeftShiftNode(kind(), x(), ConstantNode.forInt(CodeUtil.log2(c), graph()))); } // canonicalize expressions like "(a * 1) * 2" - if (x() instanceof IntegerMulNode) { - IntegerMulNode other = (IntegerMulNode) x(); - if (other.y().isConstant()) { - ConstantNode sum; - if (kind() == Kind.Int) { - sum = ConstantNode.forInt(y().asConstant().asInt() * other.y().asConstant().asInt(), graph()); - } else { - assert kind() == Kind.Long; - sum = ConstantNode.forLong(y().asConstant().asLong() * other.y().asConstant().asLong(), graph()); - } - return graph().unique(new IntegerMulNode(kind(), other.x(), sum)); - } - } + return BinaryNode.reassociate(this, ValueNode.isConstantPredicate()); } return this; } diff -r 8e098bf83c95 -r 731789427441 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java Fri Jun 15 15:59:43 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java Mon Jun 18 10:07:33 2012 +0200 @@ -51,17 +51,24 @@ if (c == 0) { return x(); } - if (kind() == Kind.Int) { - return graph().unique(new IntegerAddNode(kind(), x(), ConstantNode.forInt((int) -c, graph()))); - } else { - assert kind() == Kind.Long; - return graph().unique(new IntegerAddNode(kind(), x(), ConstantNode.forLong(-c, graph()))); + BinaryNode reassociated = BinaryNode.reassociate(this, ValueNode.isConstantPredicate()); + if (reassociated != this) { + return reassociated; + } + if (c < 0) { + if (kind() == Kind.Int) { + return IntegerArithmeticNode.add(x(), ConstantNode.forInt((int) -c, graph())); + } else { + assert kind() == Kind.Long; + return IntegerArithmeticNode.add(x(), ConstantNode.forLong(-c, graph())); + } } } else if (x().isConstant()) { long c = x().asConstant().asLong(); if (c == 0) { return graph().unique(new NegateNode(y())); } + return BinaryNode.reassociate(this, ValueNode.isConstantPredicate()); } return this; } diff -r 8e098bf83c95 -r 731789427441 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LogicNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LogicNode.java Fri Jun 15 15:59:43 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LogicNode.java Mon Jun 18 10:07:33 2012 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; /** @@ -38,4 +39,43 @@ public LogicNode(Kind kind, ValueNode x, ValueNode y) { super(kind, x, y); } + + public static LogicNode and(ValueNode v1, ValueNode v2) { + assert v1.kind() == v2.kind() && v1.graph() == v2.graph(); + Graph graph = v1.graph(); + switch(v1.kind()) { + case Int: + return graph.unique(new AndNode(Kind.Int, v1, v2)); + case Long: + return graph.unique(new AndNode(Kind.Long, v1, v2)); + default: + throw ValueNodeUtil.shouldNotReachHere(); + } + } + + public static LogicNode or(ValueNode v1, ValueNode v2) { + assert v1.kind() == v2.kind() && v1.graph() == v2.graph(); + Graph graph = v1.graph(); + switch(v1.kind()) { + case Int: + return graph.unique(new OrNode(Kind.Int, v1, v2)); + case Long: + return graph.unique(new OrNode(Kind.Long, v1, v2)); + default: + throw ValueNodeUtil.shouldNotReachHere(); + } + } + + public static LogicNode xor(ValueNode v1, ValueNode v2) { + assert v1.kind() == v2.kind() && v1.graph() == v2.graph(); + Graph graph = v1.graph(); + switch(v1.kind()) { + case Int: + return graph.unique(new XorNode(Kind.Int, v1, v2)); + case Long: + return graph.unique(new XorNode(Kind.Long, v1, v2)); + default: + throw ValueNodeUtil.shouldNotReachHere(); + } + } } diff -r 8e098bf83c95 -r 731789427441 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java Fri Jun 15 15:59:43 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java Mon Jun 18 10:07:33 2012 +0200 @@ -68,6 +68,7 @@ return x(); } } + return BinaryNode.reassociate(this, ValueNode.isConstantPredicate()); } return this; } diff -r 8e098bf83c95 -r 731789427441 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java Fri Jun 15 15:59:43 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java Mon Jun 18 10:07:33 2012 +0200 @@ -62,6 +62,7 @@ return x(); } } + return BinaryNode.reassociate(this, ValueNode.isConstantPredicate()); } return this; } diff -r 8e098bf83c95 -r 731789427441 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 Fri Jun 15 15:59:43 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java Mon Jun 18 10:07:33 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 8e098bf83c95 -r 731789427441 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 Fri Jun 15 15:59:43 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java Mon Jun 18 10:07:33 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 8e098bf83c95 -r 731789427441 graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/ReassociateAndCanonicalTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/ReassociateAndCanonicalTest.java Mon Jun 18 10:07:33 2012 +0200 @@ -0,0 +1,249 @@ +/* + * 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.compiler.tests; + +import org.junit.*; + +import com.oracle.graal.compiler.phases.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; + +public class ReassociateAndCanonicalTest extends GraalCompilerTest { + public static int rnd = (int) (Math.random() * 100); + + @Test + public void test1() { + test("test1Snippet", "ref1Snippet"); + } + + public static int test1Snippet() { + return 1 + (rnd + 2); + } + + public static int ref1Snippet() { + return rnd + 3; + } + + @Test + public void test2() { + test("test2Snippet", "ref2Snippet"); + } + + public static int test2Snippet() { + return rnd + 3; + } + + public static int ref2Snippet() { + return (rnd + 2) + 1; + } + + @Test + public void test3() { + test("test3Snippet", "ref3Snippet"); + } + + public static int test3Snippet() { + return rnd + 3; + } + + public static int ref3Snippet() { + return 1 + (2 + rnd); + } + + @Test + public void test4() { + test("test4Snippet", "ref4Snippet"); + } + + public static int test4Snippet() { + return rnd + 3; + } + + public static int ref4Snippet() { + return (2 + rnd) + 1; + } + + @Test + public void test5() { + test("test5Snippet", "ref5Snippet"); + } + + public static int test5Snippet() { + return -1 - rnd; + } + + public static int ref5Snippet() { + return 1 - (rnd + 2); + } + + @Test + public void test6() { + test("test6Snippet", "ref6Snippet"); + } + + public static int test6Snippet() { + return rnd + 1; + } + + public static int ref6Snippet() { + return (rnd + 2) - 1; + } + + @Test + public void test7() { + test("test7Snippet", "ref7Snippet"); + } + + public static int test7Snippet() { + return -1 - rnd; + } + + public static int ref7Snippet() { + return 1 - (2 + rnd); + } + + @Test + public void test8() { + test("test8Snippet", "ref8Snippet"); + } + + public static int test8Snippet() { + return rnd + 1; + } + + public static int ref8Snippet() { + return (2 + rnd) - 1; + } + + @Test + public void test9() { + test("test9Snippet", "ref9Snippet"); + } + + public static int test9Snippet() { + return rnd - 1; + } + + public static int ref9Snippet() { + return 1 + (rnd - 2); + } + + @Test + public void test10() { + test("test10Snippet", "ref10Snippet"); + } + + public static int test10Snippet() { + return rnd - 1; + } + + public static int ref10Snippet() { + return (rnd - 2) + 1; + } + + @Test + public void test11() { + test("test11Snippet", "ref11Snippet"); + } + + public static int test11Snippet() { + return -rnd + 3; + } + + public static int ref11Snippet() { + return 1 + (2 - rnd); + } + + @Test + public void test12() { + test("test12Snippet", "ref12Snippet"); + } + + public static int test12Snippet() { + return -rnd + 3; + } + + public static int ref12Snippet() { + return (2 - rnd) + 1; + } + + @Test + public void test13() { + test("test13Snippet", "ref13Snippet"); + } + + public static int test13Snippet() { + return -rnd + 3; + } + + public static int ref13Snippet() { + return 1 - (rnd - 2); + } + + @Test + public void test14() { + test("test14Snippet", "ref14Snippet"); + } + + public static int test14Snippet() { + return rnd - 3; + } + + public static int ref14Snippet() { + return (rnd - 2) - 1; + } + + @Test + public void test15() { + test("test15Snippet", "ref15Snippet"); + } + + public static int test15Snippet() { + return rnd + -1; + } + + public static int ref15Snippet() { + return 1 - (2 - rnd); + } + + @Test + public void test16() { + test("test16Snippet", "ref16Snippet"); + } + + public static int test16Snippet() { + return -rnd + 1; + } + + public static int ref16Snippet() { + return (2 - rnd) - 1; + } + + private void test(String test, String ref) { + StructuredGraph testGraph = parse(test); + new CanonicalizerPhase(null, runtime(), null).apply(testGraph); + StructuredGraph refGraph = parse(ref); + new CanonicalizerPhase(null, runtime(), null).apply(refGraph); + assertEquals(testGraph, refGraph); + } +} diff -r 8e098bf83c95 -r 731789427441 mx/projects --- a/mx/projects Fri Jun 15 15:59:43 2012 +0200 +++ b/mx/projects Mon Jun 18 10:07:33 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 +project@com.oracle.graal.boot@dependencies=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 diff -r 8e098bf83c95 -r 731789427441 src/cpu/x86/vm/c1_Runtime1_x86.cpp --- a/src/cpu/x86/vm/c1_Runtime1_x86.cpp Fri Jun 15 15:59:43 2012 +0200 +++ b/src/cpu/x86/vm/c1_Runtime1_x86.cpp Mon Jun 18 10:07:33 2012 +0200 @@ -1955,8 +1955,8 @@ break; } - case graal_verify_pointer_id: { - __ verify_oop(r13, "graal verify pointer"); + case graal_verify_oop_id: { + __ verify_oop(r13, "graal verify oop"); __ ret(0); break; } diff -r 8e098bf83c95 -r 731789427441 src/share/vm/c1/c1_Runtime1.cpp --- a/src/share/vm/c1/c1_Runtime1.cpp Fri Jun 15 15:59:43 2012 +0200 +++ b/src/share/vm/c1/c1_Runtime1.cpp Mon Jun 18 10:07:33 2012 +0200 @@ -206,7 +206,7 @@ case handle_exception_nofpu_id: // Unused on sparc #endif #ifdef GRAAL - case graal_verify_pointer_id: + case graal_verify_oop_id: case graal_unwind_exception_call_id: case graal_slow_subtype_check_id: case graal_arithmetic_frem_id: diff -r 8e098bf83c95 -r 731789427441 src/share/vm/c1/c1_Runtime1.hpp --- a/src/share/vm/c1/c1_Runtime1.hpp Fri Jun 15 15:59:43 2012 +0200 +++ b/src/share/vm/c1/c1_Runtime1.hpp Mon Jun 18 10:07:33 2012 +0200 @@ -76,7 +76,7 @@ stub(graal_arithmetic_drem) \ stub(graal_monitorenter) \ stub(graal_monitorexit) \ - stub(graal_verify_pointer) \ + stub(graal_verify_oop) \ stub(graal_set_deopt_info) \ stub(graal_create_null_pointer_exception) \ stub(graal_create_out_of_bounds_exception) \ diff -r 8e098bf83c95 -r 731789427441 src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Fri Jun 15 15:59:43 2012 +0200 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Mon Jun 18 10:07:33 2012 +0200 @@ -781,7 +781,7 @@ #else set_boolean(env, config, "windowsOs", false); #endif - set_boolean(env, config, "verifyPointers", VerifyOops); + set_boolean(env, config, "verifyOops", VerifyOops); set_boolean(env, config, "useFastLocking", UseFastLocking); set_boolean(env, config, "useFastNewObjectArray", UseFastNewObjectArray); set_boolean(env, config, "useFastNewTypeArray", UseFastNewTypeArray); @@ -823,7 +823,7 @@ set_long(env, config, "debugStub", VmIds::addStub((address)warning)); set_long(env, config, "instanceofStub", VmIds::addStub(Runtime1::entry_for(Runtime1::slow_subtype_check_id))); - set_long(env, config, "verifyPointerStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_verify_pointer_id))); + set_long(env, config, "verifyOopStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_verify_oop_id))); set_long(env, config, "newInstanceStub", VmIds::addStub(Runtime1::entry_for(newInstanceStub))); set_long(env, config, "newTypeArrayStub", VmIds::addStub(Runtime1::entry_for(Runtime1::new_type_array_id))); set_long(env, config, "newObjectArrayStub", VmIds::addStub(Runtime1::entry_for(Runtime1::new_object_array_id)));