# HG changeset patch # User Thomas Wuerthinger # Date 1339266751 -7200 # Node ID 8872bc0eebdf2e132b0fa0cb0d818a69ad815559 # Parent b6617d13ea44af15ac54fda5b6bb209f4a8b64cf Renaming hotspot.ri => hotspot.meta. diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Sat Jun 09 20:10:05 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Sat Jun 09 20:32:31 2012 +0200 @@ -29,7 +29,7 @@ import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.phases.*; import com.oracle.graal.debug.*; -import com.oracle.graal.hotspot.ri.*; +import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.nodes.*; import com.oracle.max.criutils.*; diff -r b6617d13ea44 -r 8872bc0eebdf 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 Sat Jun 09 20:10:05 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Sat Jun 09 20:32:31 2012 +0200 @@ -31,7 +31,7 @@ import com.oracle.graal.cri.*; import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.hotspot.logging.*; -import com.oracle.graal.hotspot.ri.*; +import com.oracle.graal.hotspot.meta.*; import com.oracle.max.asm.target.amd64.*; import com.oracle.max.cri.xir.*; diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotTargetMethod.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotTargetMethod.java Sat Jun 09 20:10:05 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotTargetMethod.java Sat Jun 09 20:32:31 2012 +0200 @@ -27,7 +27,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.code.CompilationResult.*; import com.oracle.graal.hotspot.logging.*; -import com.oracle.graal.hotspot.ri.*; +import com.oracle.graal.hotspot.meta.*; /** * CiTargetMethod augmented with HotSpot-specific information. diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Sat Jun 09 20:10:05 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Sat Jun 09 20:32:31 2012 +0200 @@ -28,7 +28,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.ri.*; +import com.oracle.graal.hotspot.meta.*; /** * Calls from Java into HotSpot. diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Sat Jun 09 20:10:05 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Sat Jun 09 20:32:31 2012 +0200 @@ -28,7 +28,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.ri.*; +import com.oracle.graal.hotspot.meta.*; /** * Entries into the HotSpot VM from Java code. diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java Sat Jun 09 20:10:05 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java Sat Jun 09 20:32:31 2012 +0200 @@ -28,7 +28,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.phases.*; -import com.oracle.graal.hotspot.ri.*; +import com.oracle.graal.hotspot.meta.*; /** * Calls from HotSpot into Java. diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Sat Jun 09 20:10:05 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Sat Jun 09 20:32:31 2012 +0200 @@ -37,7 +37,7 @@ import com.oracle.graal.debug.internal.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.counters.*; -import com.oracle.graal.hotspot.ri.*; +import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.snippets.*; import com.oracle.graal.java.*; import com.oracle.graal.snippets.*; diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeInfo.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeInfo.java Sat Jun 09 20:32:31 2012 +0200 @@ -0,0 +1,68 @@ +/* + * 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.hotspot.meta; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.*; + +/** + * Implementation of {@link CodeInfo} for HotSpot. + */ +public class HotSpotCodeInfo extends CompilerObject implements CodeInfo { + + private static final long serialVersionUID = -6766490427732498354L; + + private long start; + private byte[] code; + public final CompilationResult targetMethod; + private HotSpotMethodResolved method; + + public HotSpotCodeInfo(CompilationResult targetMethod, HotSpotMethodResolved method) { + assert targetMethod != null; + this.method = method; + this.targetMethod = targetMethod; + } + + @Override + public long start() { + return start; + } + + @Override + public byte[] code() { + return code; + } + + @Override + public String toString() { + int size = code == null ? 0 : code.length; + return "installed code @[" + Long.toHexString(start) + "-" + Long.toHexString(start + size) + "]"; + + } + + @Override + public ResolvedJavaMethod method() { + return method; + } +} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCompiledMethod.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCompiledMethod.java Sat Jun 09 20:32:31 2012 +0200 @@ -0,0 +1,91 @@ +/* + * 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.hotspot.meta; + +import java.lang.reflect.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.*; + +/** + * Implementation of RiCompiledMethod for HotSpot. + * Stores a reference to the nmethod which contains the compiled code. + * The nmethod also stores a weak reference to the HotSpotCompiledMethod + * instance which is necessary to keep the nmethod from being unloaded. + */ +public class HotSpotCompiledMethod extends CompilerObject implements InstalledCode { + + private static final long serialVersionUID = 156632908220561612L; + + private final ResolvedJavaMethod method; + private long nmethod; + + public HotSpotCompiledMethod(ResolvedJavaMethod method) { + this.method = method; + } + + @Override + public ResolvedJavaMethod method() { + return method; + } + + @Override + public boolean isValid() { + return nmethod != 0; + } + + @Override + public String toString() { + return "compiled method " + method + " @" + nmethod; + } + + @Override + public Object execute(Object arg1, Object arg2, Object arg3) { + assert method.signature().argumentCount(!Modifier.isStatic(method.accessFlags())) == 3; + assert method.signature().argumentKindAt(0) == Kind.Object; + assert method.signature().argumentKindAt(1) == Kind.Object; + assert !Modifier.isStatic(method.accessFlags()) || method.signature().argumentKindAt(2) == Kind.Object; + return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethod(this, arg1, arg2, arg3); + } + + private boolean checkArgs(Object... args) { + Kind[] sig = CodeUtil.signatureToKinds(method); + assert args.length == sig.length : CodeUtil.format("%H.%n(%p): expected ", method) + sig.length + " args, got " + args.length; + for (int i = 0; i < sig.length; i++) { + Object arg = args[i]; + if (arg == null) { + assert sig[i].isObject() : CodeUtil.format("%H.%n(%p): expected arg ", method) + i + " to be Object, not " + sig[i]; + } else if (!sig[i].isObject()) { + assert sig[i].toBoxedJavaClass() == arg.getClass() : CodeUtil.format("%H.%n(%p): expected arg ", method) + i + " to be " + sig[i] + ", not " + arg.getClass(); + } + } + return true; + } + + @Override + public Object executeVarargs(Object... args) { + assert checkArgs(args); + return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethodVarargs(this, args); + } +} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java Sat Jun 09 20:32:31 2012 +0200 @@ -0,0 +1,71 @@ +/* + * 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.hotspot.meta; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.*; + +/** + * Implementation of RiConstantPool for HotSpot. + */ +public class HotSpotConstantPool extends CompilerObject implements ConstantPool { + + private static final long serialVersionUID = -5443206401485234850L; + + private final HotSpotTypeResolvedImpl type; + + public HotSpotConstantPool(HotSpotTypeResolvedImpl type) { + this.type = type; + } + + @Override + public Object lookupConstant(int cpi) { + Object constant = HotSpotGraalRuntime.getInstance().getCompilerToVM().RiConstantPool_lookupConstant(type, cpi); + return constant; + } + + @Override + public Signature lookupSignature(int cpi) { + throw new UnsupportedOperationException(); + } + + @Override + public JavaMethod lookupMethod(int cpi, int byteCode) { + return HotSpotGraalRuntime.getInstance().getCompilerToVM().RiConstantPool_lookupMethod(type, cpi, (byte) byteCode); + } + + @Override + public JavaType lookupType(int cpi, int opcode) { + return HotSpotGraalRuntime.getInstance().getCompilerToVM().RiConstantPool_lookupType(type, cpi); + } + + @Override + public JavaField lookupField(int cpi, int opcode) { + return HotSpotGraalRuntime.getInstance().getCompilerToVM().RiConstantPool_lookupField(type, cpi, (byte) opcode); + } + + @Override + public void loadReferencedType(int cpi, int bytecode) { + HotSpotGraalRuntime.getInstance().getCompilerToVM().RiConstantPool_loadReferencedType(type, cpi, (byte) bytecode); + } +} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotField.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotField.java Sat Jun 09 20:32:31 2012 +0200 @@ -0,0 +1,134 @@ +/* + * 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.hotspot.meta; + +import java.lang.annotation.*; +import java.lang.reflect.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.meta.JavaType.*; +import com.oracle.graal.compiler.*; +import com.oracle.graal.hotspot.*; + +/** + * Represents a field in a HotSpot type. + */ +public class HotSpotField extends CompilerObject implements ResolvedJavaField { + + private static final long serialVersionUID = 7692985878836955683L; + private final ResolvedJavaType holder; + private final String name; + private final JavaType type; + private final int offset; + private final int accessFlags; + private Constant constant; // Constant part only valid for static fields. + + public HotSpotField(ResolvedJavaType holder, String name, JavaType type, int offset, int accessFlags) { + this.holder = holder; + this.name = name; + this.type = type; + assert offset != -1; + this.offset = offset; + this.accessFlags = accessFlags; + } + + @Override + public int accessFlags() { + return accessFlags; + } + + @Override + public Constant constantValue(Constant receiver) { + if (receiver == null) { + assert Modifier.isStatic(accessFlags); + 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); + } + } + } + return constant; + } else { + 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 null; + } + + private static boolean assumeStaticFieldsFinal(Class< ? > clazz) { + return clazz == GraalOptions.class; + } + + @Override + public ResolvedJavaType holder() { + return holder; + } + + @Override + public Kind kind() { + return type().kind(); + } + + @Override + public String name() { + return name; + } + + @Override + public JavaType type() { + return type; + } + + public int offset() { + return offset; + } + + @Override + public String toString() { + return "HotSpotField<" + CodeUtil.format("%h.%n", this) + ":" + offset + ">"; + } + + @Override + public T getAnnotation(Class annotationClass) { + Field javaField = toJava(); + if (javaField != null) { + return javaField.getAnnotation(annotationClass); + } + return null; + } + + private Field toJava() { + try { + return holder.toJava().getDeclaredField(name); + } catch (NoSuchFieldException e) { + return null; + } + } +} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphCache.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphCache.java Sat Jun 09 20:32:31 2012 +0200 @@ -0,0 +1,171 @@ +/* + * 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.meta; + +import java.io.*; +import java.lang.ref.*; +import java.util.*; +import java.util.Map.Entry; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.*; +import com.oracle.graal.cri.*; +import com.oracle.graal.nodes.*; + +/** + * This class implements the graph caching system for the HotSpot platform. + * + * This implementation does not use a map to store the actual cached graphs. The problem is that such maps keep the + * graph, and therefore the RiResolvedMethod referenced from the graph, alive. For some applications and benchmarks this + * is a problem, e.g., the DaCapoScala "scalatest" benchmark will quickly run out of perm gen because of this. + * + * This cannot be solved with a WeakHashMap, since the values within the map will keep the keys + * alive. In order for this to work we would require a weak map in which the "strongness" of the value references + * depends upon the reachability of the keys. + * + * Therefore the graph cache is implemented in such a way that it stores its cache entries within the RiResolvedMethod. + * It uses the {@link ResolvedJavaMethod#compilerStorage()} map with the HotSpotGraphCache instance as key. + * The cached graph will be kept alive as long as the RiResolvedMethod is alive, but does not prevent the method, and + * therefore the class, from being unloaded. + * + * The {@link #cachedGraphIds} map is used to find the graphs that should be removed because of deoptimization, and to + * enforce the graph cache size restriction. + */ +public class HotSpotGraphCache implements RiGraphCache { + + private static final PrintStream out = System.out; + + private volatile long hitCounter; + private volatile long missCounter; + private volatile long removeHitCounter; + private volatile long removeCounter; + private volatile long putCounter; + + /** + * An ordered hash map for looking up the methods corresponding to a specific graph id. It enforces the maximum + * graph cache size by removing the oldest (in insertion-order) element if the cache gets too big. + */ + private final class LRUCache extends LinkedHashMap> { + + private static final long serialVersionUID = -3973307040793397840L; + + public LRUCache() { + super(GraalOptions.GraphCacheSize * 2, 0.75f, false); + } + + @Override + protected boolean removeEldestEntry(Entry> eldest) { + if (size() > GraalOptions.GraphCacheSize) { + ResolvedJavaMethod method = eldest.getValue().get(); + if (method != null) { + StructuredGraph cachedGraph = (StructuredGraph) method.compilerStorage().get(HotSpotGraphCache.this); + if (cachedGraph != null && cachedGraph.graphId() == eldest.getKey()) { + method.compilerStorage().remove(HotSpotGraphCache.this); + } + } + return true; + } else { + return false; + } + } + } + + private final Map> cachedGraphIds = Collections.synchronizedMap(new LRUCache()); + + public HotSpotGraphCache() { + if (GraalOptions.PrintGraphCache) { + Runtime.getRuntime().addShutdownHook(new Thread() { + + @Override + public void run() { + out.println("put: " + putCounter); + out.println("get hit: " + hitCounter); + out.println("get miss: " + missCounter); + out.println("remove hit: " + removeHitCounter); + out.println("remove miss: " + (removeCounter - removeHitCounter)); + } + }); + } + } + + @Override + public StructuredGraph get(ResolvedJavaMethod method) { + StructuredGraph result = (StructuredGraph) method.compilerStorage().get(this); + + if (GraalOptions.PrintGraphCache) { + if (result == null) { + missCounter++; + } else { + hitCounter++; + } + } + return result; + } + + @Override + public void put(StructuredGraph graph) { + assert graph.method() != null; + cachedGraphIds.put(graph.graphId(), new WeakReference<>(graph.method())); + graph.method().compilerStorage().put(this, graph); + + if (GraalOptions.PrintGraphCache) { + putCounter++; + } + } + + public void clear() { + synchronized (cachedGraphIds) { + for (WeakReference ref : cachedGraphIds.values()) { + ResolvedJavaMethod method = ref.get(); + if (method != null) { + method.compilerStorage().remove(this); + } + } + cachedGraphIds.clear(); + hitCounter = 0; + missCounter = 0; + removeHitCounter = 0; + removeCounter = 0; + putCounter = 0; + } + } + + public void removeGraphs(long[] deoptedGraphs) { + for (long graphId : deoptedGraphs) { + WeakReference ref = cachedGraphIds.get(graphId); + ResolvedJavaMethod method = ref == null ? null : ref.get(); + if (method != null) { + StructuredGraph cachedGraph = (StructuredGraph) method.compilerStorage().get(this); + if (cachedGraph != null && cachedGraph.graphId() == graphId) { + method.compilerStorage().remove(this); + if (GraalOptions.PrintGraphCache) { + removeHitCounter++; + } + } + } + if (GraalOptions.PrintGraphCache) { + removeCounter++; + } + } + } +} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotKlassOop.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotKlassOop.java Sat Jun 09 20:32:31 2012 +0200 @@ -0,0 +1,50 @@ +/* + * 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.meta; + +import com.oracle.graal.hotspot.*; + +/** + * A mechanism for safely conveying a HotSpot klassOop value from the compiler to the C++ code. + * Such values should not be directly exposed to Java code as they are not real Java + * objects. For instance, invoking a method on them or using them in an instanceof + * expression will most likely crash the VM. + */ +public class HotSpotKlassOop extends CompilerObject { + + private static final long serialVersionUID = -5445542223575839143L; + + /** + * The Java object from which the klassOop value can be derived (by the C++ code). + */ + public final Class javaMirror; + + public HotSpotKlassOop(Class javaMirror) { + this.javaMirror = javaMirror; + } + + @Override + public String toString() { + return "HotSpotKlassOop<" + javaMirror.getName() + ">"; + } +} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethod.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethod.java Sat Jun 09 20:32:31 2012 +0200 @@ -0,0 +1,37 @@ +/* + * 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.hotspot.meta; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.*; + +public abstract class HotSpotMethod extends CompilerObject implements JavaMethod { + + private static final long serialVersionUID = 7167491397941960839L; + protected String name; + + @Override + public final String name() { + return name; + } +} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java Sat Jun 09 20:32:31 2012 +0200 @@ -0,0 +1,575 @@ +/* + * 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.meta; + +import java.util.*; + +import sun.misc.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.meta.JavaTypeProfile.*; +import com.oracle.graal.compiler.*; +import com.oracle.graal.hotspot.*; + + +public final class HotSpotMethodData extends CompilerObject { + + private static final long serialVersionUID = -8873133496591225071L; + + static { + config = HotSpotGraalRuntime.getInstance().getConfig(); + } + + // TODO (chaeubl) use same logic as in NodeClass? + private static final Unsafe unsafe = Unsafe.getUnsafe(); + private static final HotSpotMethodDataAccessor NO_DATA_NO_EXCEPTION_ACCESSOR = new NoMethodData(ExceptionSeen.FALSE); + private static final HotSpotMethodDataAccessor NO_DATA_EXCEPTION_POSSIBLY_NOT_RECORDED_ACCESSOR = new NoMethodData(ExceptionSeen.NOT_SUPPORTED); + private static final HotSpotVMConfig config; + // sorted by tag + private static final HotSpotMethodDataAccessor[] PROFILE_DATA_ACCESSORS = { + null, new BitData(), new CounterData(), new JumpData(), + new TypeCheckData(), new VirtualCallData(), new RetData(), + new BranchData(), new MultiBranchData(), new ArgInfoData() + }; + + private Object hotspotMirror; + private int normalDataSize; + private int extraDataSize; + + private HotSpotMethodData() { + throw new IllegalStateException("this constructor is never actually called, because the objects are allocated from within the VM"); + } + + public boolean hasNormalData() { + return normalDataSize > 0; + } + + public boolean hasExtraData() { + return extraDataSize > 0; + } + + public int getExtraDataBeginOffset() { + return normalDataSize; + } + + public boolean isWithin(int position) { + return position >= 0 && position < normalDataSize + extraDataSize; + } + + public int getDeoptimizationCount(DeoptimizationReason reason) { + int reasonIndex = HotSpotGraalRuntime.getInstance().getRuntime().convertDeoptReason(reason); + return unsafe.getByte(hotspotMirror, (long) config.methodDataOopTrapHistoryOffset + reasonIndex) & 0xFF; + } + + public HotSpotMethodDataAccessor getNormalData(int position) { + if (position >= normalDataSize) { + return null; + } + + HotSpotMethodDataAccessor result = getData(position); + assert result != null : "NO_DATA tag is not allowed"; + return result; + } + + public HotSpotMethodDataAccessor getExtraData(int position) { + if (position >= normalDataSize + extraDataSize) { + return null; + } + return getData(position); + } + + public static HotSpotMethodDataAccessor getNoDataAccessor(boolean exceptionPossiblyNotRecorded) { + if (exceptionPossiblyNotRecorded) { + return NO_DATA_EXCEPTION_POSSIBLY_NOT_RECORDED_ACCESSOR; + } else { + return NO_DATA_NO_EXCEPTION_ACCESSOR; + } + } + + private HotSpotMethodDataAccessor getData(int position) { + assert position >= 0 : "out of bounds"; + int tag = AbstractMethodData.readTag(this, position); + assert tag >= 0 && tag < PROFILE_DATA_ACCESSORS.length : "illegal tag"; + return PROFILE_DATA_ACCESSORS[tag]; + } + + private int readUnsignedByte(int position, int offsetInBytes) { + long fullOffsetInBytes = computeFullOffset(position, offsetInBytes); + return unsafe.getByte(hotspotMirror, fullOffsetInBytes) & 0xFF; + } + + private int readUnsignedShort(int position, int offsetInBytes) { + long fullOffsetInBytes = computeFullOffset(position, offsetInBytes); + return unsafe.getShort(hotspotMirror, fullOffsetInBytes) & 0xFFFF; + } + + private long readUnsignedInt(int position, int offsetInBytes) { + long fullOffsetInBytes = computeFullOffset(position, offsetInBytes); + return unsafe.getInt(hotspotMirror, fullOffsetInBytes) & 0xFFFFFFFFL; + } + + private int readUnsignedIntAsSignedInt(int position, int offsetInBytes) { + long value = readUnsignedInt(position, offsetInBytes); + return truncateLongToInt(value); + } + + private int readInt(int position, int offsetInBytes) { + long fullOffsetInBytes = computeFullOffset(position, offsetInBytes); + return unsafe.getInt(hotspotMirror, fullOffsetInBytes); + } + + private Object readObject(int position, int offsetInBytes) { + long fullOffsetInBytes = computeFullOffset(position, offsetInBytes); + return unsafe.getObject(hotspotMirror, fullOffsetInBytes); + } + + private static int truncateLongToInt(long value) { + return value > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) value; + } + + private static int computeFullOffset(int position, int offsetInBytes) { + return config.methodDataOopDataOffset + position + offsetInBytes; + } + + private static int cellIndexToOffset(int cells) { + return config.dataLayoutHeaderSize + cellsToBytes(cells); + } + + private static int cellsToBytes(int cells) { + return cells * config.dataLayoutCellSize; + } + + private abstract static class AbstractMethodData implements HotSpotMethodDataAccessor { + private static final int EXCEPTIONS_MASK = 0x80; + + private final int tag; + private final int staticSize; + + protected AbstractMethodData(int tag, int staticSize) { + this.tag = tag; + this.staticSize = staticSize; + } + + public int getTag() { + return tag; + } + + public static int readTag(HotSpotMethodData data, int position) { + return data.readUnsignedByte(position, config.dataLayoutTagOffset); + } + + @Override + public int getBCI(HotSpotMethodData data, int position) { + return data.readUnsignedShort(position, config.dataLayoutBCIOffset); + } + + @Override + public int getSize(HotSpotMethodData data, int position) { + return staticSize + getDynamicSize(data, position); + } + + @Override + public ExceptionSeen getExceptionSeen(HotSpotMethodData data, int position) { + return ExceptionSeen.get((getFlags(data, position) & EXCEPTIONS_MASK) != 0); + } + + @Override + public JavaTypeProfile getTypeProfile(HotSpotMethodData data, int position) { + return null; + } + + @Override + public double getBranchTakenProbability(HotSpotMethodData data, int position) { + return -1; + } + + @Override + public double[] getSwitchProbabilities(HotSpotMethodData data, int position) { + return null; + } + + @Override + public int getExecutionCount(HotSpotMethodData data, int position) { + return -1; + } + + protected int getFlags(HotSpotMethodData data, int position) { + return data.readUnsignedByte(position, config.dataLayoutFlagsOffset); + } + + protected int getDynamicSize(@SuppressWarnings("unused") HotSpotMethodData data, @SuppressWarnings("unused") int position) { + return 0; + } + } + + private static class NoMethodData extends AbstractMethodData { + private static final int NO_DATA_TAG = 0; + private static final int NO_DATA_SIZE = cellIndexToOffset(0); + + private final ExceptionSeen exceptionSeen; + + protected NoMethodData(ExceptionSeen exceptionSeen) { + super(NO_DATA_TAG, NO_DATA_SIZE); + this.exceptionSeen = exceptionSeen; + } + + @Override + public int getBCI(HotSpotMethodData data, int position) { + return -1; + } + + + @Override + public ExceptionSeen getExceptionSeen(HotSpotMethodData data, int position) { + return exceptionSeen; + } + } + + private static class BitData extends AbstractMethodData { + private static final int BIT_DATA_TAG = 1; + private static final int BIT_DATA_SIZE = cellIndexToOffset(0); + private static final int BIT_DATA_NULL_SEEN_FLAG = 0x01; + + private BitData() { + super(BIT_DATA_TAG, BIT_DATA_SIZE); + } + + protected BitData(int tag, int staticSize) { + super(tag, staticSize); + } + + @SuppressWarnings("unused") + public boolean getNullSeen(HotSpotMethodData data, int position) { + return (getFlags(data, position) & BIT_DATA_NULL_SEEN_FLAG) != 0; + } + } + + private static class CounterData extends BitData { + private static final int COUNTER_DATA_TAG = 2; + private static final int COUNTER_DATA_SIZE = cellIndexToOffset(1); + private static final int COUNTER_DATA_COUNT_OFFSET = cellIndexToOffset(0); + + public CounterData() { + super(COUNTER_DATA_TAG, COUNTER_DATA_SIZE); + } + + protected CounterData(int tag, int staticSize) { + super(tag, staticSize); + } + + @Override + public int getExecutionCount(HotSpotMethodData data, int position) { + return getCounterValue(data, position); + } + + protected int getCounterValue(HotSpotMethodData data, int position) { + return data.readUnsignedIntAsSignedInt(position, COUNTER_DATA_COUNT_OFFSET); + } + } + + private static class JumpData extends AbstractMethodData { + private static final int JUMP_DATA_TAG = 3; + private static final int JUMP_DATA_SIZE = cellIndexToOffset(2); + protected static final int TAKEN_COUNT_OFFSET = cellIndexToOffset(0); + protected static final int TAKEN_DISPLACEMENT_OFFSET = cellIndexToOffset(1); + + public JumpData() { + super(JUMP_DATA_TAG, JUMP_DATA_SIZE); + } + + protected JumpData(int tag, int staticSize) { + super(tag, staticSize); + } + + @Override + public double getBranchTakenProbability(HotSpotMethodData data, int position) { + return getExecutionCount(data, position) != 0 ? 1 : 0; + } + + @Override + public int getExecutionCount(HotSpotMethodData data, int position) { + return data.readUnsignedIntAsSignedInt(position, TAKEN_COUNT_OFFSET); + } + + @SuppressWarnings("unused") + public int getTakenDisplacement(HotSpotMethodData data, int position) { + return data.readInt(position, TAKEN_DISPLACEMENT_OFFSET); + } + } + + private abstract static class AbstractTypeData extends CounterData { + private static final int RECEIVER_TYPE_DATA_ROW_SIZE = cellsToBytes(2); + private static final int RECEIVER_TYPE_DATA_SIZE = cellIndexToOffset(1) + RECEIVER_TYPE_DATA_ROW_SIZE * config.typeProfileWidth; + private static final int RECEIVER_TYPE_DATA_FIRST_RECEIVER_OFFSET = cellIndexToOffset(1); + private static final int RECEIVER_TYPE_DATA_FIRST_COUNT_OFFSET = cellIndexToOffset(2); + + protected AbstractTypeData(int tag) { + super(tag, RECEIVER_TYPE_DATA_SIZE); + } + + @Override + public JavaTypeProfile getTypeProfile(HotSpotMethodData data, int position) { + int typeProfileWidth = config.typeProfileWidth; + + ResolvedJavaType[] types = new ResolvedJavaType[typeProfileWidth]; + long[] counts = new long[typeProfileWidth]; + long totalCount = 0; + int entries = 0; + + for (int i = 0; i < typeProfileWidth; i++) { + Object receiverKlassOop = data.readObject(position, getReceiverOffset(i)); + if (receiverKlassOop != null) { + Object graalMirror = unsafe.getObject(receiverKlassOop, (long) config.graalMirrorKlassOffset); + if (graalMirror == null) { + Class javaClass = (Class) unsafe.getObject(receiverKlassOop, (long) config.classMirrorOffset); + graalMirror = HotSpotGraalRuntime.getInstance().getCompilerToVM().getType(javaClass); + assert graalMirror != null : "must not return null"; + } + + + types[entries] = (ResolvedJavaType) graalMirror; + + long count = data.readUnsignedInt(position, getCountOffset(i)); + totalCount += count; + counts[entries] = count; + + entries++; + } + } + + totalCount += getTypesNotRecordedExecutionCount(data, position); + return createRiTypeProfile(types, counts, totalCount, entries); + } + + protected long getTypesNotRecordedExecutionCount(HotSpotMethodData data, int position) { + // checkcast/aastore/instanceof profiling in the HotSpot template-based interpreter was adjusted so that the counter + // is incremented to indicate the polymorphic case instead of decrementing it for failed type checks + return getCounterValue(data, position); + } + + private static JavaTypeProfile createRiTypeProfile(ResolvedJavaType[] types, long[] counts, long totalCount, int entries) { + if (entries <= 0 || totalCount < GraalOptions.MatureExecutionsTypeProfile) { + return null; + } + + ProfiledType[] ptypes = new ProfiledType[entries]; + double totalProbability = 0.0; + for (int i = 0; i < entries; i++) { + double p = counts[i]; + p = p / totalCount; + totalProbability += p; + ptypes[i] = new ProfiledType(types[i], p); + } + + Arrays.sort(ptypes); + + double notRecordedTypeProbability = entries < config.typeProfileWidth ? 0.0 : Math.min(1.0, Math.max(0.0, 1.0 - totalProbability)); + return new JavaTypeProfile(notRecordedTypeProbability, ptypes); + } + + private static int getReceiverOffset(int row) { + return RECEIVER_TYPE_DATA_FIRST_RECEIVER_OFFSET + row * RECEIVER_TYPE_DATA_ROW_SIZE; + } + + protected static int getCountOffset(int row) { + return RECEIVER_TYPE_DATA_FIRST_COUNT_OFFSET + row * RECEIVER_TYPE_DATA_ROW_SIZE; + } + } + + private static class TypeCheckData extends AbstractTypeData { + private static final int RECEIVER_TYPE_DATA_TAG = 4; + + public TypeCheckData() { + super(RECEIVER_TYPE_DATA_TAG); + } + + @Override + public int getExecutionCount(HotSpotMethodData data, int position) { + return -1; + } + } + + private static class VirtualCallData extends AbstractTypeData { + private static final int VIRTUAL_CALL_DATA_TAG = 5; + + public VirtualCallData() { + super(VIRTUAL_CALL_DATA_TAG); + } + + @Override + public int getExecutionCount(HotSpotMethodData data, int position) { + int typeProfileWidth = config.typeProfileWidth; + + long total = 0; + for (int i = 0; i < typeProfileWidth; i++) { + total += data.readUnsignedInt(position, getCountOffset(i)); + } + + total += getCounterValue(data, position); + return truncateLongToInt(total); + } + } + + private static class RetData extends CounterData { + private static final int RET_DATA_TAG = 6; + private static final int RET_DATA_ROW_SIZE = cellsToBytes(3); + private static final int RET_DATA_SIZE = cellIndexToOffset(1) + RET_DATA_ROW_SIZE * config.bciProfileWidth; + + public RetData() { + super(RET_DATA_TAG, RET_DATA_SIZE); + } + } + + private static class BranchData extends JumpData { + private static final int BRANCH_DATA_TAG = 7; + private static final int BRANCH_DATA_SIZE = cellIndexToOffset(3); + private static final int NOT_TAKEN_COUNT_OFFSET = cellIndexToOffset(2); + + public BranchData() { + super(BRANCH_DATA_TAG, BRANCH_DATA_SIZE); + } + + @Override + public double getBranchTakenProbability(HotSpotMethodData data, int position) { + long takenCount = data.readUnsignedInt(position, TAKEN_COUNT_OFFSET); + long notTakenCount = data.readUnsignedInt(position, NOT_TAKEN_COUNT_OFFSET); + long total = takenCount + notTakenCount; + + if (total < GraalOptions.MatureExecutionsBranch) { + return -1; + } else { + return takenCount / (double) total; + } + } + + @Override + public int getExecutionCount(HotSpotMethodData data, int position) { + long count = data.readUnsignedInt(position, TAKEN_COUNT_OFFSET) + data.readUnsignedInt(position, NOT_TAKEN_COUNT_OFFSET); + return truncateLongToInt(count); + } + } + + private static class ArrayData extends AbstractMethodData { + private static final int ARRAY_DATA_LENGTH_OFFSET = cellIndexToOffset(0); + protected static final int ARRAY_DATA_START_OFFSET = cellIndexToOffset(1); + + public ArrayData(int tag, int staticSize) { + super(tag, staticSize); + } + + @Override + protected int getDynamicSize(HotSpotMethodData data, int position) { + return cellsToBytes(getLength(data, position)); + } + + protected static int getLength(HotSpotMethodData data, int position) { + return data.readInt(position, ARRAY_DATA_LENGTH_OFFSET); + } + } + + private static class MultiBranchData extends ArrayData { + private static final int MULTI_BRANCH_DATA_TAG = 8; + private static final int MULTI_BRANCH_DATA_SIZE = cellIndexToOffset(1); + private static final int MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS = 2; + private static final int MULTI_BRANCH_DATA_ROW_SIZE = cellsToBytes(MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS); + private static final int MULTI_BRANCH_DATA_FIRST_COUNT_OFFSET = ARRAY_DATA_START_OFFSET + cellsToBytes(0); + private static final int MULTI_BRANCH_DATA_FIRST_DISPLACEMENT_OFFSET = ARRAY_DATA_START_OFFSET + cellsToBytes(1); + + public MultiBranchData() { + super(MULTI_BRANCH_DATA_TAG, MULTI_BRANCH_DATA_SIZE); + } + + @Override + public double[] getSwitchProbabilities(HotSpotMethodData data, int position) { + int arrayLength = getLength(data, position); + assert arrayLength > 0 : "switch must have at least the default case"; + assert arrayLength % MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS == 0 : "array must have full rows"; + + int length = arrayLength / MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS; + long totalCount = 0; + double[] result = new double[length]; + + // default case is first in HotSpot but last for the compiler + long count = readCount(data, position, 0); + totalCount += count; + result[length - 1] = count; + + for (int i = 1; i < length; i++) { + count = readCount(data, position, i); + totalCount += count; + result[i - 1] = count; + } + + if (totalCount < GraalOptions.MatureExecutionsPerSwitchCase * length) { + return null; + } else { + for (int i = 0; i < length; i++) { + result[i] = result[i] / totalCount; + } + return result; + } + } + + private static long readCount(HotSpotMethodData data, int position, int i) { + int offset; + long count; + offset = getCountOffset(i); + count = data.readUnsignedInt(position, offset); + return count; + } + + @Override + public int getExecutionCount(HotSpotMethodData data, int position) { + int arrayLength = getLength(data, position); + assert arrayLength > 0 : "switch must have at least the default case"; + assert arrayLength % MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS == 0 : "array must have full rows"; + + int length = arrayLength / MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS; + long totalCount = 0; + for (int i = 0; i < length; i++) { + int offset = getCountOffset(i); + totalCount += data.readUnsignedInt(position, offset); + } + + return truncateLongToInt(totalCount); + } + + private static int getCountOffset(int index) { + return MULTI_BRANCH_DATA_FIRST_COUNT_OFFSET + index * MULTI_BRANCH_DATA_ROW_SIZE; + } + + @SuppressWarnings("unused") + private static int getDisplacementOffset(int index) { + return MULTI_BRANCH_DATA_FIRST_DISPLACEMENT_OFFSET + index * MULTI_BRANCH_DATA_ROW_SIZE; + } + } + + private static class ArgInfoData extends ArrayData { + private static final int ARG_INFO_DATA_TAG = 9; + private static final int ARG_INFO_DATA_SIZE = cellIndexToOffset(1); + + public ArgInfoData() { + super(ARG_INFO_DATA_TAG, ARG_INFO_DATA_SIZE); + } + } +} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodDataAccessor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodDataAccessor.java Sat Jun 09 20:32:31 2012 +0200 @@ -0,0 +1,56 @@ +/* + * 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.hotspot.meta; + +import com.oracle.graal.api.meta.*; + +/** + * Interface for accessor objects that encapsulate the logic for accessing the different kinds of data in a HotSpot methodDataOop. + * This interface is similar to the interface {@link ProfilingInfo}, but most methods require a MethodDataObject and the + * exact position within the methodData. + */ +public interface HotSpotMethodDataAccessor { + /** + * Returns the tag stored in the LayoutData header. + * @return An integer >= 0 or -1 if not supported. + */ + int getTag(); + + /** + * Returns the BCI stored in the LayoutData header. + * @return An integer >= 0 and <= Short.MAX_VALUE, or -1 if not supported. + */ + int getBCI(HotSpotMethodData data, int position); + + /** + * Computes the size for the specific data at the given position. + * @return An integer > 0. + */ + int getSize(HotSpotMethodData data, int position); + + JavaTypeProfile getTypeProfile(HotSpotMethodData data, int position); + double getBranchTakenProbability(HotSpotMethodData data, int position); + double[] getSwitchProbabilities(HotSpotMethodData data, int position); + ExceptionSeen getExceptionSeen(HotSpotMethodData data, int position); + int getExecutionCount(HotSpotMethodData data, int position); +} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodResolved.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodResolved.java Sat Jun 09 20:32:31 2012 +0200 @@ -0,0 +1,35 @@ +/* + * 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.hotspot.meta; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.*; + +public interface HotSpotMethodResolved extends ResolvedJavaMethod { + + ResolvedJavaMethod uniqueConcreteMethod(); + int vtableEntryOffset(); + + void setCurrentTask(CompilationTask task); + CompilationTask currentTask(); +} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodResolvedImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodResolvedImpl.java Sat Jun 09 20:32:31 2012 +0200 @@ -0,0 +1,351 @@ +/* + * 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.hotspot.meta; + +import java.io.*; +import java.lang.annotation.*; +import java.lang.reflect.*; +import java.util.*; +import java.util.concurrent.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.counters.*; +import com.oracle.graal.java.bytecode.*; +import com.oracle.max.criutils.*; + +/** + * Implementation of RiMethod for resolved HotSpot methods. + */ +public final class HotSpotMethodResolvedImpl extends HotSpotMethod implements HotSpotMethodResolved { + + private static final long serialVersionUID = -5486975070147586588L; + + /** DO NOT USE IN JAVA CODE! */ + @SuppressWarnings("unused") + @Deprecated + private Object javaMirror; + + // cached values + private final int codeSize; + private final int accessFlags; + private final int maxLocals; + private final int maxStackSize; + private Signature signature; + private Boolean hasBalancedMonitors; + private Map compilerStorage; + private ResolvedJavaType holder; + private HotSpotMethodData methodData; + private byte[] code; + private boolean canBeInlined; + private int compilationComplexity; + + private CompilationTask currentTask; + + private HotSpotMethodResolvedImpl() { + throw new IllegalStateException("this constructor is never actually called, because the objects are allocated from within the VM"); + } + + @Override + public ResolvedJavaType holder() { + return holder; + } + + @Override + public int accessFlags() { + return accessFlags; + } + + @Override + public boolean canBeStaticallyBound() { + return isLeafMethod() || Modifier.isStatic(accessFlags()); + } + + @Override + public byte[] code() { + if (code == null) { + code = HotSpotGraalRuntime.getInstance().getCompilerToVM().RiMethod_code(this); + assert code.length == codeSize : "expected: " + codeSize + ", actual: " + code.length; + } + return code; + } + + @Override + public int codeSize() { + return codeSize; + } + + @Override + public ExceptionHandler[] exceptionHandlers() { + return HotSpotGraalRuntime.getInstance().getCompilerToVM().RiMethod_exceptionHandlers(this); + } + + @Override + public boolean hasBalancedMonitors() { + if (hasBalancedMonitors == null) { + hasBalancedMonitors = HotSpotGraalRuntime.getInstance().getCompilerToVM().RiMethod_hasBalancedMonitors(this); + } + return hasBalancedMonitors; + } + + @Override + public boolean isClassInitializer() { + return "".equals(name) && Modifier.isStatic(accessFlags()); + } + + @Override + public boolean isConstructor() { + return "".equals(name) && !Modifier.isStatic(accessFlags()); + } + + @Override + public boolean isLeafMethod() { + return Modifier.isFinal(accessFlags()) || Modifier.isPrivate(accessFlags()); + } + + @Override + public String jniSymbol() { + throw new UnsupportedOperationException("jniSymbol"); + } + + @Override + public int maxLocals() { + return maxLocals; + } + + @Override + public int maxStackSize() { + return maxStackSize; + } + + @Override + public StackTraceElement toStackTraceElement(int bci) { + if (bci < 0 || bci >= codeSize) { + // HotSpot code can only construct stack trace elements for valid bcis + StackTraceElement ste = HotSpotGraalRuntime.getInstance().getCompilerToVM().RiMethod_toStackTraceElement(this, 0); + return new StackTraceElement(ste.getClassName(), ste.getMethodName(), ste.getFileName(), -1); + } + return HotSpotGraalRuntime.getInstance().getCompilerToVM().RiMethod_toStackTraceElement(this, bci); + } + + @Override + public ResolvedJavaMethod uniqueConcreteMethod() { + return (ResolvedJavaMethod) HotSpotGraalRuntime.getInstance().getCompilerToVM().RiMethod_uniqueConcreteMethod(this); + } + + @Override + public Signature signature() { + if (signature == null) { + signature = new HotSpotSignature(HotSpotGraalRuntime.getInstance().getCompilerToVM().RiMethod_signature(this)); + } + return signature; + } + + @Override + public String toString() { + return "HotSpotMethod<" + CodeUtil.format("%h.%n", this) + ">"; + } + + public boolean hasCompiledCode() { + return HotSpotGraalRuntime.getInstance().getCompilerToVM().RiMethod_hasCompiledCode(this); + } + + public int compiledCodeSize() { + int result = HotSpotGraalRuntime.getInstance().getCompilerToVM().RiMethod_getCompiledCodeSize(this); + if (result > 0) { + assert result > MethodEntryCounters.getCodeSize(); + result = result - MethodEntryCounters.getCodeSize(); + } + return result; + } + + @Override + public int invocationCount() { + return HotSpotGraalRuntime.getInstance().getCompilerToVM().RiMethod_invocationCount(this); + } + + @Override + public int compilationComplexity() { + if (compilationComplexity <= 0 && codeSize() > 0) { + BytecodeStream s = new BytecodeStream(code()); + int result = 0; + int currentBC; + while ((currentBC = s.currentBC()) != Bytecodes.END) { + result += Bytecodes.compilationComplexity(currentBC); + s.next(); + } + assert result > 0; + compilationComplexity = result; + } + return compilationComplexity; + } + + private static final MethodFilter profilingInfoFilter = GraalOptions.PIFilter == null ? null : new MethodFilter(GraalOptions.PIFilter); + + /** + * Determines if the profiling info cache should be used for this method. + */ + private boolean useProfilingInfoCache() { + return GraalOptions.PICache != null && (profilingInfoFilter == null || profilingInfoFilter.matches(this)); + } + + private ProfilingInfo loadProfilingInfo() { + if (!useProfilingInfoCache()) { + return null; + } + synchronized (this) { + File file = new File(GraalOptions.PICache, JniMangle.mangleMethod(holder, name, signature(), false)); + if (file.exists()) { + try { + SnapshotProfilingInfo snapshot = SnapshotProfilingInfo.load(file, HotSpotGraalRuntime.getInstance().getRuntime()); + if (snapshot.codeSize() != codeSize) { + // The class file was probably changed - ignore the saved profile + return null; + } + return snapshot; + } catch (Exception e) { + // ignore + } + } + return null; + } + } + + private void saveProfilingInfo(ProfilingInfo info) { + if (useProfilingInfoCache()) { + synchronized (this) { + String base = JniMangle.mangleMethod(holder, name, signature(), false); + File file = new File(GraalOptions.PICache, base); + File txtFile = new File(GraalOptions.PICache, base + ".txt"); + SnapshotProfilingInfo snapshot = info instanceof SnapshotProfilingInfo ? (SnapshotProfilingInfo) info : new SnapshotProfilingInfo(info); + try { + snapshot.save(file, txtFile); + } catch (IOException e) { + // ignore + } + } + } + } + + @Override + public ProfilingInfo profilingInfo() { + ProfilingInfo info = loadProfilingInfo(); + if (info != null) { + return info; + } + + if (GraalOptions.UseProfilingInformation && methodData == null) { + methodData = HotSpotGraalRuntime.getInstance().getCompilerToVM().RiMethod_methodData(this); + } + + if (methodData == null || (!methodData.hasNormalData() && !methodData.hasExtraData())) { + // Be optimistic and return false for exceptionSeen. A methodDataOop is allocated in case of a deoptimization. + info = BaseProfilingInfo.get(ExceptionSeen.FALSE); + } else { + info = new HotSpotProfilingInfo(methodData, codeSize); + saveProfilingInfo(info); + } + return info; + } + + @Override + public Map compilerStorage() { + if (compilerStorage == null) { + compilerStorage = new ConcurrentHashMap<>(); + } + return compilerStorage; + } + + @Override + public ConstantPool getConstantPool() { + return ((HotSpotTypeResolvedImpl) holder()).constantPool(); + } + + @Override + public Annotation[][] getParameterAnnotations() { + if (isConstructor()) { + Constructor javaConstructor = toJavaConstructor(); + return javaConstructor == null ? null : javaConstructor.getParameterAnnotations(); + } + Method javaMethod = toJava(); + return javaMethod == null ? null : javaMethod.getParameterAnnotations(); + } + + @Override + public T getAnnotation(Class annotationClass) { + if (isConstructor()) { + Constructor javaConstructor = toJavaConstructor(); + return javaConstructor == null ? null : javaConstructor.getAnnotation(annotationClass); + } + Method javaMethod = toJava(); + return javaMethod == null ? null : javaMethod.getAnnotation(annotationClass); + } + + @Override + public Type[] getGenericParameterTypes() { + if (isConstructor()) { + Constructor javaConstructor = toJavaConstructor(); + return javaConstructor == null ? null : javaConstructor.getGenericParameterTypes(); + } + Method javaMethod = toJava(); + return javaMethod == null ? null : javaMethod.getGenericParameterTypes(); + } + + private Method toJava() { + try { + return holder.toJava().getDeclaredMethod(name, CodeUtil.signatureToTypes(signature(), holder)); + } catch (NoSuchMethodException e) { + return null; + } + } + + private Constructor toJavaConstructor() { + try { + return holder.toJava().getDeclaredConstructor(CodeUtil.signatureToTypes(signature(), holder)); + } catch (NoSuchMethodException e) { + return null; + } + } + + @Override + public boolean canBeInlined() { + return canBeInlined; + } + + @Override + public int vtableEntryOffset() { + return HotSpotGraalRuntime.getInstance().getCompilerToVM().RiMethod_vtableEntryOffset(this); + } + + @Override + public void setCurrentTask(CompilationTask task) { + currentTask = task; + } + + @Override + public CompilationTask currentTask() { + return currentTask; + } +} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodUnresolved.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodUnresolved.java Sat Jun 09 20:32:31 2012 +0200 @@ -0,0 +1,55 @@ +/* + * 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.hotspot.meta; + +import com.oracle.graal.api.meta.*; + +/** + * Implementation of RiMethod for unresolved HotSpot methods. + */ +public final class HotSpotMethodUnresolved extends HotSpotMethod { + private static final long serialVersionUID = 5610263481791970079L; + private final Signature signature; + protected JavaType holder; + + public HotSpotMethodUnresolved(String name, String signature, JavaType holder) { + this.name = name; + this.holder = holder; + this.signature = new HotSpotSignature(signature); + } + + @Override + public Signature signature() { + return signature; + } + + @Override + public JavaType holder() { + return holder; + } + + @Override + public String toString() { + return "HotSpotMethod<" + holder.name() + ". " + name + ", unresolved>"; + } +} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProfilingInfo.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProfilingInfo.java Sat Jun 09 20:32:31 2012 +0200 @@ -0,0 +1,154 @@ +/* + * 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.meta; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.hotspot.*; + + +public final class HotSpotProfilingInfo extends CompilerObject implements ProfilingInfo { + + private static final long serialVersionUID = -8307682725047864875L; + private static final DebugMetric metricInsufficentSpace = Debug.metric("InsufficientSpaceForProfilingData"); + + private int position; + private int hintPosition; + private int hintBCI; + private HotSpotMethodDataAccessor dataAccessor; + private HotSpotMethodData methodData; + private final int codeSize; + + public HotSpotProfilingInfo(HotSpotMethodData methodData, int codeSize) { + this.methodData = methodData; + this.codeSize = codeSize; + hintPosition = 0; + hintBCI = -1; + } + + @Override + public int codeSize() { + return codeSize; + } + + @Override + public JavaTypeProfile getTypeProfile(int bci) { + findBCI(bci, false); + return dataAccessor.getTypeProfile(methodData, position); + } + + @Override + public double getBranchTakenProbability(int bci) { + findBCI(bci, false); + return dataAccessor.getBranchTakenProbability(methodData, position); + } + + @Override + public double[] getSwitchProbabilities(int bci) { + findBCI(bci, false); + return dataAccessor.getSwitchProbabilities(methodData, position); + } + + @Override + public ExceptionSeen getExceptionSeen(int bci) { + findBCI(bci, true); + return dataAccessor.getExceptionSeen(methodData, position); + } + + @Override + public int getExecutionCount(int bci) { + findBCI(bci, false); + return dataAccessor.getExecutionCount(methodData, position); + } + + @Override + public int getDeoptimizationCount(DeoptimizationReason reason) { + return methodData.getDeoptimizationCount(reason); + } + + private void findBCI(int targetBCI, boolean searchExtraData) { + assert targetBCI >= 0 : "invalid BCI"; + + if (methodData.hasNormalData()) { + int currentPosition = targetBCI < hintBCI ? 0 : hintPosition; + HotSpotMethodDataAccessor currentAccessor; + while ((currentAccessor = methodData.getNormalData(currentPosition)) != null) { + int currentBCI = currentAccessor.getBCI(methodData, currentPosition); + if (currentBCI == targetBCI) { + normalDataFound(currentAccessor, currentPosition, currentBCI); + return; + } else if (currentBCI > targetBCI) { + break; + } + currentPosition = currentPosition + currentAccessor.getSize(methodData, currentPosition); + } + } + + boolean exceptionPossiblyNotRecorded = false; + if (searchExtraData && methodData.hasExtraData()) { + int currentPosition = methodData.getExtraDataBeginOffset(); + HotSpotMethodDataAccessor currentAccessor; + while ((currentAccessor = methodData.getExtraData(currentPosition)) != null) { + int currentBCI = currentAccessor.getBCI(methodData, currentPosition); + if (currentBCI == targetBCI) { + extraDataFound(currentAccessor, currentPosition); + return; + } + currentPosition = currentPosition + currentAccessor.getSize(methodData, currentPosition); + } + + if (!methodData.isWithin(currentPosition)) { + exceptionPossiblyNotRecorded = true; + metricInsufficentSpace.increment(); + } + } + + noDataFound(exceptionPossiblyNotRecorded); + } + + private void normalDataFound(HotSpotMethodDataAccessor data, int pos, int bci) { + setCurrentData(data, pos); + this.hintPosition = position; + this.hintBCI = bci; + } + + private void extraDataFound(HotSpotMethodDataAccessor data, int pos) { + setCurrentData(data, pos); + } + + private void noDataFound(boolean exceptionPossiblyNotRecorded) { + HotSpotMethodDataAccessor accessor = HotSpotMethodData.getNoDataAccessor(exceptionPossiblyNotRecorded); + setCurrentData(accessor, -1); + } + + private void setCurrentData(HotSpotMethodDataAccessor dataAccessor, int position) { + this.dataAccessor = dataAccessor; + this.position = position; + } + + @Override + public String toString() { + return "HotSpotProfilingInfo<" + CodeUtil.profileToString(this, null, "; ") + ">"; + } +} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRegisterConfig.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRegisterConfig.java Sat Jun 09 20:32:31 2012 +0200 @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2011, 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.meta; + +import static com.oracle.max.asm.target.amd64.AMD64.*; + +import java.util.*; + +import com.oracle.max.asm.target.amd64.*; +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.CallingConvention.*; +import com.oracle.graal.api.code.Register.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.*; + +public class HotSpotRegisterConfig implements RegisterConfig { + + // be careful - the contents of this array are duplicated in graal_CodeInstaller.cpp + private final Register[] allocatable = { + rax, rbx, rcx, rdx, rsi, rdi, r8, r9, /* r10, */r11, r12, r13, r14, /*r15*/ + xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, + xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 + }; + + private final EnumMap categorized = Register.categorize(allocatable); + + private final RegisterAttributes[] attributesMap; + + @Override + public Register[] getAllocatableRegisters() { + return allocatable; + } + + @Override + public EnumMap getCategorizedAllocatableRegisters() { + return categorized; + } + + @Override + public RegisterAttributes[] getAttributesMap() { + return attributesMap; + } + + private final Register[] generalParameterRegisters; + private final Register[] xmmParameterRegisters = {xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7}; + private final Register[] allParameterRegisters; + + private final CalleeSaveLayout csl; + + public HotSpotRegisterConfig(HotSpotVMConfig config, boolean globalStubConfig) { + if (config.windowsOs) { + generalParameterRegisters = new Register[] {rdx, r8, r9, rdi, rsi, rcx}; + } else { + generalParameterRegisters = new Register[] {rsi, rdx, rcx, r8, r9, rdi}; + } + + if (globalStubConfig) { + Register[] regs = { + rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, + r8, r9, r10, r11, r12, r13, r14, r15, + xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, + xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 + }; + csl = new CalleeSaveLayout(0, -1, 8, regs); + } else { + // We reserve space for saving RBP but don't explicitly specify + // it as a callee save register since we explicitly do the saving + // with push and pop in HotSpotFrameContext + final int size = 8; + final Register[] regs = {}; + csl = new CalleeSaveLayout(0, size, 8, regs); + } + + attributesMap = RegisterAttributes.createMap(this, AMD64.allRegisters); + allParameterRegisters = Arrays.copyOf(generalParameterRegisters, generalParameterRegisters.length + xmmParameterRegisters.length); + System.arraycopy(xmmParameterRegisters, 0, allParameterRegisters, generalParameterRegisters.length, xmmParameterRegisters.length); + } + + @Override + public Register[] getCallerSaveRegisters() { + return getAllocatableRegisters(); + } + + @Override + public Register getRegisterForRole(int index) { + throw new UnsupportedOperationException(); + } + + @Override + public CallingConvention getCallingConvention(Type type, Kind[] parameters, TargetDescription target, boolean stackOnly) { + if (type == Type.NativeCall) { + throw new UnsupportedOperationException(); + } + return callingConvention(parameters, type, target, stackOnly); + } + + public Register[] getCallingConventionRegisters(Type type, RegisterFlag flag) { + return allParameterRegisters; + } + + private CallingConvention callingConvention(Kind[] types, Type type, TargetDescription target, boolean stackOnly) { + Value[] locations = new Value[types.length]; + + int currentGeneral = 0; + int currentXMM = 0; + int currentStackOffset = 0; + + for (int i = 0; i < types.length; i++) { + final Kind kind = types[i]; + + switch (kind) { + case Byte: + case Boolean: + case Short: + case Char: + case Int: + case Long: + case Object: + if (!stackOnly && currentGeneral < generalParameterRegisters.length) { + Register register = generalParameterRegisters[currentGeneral++]; + locations[i] = register.asValue(kind); + } + break; + case Float: + case Double: + if (!stackOnly && currentXMM < xmmParameterRegisters.length) { + Register register = xmmParameterRegisters[currentXMM++]; + locations[i] = register.asValue(kind); + } + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + + if (locations[i] == null) { + locations[i] = StackSlot.get(kind.stackKind(), currentStackOffset, !type.out); + currentStackOffset += Math.max(target.sizeInBytes(kind), target.wordSize); + } + } + + return new CallingConvention(locations, currentStackOffset); + } + + @Override + public Register getReturnRegister(Kind kind) { + switch (kind) { + case Boolean: + case Byte: + case Char: + case Short: + case Int: + case Long: + case Object: + return rax; + case Float: + case Double: + return xmm0; + case Void: + case Illegal: + return null; + default: + throw new UnsupportedOperationException("no return register for type " + kind); + } + } + + @Override + public Register getScratchRegister() { + return r10; + } + + @Override + public Register getFrameRegister() { + return rsp; + } + + public CalleeSaveLayout getCalleeSaveLayout() { + return csl; + } + + @Override + public String toString() { + String res = String.format( + "Allocatable: " + Arrays.toString(getAllocatableRegisters()) + "%n" + + "CallerSave: " + Arrays.toString(getCallerSaveRegisters()) + "%n" + + "CalleeSave: " + getCalleeSaveLayout() + "%n" + + "Scratch: " + getScratchRegister() + "%n"); + return res; + } +} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Sat Jun 09 20:32:31 2012 +0200 @@ -0,0 +1,540 @@ +/* + * Copyright (c) 2011, 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.meta; + +import static com.oracle.max.cri.util.MemoryBarriers.*; + +import java.lang.reflect.*; +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.CompilationResult.*; +import com.oracle.graal.api.code.CodeUtil.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.meta.JavaType.*; +import com.oracle.graal.compiler.*; +import com.oracle.graal.compiler.target.*; +import com.oracle.graal.cri.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.hotspot.snippets.*; +import com.oracle.graal.hotspot.target.amd64.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.snippets.*; +import com.oracle.max.criutils.*; + +/** + * CRI runtime implementation for the HotSpot VM. + */ +public class HotSpotRuntime implements ExtendedRiRuntime { + public final HotSpotVMConfig config; + final HotSpotRegisterConfig regConfig; + private final HotSpotRegisterConfig globalStubRegConfig; + private final HotSpotGraalRuntime compiler; + private CheckCastSnippets.Templates checkcasts; + + public HotSpotRuntime(HotSpotVMConfig config, HotSpotGraalRuntime compiler) { + this.config = config; + this.compiler = compiler; + regConfig = new HotSpotRegisterConfig(config, false); + globalStubRegConfig = new HotSpotRegisterConfig(config, true); + + System.setProperty(Backend.BACKEND_CLASS_PROPERTY, HotSpotAMD64Backend.class.getName()); + } + + public void installSnippets() { + Snippets.install(this, compiler.getTarget(), new SystemSnippets()); + Snippets.install(this, compiler.getTarget(), new UnsafeSnippets()); + Snippets.install(this, compiler.getTarget(), new ArrayCopySnippets()); + Snippets.install(this, compiler.getTarget(), new CheckCastSnippets()); + checkcasts = new CheckCastSnippets.Templates(this); + } + + + public HotSpotGraalRuntime getCompiler() { + return compiler; + } + + @Override + public String disassemble(CodeInfo info, CompilationResult tm) { + byte[] code = info.code(); + TargetDescription target = compiler.getTarget(); + HexCodeFile hcf = new HexCodeFile(code, info.start(), target.arch.name, target.wordSize * 8); + if (tm != null) { + HexCodeFile.addAnnotations(hcf, tm.annotations()); + addExceptionHandlersComment(tm, hcf); + Register fp = regConfig.getFrameRegister(); + RefMapFormatter slotFormatter = new RefMapFormatter(target.arch, target.wordSize, fp, 0); + for (Safepoint safepoint : tm.safepoints) { + if (safepoint instanceof Call) { + Call call = (Call) safepoint; + if (call.debugInfo != null) { + hcf.addComment(call.pcOffset + call.size, CodeUtil.append(new StringBuilder(100), call.debugInfo, slotFormatter).toString()); + } + addOperandComment(hcf, call.pcOffset, "{" + getTargetName(call) + "}"); + } else { + if (safepoint.debugInfo != null) { + hcf.addComment(safepoint.pcOffset, CodeUtil.append(new StringBuilder(100), safepoint.debugInfo, slotFormatter).toString()); + } + addOperandComment(hcf, safepoint.pcOffset, "{safepoint}"); + } + } + for (DataPatch site : tm.dataReferences) { + hcf.addOperandComment(site.pcOffset, "{" + site.constant + "}"); + } + for (Mark mark : tm.marks) { + hcf.addComment(mark.pcOffset, getMarkName(mark)); + } + } + return hcf.toEmbeddedString(); + } + + /** + * Decodes a call target to a mnemonic if possible. + */ + private String getTargetName(Call call) { + Field[] fields = config.getClass().getDeclaredFields(); + for (Field f : fields) { + if (f.getName().endsWith("Stub")) { + f.setAccessible(true); + try { + if (f.get(config).equals(call.target)) { + return f.getName(); + } + } catch (Exception e) { + } + } + } + return String.valueOf(call.target); + } + + /** + * Decodes a mark to a mnemonic if possible. + */ + private static String getMarkName(Mark mark) { + Field[] fields = HotSpotXirGenerator.class.getDeclaredFields(); + for (Field f : fields) { + if (Modifier.isStatic(f.getModifiers()) && f.getName().startsWith("MARK_")) { + f.setAccessible(true); + try { + if (f.get(null).equals(mark.id)) { + return f.getName(); + } + } catch (Exception e) { + } + } + } + return "MARK:" + mark.id; + } + + private static void addExceptionHandlersComment(CompilationResult tm, HexCodeFile hcf) { + if (!tm.exceptionHandlers.isEmpty()) { + String nl = HexCodeFile.NEW_LINE; + StringBuilder buf = new StringBuilder("------ Exception Handlers ------").append(nl); + for (CompilationResult.ExceptionHandler e : tm.exceptionHandlers) { + buf.append(" "). + append(e.pcOffset).append(" -> "). + append(e.handlerPos). + append(nl); + hcf.addComment(e.pcOffset, "[exception -> " + e.handlerPos + "]"); + hcf.addComment(e.handlerPos, "[exception handler for " + e.pcOffset + "]"); + } + hcf.addComment(0, buf.toString()); + } + } + + private static void addOperandComment(HexCodeFile hcf, int pos, String comment) { + String oldValue = hcf.addOperandComment(pos, comment); + assert oldValue == null : "multiple comments for operand of instruction at " + pos + ": " + comment + ", " + oldValue; + } + + @Override + public String disassemble(ResolvedJavaMethod method) { + return compiler.getCompilerToVM().disassembleJava((HotSpotMethodResolved) method); + } + + @Override + public ResolvedJavaType getResolvedJavaType(Kind kind) { + return (ResolvedJavaType) compiler.getCompilerToVM().getType(kind.toJavaClass()); + } + + @Override + public ResolvedJavaType getTypeOf(Constant constant) { + return (ResolvedJavaType) compiler.getCompilerToVM().getRiType(constant); + } + + @Override + public int sizeOfLockData() { + // TODO shouldn't be hard coded + return 8; + } + + @Override + public boolean areConstantObjectsEqual(Constant x, Constant y) { + return compiler.getCompilerToVM().compareConstantObjects(x, y); + } + + @Override + public RegisterConfig getRegisterConfig(JavaMethod method) { + return regConfig; + } + + /** + * HotSpots needs an area suitable for storing a program counter for temporary use during the deoptimization process. + */ + @Override + public int getCustomStackAreaSize() { + // TODO shouldn't be hard coded + return 8; + } + + @Override + public int getMinimumOutgoingSize() { + return config.runtimeCallStackSize; + } + + @Override + public int getArrayLength(Constant array) { + return compiler.getCompilerToVM().getArrayLength(array); + } + + @Override + public void lower(Node n, CiLoweringTool tool) { + StructuredGraph graph = (StructuredGraph) n.graph(); + + if (n instanceof ArrayLengthNode) { + ArrayLengthNode arrayLengthNode = (ArrayLengthNode) n; + SafeReadNode safeReadArrayLength = safeReadArrayLength(arrayLengthNode.array(), StructuredGraph.INVALID_GRAPH_ID); + graph.replaceFixedWithFixed(arrayLengthNode, safeReadArrayLength); + } else if (n instanceof LoadFieldNode) { + LoadFieldNode field = (LoadFieldNode) n; + int displacement = ((HotSpotField) field.field()).offset(); + assert field.kind() != Kind.Illegal; + ReadNode memoryRead = graph.add(new ReadNode(field.object(), LocationNode.create(field.field(), field.field().kind(), displacement, graph), field.stamp())); + memoryRead.dependencies().add(tool.createNullCheckGuard(field.object(), field.leafGraphId())); + graph.replaceFixedWithFixed(field, memoryRead); + if (field.isVolatile()) { + MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_READ)); + graph.addBeforeFixed(memoryRead, preMembar); + MembarNode postMembar = graph.add(new MembarNode(JMM_POST_VOLATILE_READ)); + graph.addAfterFixed(memoryRead, postMembar); + } + } else if (n instanceof StoreFieldNode) { + StoreFieldNode storeField = (StoreFieldNode) n; + HotSpotField field = (HotSpotField) storeField.field(); + WriteNode memoryWrite = graph.add(new WriteNode(storeField.object(), storeField.value(), LocationNode.create(storeField.field(), storeField.field().kind(), field.offset(), graph))); + memoryWrite.dependencies().add(tool.createNullCheckGuard(storeField.object(), storeField.leafGraphId())); + memoryWrite.setStateAfter(storeField.stateAfter()); + graph.replaceFixedWithFixed(storeField, memoryWrite); + + FixedWithNextNode last = memoryWrite; + if (field.kind() == Kind.Object && !memoryWrite.value().isNullConstant()) { + FieldWriteBarrier writeBarrier = graph.add(new FieldWriteBarrier(memoryWrite.object())); + graph.addAfterFixed(memoryWrite, writeBarrier); + last = writeBarrier; + } + if (storeField.isVolatile()) { + MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_WRITE)); + graph.addBeforeFixed(memoryWrite, preMembar); + MembarNode postMembar = graph.add(new MembarNode(JMM_POST_VOLATILE_WRITE)); + graph.addAfterFixed(last, postMembar); + } + } else if (n instanceof CompareAndSwapNode) { + // Separate out GC barrier semantics + CompareAndSwapNode cas = (CompareAndSwapNode) n; + ValueNode expected = cas.expected(); + if (expected.kind() == Kind.Object && !cas.newValue().isNullConstant()) { + ResolvedJavaType type = cas.object().objectStamp().type(); + if (type != null && !type.isArrayClass() && type.toJava() != Object.class) { + // Use a field write barrier since it's not an array store + FieldWriteBarrier writeBarrier = graph.add(new FieldWriteBarrier(cas.object())); + graph.addAfterFixed(cas, writeBarrier); + } else { + // This may be an array store so use an array write barrier + LocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, cas.expected().kind(), cas.displacement(), cas.offset(), graph, false); + graph.addAfterFixed(cas, graph.add(new ArrayWriteBarrier(cas.object(), location))); + } + } + } else if (n instanceof LoadIndexedNode) { + LoadIndexedNode loadIndexed = (LoadIndexedNode) n; + + ValueNode boundsCheck = createBoundsCheck(loadIndexed, tool); + + Kind elementKind = loadIndexed.elementKind(); + LocationNode arrayLocation = createArrayLocation(graph, elementKind, loadIndexed.index()); + ReadNode memoryRead = graph.add(new ReadNode(loadIndexed.array(), arrayLocation, loadIndexed.stamp())); + memoryRead.dependencies().add(boundsCheck); + graph.replaceFixedWithFixed(loadIndexed, memoryRead); + } else if (n instanceof StoreIndexedNode) { + StoreIndexedNode storeIndexed = (StoreIndexedNode) n; + ValueNode boundsCheck = createBoundsCheck(storeIndexed, tool); + + Kind elementKind = storeIndexed.elementKind(); + LocationNode arrayLocation = createArrayLocation(graph, elementKind, storeIndexed.index()); + ValueNode value = storeIndexed.value(); + CheckCastNode checkcast = null; + ValueNode array = storeIndexed.array(); + if (elementKind == Kind.Object && !value.isNullConstant()) { + // Store check! + ResolvedJavaType arrayType = array.objectStamp().type(); + if (arrayType != null && array.objectStamp().isExactType()) { + ResolvedJavaType elementType = arrayType.componentType(); + if (elementType.superType() != null) { + ConstantNode type = ConstantNode.forCiConstant(elementType.getEncoding(Representation.ObjectHub), this, graph); + checkcast = graph.add(new CheckCastNode(type, elementType, value)); + graph.addBeforeFixed(storeIndexed, checkcast); + value = checkcast; + } else { + assert elementType.name().equals("Ljava/lang/Object;") : elementType.name(); + } + } else { + ValueNode guard = tool.createNullCheckGuard(array, StructuredGraph.INVALID_GRAPH_ID); + FloatingReadNode arrayClass = graph.unique(new FloatingReadNode(array, LocationNode.create(LocationNode.FINAL_LOCATION, Kind.Object, config.hubOffset, graph), null, StampFactory.objectNonNull())); + arrayClass.dependencies().add(guard); + FloatingReadNode arrayElementKlass = graph.unique(new FloatingReadNode(arrayClass, LocationNode.create(LocationNode.FINAL_LOCATION, Kind.Object, config.arrayClassElementOffset, graph), null, StampFactory.objectNonNull())); + checkcast = graph.add(new CheckCastNode(arrayElementKlass, null, value)); + graph.addBeforeFixed(storeIndexed, checkcast); + value = checkcast; + } + } + WriteNode memoryWrite = graph.add(new WriteNode(array, value, arrayLocation)); + memoryWrite.dependencies().add(boundsCheck); + memoryWrite.setStateAfter(storeIndexed.stateAfter()); + + graph.replaceFixedWithFixed(storeIndexed, memoryWrite); + + if (elementKind == Kind.Object && !value.isNullConstant()) { + graph.addAfterFixed(memoryWrite, graph.add(new ArrayWriteBarrier(array, arrayLocation))); + } + } else if (n instanceof UnsafeLoadNode) { + UnsafeLoadNode load = (UnsafeLoadNode) n; + assert load.kind() != Kind.Illegal; + IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, load.loadKind(), load.displacement(), load.offset(), graph, false); + ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, load.stamp())); + memoryRead.dependencies().add(tool.createNullCheckGuard(load.object(), StructuredGraph.INVALID_GRAPH_ID)); + graph.replaceFixedWithFixed(load, memoryRead); + } else if (n instanceof UnsafeStoreNode) { + UnsafeStoreNode store = (UnsafeStoreNode) n; + IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, store.storeKind(), store.displacement(), store.offset(), graph, false); + WriteNode write = graph.add(new WriteNode(store.object(), store.value(), location)); + write.setStateAfter(store.stateAfter()); + graph.replaceFixedWithFixed(store, write); + if (write.value().kind() == Kind.Object && !write.value().isNullConstant()) { + FieldWriteBarrier barrier = graph.add(new FieldWriteBarrier(write.object())); + graph.addBeforeFixed(write, barrier); + } + } else if (n instanceof ReadHubNode) { + ReadHubNode objectClassNode = (ReadHubNode) n; + LocationNode location = LocationNode.create(LocationNode.FINAL_LOCATION, Kind.Object, config.hubOffset, graph); + ReadNode memoryRead = graph.add(new ReadNode(objectClassNode.object(), location, StampFactory.objectNonNull())); + memoryRead.dependencies().add(tool.createNullCheckGuard(objectClassNode.object(), StructuredGraph.INVALID_GRAPH_ID)); + graph.replaceFixed(objectClassNode, memoryRead); + } else if (n instanceof CheckCastNode) { + if (shouldLowerCheckcast(graph)) { + checkcasts.lower((CheckCastNode) n, tool); + } + } else { + assert false : "Node implementing Lowerable not handled: " + n; + } + } + + private static boolean shouldLowerCheckcast(StructuredGraph graph) { + String option = GraalOptions.HIRLowerCheckcast; + if (option != null) { + if (option.length() == 0) { + return true; + } + ResolvedJavaMethod method = graph.method(); + return method != null && CodeUtil.format("%H.%n", method).contains(option); + } + return false; + } + + private IndexedLocationNode createArrayLocation(Graph graph, Kind elementKind, ValueNode index) { + return IndexedLocationNode.create(LocationNode.getArrayLocation(elementKind), elementKind, config.getArrayOffset(elementKind), index, graph, true); + } + + private SafeReadNode safeReadArrayLength(ValueNode array, long leafGraphId) { + return safeRead(array.graph(), Kind.Int, array, config.arrayLengthOffset, StampFactory.positiveInt(), leafGraphId); + } + + private static ValueNode createBoundsCheck(AccessIndexedNode n, CiLoweringTool tool) { + StructuredGraph graph = (StructuredGraph) n.graph(); + ArrayLengthNode arrayLength = graph.add(new ArrayLengthNode(n.array())); + ValueNode guard = tool.createGuard(graph.unique(new IntegerBelowThanNode(n.index(), arrayLength)), DeoptimizationReason.BoundsCheckException, DeoptimizationAction.InvalidateReprofile, n.leafGraphId()); + + graph.addBeforeFixed(n, arrayLength); + return guard; + } + + @Override + public StructuredGraph intrinsicGraph(ResolvedJavaMethod caller, int bci, ResolvedJavaMethod method, List parameters) { + JavaType holder = method.holder(); + String fullName = method.name() + method.signature().asString(); + String holderName = holder.name(); + if (holderName.equals("Ljava/lang/Object;")) { + if (fullName.equals("getClass()Ljava/lang/Class;")) { + ValueNode obj = (ValueNode) parameters.get(0); + ObjectStamp stamp = (ObjectStamp) obj.stamp(); + if (stamp.nonNull() && stamp.isExactType()) { + StructuredGraph graph = new StructuredGraph(); + ValueNode result = ConstantNode.forObject(stamp.type().toJava(), this, graph); + ReturnNode ret = graph.add(new ReturnNode(result)); + graph.start().setNext(ret); + return graph; + } + StructuredGraph graph = new StructuredGraph(); + LocalNode receiver = graph.unique(new LocalNode(0, StampFactory.objectNonNull())); + SafeReadNode klassOop = safeReadHub(graph, receiver, StructuredGraph.INVALID_GRAPH_ID); + Stamp resultStamp = StampFactory.declaredNonNull(getResolvedJavaType(Class.class)); + FloatingReadNode result = graph.unique(new FloatingReadNode(klassOop, LocationNode.create(LocationNode.FINAL_LOCATION, Kind.Object, config.classMirrorOffset, graph), null, resultStamp)); + ReturnNode ret = graph.add(new ReturnNode(result)); + graph.start().setNext(klassOop); + klassOop.setNext(ret); + return graph; + } + } else if (holderName.equals("Ljava/lang/Class;")) { + if (fullName.equals("getModifiers()I")) { + StructuredGraph graph = new StructuredGraph(); + LocalNode receiver = graph.unique(new LocalNode(0, StampFactory.objectNonNull())); + SafeReadNode klassOop = safeRead(graph, Kind.Object, receiver, config.klassOopOffset, StampFactory.objectNonNull(), StructuredGraph.INVALID_GRAPH_ID); + graph.start().setNext(klassOop); + // TODO(thomaswue): Care about primitive classes! Crashes for primitive classes at the moment (klassOop == null) + FloatingReadNode result = graph.unique(new FloatingReadNode(klassOop, LocationNode.create(LocationNode.FINAL_LOCATION, Kind.Int, config.klassModifierFlagsOffset, graph), null, StampFactory.intValue())); + ReturnNode ret = graph.add(new ReturnNode(result)); + klassOop.setNext(ret); + return graph; + } + } else if (holderName.equals("Ljava/lang/Thread;")) { + if (fullName.equals("currentThread()Ljava/lang/Thread;")) { + StructuredGraph graph = new StructuredGraph(); + ReturnNode ret = graph.add(new ReturnNode(graph.unique(new CurrentThread(config.threadObjectOffset, this)))); + graph.start().setNext(ret); + return graph; + } + } + return null; + } + + private SafeReadNode safeReadHub(Graph graph, ValueNode value, long leafGraphId) { + return safeRead(graph, Kind.Object, value, config.hubOffset, StampFactory.objectNonNull(), leafGraphId); + } + + private static SafeReadNode safeRead(Graph graph, Kind kind, ValueNode value, int offset, Stamp stamp, long leafGraphId) { + return graph.add(new SafeReadNode(value, LocationNode.create(LocationNode.FINAL_LOCATION, kind, offset, graph), stamp, leafGraphId)); + } + + public ResolvedJavaType getResolvedJavaType(Class clazz) { + return (ResolvedJavaType) compiler.getCompilerToVM().getType(clazz); + } + + public Object asCallTarget(Object target) { + return target; + } + + public long getMaxCallTargetOffset(RuntimeCall rtcall) { + return compiler.getCompilerToVM().getMaxCallTargetOffset(rtcall); + } + + public ResolvedJavaMethod getResolvedJavaMethod(Method reflectionMethod) { + return (ResolvedJavaMethod) compiler.getCompilerToVM().getRiMethod(reflectionMethod); + } + + private static HotSpotCodeInfo makeInfo(ResolvedJavaMethod method, CompilationResult code, CodeInfo[] info) { + HotSpotCodeInfo hsInfo = null; + if (info != null && info.length > 0) { + hsInfo = new HotSpotCodeInfo(code, (HotSpotMethodResolved) method); + info[0] = hsInfo; + } + return hsInfo; + } + + public void installMethod(ResolvedJavaMethod method, CompilationResult code, CodeInfo[] info) { + HotSpotCodeInfo hsInfo = makeInfo(method, code, info); + compiler.getCompilerToVM().installMethod(new HotSpotTargetMethod((HotSpotMethodResolved) method, code), true, hsInfo); + } + + @Override + public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult code, CodeInfo[] info) { + HotSpotCodeInfo hsInfo = makeInfo(method, code, info); + return compiler.getCompilerToVM().installMethod(new HotSpotTargetMethod((HotSpotMethodResolved) method, code), false, hsInfo); + } + + @Override + public RegisterConfig getGlobalStubRegisterConfig() { + return globalStubRegConfig; + } + + @Override + public CompilationResult compile(ResolvedJavaMethod method, StructuredGraph graph) { + OptimisticOptimizations optimisticOpts = OptimisticOptimizations.ALL; + return compiler.getCompiler().compileMethod(method, graph, -1, compiler.getCache(), compiler.getVMToCompiler().createPhasePlan(optimisticOpts), optimisticOpts); + } + + @Override + public int encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason) { + final int actionShift = 0; + final int reasonShift = 3; + + int actionValue = convertDeoptAction(action); + int reasonValue = convertDeoptReason(reason); + return (~(((reasonValue) << reasonShift) + ((actionValue) << actionShift))); + } + + @Override + public int convertDeoptAction(DeoptimizationAction action) { + switch(action) { + case None: return 0; + case RecompileIfTooManyDeopts: return 1; + case InvalidateReprofile: return 2; + case InvalidateRecompile: return 3; + case InvalidateStopCompiling: return 4; + default: throw GraalInternalError.shouldNotReachHere(); + } + } + + @Override + public int convertDeoptReason(DeoptimizationReason reason) { + switch(reason) { + case None: return 0; + case NullCheckException: return 1; + case BoundsCheckException: return 2; + case ClassCastException: return 3; + case ArrayStoreException: return 4; + case UnreachedCode: return 5; + case TypeCheckedInliningViolated: return 6; + case OptimizedTypeCheckViolated: return 7; + case NotCompiledExceptionHandler: return 8; + case Unresolved: return 9; + case JavaSubroutineMismatch: return 10; + case ArithmeticException: return 11; + case RuntimeConstraint: return 12; + default: throw GraalInternalError.shouldNotReachHere(); + } + } +} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSignature.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSignature.java Sat Jun 09 20:32:31 2012 +0200 @@ -0,0 +1,149 @@ +/* + * 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.hotspot.meta; + +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.java.*; + +/** + * Represents a method signature. + */ +public class HotSpotSignature extends CompilerObject implements Signature { + + private static final long serialVersionUID = -2890917956072366116L; + private final List arguments = new ArrayList<>(); + private final String returnType; + private final String originalString; + private JavaType[] argumentTypes; + private JavaType returnTypeCache; + + public HotSpotSignature(String signature) { + assert signature.length() > 0; + this.originalString = signature; + + if (signature.charAt(0) == '(') { + int cur = 1; + while (cur < signature.length() && signature.charAt(cur) != ')') { + int nextCur = parseSignature(signature, cur); + arguments.add(signature.substring(cur, nextCur)); + cur = nextCur; + } + + cur++; + int nextCur = parseSignature(signature, cur); + returnType = signature.substring(cur, nextCur); + assert nextCur == signature.length(); + } else { + returnType = null; + } + } + + private static int parseSignature(String signature, int start) { + int cur = start; + char first; + do { + first = signature.charAt(cur++); + } while (first == '['); + + switch (first) { + case 'L': + while (signature.charAt(cur) != ';') { + cur++; + } + cur++; + break; + case 'V': + case 'I': + case 'B': + case 'C': + case 'D': + case 'F': + case 'J': + case 'S': + case 'Z': + break; + default: + assert false; + } + return cur; + } + + @Override + public int argumentCount(boolean withReceiver) { + return arguments.size() + (withReceiver ? 1 : 0); + } + + @Override + public Kind argumentKindAt(int index) { + return Kind.fromTypeString(arguments.get(index)); + } + + @Override + public int argumentSlots(boolean withReceiver) { + int argSlots = 0; + for (int i = 0; i < argumentCount(false); i++) { + argSlots += FrameStateBuilder.stackSlots(argumentKindAt(i)); + } + return argSlots + (withReceiver ? 1 : 0); + } + + @Override + public JavaType argumentTypeAt(int index, ResolvedJavaType accessingClass) { + if (argumentTypes == null) { + argumentTypes = new JavaType[arguments.size()]; + } + JavaType type = argumentTypes[index]; + if (type == null || !(type instanceof ResolvedJavaType)) { + type = HotSpotGraalRuntime.getInstance().lookupType(arguments.get(index), (HotSpotTypeResolved) accessingClass, true); + argumentTypes[index] = type; + } + return type; + } + + @Override + public String asString() { + return originalString; + } + + @Override + public Kind returnKind() { + return Kind.fromTypeString(returnType); + } + + @Override + public JavaType returnType(JavaType accessingClass) { + if (returnTypeCache == null) { + returnTypeCache = HotSpotGraalRuntime.getInstance().lookupType(returnType, (HotSpotTypeResolved) accessingClass, false); + } + return returnTypeCache; + } + + @Override + public String toString() { + return "HotSpotSignature<" + originalString + ">"; + } + +} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotType.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotType.java Sat Jun 09 20:32:31 2012 +0200 @@ -0,0 +1,45 @@ +/* + * 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.hotspot.meta; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.*; + +/** + * Common interface for all HotSpot RiType-implementations. + */ +public abstract class HotSpotType extends CompilerObject implements JavaType { + private static final long serialVersionUID = -4252886265301910771L; + protected String name; + + @Override + public final String name() { + return name; + } + + /** + * Gets the object representing the C++ klassOop for this type. + * Such a value cannot be safely exposed to Java code. + */ + public abstract HotSpotKlassOop klassOop(); +} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotTypePrimitive.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotTypePrimitive.java Sat Jun 09 20:32:31 2012 +0200 @@ -0,0 +1,177 @@ +/* + * 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.hotspot.meta; + +import java.lang.annotation.*; +import java.lang.reflect.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.*; + +/** + * Implementation of RiType for primitive HotSpot types. + */ +public final class HotSpotTypePrimitive extends HotSpotType implements ResolvedJavaType { + + private static final long serialVersionUID = -6208552348908071473L; + private Kind kind; + private final HotSpotKlassOop klassOop; + + public HotSpotTypePrimitive(Kind kind) { + this.kind = kind; + this.name = String.valueOf(Character.toUpperCase(kind.typeChar)); + this.klassOop = new HotSpotKlassOop(kind.toJavaClass()); + } + + @Override + public int accessFlags() { + assert kind != null && kind.toJavaClass() != null; + return Modifier.ABSTRACT | Modifier.FINAL | Modifier.PUBLIC; + } + + @Override + public ResolvedJavaType arrayOf() { + return (ResolvedJavaType) HotSpotGraalRuntime.getInstance().getCompilerToVM().getPrimitiveArrayType(kind); + } + + @Override + public ResolvedJavaType componentType() { + return null; + } + + @Override + public ResolvedJavaType exactType() { + return this; + } + + @Override + public ResolvedJavaType superType() { + return null; + } + + @Override + public ResolvedJavaType leastCommonAncestor(ResolvedJavaType otherType) { + return null; + } + + @Override + public Constant getEncoding(Representation r) { + throw GraalInternalError.unimplemented("HotSpotTypePrimitive.getEncoding"); + } + + @Override + public Kind getRepresentationKind(Representation r) { + return kind; + } + + @Override + public boolean hasFinalizableSubclass() { + return false; + } + + @Override + public boolean hasFinalizer() { + return false; + } + + @Override + public boolean isArrayClass() { + return false; + } + + @Override + public boolean isInitialized() { + return true; + } + + @Override + public boolean isInstance(Constant obj) { + return false; + } + + @Override + public boolean isInstanceClass() { + return false; + } + + @Override + public boolean isInterface() { + return false; + } + + @Override + public boolean isSubtypeOf(ResolvedJavaType other) { + return false; + } + + @Override + public Kind kind() { + return kind; + } + + @Override + public ResolvedJavaMethod resolveMethodImpl(ResolvedJavaMethod method) { + return null; + } + + @Override + public String toString() { + return "HotSpotTypePrimitive<" + kind + ">"; + } + + @Override + public ResolvedJavaType uniqueConcreteSubtype() { + return this; + } + + @Override + public ResolvedJavaMethod uniqueConcreteMethod(ResolvedJavaMethod method) { + return null; + } + + @Override + public ResolvedJavaField[] declaredFields() { + return null; + } + + @Override + public T getAnnotation(Class annotationClass) { + return toJava().getAnnotation(annotationClass); + } + + @Override + public Class< ? > toJava() { + return kind.toJavaClass(); + } + + @Override + public ResolvedJavaType resolve(ResolvedJavaType accessingClass) { + return this; + } + + @Override + public HotSpotKlassOop klassOop() { + return klassOop; + } +} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotTypeResolved.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotTypeResolved.java Sat Jun 09 20:32:31 2012 +0200 @@ -0,0 +1,38 @@ +/* + * 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.hotspot.meta; + +import com.oracle.graal.api.meta.*; + +public interface HotSpotTypeResolved extends ResolvedJavaType { + + String toString(); + + ConstantPool constantPool(); + + int instanceSize(); + + JavaField createRiField(String name, JavaType type, int offset, int flags); + + HotSpotKlassOop klassOop(); +} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotTypeResolvedImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotTypeResolvedImpl.java Sat Jun 09 20:32:31 2012 +0200 @@ -0,0 +1,281 @@ +/* + * 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.hotspot.meta; + +import java.lang.annotation.*; +import java.lang.reflect.*; +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.*; + +/** + * Implementation of RiType for resolved non-primitive HotSpot classes. + */ +public final class HotSpotTypeResolvedImpl extends HotSpotType implements HotSpotTypeResolved { + + private static final long serialVersionUID = 3481514353553840471L; + + private Class javaMirror; + private String simpleName; + private int accessFlags; + private boolean hasFinalizer; + private boolean hasFinalizableSubclass; + private int superCheckOffset; + private boolean isArrayClass; + private boolean isInstanceClass; + private boolean isInterface; + private int instanceSize; + private HashMap fieldCache; + private ResolvedJavaType superType; + private boolean superTypeSet; + private ResolvedJavaField[] fields; + private ConstantPool constantPool; + private boolean isInitialized; + private ResolvedJavaType arrayOfType; + + private HotSpotTypeResolvedImpl() { + } + + @Override + public int accessFlags() { + return accessFlags; + } + + @Override + public ResolvedJavaType arrayOf() { + if (arrayOfType == null) { + arrayOfType = (ResolvedJavaType) HotSpotGraalRuntime.getInstance().getCompilerToVM().RiType_arrayOf(this); + } + return arrayOfType; + } + + @Override + public ResolvedJavaType componentType() { + assert isArrayClass(); + return (ResolvedJavaType) HotSpotGraalRuntime.getInstance().getCompilerToVM().RiType_componentType(this); + } + + @Override + public ResolvedJavaType uniqueConcreteSubtype() { + if (isArrayClass()) { + return Modifier.isFinal(componentType().accessFlags()) ? this : null; + } else { + return (ResolvedJavaType) HotSpotGraalRuntime.getInstance().getCompilerToVM().RiType_uniqueConcreteSubtype(this); + } + } + + @Override + public ResolvedJavaType superType() { + if (!superTypeSet) { + superType = (ResolvedJavaType) HotSpotGraalRuntime.getInstance().getCompilerToVM().RiType_superType(this); + superTypeSet = true; + } + return superType; + } + + @Override + public ResolvedJavaType leastCommonAncestor(ResolvedJavaType otherType) { + if (otherType instanceof HotSpotTypePrimitive) { + return null; + } else { + return (ResolvedJavaType) HotSpotGraalRuntime.getInstance().getCompilerToVM().RiType_leastCommonAncestor(this, (HotSpotTypeResolved) otherType); + } + } + + @Override + public ResolvedJavaType exactType() { + if (Modifier.isFinal(accessFlags)) { + return this; + } + return null; + } + + @Override + public Constant getEncoding(Representation r) { + switch (r) { + case JavaClass: + return Constant.forObject(javaMirror); + case ObjectHub: + return Constant.forObject(klassOop()); + case StaticFields: + return Constant.forObject(javaMirror); + default: + return null; + } + } + + @Override + public Kind getRepresentationKind(Representation r) { + return Kind.Object; + } + + @Override + public boolean hasFinalizableSubclass() { + return hasFinalizableSubclass; + } + + @Override + public boolean hasFinalizer() { + return hasFinalizer; + } + + @Override + public boolean isArrayClass() { + return isArrayClass; + } + + @Override + public boolean isInitialized() { + if (!isInitialized) { + isInitialized = HotSpotGraalRuntime.getInstance().getCompilerToVM().RiType_isInitialized(this); + } + return isInitialized; + } + + @Override + public boolean isInstance(Constant obj) { + return javaMirror.isInstance(obj); + } + + @Override + public boolean isInstanceClass() { + return isInstanceClass; + } + + @Override + public boolean isInterface() { + return isInterface; + } + + @Override + public boolean isSubtypeOf(ResolvedJavaType other) { + if (other instanceof HotSpotTypeResolved) { + return HotSpotGraalRuntime.getInstance().getCompilerToVM().RiType_isSubtypeOf(this, other); + } + // No resolved type is a subtype of an unresolved type. + return false; + } + + @Override + public Kind kind() { + return Kind.Object; + } + + @Override + public ResolvedJavaMethod resolveMethodImpl(ResolvedJavaMethod method) { + assert method instanceof HotSpotMethod; + return (ResolvedJavaMethod) HotSpotGraalRuntime.getInstance().getCompilerToVM().RiType_resolveMethodImpl(this, method.name(), method.signature().asString()); + } + + @Override + public String toString() { + return "HotSpotType<" + simpleName + ", resolved>"; + } + + @Override + public ConstantPool constantPool() { + if (constantPool == null) { + constantPool = new HotSpotConstantPool(this); + } + return constantPool; + } + + @Override + public int instanceSize() { + return instanceSize; + } + + @Override + public synchronized ResolvedJavaField createRiField(String fieldName, JavaType type, int offset, int flags) { + ResolvedJavaField result = null; + + long id = offset + ((long) flags << 32); + + // (thomaswue) Must cache the fields, because the local load elimination only works if the objects from two field lookups are identical. + if (fieldCache == null) { + fieldCache = new HashMap<>(8); + } else { + result = fieldCache.get(id); + } + + if (result == null) { + result = new HotSpotField(this, fieldName, type, offset, flags); + fieldCache.put(id, result); + } else { + assert result.name().equals(fieldName); + assert result.accessFlags() == flags; + } + + return result; + } + + @Override + public ResolvedJavaMethod uniqueConcreteMethod(ResolvedJavaMethod method) { + return ((HotSpotMethodResolved) method).uniqueConcreteMethod(); + } + + @Override + public ResolvedJavaField[] declaredFields() { + if (fields == null) { + fields = HotSpotGraalRuntime.getInstance().getCompilerToVM().RiType_fields(this); + } + return fields; + } + + @Override + public Class< ? > toJava() { + return javaMirror; + } + + @Override + public T getAnnotation(Class annotationClass) { + return toJava().getAnnotation(annotationClass); + } + + @Override + public ResolvedJavaType resolve(ResolvedJavaType accessingClass) { + return this; + } + + // this value may require identity semantics so cache it + private HotSpotKlassOop klassOopCache; + + @Override + public synchronized HotSpotKlassOop klassOop() { + if (klassOopCache == null) { + klassOopCache = new HotSpotKlassOop(javaMirror); + } + return klassOopCache; + } + + private static final int SECONDARY_SUPER_CACHE_OFFSET = HotSpotGraalRuntime.getInstance().getConfig().secondarySuperCacheOffset; + + public boolean isPrimaryType() { + return SECONDARY_SUPER_CACHE_OFFSET != superCheckOffset; + } + + public int superCheckOffset() { + return superCheckOffset; + } +} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotTypeUnresolved.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotTypeUnresolved.java Sat Jun 09 20:32:31 2012 +0200 @@ -0,0 +1,125 @@ +/* + * 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.hotspot.meta; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.*; + +/** + * Implementation of RiType for unresolved HotSpot classes. + */ +public class HotSpotTypeUnresolved extends HotSpotType { + + private static final long serialVersionUID = -2320936267633521314L; + public final String simpleName; + public final int dimensions; + + /** + * Creates a new unresolved type for a specified type descriptor. + */ + public HotSpotTypeUnresolved(String name) { + assert name.length() > 0 : "name cannot be empty"; + + int dims = 0; + int startIndex = 0; + while (name.charAt(startIndex) == '[') { + startIndex++; + dims++; + } + + // Decode name if necessary. + if (name.charAt(name.length() - 1) == ';') { + assert name.charAt(startIndex) == 'L'; + this.simpleName = name.substring(startIndex + 1, name.length() - 1); + this.name = name; + } else { + this.simpleName = name; + this.name = getFullName(name, dims); + } + + this.dimensions = dims; + } + + public HotSpotTypeUnresolved(String name, int dimensions) { + assert dimensions >= 0; + this.simpleName = name; + this.dimensions = dimensions; + this.name = getFullName(name, dimensions); + } + + private static String getFullName(String name, int dimensions) { + StringBuilder str = new StringBuilder(name.length() + dimensions + 2); + for (int i = 0; i < dimensions; i++) { + str.append('['); + } + str.append('L').append(name).append(';'); + return str.toString(); + } + + @Override + public JavaType componentType() { + assert dimensions > 0 : "no array class" + name(); + return new HotSpotTypeUnresolved(simpleName, dimensions - 1); + } + + @Override + public JavaType arrayOf() { + return new HotSpotTypeUnresolved(simpleName, dimensions + 1); + } + + @Override + public Kind kind() { + return Kind.Object; + } + + @Override + public int hashCode() { + return simpleName.hashCode(); + } + + @Override + public boolean equals(Object o) { + return o == this; + } + + @Override + public String toString() { + return "HotSpotType<" + simpleName + ", unresolved>"; + } + + @Override + public Kind getRepresentationKind(JavaType.Representation r) { + return Kind.Object; + } + + @Override + public ResolvedJavaType resolve(ResolvedJavaType accessingClass) { + return (ResolvedJavaType) HotSpotGraalRuntime.getInstance().lookupType(name, (HotSpotTypeResolved) accessingClass, true); + } + + @Override + public HotSpotKlassOop klassOop() { + throw GraalInternalError.shouldNotReachHere("HotSpotTypeUnresolved.klassOop"); + } +} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotXirGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotXirGenerator.java Sat Jun 09 20:32:31 2012 +0200 @@ -0,0 +1,1049 @@ +/* + * Copyright (c) 2011, 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.meta; + +import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.hotspot.meta.TemplateFlag.*; + +import java.io.*; +import java.util.*; +import java.util.concurrent.*; + +import sun.misc.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.Address.*; +import com.oracle.graal.api.code.Register.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.*; +import com.oracle.graal.hotspot.*; +import com.oracle.max.asm.target.amd64.*; +import com.oracle.max.cri.xir.*; +import com.oracle.max.cri.xir.CiXirAssembler.XirConstant; +import com.oracle.max.cri.xir.CiXirAssembler.XirLabel; +import com.oracle.max.cri.xir.CiXirAssembler.XirMark; +import com.oracle.max.cri.xir.CiXirAssembler.XirOperand; +import com.oracle.max.cri.xir.CiXirAssembler.XirParameter; +import com.oracle.max.criutils.*; + +public class HotSpotXirGenerator implements RiXirGenerator { + + // this needs to correspond to graal_CodeInstaller.hpp + // @formatter:off + public static final Integer MARK_VERIFIED_ENTRY = 0x0001; + public static final Integer MARK_UNVERIFIED_ENTRY = 0x0002; + public static final Integer MARK_OSR_ENTRY = 0x0003; + public static final Integer MARK_UNWIND_ENTRY = 0x0004; + public static final Integer MARK_EXCEPTION_HANDLER_ENTRY = 0x0005; + public static final Integer MARK_DEOPT_HANDLER_ENTRY = 0x0006; + + public static final Integer MARK_STATIC_CALL_STUB = 0x1000; + + public static final Integer MARK_INVOKEINTERFACE = 0x2001; + public static final Integer MARK_INVOKESTATIC = 0x2002; + public static final Integer MARK_INVOKESPECIAL = 0x2003; + public static final Integer MARK_INVOKEVIRTUAL = 0x2004; + + public static final Integer MARK_IMPLICIT_NULL = 0x3000; + public static final Integer MARK_POLL_NEAR = 0x3001; + public static final Integer MARK_POLL_RETURN_NEAR = 0x3002; + public static final Integer MARK_POLL_FAR = 0x3003; + public static final Integer MARK_POLL_RETURN_FAR = 0x3004; + + // @formatter:on + + private final HotSpotVMConfig config; + private final TargetDescription target; + private final RegisterConfig registerConfig; + private final HotSpotGraalRuntime compiler; + + + private CiXirAssembler globalAsm; + + public HotSpotXirGenerator(HotSpotVMConfig config, TargetDescription target, RegisterConfig registerConfig, HotSpotGraalRuntime compiler) { + this.config = config; + this.target = target; + this.registerConfig = registerConfig; + this.compiler = compiler; + } + + private XirConstant wordConst(CiXirAssembler asm, long value) { + if (target.wordKind == Kind.Long) { + return asm.createConstant(Constant.forLong(value)); + } else { + assert target.wordKind == Kind.Int; + return asm.createConstant(Constant.forInt((int) value)); + } + } + + private XirArgument wordArg(long value) { + if (target.wordKind == Kind.Long) { + return XirArgument.forLong(value); + } else { + assert target.wordKind == Kind.Int; + return XirArgument.forInt((int) value); + } + } + + private SimpleTemplates invokeInterfaceTemplates = new SimpleTemplates(NULL_CHECK) { + + @Override + protected XirTemplate create(CiXirAssembler asm, long flags) { + asm.restart(); + XirParameter receiver = asm.createInputParameter("receiver", Kind.Object); + XirParameter addr = asm.createConstantInputParameter("addr", target.wordKind); + XirOperand temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.rax); + XirOperand tempO = asm.createRegister("tempO", Kind.Object, AMD64.rax); + + if (is(NULL_CHECK, flags)) { + asm.mark(MARK_IMPLICIT_NULL); + asm.pload(target.wordKind, temp, receiver, true); + } + asm.mark(MARK_INVOKEINTERFACE); + asm.mov(tempO, asm.createConstant(Constant.forObject(HotSpotProxy.DUMMY_CONSTANT_OBJ))); + + return asm.finishTemplate(addr, "invokeinterface"); + } + }; + + private SimpleTemplates invokeVirtualTemplates = new SimpleTemplates(NULL_CHECK) { + + @Override + protected XirTemplate create(CiXirAssembler asm, long flags) { + asm.restart(); + XirParameter receiver = asm.createInputParameter("receiver", Kind.Object); + XirParameter addr = asm.createConstantInputParameter("addr", target.wordKind); + XirOperand temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.rax); + XirOperand tempO = asm.createRegister("tempO", Kind.Object, AMD64.rax); + + if (is(NULL_CHECK, flags)) { + asm.mark(MARK_IMPLICIT_NULL); + asm.pload(target.wordKind, temp, receiver, true); + } + asm.mark(MARK_INVOKEVIRTUAL); + asm.mov(tempO, asm.createConstant(Constant.forObject(HotSpotProxy.DUMMY_CONSTANT_OBJ))); + + return asm.finishTemplate(addr, "invokevirtual"); + } + }; + + private IndexTemplates inlinedInvokeVirtualTemplates = new IndexTemplates(NULL_CHECK) { + + @Override + protected XirTemplate create(CiXirAssembler asm, long flags, int vtableEntryOffset) { + asm.restart(); + XirParameter receiver = asm.createInputParameter("receiver", Kind.Object); + XirOperand temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.rax); + XirOperand method = asm.createRegisterTemp("method", Kind.Object, AMD64.rbx); + + // load class from receiver + if (is(NULL_CHECK, flags)) { + asm.mark(MARK_IMPLICIT_NULL); + } + asm.pload(target.wordKind, temp, receiver, asm.i(config.hubOffset), true); + // load vtable entry + asm.pload(target.wordKind, method, temp, asm.i(vtableEntryOffset), false); + // load entry point from methodOop + asm.mark(MARK_IMPLICIT_NULL); + asm.pload(target.wordKind, temp, method, asm.i(config.methodCompiledEntryOffset), true); + asm.mark(MARK_INVOKEVIRTUAL); + + return asm.finishTemplate(temp, "invokevirtual"); + } + }; + + private SimpleTemplates invokeSpecialTemplates = new SimpleTemplates(NULL_CHECK) { + + @Override + protected XirTemplate create(CiXirAssembler asm, long flags) { + asm.restart(); + XirParameter receiver = asm.createInputParameter("receiver", Kind.Object); + XirParameter addr = asm.createConstantInputParameter("addr", target.wordKind); + XirOperand temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.rax); + XirLabel stub = asm.createOutOfLineLabel("call stub"); + + if (is(NULL_CHECK, flags)) { + asm.mark(MARK_IMPLICIT_NULL); + asm.pload(target.wordKind, temp, receiver, true); + } + asm.mark(MARK_INVOKESPECIAL); + + // -- out of line ------------------------------------------------------- + asm.bindOutOfLine(stub); + XirOperand method = asm.createRegisterTemp("method", target.wordKind, AMD64.rbx); + asm.mark(MARK_STATIC_CALL_STUB, XirMark.CALLSITE); + asm.mov(method, wordConst(asm, 0)); + XirLabel dummy = asm.createOutOfLineLabel("dummy"); + asm.jmp(dummy); + asm.bindOutOfLine(dummy); + + return asm.finishTemplate(addr, "invokespecial"); + } + }; + + private SimpleTemplates invokeStaticTemplates = new SimpleTemplates() { + + @Override + protected XirTemplate create(CiXirAssembler asm, long flags) { + asm.restart(); + XirParameter addr = asm.createConstantInputParameter("addr", target.wordKind); + + XirLabel stub = asm.createOutOfLineLabel("call stub"); + asm.mark(MARK_INVOKESTATIC); + + // -- out of line ------------------------------------------------------- + asm.bindOutOfLine(stub); + XirOperand method = asm.createRegisterTemp("method", target.wordKind, AMD64.rbx); + asm.mark(MARK_STATIC_CALL_STUB, XirMark.CALLSITE); + asm.mov(method, wordConst(asm, 0)); + XirLabel dummy = asm.createOutOfLineLabel("dummy"); + asm.jmp(dummy); + asm.bindOutOfLine(dummy); + + return asm.finishTemplate(addr, "invokestatic"); + } + }; + + private SimpleTemplates monitorEnterTemplates = new SimpleTemplates(NULL_CHECK) { + + @Override + protected XirTemplate create(CiXirAssembler asm, long flags) { + asm.restart(Kind.Void); + XirParameter object = asm.createInputParameter("object", Kind.Object); + XirParameter lock = asm.createInputParameter("lock", target.wordKind); + + if (is(NULL_CHECK, flags)) { + asm.mark(MARK_IMPLICIT_NULL); + asm.pload(target.wordKind, asm.createTemp("temp", target.wordKind), object, true); + } + + + // (thomaswue) It is important to use for this runtime call the debug info AFTER the monitor enter. Otherwise the monitor object + // is not correctly garbage collected. + final boolean useInfoAfter = true; + + if (config.useFastLocking) { + useRegisters(asm, AMD64.rax, AMD64.rbx); + useRegisters(asm, getGeneralParameterRegister(0)); + useRegisters(asm, getGeneralParameterRegister(1)); + asm.callRuntime(config.fastMonitorEnterStub, null, useInfoAfter, object, lock); + } else { + asm.reserveOutgoingStack(target.wordSize * 2); + XirOperand rsp = asm.createRegister("rsp", target.wordKind, asRegister(AMD64.RSP)); + asm.pstore(Kind.Object, rsp, asm.i(target.wordSize), object, false); + asm.pstore(target.wordKind, rsp, asm.i(0), lock, false); + asm.callRuntime(config.monitorEnterStub, null, useInfoAfter); + } + + return asm.finishTemplate("monitorEnter"); + } + }; + + private Register getGeneralParameterRegister(int index) { + return registerConfig.getCallingConventionRegisters(CallingConvention.Type.RuntimeCall, RegisterFlag.CPU)[index]; + } + + private SimpleTemplates monitorExitTemplates = new SimpleTemplates(NULL_CHECK) { + + @Override + protected XirTemplate create(CiXirAssembler asm, long flags) { + asm.restart(Kind.Void); + XirParameter object = asm.createInputParameter("object", Kind.Object); + XirParameter lock = asm.createInputParameter("lock", target.wordKind); + + if (config.useFastLocking) { + useRegisters(asm, AMD64.rax, AMD64.rbx); + useRegisters(asm, getGeneralParameterRegister(0)); + useRegisters(asm, getGeneralParameterRegister(1)); + asm.callRuntime(config.fastMonitorExitStub, null, object, lock); + } else { + asm.reserveOutgoingStack(target.wordSize); + asm.pstore(target.wordKind, asm.createRegister("rsp", target.wordKind, asRegister(AMD64.RSP)), asm.i(0), lock, false); + asm.callRuntime(config.monitorExitStub, null); + } + + return asm.finishTemplate("monitorExit"); + } + }; + + private final IndexTemplates newInstanceTemplates = new IndexTemplates() { + + @Override + protected XirTemplate create(CiXirAssembler asm, long flags, int size) { + XirOperand result = asm.restart(target.wordKind); + XirOperand hub = asm.createInputParameter("hub", Kind.Object); + + XirOperand temp1 = asm.createRegisterTemp("temp1", target.wordKind, AMD64.rcx); + XirOperand temp1o = asm.createRegister("temp1o", Kind.Object, AMD64.rcx); + XirOperand temp2 = asm.createRegisterTemp("temp2", target.wordKind, AMD64.rbx); + XirOperand temp2i = asm.createRegister("temp2i", Kind.Int, AMD64.rbx); + useRegisters(asm, AMD64.rsi); + XirLabel tlabFull = asm.createOutOfLineLabel("tlab full"); + XirLabel resume = asm.createInlineLabel("resume"); + + // check if the class is already initialized + asm.pload(Kind.Int, temp2i, hub, asm.i(config.klassStateOffset), false); + asm.jneq(tlabFull, temp2i, asm.i(config.klassStateFullyInitialized)); + + XirOperand thread = asm.createRegisterTemp("thread", target.wordKind, AMD64.r15); + asm.pload(target.wordKind, result, thread, asm.i(config.threadTlabTopOffset), false); + asm.add(temp1, result, wordConst(asm, size)); + asm.pload(target.wordKind, temp2, thread, asm.i(config.threadTlabEndOffset), false); + + asm.jgt(tlabFull, temp1, temp2); + asm.pstore(target.wordKind, thread, asm.i(config.threadTlabTopOffset), temp1, false); + + asm.bindInline(resume); + + asm.pload(target.wordKind, temp1, hub, asm.i(config.instanceHeaderPrototypeOffset), false); + asm.pstore(target.wordKind, result, temp1, false); + asm.mov(temp1o, hub); // need a temporary register since Intel cannot store 64-bit constants to memory + asm.pstore(Kind.Object, result, asm.i(config.hubOffset), temp1o, false); + + if (size > 2 * target.wordSize) { + asm.mov(temp1, wordConst(asm, 0)); + for (int offset = 2 * target.wordSize; offset < size; offset += target.wordSize) { + asm.pstore(target.wordKind, result, asm.i(offset), temp1, false); + } + } + + // -- out of line ------------------------------------------------------- + asm.bindOutOfLine(tlabFull); + XirOperand arg = asm.createRegisterTemp("runtime call argument", Kind.Object, AMD64.rdx); + asm.mov(arg, hub); + useRegisters(asm, AMD64.rax); + asm.callRuntime(config.newInstanceStub, result); + asm.jmp(resume); + + return asm.finishTemplate("new instance"); + } + }; + + private SimpleTemplates newObjectArrayTemplates = new SimpleTemplates() { + + @Override + protected XirTemplate create(CiXirAssembler asm, long flags) { + emitNewTypeArray(asm, Kind.Object, config.useFastNewObjectArray, config.newObjectArrayStub); + return asm.finishTemplate("newObjectArray"); + } + }; + + private void emitNewTypeArray(CiXirAssembler asm, Kind kind, boolean useFast, long slowPathStub) { + XirOperand result = asm.restart(target.wordKind); + + XirParameter lengthParam = asm.createInputParameter("length", Kind.Int, true); + + XirOperand length = asm.createRegisterTemp("length", Kind.Int, AMD64.rbx); + XirOperand hub = asm.createRegisterTemp("hub", Kind.Object, AMD64.rdx); + + // Registers rsi, rcx, rdi, and rax are needed by the runtime call. + // Hub needs to be on rdx, length on rbx. + XirOperand temp1 = asm.createRegisterTemp("temp1", target.wordKind, AMD64.rcx); + XirOperand temp1o = asm.createRegister("temp1o", Kind.Object, AMD64.rcx); + XirOperand temp2 = asm.createRegisterTemp("temp2", target.wordKind, AMD64.rax); + XirOperand temp3 = asm.createRegisterTemp("temp3", target.wordKind, AMD64.rdi); + XirOperand size = asm.createRegisterTemp("size", Kind.Int, AMD64.rsi); + + asm.mov(hub, asm.createConstantInputParameter("hub", Kind.Object)); + asm.mov(length, lengthParam); + + if (useFast) { + + XirLabel slowPath = asm.createOutOfLineLabel("slowPath"); + + XirLabel done = asm.createInlineLabel("done"); + + // Check for negative array size. + // TODO: Also check for upper bound + asm.jlt(slowPath, length, asm.i(0)); + + final int aligning = target.wordSize; + final int arrayLengthOffset = target.wordSize * 2; + final int arrayElementOffset = config.getArrayOffset(kind); + + // Calculate aligned size + asm.mov(size, length); + int scale = CodeUtil.log2(target.sizeInBytes(kind)); + if (scale != 0) { + asm.shl(size, size, asm.i(scale)); + } + asm.add(size, size, asm.i(arrayElementOffset + aligning - 1)); + long mask = 0xFFFFFFFFL; + mask <<= CodeUtil.log2(aligning); + asm.and(size, size, asm.i((int) mask)); + + // Try tlab allocation + XirOperand thread = asm.createRegisterTemp("thread", target.wordKind, AMD64.r15); + asm.pload(target.wordKind, result, thread, asm.i(config.threadTlabTopOffset), false); + asm.add(temp1, result, size); + asm.pload(target.wordKind, temp2, thread, asm.i(config.threadTlabEndOffset), false); + asm.jgt(slowPath, temp1, temp2); + asm.pstore(target.wordKind, thread, asm.i(config.threadTlabTopOffset), temp1, false); + + // Now the new object is in result, store mark word and klass + asm.pload(target.wordKind, temp1, hub, asm.i(config.instanceHeaderPrototypeOffset), false); + asm.pstore(target.wordKind, result, temp1, false); + asm.mov(temp1o, hub); // need a temporary register since Intel cannot store 64-bit constants to memory + asm.pstore(Kind.Object, result, asm.i(config.hubOffset), temp1o, false); + + // Store array length + asm.pstore(Kind.Int, result, asm.i(arrayLengthOffset), length, false); + + // Initialize with 0 + XirLabel top = asm.createInlineLabel("top"); + asm.sub(size, size, asm.i(arrayElementOffset)); + asm.shr(size, size, asm.i(Scale.Times8.log2)); + asm.jeq(done, size, asm.i(0)); + asm.xor(temp3, temp3, temp3); + asm.bindInline(top); + asm.pstore(target.wordKind, result, size, temp3, arrayElementOffset - target.wordSize, Scale.Times8, false); + asm.decAndJumpNotZero(top, size); + + asm.bindInline(done); + + // Slow path + asm.bindOutOfLine(slowPath); + asm.callRuntime(slowPathStub, result); + asm.jmp(done); + } else { + asm.callRuntime(slowPathStub, result); + } + } + + private KindTemplates newTypeArrayTemplates = new KindTemplates() { + @Override + protected XirTemplate create(CiXirAssembler asm, long flags, Kind kind) { + emitNewTypeArray(asm, kind, config.useFastNewTypeArray, config.newTypeArrayStub); + return asm.finishTemplate("newTypeArray<" + kind.toString() + ">"); + } + }; + + private final IndexTemplates multiNewArrayTemplate = new IndexTemplates() { + + @Override + protected XirTemplate create(CiXirAssembler asm, long flags, int dimensions) { + XirOperand result = asm.restart(Kind.Object); + + XirOperand hub = asm.createRegisterTemp("hub", Kind.Object, AMD64.rax); + XirOperand rank = asm.createRegisterTemp("rank", Kind.Int, AMD64.rbx); + XirOperand sizes = asm.createRegisterTemp("sizes", Kind.Long, AMD64.rcx); + XirOperand thread = asm.createRegisterTemp("thread", Kind.Long, AMD64.r15); + asm.add(sizes, thread, asm.l(config.threadMultiNewArrayStorage)); + for (int i = 0; i < dimensions; i++) { + XirParameter length = asm.createInputParameter("length" + i, Kind.Int, true); + asm.pstore(Kind.Int, sizes, asm.i(i * target.sizeInBytes(Kind.Int)), length, false); + } + + asm.mov(hub, asm.createConstantInputParameter("hub", Kind.Object)); + + asm.mov(rank, asm.i(dimensions)); + // not necessary because we already have a temp in rax: useRegisters(asm, AMD64.rax); + asm.callRuntime(config.newMultiArrayStub, result); + return asm.finishTemplate("multiNewArray" + dimensions); + } + }; + + enum CheckcastCounter { + hintsHit("hit a hint type"), + hintsMissed("missed the hint types"), + exact("tested type is (statically) final"), + noHints_class("profile information is not used (test type is a class)"), + noHints_iface("profile information is not used (test type is an interface)"), + noHints_unknown("test type is not a compile-time constant"), + isNull("object tested is null"), + exception("type test failed with a ClassCastException"); + + public final String desc; + + private CheckcastCounter(String desc) { + this.desc = desc; + } + + static final CheckcastCounter[] VALUES = values(); + } + + private static final long[] checkcastCounters = new long[CheckcastCounter.VALUES.length]; + + private IndexTemplates checkCastTemplates = new IndexTemplates(NULL_CHECK, EXACT_HINTS) { + + private void incCounter(CiXirAssembler asm, XirOperand counter, XirParameter counters, CheckcastCounter offset) { + int disp = Unsafe.getUnsafe().arrayBaseOffset(long[].class); + Scale scale = Scale.fromInt(Unsafe.getUnsafe().arrayIndexScale(long[].class)); + XirConstant index = asm.i(offset.ordinal()); + asm.pload(Kind.Long, counter, counters, index, disp, scale, false); + asm.add(counter, counter, asm.i(1)); + asm.pstore(Kind.Long, counters, index, counter, disp, scale, false); + } + + @Override + protected XirTemplate create(CiXirAssembler asm, long flags, int hintCount) { + asm.restart(Kind.Void); + boolean exact = is(EXACT_HINTS, flags); + XirParameter counters = GraalOptions.CheckcastCounters ? asm.createConstantInputParameter("counters", Kind.Object) : null; + XirParameter object = asm.createInputParameter("object", Kind.Object); + final XirOperand hub = exact ? null : asm.createConstantInputParameter("hub", Kind.Object); + + XirOperand objHub = asm.createTemp("objHub", Kind.Object); + XirOperand counter = counters != null ? asm.createTemp("counter", Kind.Long) : null; + + XirLabel success = asm.createInlineLabel("success"); + XirLabel slowPath = asm.createOutOfLineLabel("slow path"); + + if (is(NULL_CHECK, flags)) { + // null can be cast to anything + if (counters != null) { + XirLabel isNotNull = asm.createInlineLabel("isNull"); + asm.jneq(isNotNull, object, asm.o(null)); + incCounter(asm, counter, counters, CheckcastCounter.isNull); + asm.jmp(success); + asm.bindInline(isNotNull); + } else { + asm.jeq(success, object, asm.o(null)); + } + + } + + asm.pload(Kind.Object, objHub, object, asm.i(config.hubOffset), false); + if (hintCount == 0) { + assert !exact; + if (counters != null) { + CheckcastCounter cc; + if (is(NULL_TYPE, flags)) { + cc = CheckcastCounter.noHints_unknown; + } else if (is(INTERFACE_TYPE, flags)) { + cc = CheckcastCounter.noHints_iface; + } else { + cc = CheckcastCounter.noHints_class; + } + incCounter(asm, counter, counters, cc); + } + + checkSubtype(asm, objHub, objHub, hub); + asm.jeq(slowPath, objHub, asm.o(null)); + asm.bindInline(success); + + // -- out of line ------------------------------------------------------- + asm.bindOutOfLine(slowPath); + } else { + XirLabel hintsSuccess = counters == null ? success : asm.createInlineLabel("hintsSuccess"); + XirOperand scratchObject = asm.createRegisterTemp("scratch", Kind.Object, AMD64.r10); + // if we get an exact match: succeed immediately + for (int i = 0; i < hintCount; i++) { + XirParameter hintHub = asm.createConstantInputParameter("hintHub" + i, Kind.Object); + asm.mov(scratchObject, hintHub); + if (i < hintCount - 1) { + asm.jeq(hintsSuccess, objHub, scratchObject); + } else { + asm.jneq(slowPath, objHub, scratchObject); + } + } + + if (counters != null) { + asm.bindInline(hintsSuccess); + incCounter(asm, counter, counters, exact ? CheckcastCounter.exact : CheckcastCounter.hintsHit); + } + + asm.bindInline(success); + + // -- out of line ------------------------------------------------------- + asm.bindOutOfLine(slowPath); + if (!exact) { + if (counters != null) { + incCounter(asm, counter, counters, CheckcastCounter.hintsMissed); + } + checkSubtype(asm, objHub, objHub, hub); + asm.jneq(success, objHub, asm.o(null)); + } + } + + if (counters != null) { + incCounter(asm, counter, counters, CheckcastCounter.exception); + } + DeoptimizationReason deoptReason = exact ? DeoptimizationReason.OptimizedTypeCheckViolated : DeoptimizationReason.ClassCastException; + XirOperand scratch = asm.createRegisterTemp("scratch", target.wordKind, AMD64.r10); + asm.mov(scratch, wordConst(asm, compiler.getRuntime().encodeDeoptActionAndReason(DeoptimizationAction.InvalidateReprofile, deoptReason))); + asm.callRuntime(RuntimeCall.Deoptimize, null); + asm.shouldNotReachHere(); + + return asm.finishTemplate("checkcast"); + } + }; + + private IndexTemplates instanceOfTemplates = new IndexTemplates(NULL_CHECK, EXACT_HINTS) { + + @Override + protected XirTemplate create(CiXirAssembler asm, long flags, int hintCount) { + asm.restart(Kind.Void); + XirParameter object = asm.createInputParameter("object", Kind.Object); + final XirOperand hub = is(EXACT_HINTS, flags) ? null : asm.createConstantInputParameter("hub", Kind.Object); + + XirOperand objHub = asm.createTemp("objHub", Kind.Object); + + XirLabel trueSucc = asm.createInlineLabel(XirLabel.TrueSuccessor); + XirLabel falseSucc = asm.createInlineLabel(XirLabel.FalseSuccessor); + + if (is(NULL_CHECK, flags)) { + // null isn't "instanceof" anything + asm.jeq(falseSucc, object, asm.o(null)); + } + + asm.pload(Kind.Object, objHub, object, asm.i(config.hubOffset), false); + if (hintCount == 0) { + assert !is(EXACT_HINTS, flags); + checkSubtype(asm, objHub, objHub, hub); + asm.jeq(falseSucc, objHub, asm.o(null)); + asm.jmp(trueSucc); + } else { + XirLabel slowPath = null; + XirOperand scratchObject = asm.createRegisterTemp("scratch", Kind.Object, AMD64.r10); + + // if we get an exact match: succeed immediately + for (int i = 0; i < hintCount; i++) { + XirParameter hintHub = asm.createConstantInputParameter("hintHub" + i, Kind.Object); + asm.mov(scratchObject, hintHub); + if (i < hintCount - 1) { + asm.jeq(trueSucc, objHub, scratchObject); + } else { + if (is(EXACT_HINTS, flags)) { + asm.jneq(falseSucc, objHub, scratchObject); + asm.jmp(trueSucc); + } else { + slowPath = asm.createOutOfLineLabel("slow path"); + asm.jneq(slowPath, objHub, scratchObject); + asm.jmp(trueSucc); + } + } + } + + // -- out of line ------------------------------------------------------- + if (slowPath != null) { + asm.bindOutOfLine(slowPath); + checkSubtype(asm, objHub, objHub, hub); + asm.jeq(falseSucc, objHub, asm.o(null)); + asm.jmp(trueSucc); + } + } + + return asm.finishTemplate("instanceof"); + } + }; + + private IndexTemplates materializeInstanceOfTemplates = new IndexTemplates(NULL_CHECK, EXACT_HINTS) { + + @Override + protected XirTemplate create(CiXirAssembler asm, long flags, int hintCount) { + XirOperand result = asm.restart(Kind.Int); + XirParameter object = asm.createInputParameter("object", Kind.Object); + final XirOperand hub = is(EXACT_HINTS, flags) ? null : asm.createConstantInputParameter("hub", Kind.Object); + XirOperand trueValue = asm.createInputParameter("trueValue", Kind.Int); + XirOperand falseValue = asm.createInputParameter("falseValue", Kind.Int); + + XirOperand objHub = asm.createTemp("objHub", Kind.Object); + + XirLabel end = asm.createInlineLabel("end"); + XirLabel falseSucc = asm.createInlineLabel("ko"); + + if (is(NULL_CHECK, flags)) { + // null isn't "instanceof" anything + asm.jeq(falseSucc, object, asm.o(null)); + } + + asm.pload(Kind.Object, objHub, object, asm.i(config.hubOffset), false); + asm.mov(result, trueValue); + + if (hintCount == 0) { + assert !is(EXACT_HINTS, flags); + checkSubtype(asm, objHub, objHub, hub); + asm.jneq(end, objHub, asm.o(null)); + asm.bindInline(falseSucc); + asm.mov(result, falseValue); + asm.bindInline(end); + } else { + XirLabel slowPath = null; + XirOperand scratchObject = asm.createRegisterTemp("scratch", Kind.Object, AMD64.r10); + + // if we get an exact match: succeed immediately + for (int i = 0; i < hintCount; i++) { + XirParameter hintHub = asm.createConstantInputParameter("hintHub" + i, Kind.Object); + asm.mov(scratchObject, hintHub); + if (i < hintCount - 1) { + asm.jeq(end, objHub, scratchObject); + } else { + if (is(EXACT_HINTS, flags)) { + asm.jeq(end, objHub, scratchObject); + } else { + slowPath = asm.createOutOfLineLabel("slow path"); + asm.jeq(end, objHub, scratchObject); + asm.jmp(slowPath); + } + } + } + asm.bindInline(falseSucc); + asm.mov(result, falseValue); + asm.bindInline(end); + + // -- out of line ------------------------------------------------------- + if (slowPath != null) { + asm.bindOutOfLine(slowPath); + checkSubtype(asm, objHub, objHub, hub); + asm.jeq(falseSucc, objHub, asm.o(null)); + asm.jmp(end); + } + } + + return asm.finishTemplate("instanceof"); + } + }; + + private SimpleTemplates typeCheckTemplates = new SimpleTemplates(NULL_CHECK) { + @Override + protected XirTemplate create(CiXirAssembler asm, long flags) { + asm.restart(Kind.Void); + XirParameter objHub = asm.createInputParameter("objectHub", Kind.Object); + XirOperand hub = asm.createConstantInputParameter("hub", Kind.Object); + XirLabel falseSucc = asm.createInlineLabel(XirLabel.FalseSuccessor); + + XirOperand checkHub = asm.createTemp("checkHub", Kind.Object); + + if (is(NULL_CHECK, flags)) { + asm.mark(MARK_IMPLICIT_NULL); + } + + asm.mov(checkHub, hub); + // if we get an exact match: continue. + asm.jneq(falseSucc, objHub, checkHub); + + return asm.finishTemplate("typeCheck"); + } + }; + + @Override + public XirSnippet genInvokeInterface(XirSite site, XirArgument receiver, JavaMethod method) { + return new XirSnippet(invokeInterfaceTemplates.get(site), receiver, wordArg(0)); + } + + @Override + public XirSnippet genInvokeVirtual(XirSite site, XirArgument receiver, JavaMethod method, boolean megamorph) { + int vtableEntryOffset = 0; + + if (GraalOptions.InlineVTableStubs && (GraalOptions.AlwaysInlineVTableStubs || megamorph)) { + HotSpotMethodResolved hsMethod = (HotSpotMethodResolved) method; + if (!hsMethod.holder().isInterface()) { + vtableEntryOffset = hsMethod.vtableEntryOffset(); + } + } + if (vtableEntryOffset > 0) { + return new XirSnippet(inlinedInvokeVirtualTemplates.get(site, vtableEntryOffset), receiver); + } else { + return new XirSnippet(invokeVirtualTemplates.get(site), receiver, wordArg(0)); + } + } + + @Override + public XirSnippet genInvokeSpecial(XirSite site, XirArgument receiver, JavaMethod method) { + return new XirSnippet(invokeSpecialTemplates.get(site), receiver, wordArg(0)); + } + + @Override + public XirSnippet genInvokeStatic(XirSite site, JavaMethod method) { + return new XirSnippet(invokeStaticTemplates.get(site), wordArg(0)); + } + + @Override + public XirSnippet genMonitorEnter(XirSite site, XirArgument receiver, XirArgument lockAddress) { + return new XirSnippet(monitorEnterTemplates.get(site), receiver, lockAddress); + } + + @Override + public XirSnippet genMonitorExit(XirSite site, XirArgument receiver, XirArgument lockAddress) { + return new XirSnippet(monitorExitTemplates.get(site), receiver, lockAddress); + } + + @Override + public XirSnippet genNewInstance(XirSite site, JavaType type) { + HotSpotTypeResolved resolvedType = (HotSpotTypeResolved) type; + int instanceSize = resolvedType.instanceSize(); + return new XirSnippet(newInstanceTemplates.get(site, instanceSize), XirArgument.forObject(resolvedType.klassOop())); + } + + @Override + public XirSnippet genNewArray(XirSite site, XirArgument length, Kind elementKind, JavaType componentType, JavaType arrayType) { + if (elementKind == Kind.Object) { + assert arrayType instanceof ResolvedJavaType; + return new XirSnippet(newObjectArrayTemplates.get(site), length, XirArgument.forObject(((HotSpotType) arrayType).klassOop())); + } else { + assert arrayType == null; + JavaType primitiveArrayType = compiler.getCompilerToVM().getPrimitiveArrayType(elementKind); + return new XirSnippet(newTypeArrayTemplates.get(site, elementKind), length, XirArgument.forObject(((HotSpotType) primitiveArrayType).klassOop())); + } + } + + @Override + public XirSnippet genNewMultiArray(XirSite site, XirArgument[] lengths, JavaType type) { + XirArgument[] params = Arrays.copyOf(lengths, lengths.length + 1); + params[lengths.length] = XirArgument.forObject(((HotSpotType) type).klassOop()); + return new XirSnippet(multiNewArrayTemplate.get(site, lengths.length), params); + } + + @Override + public XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, ResolvedJavaType type, JavaTypeProfile profile) { + final boolean useCounters = GraalOptions.CheckcastCounters; + TypeCheckHints hints = new TypeCheckHints(type, profile, site.assumptions(), GraalOptions.CheckcastMinHintHitProbability, GraalOptions.CheckcastMaxHints); + int hintsLength = hints.types.length; + if (hintsLength == 0) { + if (useCounters) { + if (type == null) { + return new XirSnippet(checkCastTemplates.get(site, 0, NULL_TYPE), XirArgument.forObject(checkcastCounters), receiver, hub); + } else if (type.isInterface()) { + return new XirSnippet(checkCastTemplates.get(site, 0, INTERFACE_TYPE), XirArgument.forObject(checkcastCounters), receiver, hub); + } else { + return new XirSnippet(checkCastTemplates.get(site, 0), XirArgument.forObject(checkcastCounters), receiver, hub); + } + } else { + return new XirSnippet(checkCastTemplates.get(site, 0), receiver, hub); + } + } else { + XirArgument[] params = new XirArgument[(useCounters ? 1 : 0) + hintsLength + (hints.exact ? 1 : 2)]; + int i = 0; + if (useCounters) { + params[i++] = XirArgument.forObject(checkcastCounters); + } + params[i++] = receiver; + if (!hints.exact) { + params[i++] = hub; + } + for (ResolvedJavaType hint : hints.types) { + params[i++] = XirArgument.forObject(((HotSpotType) hint).klassOop()); + } + XirTemplate template = hints.exact ? checkCastTemplates.get(site, hintsLength, EXACT_HINTS) : checkCastTemplates.get(site, hintsLength); + return new XirSnippet(template, params); + } + } + + @Override + public XirSnippet genInstanceOf(XirSite site, XirArgument object, XirArgument hub, ResolvedJavaType type, JavaTypeProfile profile) { + TypeCheckHints hints = new TypeCheckHints(type, profile, site.assumptions(), GraalOptions.InstanceOfMinHintHitProbability, GraalOptions.InstanceOfMaxHints); + int hintsLength = hints.types.length; + if (hintsLength == 0) { + return new XirSnippet(instanceOfTemplates.get(site, 0), object, hub); + } else { + XirArgument[] params = new XirArgument[hintsLength + (hints.exact ? 1 : 2)]; + int i = 0; + params[i++] = object; + if (!hints.exact) { + params[i++] = hub; + } + for (ResolvedJavaType hint : hints.types) { + params[i++] = XirArgument.forObject(((HotSpotType) hint).klassOop()); + } + XirTemplate template = hints.exact ? instanceOfTemplates.get(site, hintsLength, EXACT_HINTS) : instanceOfTemplates.get(site, hintsLength); + return new XirSnippet(template, params); + } + } + + @Override + public XirSnippet genMaterializeInstanceOf(XirSite site, XirArgument object, XirArgument hub, XirArgument trueValue, XirArgument falseValue, ResolvedJavaType type, JavaTypeProfile profile) { + TypeCheckHints hints = new TypeCheckHints(type, profile, site.assumptions(), GraalOptions.InstanceOfMinHintHitProbability, GraalOptions.InstanceOfMaxHints); + int hintsLength = hints.types.length; + if (hintsLength == 0) { + return new XirSnippet(materializeInstanceOfTemplates.get(site, 0), object, hub, trueValue, falseValue); + } else { + XirArgument[] params = new XirArgument[hintsLength + (hints.exact ? 3 : 4)]; + int i = 0; + params[i++] = object; + if (!hints.exact) { + params[i++] = hub; + } + params[i++] = trueValue; + params[i++] = falseValue; + for (ResolvedJavaType hint : hints.types) { + params[i++] = XirArgument.forObject(((HotSpotType) hint).klassOop()); + } + XirTemplate template = hints.exact ? materializeInstanceOfTemplates.get(site, hintsLength, EXACT_HINTS) : materializeInstanceOfTemplates.get(site, hintsLength); + return new XirSnippet(template, params); + } + } + + @Override + public XirSnippet genTypeBranch(XirSite site, XirArgument thisHub, XirArgument otherHub, JavaType type) { + assert type instanceof ResolvedJavaType; + return new XirSnippet(typeCheckTemplates.get(site), thisHub, otherHub); + } + + @Override + public void initialize(CiXirAssembler asm) { + this.globalAsm = asm; + } + + private void checkSubtype(CiXirAssembler asm, XirOperand result, XirOperand objHub, XirOperand hub) { + asm.push(objHub); + asm.push(hub); + asm.callRuntime(config.instanceofStub, null); + asm.pop(result); + asm.pop(result); + } + + private static void useRegisters(CiXirAssembler asm, Register... registers) { + if (registers != null) { + for (Register register : registers) { + asm.createRegisterTemp("reg", Kind.Illegal, register); + } + } + } + + public boolean is(TemplateFlag check, long flags) { + return (flags & check.bits()) == check.bits(); + } + + /** + * Base class for all the ondemand template generators. It is not normally subclassed directly, but through one of + * its subclasses (SimpleTemplates, KindTemplates, IndexTemplates). + */ + private abstract class Templates { + + private ConcurrentHashMap templates = new ConcurrentHashMap<>(); + private final long mask; + + /** + * Each flag passed to this method will cause templates with and without it to be generated. + */ + public Templates(TemplateFlag... flags) { + this.mask = getBits((int) INDEX_MASK, null, flags); + } + + protected abstract XirTemplate create(CiXirAssembler asm, long flags); + + protected long getBits(int index, XirSite site, TemplateFlag... flags) { + long bits = index; + if (site != null) { + bits |= site.requiresNullCheck() ? NULL_CHECK.bits() : 0; + bits |= site.requiresReadBarrier() ? READ_BARRIER.bits() : 0; + bits |= site.requiresWriteBarrier() ? WRITE_BARRIER.bits() : 0; + bits |= site.requiresArrayStoreCheck() ? STORE_CHECK.bits() : 0; + bits |= site.requiresBoundsCheck() ? BOUNDS_CHECK.bits() : 0; + } + if (flags != null) { + for (TemplateFlag flag : flags) { + bits |= flag.bits(); + } + } + return bits; + } + + protected XirTemplate getInternal(long flags) { + long maskedFlags = flags & mask; + XirTemplate template = templates.get(maskedFlags); + if (template == null) { + template = create(HotSpotXirGenerator.this.globalAsm.copy(), maskedFlags); + templates.put(maskedFlags, template); + } + return template; + } + } + + private abstract class SimpleTemplates extends Templates { + + public SimpleTemplates(TemplateFlag... flags) { + super(flags); + } + + public XirTemplate get(XirSite site, TemplateFlag... flags) { + return getInternal(getBits(0, site, flags)); + } + } + + private abstract class IndexTemplates extends Templates { + + public IndexTemplates(TemplateFlag... flags) { + super(flags); + } + + @Override + protected final XirTemplate create(CiXirAssembler asm, long flags) { + return create(asm, flags & FLAGS_MASK, (int) (flags & INDEX_MASK)); + } + + protected abstract XirTemplate create(CiXirAssembler asm, long flags, int index); + + public XirTemplate get(XirSite site, int size, TemplateFlag... flags) { + return getInternal(getBits(size, site, flags)); + } + } + + private abstract class KindTemplates extends Templates { + + public KindTemplates(TemplateFlag... flags) { + super(flags); + } + + @Override + protected final XirTemplate create(CiXirAssembler asm, long flags) { + return create(asm, flags & FLAGS_MASK, Kind.VALUES[(int) (flags & INDEX_MASK)]); + } + + protected abstract XirTemplate create(CiXirAssembler asm, long flags, Kind kind); + + public XirTemplate get(XirSite site, Kind kind, TemplateFlag... flags) { + return getInternal(getBits(kind.ordinal(), site, flags)); + } + } + + private static void printCounter(PrintStream out, CheckcastCounter name, long count, long total) { + double percent = total == 0D ? 0D : ((double) (count * 100)) / total; + out.println(String.format("%16s: %5.2f%%%10d // %s", name, percent, count, name.desc)); + } + + public static void printCheckcastCounters(PrintStream out) { + class Count implements Comparable { + long c; + CheckcastCounter name; + Count(long c, CheckcastCounter name) { + this.c = c; + this.name = name; + } + public int compareTo(Count o) { + return (int) (o.c - c); + } + } + + long total = 0; + Count[] counters = new Count[checkcastCounters.length]; + for (int i = 0; i < counters.length; i++) { + counters[i] = new Count(checkcastCounters[i], CheckcastCounter.VALUES[i]); + total += checkcastCounters[i]; + } + Arrays.sort(counters); + + out.println(); + out.println("** XIR checkcast counters **"); + for (Count c : counters) { + printCounter(out, c.name, c.c, total); + } + } + + public static void printCounters(PrintStream out) { + if (GraalOptions.CheckcastCounters) { + printCheckcastCounters(out); + } + } +} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/TemplateFlag.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/TemplateFlag.java Sat Jun 09 20:32:31 2012 +0200 @@ -0,0 +1,48 @@ +/* + * 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.hotspot.meta; + +enum TemplateFlag { + NULL_CHECK, + READ_BARRIER, + WRITE_BARRIER, + STORE_CHECK, + BOUNDS_CHECK, + GIVEN_LENGTH, + INPUTS_DIFFERENT, + INPUTS_SAME, + STATIC_METHOD, + SYNCHRONIZED, + INTERFACE_TYPE, + NULL_TYPE, + EXACT_HINTS; + + private static final long FIRST_FLAG = 0x0000000100000000L; + public static final long FLAGS_MASK = 0x0000FFFF00000000L; + public static final long INDEX_MASK = 0x00000000FFFFFFFFL; + + public long bits() { + assert ((FIRST_FLAG << ordinal()) & FLAGS_MASK) != 0; + return FIRST_FLAG << ordinal(); + } +} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotCodeInfo.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotCodeInfo.java Sat Jun 09 20:10:05 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ -/* - * 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.hotspot.ri; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.hotspot.*; - -/** - * Implementation of {@link CodeInfo} for HotSpot. - */ -public class HotSpotCodeInfo extends CompilerObject implements CodeInfo { - - private static final long serialVersionUID = -6766490427732498354L; - - private long start; - private byte[] code; - public final CompilationResult targetMethod; - private HotSpotMethodResolved method; - - public HotSpotCodeInfo(CompilationResult targetMethod, HotSpotMethodResolved method) { - assert targetMethod != null; - this.method = method; - this.targetMethod = targetMethod; - } - - @Override - public long start() { - return start; - } - - @Override - public byte[] code() { - return code; - } - - @Override - public String toString() { - int size = code == null ? 0 : code.length; - return "installed code @[" + Long.toHexString(start) + "-" + Long.toHexString(start + size) + "]"; - - } - - @Override - public ResolvedJavaMethod method() { - return method; - } -} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotCompiledMethod.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotCompiledMethod.java Sat Jun 09 20:10:05 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,91 +0,0 @@ -/* - * 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.hotspot.ri; - -import java.lang.reflect.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.hotspot.*; - -/** - * Implementation of RiCompiledMethod for HotSpot. - * Stores a reference to the nmethod which contains the compiled code. - * The nmethod also stores a weak reference to the HotSpotCompiledMethod - * instance which is necessary to keep the nmethod from being unloaded. - */ -public class HotSpotCompiledMethod extends CompilerObject implements InstalledCode { - - private static final long serialVersionUID = 156632908220561612L; - - private final ResolvedJavaMethod method; - private long nmethod; - - public HotSpotCompiledMethod(ResolvedJavaMethod method) { - this.method = method; - } - - @Override - public ResolvedJavaMethod method() { - return method; - } - - @Override - public boolean isValid() { - return nmethod != 0; - } - - @Override - public String toString() { - return "compiled method " + method + " @" + nmethod; - } - - @Override - public Object execute(Object arg1, Object arg2, Object arg3) { - assert method.signature().argumentCount(!Modifier.isStatic(method.accessFlags())) == 3; - assert method.signature().argumentKindAt(0) == Kind.Object; - assert method.signature().argumentKindAt(1) == Kind.Object; - assert !Modifier.isStatic(method.accessFlags()) || method.signature().argumentKindAt(2) == Kind.Object; - return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethod(this, arg1, arg2, arg3); - } - - private boolean checkArgs(Object... args) { - Kind[] sig = CodeUtil.signatureToKinds(method); - assert args.length == sig.length : CodeUtil.format("%H.%n(%p): expected ", method) + sig.length + " args, got " + args.length; - for (int i = 0; i < sig.length; i++) { - Object arg = args[i]; - if (arg == null) { - assert sig[i].isObject() : CodeUtil.format("%H.%n(%p): expected arg ", method) + i + " to be Object, not " + sig[i]; - } else if (!sig[i].isObject()) { - assert sig[i].toBoxedJavaClass() == arg.getClass() : CodeUtil.format("%H.%n(%p): expected arg ", method) + i + " to be " + sig[i] + ", not " + arg.getClass(); - } - } - return true; - } - - @Override - public Object executeVarargs(Object... args) { - assert checkArgs(args); - return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethodVarargs(this, args); - } -} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotConstantPool.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotConstantPool.java Sat Jun 09 20:10:05 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -/* - * 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.hotspot.ri; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.hotspot.*; - -/** - * Implementation of RiConstantPool for HotSpot. - */ -public class HotSpotConstantPool extends CompilerObject implements ConstantPool { - - private static final long serialVersionUID = -5443206401485234850L; - - private final HotSpotTypeResolvedImpl type; - - public HotSpotConstantPool(HotSpotTypeResolvedImpl type) { - this.type = type; - } - - @Override - public Object lookupConstant(int cpi) { - Object constant = HotSpotGraalRuntime.getInstance().getCompilerToVM().RiConstantPool_lookupConstant(type, cpi); - return constant; - } - - @Override - public Signature lookupSignature(int cpi) { - throw new UnsupportedOperationException(); - } - - @Override - public JavaMethod lookupMethod(int cpi, int byteCode) { - return HotSpotGraalRuntime.getInstance().getCompilerToVM().RiConstantPool_lookupMethod(type, cpi, (byte) byteCode); - } - - @Override - public JavaType lookupType(int cpi, int opcode) { - return HotSpotGraalRuntime.getInstance().getCompilerToVM().RiConstantPool_lookupType(type, cpi); - } - - @Override - public JavaField lookupField(int cpi, int opcode) { - return HotSpotGraalRuntime.getInstance().getCompilerToVM().RiConstantPool_lookupField(type, cpi, (byte) opcode); - } - - @Override - public void loadReferencedType(int cpi, int bytecode) { - HotSpotGraalRuntime.getInstance().getCompilerToVM().RiConstantPool_loadReferencedType(type, cpi, (byte) bytecode); - } -} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotField.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotField.java Sat Jun 09 20:10:05 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,134 +0,0 @@ -/* - * 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.hotspot.ri; - -import java.lang.annotation.*; -import java.lang.reflect.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.meta.JavaType.*; -import com.oracle.graal.compiler.*; -import com.oracle.graal.hotspot.*; - -/** - * Represents a field in a HotSpot type. - */ -public class HotSpotField extends CompilerObject implements ResolvedJavaField { - - private static final long serialVersionUID = 7692985878836955683L; - private final ResolvedJavaType holder; - private final String name; - private final JavaType type; - private final int offset; - private final int accessFlags; - private Constant constant; // Constant part only valid for static fields. - - public HotSpotField(ResolvedJavaType holder, String name, JavaType type, int offset, int accessFlags) { - this.holder = holder; - this.name = name; - this.type = type; - assert offset != -1; - this.offset = offset; - this.accessFlags = accessFlags; - } - - @Override - public int accessFlags() { - return accessFlags; - } - - @Override - public Constant constantValue(Constant receiver) { - if (receiver == null) { - assert Modifier.isStatic(accessFlags); - 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); - } - } - } - return constant; - } else { - 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 null; - } - - private static boolean assumeStaticFieldsFinal(Class< ? > clazz) { - return clazz == GraalOptions.class; - } - - @Override - public ResolvedJavaType holder() { - return holder; - } - - @Override - public Kind kind() { - return type().kind(); - } - - @Override - public String name() { - return name; - } - - @Override - public JavaType type() { - return type; - } - - public int offset() { - return offset; - } - - @Override - public String toString() { - return "HotSpotField<" + CodeUtil.format("%h.%n", this) + ":" + offset + ">"; - } - - @Override - public T getAnnotation(Class annotationClass) { - Field javaField = toJava(); - if (javaField != null) { - return javaField.getAnnotation(annotationClass); - } - return null; - } - - private Field toJava() { - try { - return holder.toJava().getDeclaredField(name); - } catch (NoSuchFieldException e) { - return null; - } - } -} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotGraphCache.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotGraphCache.java Sat Jun 09 20:10:05 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,171 +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.hotspot.ri; - -import java.io.*; -import java.lang.ref.*; -import java.util.*; -import java.util.Map.Entry; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.*; -import com.oracle.graal.cri.*; -import com.oracle.graal.nodes.*; - -/** - * This class implements the graph caching system for the HotSpot platform. - * - * This implementation does not use a map to store the actual cached graphs. The problem is that such maps keep the - * graph, and therefore the RiResolvedMethod referenced from the graph, alive. For some applications and benchmarks this - * is a problem, e.g., the DaCapoScala "scalatest" benchmark will quickly run out of perm gen because of this. - * - * This cannot be solved with a WeakHashMap, since the values within the map will keep the keys - * alive. In order for this to work we would require a weak map in which the "strongness" of the value references - * depends upon the reachability of the keys. - * - * Therefore the graph cache is implemented in such a way that it stores its cache entries within the RiResolvedMethod. - * It uses the {@link ResolvedJavaMethod#compilerStorage()} map with the HotSpotGraphCache instance as key. - * The cached graph will be kept alive as long as the RiResolvedMethod is alive, but does not prevent the method, and - * therefore the class, from being unloaded. - * - * The {@link #cachedGraphIds} map is used to find the graphs that should be removed because of deoptimization, and to - * enforce the graph cache size restriction. - */ -public class HotSpotGraphCache implements RiGraphCache { - - private static final PrintStream out = System.out; - - private volatile long hitCounter; - private volatile long missCounter; - private volatile long removeHitCounter; - private volatile long removeCounter; - private volatile long putCounter; - - /** - * An ordered hash map for looking up the methods corresponding to a specific graph id. It enforces the maximum - * graph cache size by removing the oldest (in insertion-order) element if the cache gets too big. - */ - private final class LRUCache extends LinkedHashMap> { - - private static final long serialVersionUID = -3973307040793397840L; - - public LRUCache() { - super(GraalOptions.GraphCacheSize * 2, 0.75f, false); - } - - @Override - protected boolean removeEldestEntry(Entry> eldest) { - if (size() > GraalOptions.GraphCacheSize) { - ResolvedJavaMethod method = eldest.getValue().get(); - if (method != null) { - StructuredGraph cachedGraph = (StructuredGraph) method.compilerStorage().get(HotSpotGraphCache.this); - if (cachedGraph != null && cachedGraph.graphId() == eldest.getKey()) { - method.compilerStorage().remove(HotSpotGraphCache.this); - } - } - return true; - } else { - return false; - } - } - } - - private final Map> cachedGraphIds = Collections.synchronizedMap(new LRUCache()); - - public HotSpotGraphCache() { - if (GraalOptions.PrintGraphCache) { - Runtime.getRuntime().addShutdownHook(new Thread() { - - @Override - public void run() { - out.println("put: " + putCounter); - out.println("get hit: " + hitCounter); - out.println("get miss: " + missCounter); - out.println("remove hit: " + removeHitCounter); - out.println("remove miss: " + (removeCounter - removeHitCounter)); - } - }); - } - } - - @Override - public StructuredGraph get(ResolvedJavaMethod method) { - StructuredGraph result = (StructuredGraph) method.compilerStorage().get(this); - - if (GraalOptions.PrintGraphCache) { - if (result == null) { - missCounter++; - } else { - hitCounter++; - } - } - return result; - } - - @Override - public void put(StructuredGraph graph) { - assert graph.method() != null; - cachedGraphIds.put(graph.graphId(), new WeakReference<>(graph.method())); - graph.method().compilerStorage().put(this, graph); - - if (GraalOptions.PrintGraphCache) { - putCounter++; - } - } - - public void clear() { - synchronized (cachedGraphIds) { - for (WeakReference ref : cachedGraphIds.values()) { - ResolvedJavaMethod method = ref.get(); - if (method != null) { - method.compilerStorage().remove(this); - } - } - cachedGraphIds.clear(); - hitCounter = 0; - missCounter = 0; - removeHitCounter = 0; - removeCounter = 0; - putCounter = 0; - } - } - - public void removeGraphs(long[] deoptedGraphs) { - for (long graphId : deoptedGraphs) { - WeakReference ref = cachedGraphIds.get(graphId); - ResolvedJavaMethod method = ref == null ? null : ref.get(); - if (method != null) { - StructuredGraph cachedGraph = (StructuredGraph) method.compilerStorage().get(this); - if (cachedGraph != null && cachedGraph.graphId() == graphId) { - method.compilerStorage().remove(this); - if (GraalOptions.PrintGraphCache) { - removeHitCounter++; - } - } - } - if (GraalOptions.PrintGraphCache) { - removeCounter++; - } - } - } -} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotKlassOop.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotKlassOop.java Sat Jun 09 20:10:05 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +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.hotspot.ri; - -import com.oracle.graal.hotspot.*; - -/** - * A mechanism for safely conveying a HotSpot klassOop value from the compiler to the C++ code. - * Such values should not be directly exposed to Java code as they are not real Java - * objects. For instance, invoking a method on them or using them in an instanceof - * expression will most likely crash the VM. - */ -public class HotSpotKlassOop extends CompilerObject { - - private static final long serialVersionUID = -5445542223575839143L; - - /** - * The Java object from which the klassOop value can be derived (by the C++ code). - */ - public final Class javaMirror; - - public HotSpotKlassOop(Class javaMirror) { - this.javaMirror = javaMirror; - } - - @Override - public String toString() { - return "HotSpotKlassOop<" + javaMirror.getName() + ">"; - } -} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethod.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethod.java Sat Jun 09 20:10:05 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -/* - * 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.hotspot.ri; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.hotspot.*; - -public abstract class HotSpotMethod extends CompilerObject implements JavaMethod { - - private static final long serialVersionUID = 7167491397941960839L; - protected String name; - - @Override - public final String name() { - return name; - } -} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodData.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodData.java Sat Jun 09 20:10:05 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,575 +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.hotspot.ri; - -import java.util.*; - -import sun.misc.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.meta.JavaTypeProfile.*; -import com.oracle.graal.compiler.*; -import com.oracle.graal.hotspot.*; - - -public final class HotSpotMethodData extends CompilerObject { - - private static final long serialVersionUID = -8873133496591225071L; - - static { - config = HotSpotGraalRuntime.getInstance().getConfig(); - } - - // TODO (chaeubl) use same logic as in NodeClass? - private static final Unsafe unsafe = Unsafe.getUnsafe(); - private static final HotSpotMethodDataAccessor NO_DATA_NO_EXCEPTION_ACCESSOR = new NoMethodData(ExceptionSeen.FALSE); - private static final HotSpotMethodDataAccessor NO_DATA_EXCEPTION_POSSIBLY_NOT_RECORDED_ACCESSOR = new NoMethodData(ExceptionSeen.NOT_SUPPORTED); - private static final HotSpotVMConfig config; - // sorted by tag - private static final HotSpotMethodDataAccessor[] PROFILE_DATA_ACCESSORS = { - null, new BitData(), new CounterData(), new JumpData(), - new TypeCheckData(), new VirtualCallData(), new RetData(), - new BranchData(), new MultiBranchData(), new ArgInfoData() - }; - - private Object hotspotMirror; - private int normalDataSize; - private int extraDataSize; - - private HotSpotMethodData() { - throw new IllegalStateException("this constructor is never actually called, because the objects are allocated from within the VM"); - } - - public boolean hasNormalData() { - return normalDataSize > 0; - } - - public boolean hasExtraData() { - return extraDataSize > 0; - } - - public int getExtraDataBeginOffset() { - return normalDataSize; - } - - public boolean isWithin(int position) { - return position >= 0 && position < normalDataSize + extraDataSize; - } - - public int getDeoptimizationCount(DeoptimizationReason reason) { - int reasonIndex = HotSpotGraalRuntime.getInstance().getRuntime().convertDeoptReason(reason); - return unsafe.getByte(hotspotMirror, (long) config.methodDataOopTrapHistoryOffset + reasonIndex) & 0xFF; - } - - public HotSpotMethodDataAccessor getNormalData(int position) { - if (position >= normalDataSize) { - return null; - } - - HotSpotMethodDataAccessor result = getData(position); - assert result != null : "NO_DATA tag is not allowed"; - return result; - } - - public HotSpotMethodDataAccessor getExtraData(int position) { - if (position >= normalDataSize + extraDataSize) { - return null; - } - return getData(position); - } - - public static HotSpotMethodDataAccessor getNoDataAccessor(boolean exceptionPossiblyNotRecorded) { - if (exceptionPossiblyNotRecorded) { - return NO_DATA_EXCEPTION_POSSIBLY_NOT_RECORDED_ACCESSOR; - } else { - return NO_DATA_NO_EXCEPTION_ACCESSOR; - } - } - - private HotSpotMethodDataAccessor getData(int position) { - assert position >= 0 : "out of bounds"; - int tag = AbstractMethodData.readTag(this, position); - assert tag >= 0 && tag < PROFILE_DATA_ACCESSORS.length : "illegal tag"; - return PROFILE_DATA_ACCESSORS[tag]; - } - - private int readUnsignedByte(int position, int offsetInBytes) { - long fullOffsetInBytes = computeFullOffset(position, offsetInBytes); - return unsafe.getByte(hotspotMirror, fullOffsetInBytes) & 0xFF; - } - - private int readUnsignedShort(int position, int offsetInBytes) { - long fullOffsetInBytes = computeFullOffset(position, offsetInBytes); - return unsafe.getShort(hotspotMirror, fullOffsetInBytes) & 0xFFFF; - } - - private long readUnsignedInt(int position, int offsetInBytes) { - long fullOffsetInBytes = computeFullOffset(position, offsetInBytes); - return unsafe.getInt(hotspotMirror, fullOffsetInBytes) & 0xFFFFFFFFL; - } - - private int readUnsignedIntAsSignedInt(int position, int offsetInBytes) { - long value = readUnsignedInt(position, offsetInBytes); - return truncateLongToInt(value); - } - - private int readInt(int position, int offsetInBytes) { - long fullOffsetInBytes = computeFullOffset(position, offsetInBytes); - return unsafe.getInt(hotspotMirror, fullOffsetInBytes); - } - - private Object readObject(int position, int offsetInBytes) { - long fullOffsetInBytes = computeFullOffset(position, offsetInBytes); - return unsafe.getObject(hotspotMirror, fullOffsetInBytes); - } - - private static int truncateLongToInt(long value) { - return value > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) value; - } - - private static int computeFullOffset(int position, int offsetInBytes) { - return config.methodDataOopDataOffset + position + offsetInBytes; - } - - private static int cellIndexToOffset(int cells) { - return config.dataLayoutHeaderSize + cellsToBytes(cells); - } - - private static int cellsToBytes(int cells) { - return cells * config.dataLayoutCellSize; - } - - private abstract static class AbstractMethodData implements HotSpotMethodDataAccessor { - private static final int EXCEPTIONS_MASK = 0x80; - - private final int tag; - private final int staticSize; - - protected AbstractMethodData(int tag, int staticSize) { - this.tag = tag; - this.staticSize = staticSize; - } - - public int getTag() { - return tag; - } - - public static int readTag(HotSpotMethodData data, int position) { - return data.readUnsignedByte(position, config.dataLayoutTagOffset); - } - - @Override - public int getBCI(HotSpotMethodData data, int position) { - return data.readUnsignedShort(position, config.dataLayoutBCIOffset); - } - - @Override - public int getSize(HotSpotMethodData data, int position) { - return staticSize + getDynamicSize(data, position); - } - - @Override - public ExceptionSeen getExceptionSeen(HotSpotMethodData data, int position) { - return ExceptionSeen.get((getFlags(data, position) & EXCEPTIONS_MASK) != 0); - } - - @Override - public JavaTypeProfile getTypeProfile(HotSpotMethodData data, int position) { - return null; - } - - @Override - public double getBranchTakenProbability(HotSpotMethodData data, int position) { - return -1; - } - - @Override - public double[] getSwitchProbabilities(HotSpotMethodData data, int position) { - return null; - } - - @Override - public int getExecutionCount(HotSpotMethodData data, int position) { - return -1; - } - - protected int getFlags(HotSpotMethodData data, int position) { - return data.readUnsignedByte(position, config.dataLayoutFlagsOffset); - } - - protected int getDynamicSize(@SuppressWarnings("unused") HotSpotMethodData data, @SuppressWarnings("unused") int position) { - return 0; - } - } - - private static class NoMethodData extends AbstractMethodData { - private static final int NO_DATA_TAG = 0; - private static final int NO_DATA_SIZE = cellIndexToOffset(0); - - private final ExceptionSeen exceptionSeen; - - protected NoMethodData(ExceptionSeen exceptionSeen) { - super(NO_DATA_TAG, NO_DATA_SIZE); - this.exceptionSeen = exceptionSeen; - } - - @Override - public int getBCI(HotSpotMethodData data, int position) { - return -1; - } - - - @Override - public ExceptionSeen getExceptionSeen(HotSpotMethodData data, int position) { - return exceptionSeen; - } - } - - private static class BitData extends AbstractMethodData { - private static final int BIT_DATA_TAG = 1; - private static final int BIT_DATA_SIZE = cellIndexToOffset(0); - private static final int BIT_DATA_NULL_SEEN_FLAG = 0x01; - - private BitData() { - super(BIT_DATA_TAG, BIT_DATA_SIZE); - } - - protected BitData(int tag, int staticSize) { - super(tag, staticSize); - } - - @SuppressWarnings("unused") - public boolean getNullSeen(HotSpotMethodData data, int position) { - return (getFlags(data, position) & BIT_DATA_NULL_SEEN_FLAG) != 0; - } - } - - private static class CounterData extends BitData { - private static final int COUNTER_DATA_TAG = 2; - private static final int COUNTER_DATA_SIZE = cellIndexToOffset(1); - private static final int COUNTER_DATA_COUNT_OFFSET = cellIndexToOffset(0); - - public CounterData() { - super(COUNTER_DATA_TAG, COUNTER_DATA_SIZE); - } - - protected CounterData(int tag, int staticSize) { - super(tag, staticSize); - } - - @Override - public int getExecutionCount(HotSpotMethodData data, int position) { - return getCounterValue(data, position); - } - - protected int getCounterValue(HotSpotMethodData data, int position) { - return data.readUnsignedIntAsSignedInt(position, COUNTER_DATA_COUNT_OFFSET); - } - } - - private static class JumpData extends AbstractMethodData { - private static final int JUMP_DATA_TAG = 3; - private static final int JUMP_DATA_SIZE = cellIndexToOffset(2); - protected static final int TAKEN_COUNT_OFFSET = cellIndexToOffset(0); - protected static final int TAKEN_DISPLACEMENT_OFFSET = cellIndexToOffset(1); - - public JumpData() { - super(JUMP_DATA_TAG, JUMP_DATA_SIZE); - } - - protected JumpData(int tag, int staticSize) { - super(tag, staticSize); - } - - @Override - public double getBranchTakenProbability(HotSpotMethodData data, int position) { - return getExecutionCount(data, position) != 0 ? 1 : 0; - } - - @Override - public int getExecutionCount(HotSpotMethodData data, int position) { - return data.readUnsignedIntAsSignedInt(position, TAKEN_COUNT_OFFSET); - } - - @SuppressWarnings("unused") - public int getTakenDisplacement(HotSpotMethodData data, int position) { - return data.readInt(position, TAKEN_DISPLACEMENT_OFFSET); - } - } - - private abstract static class AbstractTypeData extends CounterData { - private static final int RECEIVER_TYPE_DATA_ROW_SIZE = cellsToBytes(2); - private static final int RECEIVER_TYPE_DATA_SIZE = cellIndexToOffset(1) + RECEIVER_TYPE_DATA_ROW_SIZE * config.typeProfileWidth; - private static final int RECEIVER_TYPE_DATA_FIRST_RECEIVER_OFFSET = cellIndexToOffset(1); - private static final int RECEIVER_TYPE_DATA_FIRST_COUNT_OFFSET = cellIndexToOffset(2); - - protected AbstractTypeData(int tag) { - super(tag, RECEIVER_TYPE_DATA_SIZE); - } - - @Override - public JavaTypeProfile getTypeProfile(HotSpotMethodData data, int position) { - int typeProfileWidth = config.typeProfileWidth; - - ResolvedJavaType[] types = new ResolvedJavaType[typeProfileWidth]; - long[] counts = new long[typeProfileWidth]; - long totalCount = 0; - int entries = 0; - - for (int i = 0; i < typeProfileWidth; i++) { - Object receiverKlassOop = data.readObject(position, getReceiverOffset(i)); - if (receiverKlassOop != null) { - Object graalMirror = unsafe.getObject(receiverKlassOop, (long) config.graalMirrorKlassOffset); - if (graalMirror == null) { - Class javaClass = (Class) unsafe.getObject(receiverKlassOop, (long) config.classMirrorOffset); - graalMirror = HotSpotGraalRuntime.getInstance().getCompilerToVM().getType(javaClass); - assert graalMirror != null : "must not return null"; - } - - - types[entries] = (ResolvedJavaType) graalMirror; - - long count = data.readUnsignedInt(position, getCountOffset(i)); - totalCount += count; - counts[entries] = count; - - entries++; - } - } - - totalCount += getTypesNotRecordedExecutionCount(data, position); - return createRiTypeProfile(types, counts, totalCount, entries); - } - - protected long getTypesNotRecordedExecutionCount(HotSpotMethodData data, int position) { - // checkcast/aastore/instanceof profiling in the HotSpot template-based interpreter was adjusted so that the counter - // is incremented to indicate the polymorphic case instead of decrementing it for failed type checks - return getCounterValue(data, position); - } - - private static JavaTypeProfile createRiTypeProfile(ResolvedJavaType[] types, long[] counts, long totalCount, int entries) { - if (entries <= 0 || totalCount < GraalOptions.MatureExecutionsTypeProfile) { - return null; - } - - ProfiledType[] ptypes = new ProfiledType[entries]; - double totalProbability = 0.0; - for (int i = 0; i < entries; i++) { - double p = counts[i]; - p = p / totalCount; - totalProbability += p; - ptypes[i] = new ProfiledType(types[i], p); - } - - Arrays.sort(ptypes); - - double notRecordedTypeProbability = entries < config.typeProfileWidth ? 0.0 : Math.min(1.0, Math.max(0.0, 1.0 - totalProbability)); - return new JavaTypeProfile(notRecordedTypeProbability, ptypes); - } - - private static int getReceiverOffset(int row) { - return RECEIVER_TYPE_DATA_FIRST_RECEIVER_OFFSET + row * RECEIVER_TYPE_DATA_ROW_SIZE; - } - - protected static int getCountOffset(int row) { - return RECEIVER_TYPE_DATA_FIRST_COUNT_OFFSET + row * RECEIVER_TYPE_DATA_ROW_SIZE; - } - } - - private static class TypeCheckData extends AbstractTypeData { - private static final int RECEIVER_TYPE_DATA_TAG = 4; - - public TypeCheckData() { - super(RECEIVER_TYPE_DATA_TAG); - } - - @Override - public int getExecutionCount(HotSpotMethodData data, int position) { - return -1; - } - } - - private static class VirtualCallData extends AbstractTypeData { - private static final int VIRTUAL_CALL_DATA_TAG = 5; - - public VirtualCallData() { - super(VIRTUAL_CALL_DATA_TAG); - } - - @Override - public int getExecutionCount(HotSpotMethodData data, int position) { - int typeProfileWidth = config.typeProfileWidth; - - long total = 0; - for (int i = 0; i < typeProfileWidth; i++) { - total += data.readUnsignedInt(position, getCountOffset(i)); - } - - total += getCounterValue(data, position); - return truncateLongToInt(total); - } - } - - private static class RetData extends CounterData { - private static final int RET_DATA_TAG = 6; - private static final int RET_DATA_ROW_SIZE = cellsToBytes(3); - private static final int RET_DATA_SIZE = cellIndexToOffset(1) + RET_DATA_ROW_SIZE * config.bciProfileWidth; - - public RetData() { - super(RET_DATA_TAG, RET_DATA_SIZE); - } - } - - private static class BranchData extends JumpData { - private static final int BRANCH_DATA_TAG = 7; - private static final int BRANCH_DATA_SIZE = cellIndexToOffset(3); - private static final int NOT_TAKEN_COUNT_OFFSET = cellIndexToOffset(2); - - public BranchData() { - super(BRANCH_DATA_TAG, BRANCH_DATA_SIZE); - } - - @Override - public double getBranchTakenProbability(HotSpotMethodData data, int position) { - long takenCount = data.readUnsignedInt(position, TAKEN_COUNT_OFFSET); - long notTakenCount = data.readUnsignedInt(position, NOT_TAKEN_COUNT_OFFSET); - long total = takenCount + notTakenCount; - - if (total < GraalOptions.MatureExecutionsBranch) { - return -1; - } else { - return takenCount / (double) total; - } - } - - @Override - public int getExecutionCount(HotSpotMethodData data, int position) { - long count = data.readUnsignedInt(position, TAKEN_COUNT_OFFSET) + data.readUnsignedInt(position, NOT_TAKEN_COUNT_OFFSET); - return truncateLongToInt(count); - } - } - - private static class ArrayData extends AbstractMethodData { - private static final int ARRAY_DATA_LENGTH_OFFSET = cellIndexToOffset(0); - protected static final int ARRAY_DATA_START_OFFSET = cellIndexToOffset(1); - - public ArrayData(int tag, int staticSize) { - super(tag, staticSize); - } - - @Override - protected int getDynamicSize(HotSpotMethodData data, int position) { - return cellsToBytes(getLength(data, position)); - } - - protected static int getLength(HotSpotMethodData data, int position) { - return data.readInt(position, ARRAY_DATA_LENGTH_OFFSET); - } - } - - private static class MultiBranchData extends ArrayData { - private static final int MULTI_BRANCH_DATA_TAG = 8; - private static final int MULTI_BRANCH_DATA_SIZE = cellIndexToOffset(1); - private static final int MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS = 2; - private static final int MULTI_BRANCH_DATA_ROW_SIZE = cellsToBytes(MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS); - private static final int MULTI_BRANCH_DATA_FIRST_COUNT_OFFSET = ARRAY_DATA_START_OFFSET + cellsToBytes(0); - private static final int MULTI_BRANCH_DATA_FIRST_DISPLACEMENT_OFFSET = ARRAY_DATA_START_OFFSET + cellsToBytes(1); - - public MultiBranchData() { - super(MULTI_BRANCH_DATA_TAG, MULTI_BRANCH_DATA_SIZE); - } - - @Override - public double[] getSwitchProbabilities(HotSpotMethodData data, int position) { - int arrayLength = getLength(data, position); - assert arrayLength > 0 : "switch must have at least the default case"; - assert arrayLength % MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS == 0 : "array must have full rows"; - - int length = arrayLength / MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS; - long totalCount = 0; - double[] result = new double[length]; - - // default case is first in HotSpot but last for the compiler - long count = readCount(data, position, 0); - totalCount += count; - result[length - 1] = count; - - for (int i = 1; i < length; i++) { - count = readCount(data, position, i); - totalCount += count; - result[i - 1] = count; - } - - if (totalCount < GraalOptions.MatureExecutionsPerSwitchCase * length) { - return null; - } else { - for (int i = 0; i < length; i++) { - result[i] = result[i] / totalCount; - } - return result; - } - } - - private static long readCount(HotSpotMethodData data, int position, int i) { - int offset; - long count; - offset = getCountOffset(i); - count = data.readUnsignedInt(position, offset); - return count; - } - - @Override - public int getExecutionCount(HotSpotMethodData data, int position) { - int arrayLength = getLength(data, position); - assert arrayLength > 0 : "switch must have at least the default case"; - assert arrayLength % MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS == 0 : "array must have full rows"; - - int length = arrayLength / MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS; - long totalCount = 0; - for (int i = 0; i < length; i++) { - int offset = getCountOffset(i); - totalCount += data.readUnsignedInt(position, offset); - } - - return truncateLongToInt(totalCount); - } - - private static int getCountOffset(int index) { - return MULTI_BRANCH_DATA_FIRST_COUNT_OFFSET + index * MULTI_BRANCH_DATA_ROW_SIZE; - } - - @SuppressWarnings("unused") - private static int getDisplacementOffset(int index) { - return MULTI_BRANCH_DATA_FIRST_DISPLACEMENT_OFFSET + index * MULTI_BRANCH_DATA_ROW_SIZE; - } - } - - private static class ArgInfoData extends ArrayData { - private static final int ARG_INFO_DATA_TAG = 9; - private static final int ARG_INFO_DATA_SIZE = cellIndexToOffset(1); - - public ArgInfoData() { - super(ARG_INFO_DATA_TAG, ARG_INFO_DATA_SIZE); - } - } -} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodDataAccessor.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodDataAccessor.java Sat Jun 09 20:10:05 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -/* - * 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.hotspot.ri; - -import com.oracle.graal.api.meta.*; - -/** - * Interface for accessor objects that encapsulate the logic for accessing the different kinds of data in a HotSpot methodDataOop. - * This interface is similar to the interface {@link ProfilingInfo}, but most methods require a MethodDataObject and the - * exact position within the methodData. - */ -public interface HotSpotMethodDataAccessor { - /** - * Returns the tag stored in the LayoutData header. - * @return An integer >= 0 or -1 if not supported. - */ - int getTag(); - - /** - * Returns the BCI stored in the LayoutData header. - * @return An integer >= 0 and <= Short.MAX_VALUE, or -1 if not supported. - */ - int getBCI(HotSpotMethodData data, int position); - - /** - * Computes the size for the specific data at the given position. - * @return An integer > 0. - */ - int getSize(HotSpotMethodData data, int position); - - JavaTypeProfile getTypeProfile(HotSpotMethodData data, int position); - double getBranchTakenProbability(HotSpotMethodData data, int position); - double[] getSwitchProbabilities(HotSpotMethodData data, int position); - ExceptionSeen getExceptionSeen(HotSpotMethodData data, int position); - int getExecutionCount(HotSpotMethodData data, int position); -} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodResolved.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodResolved.java Sat Jun 09 20:10:05 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -/* - * 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.hotspot.ri; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.hotspot.*; - -public interface HotSpotMethodResolved extends ResolvedJavaMethod { - - ResolvedJavaMethod uniqueConcreteMethod(); - int vtableEntryOffset(); - - void setCurrentTask(CompilationTask task); - CompilationTask currentTask(); -} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodResolvedImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodResolvedImpl.java Sat Jun 09 20:10:05 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,351 +0,0 @@ -/* - * 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.hotspot.ri; - -import java.io.*; -import java.lang.annotation.*; -import java.lang.reflect.*; -import java.util.*; -import java.util.concurrent.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.*; -import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.counters.*; -import com.oracle.graal.java.bytecode.*; -import com.oracle.max.criutils.*; - -/** - * Implementation of RiMethod for resolved HotSpot methods. - */ -public final class HotSpotMethodResolvedImpl extends HotSpotMethod implements HotSpotMethodResolved { - - private static final long serialVersionUID = -5486975070147586588L; - - /** DO NOT USE IN JAVA CODE! */ - @SuppressWarnings("unused") - @Deprecated - private Object javaMirror; - - // cached values - private final int codeSize; - private final int accessFlags; - private final int maxLocals; - private final int maxStackSize; - private Signature signature; - private Boolean hasBalancedMonitors; - private Map compilerStorage; - private ResolvedJavaType holder; - private HotSpotMethodData methodData; - private byte[] code; - private boolean canBeInlined; - private int compilationComplexity; - - private CompilationTask currentTask; - - private HotSpotMethodResolvedImpl() { - throw new IllegalStateException("this constructor is never actually called, because the objects are allocated from within the VM"); - } - - @Override - public ResolvedJavaType holder() { - return holder; - } - - @Override - public int accessFlags() { - return accessFlags; - } - - @Override - public boolean canBeStaticallyBound() { - return isLeafMethod() || Modifier.isStatic(accessFlags()); - } - - @Override - public byte[] code() { - if (code == null) { - code = HotSpotGraalRuntime.getInstance().getCompilerToVM().RiMethod_code(this); - assert code.length == codeSize : "expected: " + codeSize + ", actual: " + code.length; - } - return code; - } - - @Override - public int codeSize() { - return codeSize; - } - - @Override - public ExceptionHandler[] exceptionHandlers() { - return HotSpotGraalRuntime.getInstance().getCompilerToVM().RiMethod_exceptionHandlers(this); - } - - @Override - public boolean hasBalancedMonitors() { - if (hasBalancedMonitors == null) { - hasBalancedMonitors = HotSpotGraalRuntime.getInstance().getCompilerToVM().RiMethod_hasBalancedMonitors(this); - } - return hasBalancedMonitors; - } - - @Override - public boolean isClassInitializer() { - return "".equals(name) && Modifier.isStatic(accessFlags()); - } - - @Override - public boolean isConstructor() { - return "".equals(name) && !Modifier.isStatic(accessFlags()); - } - - @Override - public boolean isLeafMethod() { - return Modifier.isFinal(accessFlags()) || Modifier.isPrivate(accessFlags()); - } - - @Override - public String jniSymbol() { - throw new UnsupportedOperationException("jniSymbol"); - } - - @Override - public int maxLocals() { - return maxLocals; - } - - @Override - public int maxStackSize() { - return maxStackSize; - } - - @Override - public StackTraceElement toStackTraceElement(int bci) { - if (bci < 0 || bci >= codeSize) { - // HotSpot code can only construct stack trace elements for valid bcis - StackTraceElement ste = HotSpotGraalRuntime.getInstance().getCompilerToVM().RiMethod_toStackTraceElement(this, 0); - return new StackTraceElement(ste.getClassName(), ste.getMethodName(), ste.getFileName(), -1); - } - return HotSpotGraalRuntime.getInstance().getCompilerToVM().RiMethod_toStackTraceElement(this, bci); - } - - @Override - public ResolvedJavaMethod uniqueConcreteMethod() { - return (ResolvedJavaMethod) HotSpotGraalRuntime.getInstance().getCompilerToVM().RiMethod_uniqueConcreteMethod(this); - } - - @Override - public Signature signature() { - if (signature == null) { - signature = new HotSpotSignature(HotSpotGraalRuntime.getInstance().getCompilerToVM().RiMethod_signature(this)); - } - return signature; - } - - @Override - public String toString() { - return "HotSpotMethod<" + CodeUtil.format("%h.%n", this) + ">"; - } - - public boolean hasCompiledCode() { - return HotSpotGraalRuntime.getInstance().getCompilerToVM().RiMethod_hasCompiledCode(this); - } - - public int compiledCodeSize() { - int result = HotSpotGraalRuntime.getInstance().getCompilerToVM().RiMethod_getCompiledCodeSize(this); - if (result > 0) { - assert result > MethodEntryCounters.getCodeSize(); - result = result - MethodEntryCounters.getCodeSize(); - } - return result; - } - - @Override - public int invocationCount() { - return HotSpotGraalRuntime.getInstance().getCompilerToVM().RiMethod_invocationCount(this); - } - - @Override - public int compilationComplexity() { - if (compilationComplexity <= 0 && codeSize() > 0) { - BytecodeStream s = new BytecodeStream(code()); - int result = 0; - int currentBC; - while ((currentBC = s.currentBC()) != Bytecodes.END) { - result += Bytecodes.compilationComplexity(currentBC); - s.next(); - } - assert result > 0; - compilationComplexity = result; - } - return compilationComplexity; - } - - private static final MethodFilter profilingInfoFilter = GraalOptions.PIFilter == null ? null : new MethodFilter(GraalOptions.PIFilter); - - /** - * Determines if the profiling info cache should be used for this method. - */ - private boolean useProfilingInfoCache() { - return GraalOptions.PICache != null && (profilingInfoFilter == null || profilingInfoFilter.matches(this)); - } - - private ProfilingInfo loadProfilingInfo() { - if (!useProfilingInfoCache()) { - return null; - } - synchronized (this) { - File file = new File(GraalOptions.PICache, JniMangle.mangleMethod(holder, name, signature(), false)); - if (file.exists()) { - try { - SnapshotProfilingInfo snapshot = SnapshotProfilingInfo.load(file, HotSpotGraalRuntime.getInstance().getRuntime()); - if (snapshot.codeSize() != codeSize) { - // The class file was probably changed - ignore the saved profile - return null; - } - return snapshot; - } catch (Exception e) { - // ignore - } - } - return null; - } - } - - private void saveProfilingInfo(ProfilingInfo info) { - if (useProfilingInfoCache()) { - synchronized (this) { - String base = JniMangle.mangleMethod(holder, name, signature(), false); - File file = new File(GraalOptions.PICache, base); - File txtFile = new File(GraalOptions.PICache, base + ".txt"); - SnapshotProfilingInfo snapshot = info instanceof SnapshotProfilingInfo ? (SnapshotProfilingInfo) info : new SnapshotProfilingInfo(info); - try { - snapshot.save(file, txtFile); - } catch (IOException e) { - // ignore - } - } - } - } - - @Override - public ProfilingInfo profilingInfo() { - ProfilingInfo info = loadProfilingInfo(); - if (info != null) { - return info; - } - - if (GraalOptions.UseProfilingInformation && methodData == null) { - methodData = HotSpotGraalRuntime.getInstance().getCompilerToVM().RiMethod_methodData(this); - } - - if (methodData == null || (!methodData.hasNormalData() && !methodData.hasExtraData())) { - // Be optimistic and return false for exceptionSeen. A methodDataOop is allocated in case of a deoptimization. - info = BaseProfilingInfo.get(ExceptionSeen.FALSE); - } else { - info = new HotSpotProfilingInfo(methodData, codeSize); - saveProfilingInfo(info); - } - return info; - } - - @Override - public Map compilerStorage() { - if (compilerStorage == null) { - compilerStorage = new ConcurrentHashMap<>(); - } - return compilerStorage; - } - - @Override - public ConstantPool getConstantPool() { - return ((HotSpotTypeResolvedImpl) holder()).constantPool(); - } - - @Override - public Annotation[][] getParameterAnnotations() { - if (isConstructor()) { - Constructor javaConstructor = toJavaConstructor(); - return javaConstructor == null ? null : javaConstructor.getParameterAnnotations(); - } - Method javaMethod = toJava(); - return javaMethod == null ? null : javaMethod.getParameterAnnotations(); - } - - @Override - public T getAnnotation(Class annotationClass) { - if (isConstructor()) { - Constructor javaConstructor = toJavaConstructor(); - return javaConstructor == null ? null : javaConstructor.getAnnotation(annotationClass); - } - Method javaMethod = toJava(); - return javaMethod == null ? null : javaMethod.getAnnotation(annotationClass); - } - - @Override - public Type[] getGenericParameterTypes() { - if (isConstructor()) { - Constructor javaConstructor = toJavaConstructor(); - return javaConstructor == null ? null : javaConstructor.getGenericParameterTypes(); - } - Method javaMethod = toJava(); - return javaMethod == null ? null : javaMethod.getGenericParameterTypes(); - } - - private Method toJava() { - try { - return holder.toJava().getDeclaredMethod(name, CodeUtil.signatureToTypes(signature(), holder)); - } catch (NoSuchMethodException e) { - return null; - } - } - - private Constructor toJavaConstructor() { - try { - return holder.toJava().getDeclaredConstructor(CodeUtil.signatureToTypes(signature(), holder)); - } catch (NoSuchMethodException e) { - return null; - } - } - - @Override - public boolean canBeInlined() { - return canBeInlined; - } - - @Override - public int vtableEntryOffset() { - return HotSpotGraalRuntime.getInstance().getCompilerToVM().RiMethod_vtableEntryOffset(this); - } - - @Override - public void setCurrentTask(CompilationTask task) { - currentTask = task; - } - - @Override - public CompilationTask currentTask() { - return currentTask; - } -} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodUnresolved.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodUnresolved.java Sat Jun 09 20:10:05 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -/* - * 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.hotspot.ri; - -import com.oracle.graal.api.meta.*; - -/** - * Implementation of RiMethod for unresolved HotSpot methods. - */ -public final class HotSpotMethodUnresolved extends HotSpotMethod { - private static final long serialVersionUID = 5610263481791970079L; - private final Signature signature; - protected JavaType holder; - - public HotSpotMethodUnresolved(String name, String signature, JavaType holder) { - this.name = name; - this.holder = holder; - this.signature = new HotSpotSignature(signature); - } - - @Override - public Signature signature() { - return signature; - } - - @Override - public JavaType holder() { - return holder; - } - - @Override - public String toString() { - return "HotSpotMethod<" + holder.name() + ". " + name + ", unresolved>"; - } -} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotProfilingInfo.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotProfilingInfo.java Sat Jun 09 20:10:05 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,154 +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.hotspot.ri; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.hotspot.*; - - -public final class HotSpotProfilingInfo extends CompilerObject implements ProfilingInfo { - - private static final long serialVersionUID = -8307682725047864875L; - private static final DebugMetric metricInsufficentSpace = Debug.metric("InsufficientSpaceForProfilingData"); - - private int position; - private int hintPosition; - private int hintBCI; - private HotSpotMethodDataAccessor dataAccessor; - private HotSpotMethodData methodData; - private final int codeSize; - - public HotSpotProfilingInfo(HotSpotMethodData methodData, int codeSize) { - this.methodData = methodData; - this.codeSize = codeSize; - hintPosition = 0; - hintBCI = -1; - } - - @Override - public int codeSize() { - return codeSize; - } - - @Override - public JavaTypeProfile getTypeProfile(int bci) { - findBCI(bci, false); - return dataAccessor.getTypeProfile(methodData, position); - } - - @Override - public double getBranchTakenProbability(int bci) { - findBCI(bci, false); - return dataAccessor.getBranchTakenProbability(methodData, position); - } - - @Override - public double[] getSwitchProbabilities(int bci) { - findBCI(bci, false); - return dataAccessor.getSwitchProbabilities(methodData, position); - } - - @Override - public ExceptionSeen getExceptionSeen(int bci) { - findBCI(bci, true); - return dataAccessor.getExceptionSeen(methodData, position); - } - - @Override - public int getExecutionCount(int bci) { - findBCI(bci, false); - return dataAccessor.getExecutionCount(methodData, position); - } - - @Override - public int getDeoptimizationCount(DeoptimizationReason reason) { - return methodData.getDeoptimizationCount(reason); - } - - private void findBCI(int targetBCI, boolean searchExtraData) { - assert targetBCI >= 0 : "invalid BCI"; - - if (methodData.hasNormalData()) { - int currentPosition = targetBCI < hintBCI ? 0 : hintPosition; - HotSpotMethodDataAccessor currentAccessor; - while ((currentAccessor = methodData.getNormalData(currentPosition)) != null) { - int currentBCI = currentAccessor.getBCI(methodData, currentPosition); - if (currentBCI == targetBCI) { - normalDataFound(currentAccessor, currentPosition, currentBCI); - return; - } else if (currentBCI > targetBCI) { - break; - } - currentPosition = currentPosition + currentAccessor.getSize(methodData, currentPosition); - } - } - - boolean exceptionPossiblyNotRecorded = false; - if (searchExtraData && methodData.hasExtraData()) { - int currentPosition = methodData.getExtraDataBeginOffset(); - HotSpotMethodDataAccessor currentAccessor; - while ((currentAccessor = methodData.getExtraData(currentPosition)) != null) { - int currentBCI = currentAccessor.getBCI(methodData, currentPosition); - if (currentBCI == targetBCI) { - extraDataFound(currentAccessor, currentPosition); - return; - } - currentPosition = currentPosition + currentAccessor.getSize(methodData, currentPosition); - } - - if (!methodData.isWithin(currentPosition)) { - exceptionPossiblyNotRecorded = true; - metricInsufficentSpace.increment(); - } - } - - noDataFound(exceptionPossiblyNotRecorded); - } - - private void normalDataFound(HotSpotMethodDataAccessor data, int pos, int bci) { - setCurrentData(data, pos); - this.hintPosition = position; - this.hintBCI = bci; - } - - private void extraDataFound(HotSpotMethodDataAccessor data, int pos) { - setCurrentData(data, pos); - } - - private void noDataFound(boolean exceptionPossiblyNotRecorded) { - HotSpotMethodDataAccessor accessor = HotSpotMethodData.getNoDataAccessor(exceptionPossiblyNotRecorded); - setCurrentData(accessor, -1); - } - - private void setCurrentData(HotSpotMethodDataAccessor dataAccessor, int position) { - this.dataAccessor = dataAccessor; - this.position = position; - } - - @Override - public String toString() { - return "HotSpotProfilingInfo<" + CodeUtil.profileToString(this, null, "; ") + ">"; - } -} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRegisterConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRegisterConfig.java Sat Jun 09 20:10:05 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,210 +0,0 @@ -/* - * Copyright (c) 2011, 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.ri; - -import static com.oracle.max.asm.target.amd64.AMD64.*; - -import java.util.*; - -import com.oracle.max.asm.target.amd64.*; -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.CallingConvention.*; -import com.oracle.graal.api.code.Register.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.hotspot.*; - -public class HotSpotRegisterConfig implements RegisterConfig { - - // be careful - the contents of this array are duplicated in graal_CodeInstaller.cpp - private final Register[] allocatable = { - rax, rbx, rcx, rdx, rsi, rdi, r8, r9, /* r10, */r11, r12, r13, r14, /*r15*/ - xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, - xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 - }; - - private final EnumMap categorized = Register.categorize(allocatable); - - private final RegisterAttributes[] attributesMap; - - @Override - public Register[] getAllocatableRegisters() { - return allocatable; - } - - @Override - public EnumMap getCategorizedAllocatableRegisters() { - return categorized; - } - - @Override - public RegisterAttributes[] getAttributesMap() { - return attributesMap; - } - - private final Register[] generalParameterRegisters; - private final Register[] xmmParameterRegisters = {xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7}; - private final Register[] allParameterRegisters; - - private final CalleeSaveLayout csl; - - public HotSpotRegisterConfig(HotSpotVMConfig config, boolean globalStubConfig) { - if (config.windowsOs) { - generalParameterRegisters = new Register[] {rdx, r8, r9, rdi, rsi, rcx}; - } else { - generalParameterRegisters = new Register[] {rsi, rdx, rcx, r8, r9, rdi}; - } - - if (globalStubConfig) { - Register[] regs = { - rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, - r8, r9, r10, r11, r12, r13, r14, r15, - xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, - xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 - }; - csl = new CalleeSaveLayout(0, -1, 8, regs); - } else { - // We reserve space for saving RBP but don't explicitly specify - // it as a callee save register since we explicitly do the saving - // with push and pop in HotSpotFrameContext - final int size = 8; - final Register[] regs = {}; - csl = new CalleeSaveLayout(0, size, 8, regs); - } - - attributesMap = RegisterAttributes.createMap(this, AMD64.allRegisters); - allParameterRegisters = Arrays.copyOf(generalParameterRegisters, generalParameterRegisters.length + xmmParameterRegisters.length); - System.arraycopy(xmmParameterRegisters, 0, allParameterRegisters, generalParameterRegisters.length, xmmParameterRegisters.length); - } - - @Override - public Register[] getCallerSaveRegisters() { - return getAllocatableRegisters(); - } - - @Override - public Register getRegisterForRole(int index) { - throw new UnsupportedOperationException(); - } - - @Override - public CallingConvention getCallingConvention(Type type, Kind[] parameters, TargetDescription target, boolean stackOnly) { - if (type == Type.NativeCall) { - throw new UnsupportedOperationException(); - } - return callingConvention(parameters, type, target, stackOnly); - } - - public Register[] getCallingConventionRegisters(Type type, RegisterFlag flag) { - return allParameterRegisters; - } - - private CallingConvention callingConvention(Kind[] types, Type type, TargetDescription target, boolean stackOnly) { - Value[] locations = new Value[types.length]; - - int currentGeneral = 0; - int currentXMM = 0; - int currentStackOffset = 0; - - for (int i = 0; i < types.length; i++) { - final Kind kind = types[i]; - - switch (kind) { - case Byte: - case Boolean: - case Short: - case Char: - case Int: - case Long: - case Object: - if (!stackOnly && currentGeneral < generalParameterRegisters.length) { - Register register = generalParameterRegisters[currentGeneral++]; - locations[i] = register.asValue(kind); - } - break; - case Float: - case Double: - if (!stackOnly && currentXMM < xmmParameterRegisters.length) { - Register register = xmmParameterRegisters[currentXMM++]; - locations[i] = register.asValue(kind); - } - break; - default: - throw GraalInternalError.shouldNotReachHere(); - } - - if (locations[i] == null) { - locations[i] = StackSlot.get(kind.stackKind(), currentStackOffset, !type.out); - currentStackOffset += Math.max(target.sizeInBytes(kind), target.wordSize); - } - } - - return new CallingConvention(locations, currentStackOffset); - } - - @Override - public Register getReturnRegister(Kind kind) { - switch (kind) { - case Boolean: - case Byte: - case Char: - case Short: - case Int: - case Long: - case Object: - return rax; - case Float: - case Double: - return xmm0; - case Void: - case Illegal: - return null; - default: - throw new UnsupportedOperationException("no return register for type " + kind); - } - } - - @Override - public Register getScratchRegister() { - return r10; - } - - @Override - public Register getFrameRegister() { - return rsp; - } - - public CalleeSaveLayout getCalleeSaveLayout() { - return csl; - } - - @Override - public String toString() { - String res = String.format( - "Allocatable: " + Arrays.toString(getAllocatableRegisters()) + "%n" + - "CallerSave: " + Arrays.toString(getCallerSaveRegisters()) + "%n" + - "CalleeSave: " + getCalleeSaveLayout() + "%n" + - "Scratch: " + getScratchRegister() + "%n"); - return res; - } -} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java Sat Jun 09 20:10:05 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,540 +0,0 @@ -/* - * Copyright (c) 2011, 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.ri; - -import static com.oracle.max.cri.util.MemoryBarriers.*; - -import java.lang.reflect.*; -import java.util.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.CompilationResult.*; -import com.oracle.graal.api.code.CodeUtil.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.meta.JavaType.*; -import com.oracle.graal.compiler.*; -import com.oracle.graal.compiler.target.*; -import com.oracle.graal.cri.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.nodes.*; -import com.oracle.graal.hotspot.snippets.*; -import com.oracle.graal.hotspot.target.amd64.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.type.*; -import com.oracle.graal.snippets.*; -import com.oracle.max.criutils.*; - -/** - * CRI runtime implementation for the HotSpot VM. - */ -public class HotSpotRuntime implements ExtendedRiRuntime { - public final HotSpotVMConfig config; - final HotSpotRegisterConfig regConfig; - private final HotSpotRegisterConfig globalStubRegConfig; - private final HotSpotGraalRuntime compiler; - private CheckCastSnippets.Templates checkcasts; - - public HotSpotRuntime(HotSpotVMConfig config, HotSpotGraalRuntime compiler) { - this.config = config; - this.compiler = compiler; - regConfig = new HotSpotRegisterConfig(config, false); - globalStubRegConfig = new HotSpotRegisterConfig(config, true); - - System.setProperty(Backend.BACKEND_CLASS_PROPERTY, HotSpotAMD64Backend.class.getName()); - } - - public void installSnippets() { - Snippets.install(this, compiler.getTarget(), new SystemSnippets()); - Snippets.install(this, compiler.getTarget(), new UnsafeSnippets()); - Snippets.install(this, compiler.getTarget(), new ArrayCopySnippets()); - Snippets.install(this, compiler.getTarget(), new CheckCastSnippets()); - checkcasts = new CheckCastSnippets.Templates(this); - } - - - public HotSpotGraalRuntime getCompiler() { - return compiler; - } - - @Override - public String disassemble(CodeInfo info, CompilationResult tm) { - byte[] code = info.code(); - TargetDescription target = compiler.getTarget(); - HexCodeFile hcf = new HexCodeFile(code, info.start(), target.arch.name, target.wordSize * 8); - if (tm != null) { - HexCodeFile.addAnnotations(hcf, tm.annotations()); - addExceptionHandlersComment(tm, hcf); - Register fp = regConfig.getFrameRegister(); - RefMapFormatter slotFormatter = new RefMapFormatter(target.arch, target.wordSize, fp, 0); - for (Safepoint safepoint : tm.safepoints) { - if (safepoint instanceof Call) { - Call call = (Call) safepoint; - if (call.debugInfo != null) { - hcf.addComment(call.pcOffset + call.size, CodeUtil.append(new StringBuilder(100), call.debugInfo, slotFormatter).toString()); - } - addOperandComment(hcf, call.pcOffset, "{" + getTargetName(call) + "}"); - } else { - if (safepoint.debugInfo != null) { - hcf.addComment(safepoint.pcOffset, CodeUtil.append(new StringBuilder(100), safepoint.debugInfo, slotFormatter).toString()); - } - addOperandComment(hcf, safepoint.pcOffset, "{safepoint}"); - } - } - for (DataPatch site : tm.dataReferences) { - hcf.addOperandComment(site.pcOffset, "{" + site.constant + "}"); - } - for (Mark mark : tm.marks) { - hcf.addComment(mark.pcOffset, getMarkName(mark)); - } - } - return hcf.toEmbeddedString(); - } - - /** - * Decodes a call target to a mnemonic if possible. - */ - private String getTargetName(Call call) { - Field[] fields = config.getClass().getDeclaredFields(); - for (Field f : fields) { - if (f.getName().endsWith("Stub")) { - f.setAccessible(true); - try { - if (f.get(config).equals(call.target)) { - return f.getName(); - } - } catch (Exception e) { - } - } - } - return String.valueOf(call.target); - } - - /** - * Decodes a mark to a mnemonic if possible. - */ - private static String getMarkName(Mark mark) { - Field[] fields = HotSpotXirGenerator.class.getDeclaredFields(); - for (Field f : fields) { - if (Modifier.isStatic(f.getModifiers()) && f.getName().startsWith("MARK_")) { - f.setAccessible(true); - try { - if (f.get(null).equals(mark.id)) { - return f.getName(); - } - } catch (Exception e) { - } - } - } - return "MARK:" + mark.id; - } - - private static void addExceptionHandlersComment(CompilationResult tm, HexCodeFile hcf) { - if (!tm.exceptionHandlers.isEmpty()) { - String nl = HexCodeFile.NEW_LINE; - StringBuilder buf = new StringBuilder("------ Exception Handlers ------").append(nl); - for (CompilationResult.ExceptionHandler e : tm.exceptionHandlers) { - buf.append(" "). - append(e.pcOffset).append(" -> "). - append(e.handlerPos). - append(nl); - hcf.addComment(e.pcOffset, "[exception -> " + e.handlerPos + "]"); - hcf.addComment(e.handlerPos, "[exception handler for " + e.pcOffset + "]"); - } - hcf.addComment(0, buf.toString()); - } - } - - private static void addOperandComment(HexCodeFile hcf, int pos, String comment) { - String oldValue = hcf.addOperandComment(pos, comment); - assert oldValue == null : "multiple comments for operand of instruction at " + pos + ": " + comment + ", " + oldValue; - } - - @Override - public String disassemble(ResolvedJavaMethod method) { - return compiler.getCompilerToVM().disassembleJava((HotSpotMethodResolved) method); - } - - @Override - public ResolvedJavaType getResolvedJavaType(Kind kind) { - return (ResolvedJavaType) compiler.getCompilerToVM().getType(kind.toJavaClass()); - } - - @Override - public ResolvedJavaType getTypeOf(Constant constant) { - return (ResolvedJavaType) compiler.getCompilerToVM().getRiType(constant); - } - - @Override - public int sizeOfLockData() { - // TODO shouldn't be hard coded - return 8; - } - - @Override - public boolean areConstantObjectsEqual(Constant x, Constant y) { - return compiler.getCompilerToVM().compareConstantObjects(x, y); - } - - @Override - public RegisterConfig getRegisterConfig(JavaMethod method) { - return regConfig; - } - - /** - * HotSpots needs an area suitable for storing a program counter for temporary use during the deoptimization process. - */ - @Override - public int getCustomStackAreaSize() { - // TODO shouldn't be hard coded - return 8; - } - - @Override - public int getMinimumOutgoingSize() { - return config.runtimeCallStackSize; - } - - @Override - public int getArrayLength(Constant array) { - return compiler.getCompilerToVM().getArrayLength(array); - } - - @Override - public void lower(Node n, CiLoweringTool tool) { - StructuredGraph graph = (StructuredGraph) n.graph(); - - if (n instanceof ArrayLengthNode) { - ArrayLengthNode arrayLengthNode = (ArrayLengthNode) n; - SafeReadNode safeReadArrayLength = safeReadArrayLength(arrayLengthNode.array(), StructuredGraph.INVALID_GRAPH_ID); - graph.replaceFixedWithFixed(arrayLengthNode, safeReadArrayLength); - } else if (n instanceof LoadFieldNode) { - LoadFieldNode field = (LoadFieldNode) n; - int displacement = ((HotSpotField) field.field()).offset(); - assert field.kind() != Kind.Illegal; - ReadNode memoryRead = graph.add(new ReadNode(field.object(), LocationNode.create(field.field(), field.field().kind(), displacement, graph), field.stamp())); - memoryRead.dependencies().add(tool.createNullCheckGuard(field.object(), field.leafGraphId())); - graph.replaceFixedWithFixed(field, memoryRead); - if (field.isVolatile()) { - MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_READ)); - graph.addBeforeFixed(memoryRead, preMembar); - MembarNode postMembar = graph.add(new MembarNode(JMM_POST_VOLATILE_READ)); - graph.addAfterFixed(memoryRead, postMembar); - } - } else if (n instanceof StoreFieldNode) { - StoreFieldNode storeField = (StoreFieldNode) n; - HotSpotField field = (HotSpotField) storeField.field(); - WriteNode memoryWrite = graph.add(new WriteNode(storeField.object(), storeField.value(), LocationNode.create(storeField.field(), storeField.field().kind(), field.offset(), graph))); - memoryWrite.dependencies().add(tool.createNullCheckGuard(storeField.object(), storeField.leafGraphId())); - memoryWrite.setStateAfter(storeField.stateAfter()); - graph.replaceFixedWithFixed(storeField, memoryWrite); - - FixedWithNextNode last = memoryWrite; - if (field.kind() == Kind.Object && !memoryWrite.value().isNullConstant()) { - FieldWriteBarrier writeBarrier = graph.add(new FieldWriteBarrier(memoryWrite.object())); - graph.addAfterFixed(memoryWrite, writeBarrier); - last = writeBarrier; - } - if (storeField.isVolatile()) { - MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_WRITE)); - graph.addBeforeFixed(memoryWrite, preMembar); - MembarNode postMembar = graph.add(new MembarNode(JMM_POST_VOLATILE_WRITE)); - graph.addAfterFixed(last, postMembar); - } - } else if (n instanceof CompareAndSwapNode) { - // Separate out GC barrier semantics - CompareAndSwapNode cas = (CompareAndSwapNode) n; - ValueNode expected = cas.expected(); - if (expected.kind() == Kind.Object && !cas.newValue().isNullConstant()) { - ResolvedJavaType type = cas.object().objectStamp().type(); - if (type != null && !type.isArrayClass() && type.toJava() != Object.class) { - // Use a field write barrier since it's not an array store - FieldWriteBarrier writeBarrier = graph.add(new FieldWriteBarrier(cas.object())); - graph.addAfterFixed(cas, writeBarrier); - } else { - // This may be an array store so use an array write barrier - LocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, cas.expected().kind(), cas.displacement(), cas.offset(), graph, false); - graph.addAfterFixed(cas, graph.add(new ArrayWriteBarrier(cas.object(), location))); - } - } - } else if (n instanceof LoadIndexedNode) { - LoadIndexedNode loadIndexed = (LoadIndexedNode) n; - - ValueNode boundsCheck = createBoundsCheck(loadIndexed, tool); - - Kind elementKind = loadIndexed.elementKind(); - LocationNode arrayLocation = createArrayLocation(graph, elementKind, loadIndexed.index()); - ReadNode memoryRead = graph.add(new ReadNode(loadIndexed.array(), arrayLocation, loadIndexed.stamp())); - memoryRead.dependencies().add(boundsCheck); - graph.replaceFixedWithFixed(loadIndexed, memoryRead); - } else if (n instanceof StoreIndexedNode) { - StoreIndexedNode storeIndexed = (StoreIndexedNode) n; - ValueNode boundsCheck = createBoundsCheck(storeIndexed, tool); - - Kind elementKind = storeIndexed.elementKind(); - LocationNode arrayLocation = createArrayLocation(graph, elementKind, storeIndexed.index()); - ValueNode value = storeIndexed.value(); - CheckCastNode checkcast = null; - ValueNode array = storeIndexed.array(); - if (elementKind == Kind.Object && !value.isNullConstant()) { - // Store check! - ResolvedJavaType arrayType = array.objectStamp().type(); - if (arrayType != null && array.objectStamp().isExactType()) { - ResolvedJavaType elementType = arrayType.componentType(); - if (elementType.superType() != null) { - ConstantNode type = ConstantNode.forCiConstant(elementType.getEncoding(Representation.ObjectHub), this, graph); - checkcast = graph.add(new CheckCastNode(type, elementType, value)); - graph.addBeforeFixed(storeIndexed, checkcast); - value = checkcast; - } else { - assert elementType.name().equals("Ljava/lang/Object;") : elementType.name(); - } - } else { - ValueNode guard = tool.createNullCheckGuard(array, StructuredGraph.INVALID_GRAPH_ID); - FloatingReadNode arrayClass = graph.unique(new FloatingReadNode(array, LocationNode.create(LocationNode.FINAL_LOCATION, Kind.Object, config.hubOffset, graph), null, StampFactory.objectNonNull())); - arrayClass.dependencies().add(guard); - FloatingReadNode arrayElementKlass = graph.unique(new FloatingReadNode(arrayClass, LocationNode.create(LocationNode.FINAL_LOCATION, Kind.Object, config.arrayClassElementOffset, graph), null, StampFactory.objectNonNull())); - checkcast = graph.add(new CheckCastNode(arrayElementKlass, null, value)); - graph.addBeforeFixed(storeIndexed, checkcast); - value = checkcast; - } - } - WriteNode memoryWrite = graph.add(new WriteNode(array, value, arrayLocation)); - memoryWrite.dependencies().add(boundsCheck); - memoryWrite.setStateAfter(storeIndexed.stateAfter()); - - graph.replaceFixedWithFixed(storeIndexed, memoryWrite); - - if (elementKind == Kind.Object && !value.isNullConstant()) { - graph.addAfterFixed(memoryWrite, graph.add(new ArrayWriteBarrier(array, arrayLocation))); - } - } else if (n instanceof UnsafeLoadNode) { - UnsafeLoadNode load = (UnsafeLoadNode) n; - assert load.kind() != Kind.Illegal; - IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, load.loadKind(), load.displacement(), load.offset(), graph, false); - ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, load.stamp())); - memoryRead.dependencies().add(tool.createNullCheckGuard(load.object(), StructuredGraph.INVALID_GRAPH_ID)); - graph.replaceFixedWithFixed(load, memoryRead); - } else if (n instanceof UnsafeStoreNode) { - UnsafeStoreNode store = (UnsafeStoreNode) n; - IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, store.storeKind(), store.displacement(), store.offset(), graph, false); - WriteNode write = graph.add(new WriteNode(store.object(), store.value(), location)); - write.setStateAfter(store.stateAfter()); - graph.replaceFixedWithFixed(store, write); - if (write.value().kind() == Kind.Object && !write.value().isNullConstant()) { - FieldWriteBarrier barrier = graph.add(new FieldWriteBarrier(write.object())); - graph.addBeforeFixed(write, barrier); - } - } else if (n instanceof ReadHubNode) { - ReadHubNode objectClassNode = (ReadHubNode) n; - LocationNode location = LocationNode.create(LocationNode.FINAL_LOCATION, Kind.Object, config.hubOffset, graph); - ReadNode memoryRead = graph.add(new ReadNode(objectClassNode.object(), location, StampFactory.objectNonNull())); - memoryRead.dependencies().add(tool.createNullCheckGuard(objectClassNode.object(), StructuredGraph.INVALID_GRAPH_ID)); - graph.replaceFixed(objectClassNode, memoryRead); - } else if (n instanceof CheckCastNode) { - if (shouldLowerCheckcast(graph)) { - checkcasts.lower((CheckCastNode) n, tool); - } - } else { - assert false : "Node implementing Lowerable not handled: " + n; - } - } - - private static boolean shouldLowerCheckcast(StructuredGraph graph) { - String option = GraalOptions.HIRLowerCheckcast; - if (option != null) { - if (option.length() == 0) { - return true; - } - ResolvedJavaMethod method = graph.method(); - return method != null && CodeUtil.format("%H.%n", method).contains(option); - } - return false; - } - - private IndexedLocationNode createArrayLocation(Graph graph, Kind elementKind, ValueNode index) { - return IndexedLocationNode.create(LocationNode.getArrayLocation(elementKind), elementKind, config.getArrayOffset(elementKind), index, graph, true); - } - - private SafeReadNode safeReadArrayLength(ValueNode array, long leafGraphId) { - return safeRead(array.graph(), Kind.Int, array, config.arrayLengthOffset, StampFactory.positiveInt(), leafGraphId); - } - - private static ValueNode createBoundsCheck(AccessIndexedNode n, CiLoweringTool tool) { - StructuredGraph graph = (StructuredGraph) n.graph(); - ArrayLengthNode arrayLength = graph.add(new ArrayLengthNode(n.array())); - ValueNode guard = tool.createGuard(graph.unique(new IntegerBelowThanNode(n.index(), arrayLength)), DeoptimizationReason.BoundsCheckException, DeoptimizationAction.InvalidateReprofile, n.leafGraphId()); - - graph.addBeforeFixed(n, arrayLength); - return guard; - } - - @Override - public StructuredGraph intrinsicGraph(ResolvedJavaMethod caller, int bci, ResolvedJavaMethod method, List parameters) { - JavaType holder = method.holder(); - String fullName = method.name() + method.signature().asString(); - String holderName = holder.name(); - if (holderName.equals("Ljava/lang/Object;")) { - if (fullName.equals("getClass()Ljava/lang/Class;")) { - ValueNode obj = (ValueNode) parameters.get(0); - ObjectStamp stamp = (ObjectStamp) obj.stamp(); - if (stamp.nonNull() && stamp.isExactType()) { - StructuredGraph graph = new StructuredGraph(); - ValueNode result = ConstantNode.forObject(stamp.type().toJava(), this, graph); - ReturnNode ret = graph.add(new ReturnNode(result)); - graph.start().setNext(ret); - return graph; - } - StructuredGraph graph = new StructuredGraph(); - LocalNode receiver = graph.unique(new LocalNode(0, StampFactory.objectNonNull())); - SafeReadNode klassOop = safeReadHub(graph, receiver, StructuredGraph.INVALID_GRAPH_ID); - Stamp resultStamp = StampFactory.declaredNonNull(getResolvedJavaType(Class.class)); - FloatingReadNode result = graph.unique(new FloatingReadNode(klassOop, LocationNode.create(LocationNode.FINAL_LOCATION, Kind.Object, config.classMirrorOffset, graph), null, resultStamp)); - ReturnNode ret = graph.add(new ReturnNode(result)); - graph.start().setNext(klassOop); - klassOop.setNext(ret); - return graph; - } - } else if (holderName.equals("Ljava/lang/Class;")) { - if (fullName.equals("getModifiers()I")) { - StructuredGraph graph = new StructuredGraph(); - LocalNode receiver = graph.unique(new LocalNode(0, StampFactory.objectNonNull())); - SafeReadNode klassOop = safeRead(graph, Kind.Object, receiver, config.klassOopOffset, StampFactory.objectNonNull(), StructuredGraph.INVALID_GRAPH_ID); - graph.start().setNext(klassOop); - // TODO(thomaswue): Care about primitive classes! Crashes for primitive classes at the moment (klassOop == null) - FloatingReadNode result = graph.unique(new FloatingReadNode(klassOop, LocationNode.create(LocationNode.FINAL_LOCATION, Kind.Int, config.klassModifierFlagsOffset, graph), null, StampFactory.intValue())); - ReturnNode ret = graph.add(new ReturnNode(result)); - klassOop.setNext(ret); - return graph; - } - } else if (holderName.equals("Ljava/lang/Thread;")) { - if (fullName.equals("currentThread()Ljava/lang/Thread;")) { - StructuredGraph graph = new StructuredGraph(); - ReturnNode ret = graph.add(new ReturnNode(graph.unique(new CurrentThread(config.threadObjectOffset, this)))); - graph.start().setNext(ret); - return graph; - } - } - return null; - } - - private SafeReadNode safeReadHub(Graph graph, ValueNode value, long leafGraphId) { - return safeRead(graph, Kind.Object, value, config.hubOffset, StampFactory.objectNonNull(), leafGraphId); - } - - private static SafeReadNode safeRead(Graph graph, Kind kind, ValueNode value, int offset, Stamp stamp, long leafGraphId) { - return graph.add(new SafeReadNode(value, LocationNode.create(LocationNode.FINAL_LOCATION, kind, offset, graph), stamp, leafGraphId)); - } - - public ResolvedJavaType getResolvedJavaType(Class clazz) { - return (ResolvedJavaType) compiler.getCompilerToVM().getType(clazz); - } - - public Object asCallTarget(Object target) { - return target; - } - - public long getMaxCallTargetOffset(RuntimeCall rtcall) { - return compiler.getCompilerToVM().getMaxCallTargetOffset(rtcall); - } - - public ResolvedJavaMethod getResolvedJavaMethod(Method reflectionMethod) { - return (ResolvedJavaMethod) compiler.getCompilerToVM().getRiMethod(reflectionMethod); - } - - private static HotSpotCodeInfo makeInfo(ResolvedJavaMethod method, CompilationResult code, CodeInfo[] info) { - HotSpotCodeInfo hsInfo = null; - if (info != null && info.length > 0) { - hsInfo = new HotSpotCodeInfo(code, (HotSpotMethodResolved) method); - info[0] = hsInfo; - } - return hsInfo; - } - - public void installMethod(ResolvedJavaMethod method, CompilationResult code, CodeInfo[] info) { - HotSpotCodeInfo hsInfo = makeInfo(method, code, info); - compiler.getCompilerToVM().installMethod(new HotSpotTargetMethod((HotSpotMethodResolved) method, code), true, hsInfo); - } - - @Override - public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult code, CodeInfo[] info) { - HotSpotCodeInfo hsInfo = makeInfo(method, code, info); - return compiler.getCompilerToVM().installMethod(new HotSpotTargetMethod((HotSpotMethodResolved) method, code), false, hsInfo); - } - - @Override - public RegisterConfig getGlobalStubRegisterConfig() { - return globalStubRegConfig; - } - - @Override - public CompilationResult compile(ResolvedJavaMethod method, StructuredGraph graph) { - OptimisticOptimizations optimisticOpts = OptimisticOptimizations.ALL; - return compiler.getCompiler().compileMethod(method, graph, -1, compiler.getCache(), compiler.getVMToCompiler().createPhasePlan(optimisticOpts), optimisticOpts); - } - - @Override - public int encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason) { - final int actionShift = 0; - final int reasonShift = 3; - - int actionValue = convertDeoptAction(action); - int reasonValue = convertDeoptReason(reason); - return (~(((reasonValue) << reasonShift) + ((actionValue) << actionShift))); - } - - @Override - public int convertDeoptAction(DeoptimizationAction action) { - switch(action) { - case None: return 0; - case RecompileIfTooManyDeopts: return 1; - case InvalidateReprofile: return 2; - case InvalidateRecompile: return 3; - case InvalidateStopCompiling: return 4; - default: throw GraalInternalError.shouldNotReachHere(); - } - } - - @Override - public int convertDeoptReason(DeoptimizationReason reason) { - switch(reason) { - case None: return 0; - case NullCheckException: return 1; - case BoundsCheckException: return 2; - case ClassCastException: return 3; - case ArrayStoreException: return 4; - case UnreachedCode: return 5; - case TypeCheckedInliningViolated: return 6; - case OptimizedTypeCheckViolated: return 7; - case NotCompiledExceptionHandler: return 8; - case Unresolved: return 9; - case JavaSubroutineMismatch: return 10; - case ArithmeticException: return 11; - case RuntimeConstraint: return 12; - default: throw GraalInternalError.shouldNotReachHere(); - } - } -} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotSignature.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotSignature.java Sat Jun 09 20:10:05 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,149 +0,0 @@ -/* - * 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.hotspot.ri; - -import java.util.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.hotspot.*; -import com.oracle.graal.java.*; - -/** - * Represents a method signature. - */ -public class HotSpotSignature extends CompilerObject implements Signature { - - private static final long serialVersionUID = -2890917956072366116L; - private final List arguments = new ArrayList<>(); - private final String returnType; - private final String originalString; - private JavaType[] argumentTypes; - private JavaType returnTypeCache; - - public HotSpotSignature(String signature) { - assert signature.length() > 0; - this.originalString = signature; - - if (signature.charAt(0) == '(') { - int cur = 1; - while (cur < signature.length() && signature.charAt(cur) != ')') { - int nextCur = parseSignature(signature, cur); - arguments.add(signature.substring(cur, nextCur)); - cur = nextCur; - } - - cur++; - int nextCur = parseSignature(signature, cur); - returnType = signature.substring(cur, nextCur); - assert nextCur == signature.length(); - } else { - returnType = null; - } - } - - private static int parseSignature(String signature, int start) { - int cur = start; - char first; - do { - first = signature.charAt(cur++); - } while (first == '['); - - switch (first) { - case 'L': - while (signature.charAt(cur) != ';') { - cur++; - } - cur++; - break; - case 'V': - case 'I': - case 'B': - case 'C': - case 'D': - case 'F': - case 'J': - case 'S': - case 'Z': - break; - default: - assert false; - } - return cur; - } - - @Override - public int argumentCount(boolean withReceiver) { - return arguments.size() + (withReceiver ? 1 : 0); - } - - @Override - public Kind argumentKindAt(int index) { - return Kind.fromTypeString(arguments.get(index)); - } - - @Override - public int argumentSlots(boolean withReceiver) { - int argSlots = 0; - for (int i = 0; i < argumentCount(false); i++) { - argSlots += FrameStateBuilder.stackSlots(argumentKindAt(i)); - } - return argSlots + (withReceiver ? 1 : 0); - } - - @Override - public JavaType argumentTypeAt(int index, ResolvedJavaType accessingClass) { - if (argumentTypes == null) { - argumentTypes = new JavaType[arguments.size()]; - } - JavaType type = argumentTypes[index]; - if (type == null || !(type instanceof ResolvedJavaType)) { - type = HotSpotGraalRuntime.getInstance().lookupType(arguments.get(index), (HotSpotTypeResolved) accessingClass, true); - argumentTypes[index] = type; - } - return type; - } - - @Override - public String asString() { - return originalString; - } - - @Override - public Kind returnKind() { - return Kind.fromTypeString(returnType); - } - - @Override - public JavaType returnType(JavaType accessingClass) { - if (returnTypeCache == null) { - returnTypeCache = HotSpotGraalRuntime.getInstance().lookupType(returnType, (HotSpotTypeResolved) accessingClass, false); - } - return returnTypeCache; - } - - @Override - public String toString() { - return "HotSpotSignature<" + originalString + ">"; - } - -} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotType.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotType.java Sat Jun 09 20:10:05 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -/* - * 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.hotspot.ri; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.hotspot.*; - -/** - * Common interface for all HotSpot RiType-implementations. - */ -public abstract class HotSpotType extends CompilerObject implements JavaType { - private static final long serialVersionUID = -4252886265301910771L; - protected String name; - - @Override - public final String name() { - return name; - } - - /** - * Gets the object representing the C++ klassOop for this type. - * Such a value cannot be safely exposed to Java code. - */ - public abstract HotSpotKlassOop klassOop(); -} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotTypePrimitive.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotTypePrimitive.java Sat Jun 09 20:10:05 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,177 +0,0 @@ -/* - * 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.hotspot.ri; - -import java.lang.annotation.*; -import java.lang.reflect.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.hotspot.*; - -/** - * Implementation of RiType for primitive HotSpot types. - */ -public final class HotSpotTypePrimitive extends HotSpotType implements ResolvedJavaType { - - private static final long serialVersionUID = -6208552348908071473L; - private Kind kind; - private final HotSpotKlassOop klassOop; - - public HotSpotTypePrimitive(Kind kind) { - this.kind = kind; - this.name = String.valueOf(Character.toUpperCase(kind.typeChar)); - this.klassOop = new HotSpotKlassOop(kind.toJavaClass()); - } - - @Override - public int accessFlags() { - assert kind != null && kind.toJavaClass() != null; - return Modifier.ABSTRACT | Modifier.FINAL | Modifier.PUBLIC; - } - - @Override - public ResolvedJavaType arrayOf() { - return (ResolvedJavaType) HotSpotGraalRuntime.getInstance().getCompilerToVM().getPrimitiveArrayType(kind); - } - - @Override - public ResolvedJavaType componentType() { - return null; - } - - @Override - public ResolvedJavaType exactType() { - return this; - } - - @Override - public ResolvedJavaType superType() { - return null; - } - - @Override - public ResolvedJavaType leastCommonAncestor(ResolvedJavaType otherType) { - return null; - } - - @Override - public Constant getEncoding(Representation r) { - throw GraalInternalError.unimplemented("HotSpotTypePrimitive.getEncoding"); - } - - @Override - public Kind getRepresentationKind(Representation r) { - return kind; - } - - @Override - public boolean hasFinalizableSubclass() { - return false; - } - - @Override - public boolean hasFinalizer() { - return false; - } - - @Override - public boolean isArrayClass() { - return false; - } - - @Override - public boolean isInitialized() { - return true; - } - - @Override - public boolean isInstance(Constant obj) { - return false; - } - - @Override - public boolean isInstanceClass() { - return false; - } - - @Override - public boolean isInterface() { - return false; - } - - @Override - public boolean isSubtypeOf(ResolvedJavaType other) { - return false; - } - - @Override - public Kind kind() { - return kind; - } - - @Override - public ResolvedJavaMethod resolveMethodImpl(ResolvedJavaMethod method) { - return null; - } - - @Override - public String toString() { - return "HotSpotTypePrimitive<" + kind + ">"; - } - - @Override - public ResolvedJavaType uniqueConcreteSubtype() { - return this; - } - - @Override - public ResolvedJavaMethod uniqueConcreteMethod(ResolvedJavaMethod method) { - return null; - } - - @Override - public ResolvedJavaField[] declaredFields() { - return null; - } - - @Override - public T getAnnotation(Class annotationClass) { - return toJava().getAnnotation(annotationClass); - } - - @Override - public Class< ? > toJava() { - return kind.toJavaClass(); - } - - @Override - public ResolvedJavaType resolve(ResolvedJavaType accessingClass) { - return this; - } - - @Override - public HotSpotKlassOop klassOop() { - return klassOop; - } -} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotTypeResolved.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotTypeResolved.java Sat Jun 09 20:10:05 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -/* - * 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.hotspot.ri; - -import com.oracle.graal.api.meta.*; - -public interface HotSpotTypeResolved extends ResolvedJavaType { - - String toString(); - - ConstantPool constantPool(); - - int instanceSize(); - - JavaField createRiField(String name, JavaType type, int offset, int flags); - - HotSpotKlassOop klassOop(); -} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotTypeResolvedImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotTypeResolvedImpl.java Sat Jun 09 20:10:05 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,281 +0,0 @@ -/* - * 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.hotspot.ri; - -import java.lang.annotation.*; -import java.lang.reflect.*; -import java.util.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.hotspot.*; - -/** - * Implementation of RiType for resolved non-primitive HotSpot classes. - */ -public final class HotSpotTypeResolvedImpl extends HotSpotType implements HotSpotTypeResolved { - - private static final long serialVersionUID = 3481514353553840471L; - - private Class javaMirror; - private String simpleName; - private int accessFlags; - private boolean hasFinalizer; - private boolean hasFinalizableSubclass; - private int superCheckOffset; - private boolean isArrayClass; - private boolean isInstanceClass; - private boolean isInterface; - private int instanceSize; - private HashMap fieldCache; - private ResolvedJavaType superType; - private boolean superTypeSet; - private ResolvedJavaField[] fields; - private ConstantPool constantPool; - private boolean isInitialized; - private ResolvedJavaType arrayOfType; - - private HotSpotTypeResolvedImpl() { - } - - @Override - public int accessFlags() { - return accessFlags; - } - - @Override - public ResolvedJavaType arrayOf() { - if (arrayOfType == null) { - arrayOfType = (ResolvedJavaType) HotSpotGraalRuntime.getInstance().getCompilerToVM().RiType_arrayOf(this); - } - return arrayOfType; - } - - @Override - public ResolvedJavaType componentType() { - assert isArrayClass(); - return (ResolvedJavaType) HotSpotGraalRuntime.getInstance().getCompilerToVM().RiType_componentType(this); - } - - @Override - public ResolvedJavaType uniqueConcreteSubtype() { - if (isArrayClass()) { - return Modifier.isFinal(componentType().accessFlags()) ? this : null; - } else { - return (ResolvedJavaType) HotSpotGraalRuntime.getInstance().getCompilerToVM().RiType_uniqueConcreteSubtype(this); - } - } - - @Override - public ResolvedJavaType superType() { - if (!superTypeSet) { - superType = (ResolvedJavaType) HotSpotGraalRuntime.getInstance().getCompilerToVM().RiType_superType(this); - superTypeSet = true; - } - return superType; - } - - @Override - public ResolvedJavaType leastCommonAncestor(ResolvedJavaType otherType) { - if (otherType instanceof HotSpotTypePrimitive) { - return null; - } else { - return (ResolvedJavaType) HotSpotGraalRuntime.getInstance().getCompilerToVM().RiType_leastCommonAncestor(this, (HotSpotTypeResolved) otherType); - } - } - - @Override - public ResolvedJavaType exactType() { - if (Modifier.isFinal(accessFlags)) { - return this; - } - return null; - } - - @Override - public Constant getEncoding(Representation r) { - switch (r) { - case JavaClass: - return Constant.forObject(javaMirror); - case ObjectHub: - return Constant.forObject(klassOop()); - case StaticFields: - return Constant.forObject(javaMirror); - default: - return null; - } - } - - @Override - public Kind getRepresentationKind(Representation r) { - return Kind.Object; - } - - @Override - public boolean hasFinalizableSubclass() { - return hasFinalizableSubclass; - } - - @Override - public boolean hasFinalizer() { - return hasFinalizer; - } - - @Override - public boolean isArrayClass() { - return isArrayClass; - } - - @Override - public boolean isInitialized() { - if (!isInitialized) { - isInitialized = HotSpotGraalRuntime.getInstance().getCompilerToVM().RiType_isInitialized(this); - } - return isInitialized; - } - - @Override - public boolean isInstance(Constant obj) { - return javaMirror.isInstance(obj); - } - - @Override - public boolean isInstanceClass() { - return isInstanceClass; - } - - @Override - public boolean isInterface() { - return isInterface; - } - - @Override - public boolean isSubtypeOf(ResolvedJavaType other) { - if (other instanceof HotSpotTypeResolved) { - return HotSpotGraalRuntime.getInstance().getCompilerToVM().RiType_isSubtypeOf(this, other); - } - // No resolved type is a subtype of an unresolved type. - return false; - } - - @Override - public Kind kind() { - return Kind.Object; - } - - @Override - public ResolvedJavaMethod resolveMethodImpl(ResolvedJavaMethod method) { - assert method instanceof HotSpotMethod; - return (ResolvedJavaMethod) HotSpotGraalRuntime.getInstance().getCompilerToVM().RiType_resolveMethodImpl(this, method.name(), method.signature().asString()); - } - - @Override - public String toString() { - return "HotSpotType<" + simpleName + ", resolved>"; - } - - @Override - public ConstantPool constantPool() { - if (constantPool == null) { - constantPool = new HotSpotConstantPool(this); - } - return constantPool; - } - - @Override - public int instanceSize() { - return instanceSize; - } - - @Override - public synchronized ResolvedJavaField createRiField(String fieldName, JavaType type, int offset, int flags) { - ResolvedJavaField result = null; - - long id = offset + ((long) flags << 32); - - // (thomaswue) Must cache the fields, because the local load elimination only works if the objects from two field lookups are identical. - if (fieldCache == null) { - fieldCache = new HashMap<>(8); - } else { - result = fieldCache.get(id); - } - - if (result == null) { - result = new HotSpotField(this, fieldName, type, offset, flags); - fieldCache.put(id, result); - } else { - assert result.name().equals(fieldName); - assert result.accessFlags() == flags; - } - - return result; - } - - @Override - public ResolvedJavaMethod uniqueConcreteMethod(ResolvedJavaMethod method) { - return ((HotSpotMethodResolved) method).uniqueConcreteMethod(); - } - - @Override - public ResolvedJavaField[] declaredFields() { - if (fields == null) { - fields = HotSpotGraalRuntime.getInstance().getCompilerToVM().RiType_fields(this); - } - return fields; - } - - @Override - public Class< ? > toJava() { - return javaMirror; - } - - @Override - public T getAnnotation(Class annotationClass) { - return toJava().getAnnotation(annotationClass); - } - - @Override - public ResolvedJavaType resolve(ResolvedJavaType accessingClass) { - return this; - } - - // this value may require identity semantics so cache it - private HotSpotKlassOop klassOopCache; - - @Override - public synchronized HotSpotKlassOop klassOop() { - if (klassOopCache == null) { - klassOopCache = new HotSpotKlassOop(javaMirror); - } - return klassOopCache; - } - - private static final int SECONDARY_SUPER_CACHE_OFFSET = HotSpotGraalRuntime.getInstance().getConfig().secondarySuperCacheOffset; - - public boolean isPrimaryType() { - return SECONDARY_SUPER_CACHE_OFFSET != superCheckOffset; - } - - public int superCheckOffset() { - return superCheckOffset; - } -} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotTypeUnresolved.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotTypeUnresolved.java Sat Jun 09 20:10:05 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,125 +0,0 @@ -/* - * 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.hotspot.ri; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.hotspot.*; - -/** - * Implementation of RiType for unresolved HotSpot classes. - */ -public class HotSpotTypeUnresolved extends HotSpotType { - - private static final long serialVersionUID = -2320936267633521314L; - public final String simpleName; - public final int dimensions; - - /** - * Creates a new unresolved type for a specified type descriptor. - */ - public HotSpotTypeUnresolved(String name) { - assert name.length() > 0 : "name cannot be empty"; - - int dims = 0; - int startIndex = 0; - while (name.charAt(startIndex) == '[') { - startIndex++; - dims++; - } - - // Decode name if necessary. - if (name.charAt(name.length() - 1) == ';') { - assert name.charAt(startIndex) == 'L'; - this.simpleName = name.substring(startIndex + 1, name.length() - 1); - this.name = name; - } else { - this.simpleName = name; - this.name = getFullName(name, dims); - } - - this.dimensions = dims; - } - - public HotSpotTypeUnresolved(String name, int dimensions) { - assert dimensions >= 0; - this.simpleName = name; - this.dimensions = dimensions; - this.name = getFullName(name, dimensions); - } - - private static String getFullName(String name, int dimensions) { - StringBuilder str = new StringBuilder(name.length() + dimensions + 2); - for (int i = 0; i < dimensions; i++) { - str.append('['); - } - str.append('L').append(name).append(';'); - return str.toString(); - } - - @Override - public JavaType componentType() { - assert dimensions > 0 : "no array class" + name(); - return new HotSpotTypeUnresolved(simpleName, dimensions - 1); - } - - @Override - public JavaType arrayOf() { - return new HotSpotTypeUnresolved(simpleName, dimensions + 1); - } - - @Override - public Kind kind() { - return Kind.Object; - } - - @Override - public int hashCode() { - return simpleName.hashCode(); - } - - @Override - public boolean equals(Object o) { - return o == this; - } - - @Override - public String toString() { - return "HotSpotType<" + simpleName + ", unresolved>"; - } - - @Override - public Kind getRepresentationKind(JavaType.Representation r) { - return Kind.Object; - } - - @Override - public ResolvedJavaType resolve(ResolvedJavaType accessingClass) { - return (ResolvedJavaType) HotSpotGraalRuntime.getInstance().lookupType(name, (HotSpotTypeResolved) accessingClass, true); - } - - @Override - public HotSpotKlassOop klassOop() { - throw GraalInternalError.shouldNotReachHere("HotSpotTypeUnresolved.klassOop"); - } -} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotXirGenerator.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotXirGenerator.java Sat Jun 09 20:10:05 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1049 +0,0 @@ -/* - * Copyright (c) 2011, 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.ri; - -import static com.oracle.graal.api.code.ValueUtil.*; -import static com.oracle.graal.hotspot.ri.TemplateFlag.*; - -import java.io.*; -import java.util.*; -import java.util.concurrent.*; - -import sun.misc.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.Address.*; -import com.oracle.graal.api.code.Register.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.*; -import com.oracle.graal.hotspot.*; -import com.oracle.max.asm.target.amd64.*; -import com.oracle.max.cri.xir.*; -import com.oracle.max.cri.xir.CiXirAssembler.XirConstant; -import com.oracle.max.cri.xir.CiXirAssembler.XirLabel; -import com.oracle.max.cri.xir.CiXirAssembler.XirMark; -import com.oracle.max.cri.xir.CiXirAssembler.XirOperand; -import com.oracle.max.cri.xir.CiXirAssembler.XirParameter; -import com.oracle.max.criutils.*; - -public class HotSpotXirGenerator implements RiXirGenerator { - - // this needs to correspond to graal_CodeInstaller.hpp - // @formatter:off - public static final Integer MARK_VERIFIED_ENTRY = 0x0001; - public static final Integer MARK_UNVERIFIED_ENTRY = 0x0002; - public static final Integer MARK_OSR_ENTRY = 0x0003; - public static final Integer MARK_UNWIND_ENTRY = 0x0004; - public static final Integer MARK_EXCEPTION_HANDLER_ENTRY = 0x0005; - public static final Integer MARK_DEOPT_HANDLER_ENTRY = 0x0006; - - public static final Integer MARK_STATIC_CALL_STUB = 0x1000; - - public static final Integer MARK_INVOKEINTERFACE = 0x2001; - public static final Integer MARK_INVOKESTATIC = 0x2002; - public static final Integer MARK_INVOKESPECIAL = 0x2003; - public static final Integer MARK_INVOKEVIRTUAL = 0x2004; - - public static final Integer MARK_IMPLICIT_NULL = 0x3000; - public static final Integer MARK_POLL_NEAR = 0x3001; - public static final Integer MARK_POLL_RETURN_NEAR = 0x3002; - public static final Integer MARK_POLL_FAR = 0x3003; - public static final Integer MARK_POLL_RETURN_FAR = 0x3004; - - // @formatter:on - - private final HotSpotVMConfig config; - private final TargetDescription target; - private final RegisterConfig registerConfig; - private final HotSpotGraalRuntime compiler; - - - private CiXirAssembler globalAsm; - - public HotSpotXirGenerator(HotSpotVMConfig config, TargetDescription target, RegisterConfig registerConfig, HotSpotGraalRuntime compiler) { - this.config = config; - this.target = target; - this.registerConfig = registerConfig; - this.compiler = compiler; - } - - private XirConstant wordConst(CiXirAssembler asm, long value) { - if (target.wordKind == Kind.Long) { - return asm.createConstant(Constant.forLong(value)); - } else { - assert target.wordKind == Kind.Int; - return asm.createConstant(Constant.forInt((int) value)); - } - } - - private XirArgument wordArg(long value) { - if (target.wordKind == Kind.Long) { - return XirArgument.forLong(value); - } else { - assert target.wordKind == Kind.Int; - return XirArgument.forInt((int) value); - } - } - - private SimpleTemplates invokeInterfaceTemplates = new SimpleTemplates(NULL_CHECK) { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { - asm.restart(); - XirParameter receiver = asm.createInputParameter("receiver", Kind.Object); - XirParameter addr = asm.createConstantInputParameter("addr", target.wordKind); - XirOperand temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.rax); - XirOperand tempO = asm.createRegister("tempO", Kind.Object, AMD64.rax); - - if (is(NULL_CHECK, flags)) { - asm.mark(MARK_IMPLICIT_NULL); - asm.pload(target.wordKind, temp, receiver, true); - } - asm.mark(MARK_INVOKEINTERFACE); - asm.mov(tempO, asm.createConstant(Constant.forObject(HotSpotProxy.DUMMY_CONSTANT_OBJ))); - - return asm.finishTemplate(addr, "invokeinterface"); - } - }; - - private SimpleTemplates invokeVirtualTemplates = new SimpleTemplates(NULL_CHECK) { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { - asm.restart(); - XirParameter receiver = asm.createInputParameter("receiver", Kind.Object); - XirParameter addr = asm.createConstantInputParameter("addr", target.wordKind); - XirOperand temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.rax); - XirOperand tempO = asm.createRegister("tempO", Kind.Object, AMD64.rax); - - if (is(NULL_CHECK, flags)) { - asm.mark(MARK_IMPLICIT_NULL); - asm.pload(target.wordKind, temp, receiver, true); - } - asm.mark(MARK_INVOKEVIRTUAL); - asm.mov(tempO, asm.createConstant(Constant.forObject(HotSpotProxy.DUMMY_CONSTANT_OBJ))); - - return asm.finishTemplate(addr, "invokevirtual"); - } - }; - - private IndexTemplates inlinedInvokeVirtualTemplates = new IndexTemplates(NULL_CHECK) { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags, int vtableEntryOffset) { - asm.restart(); - XirParameter receiver = asm.createInputParameter("receiver", Kind.Object); - XirOperand temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.rax); - XirOperand method = asm.createRegisterTemp("method", Kind.Object, AMD64.rbx); - - // load class from receiver - if (is(NULL_CHECK, flags)) { - asm.mark(MARK_IMPLICIT_NULL); - } - asm.pload(target.wordKind, temp, receiver, asm.i(config.hubOffset), true); - // load vtable entry - asm.pload(target.wordKind, method, temp, asm.i(vtableEntryOffset), false); - // load entry point from methodOop - asm.mark(MARK_IMPLICIT_NULL); - asm.pload(target.wordKind, temp, method, asm.i(config.methodCompiledEntryOffset), true); - asm.mark(MARK_INVOKEVIRTUAL); - - return asm.finishTemplate(temp, "invokevirtual"); - } - }; - - private SimpleTemplates invokeSpecialTemplates = new SimpleTemplates(NULL_CHECK) { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { - asm.restart(); - XirParameter receiver = asm.createInputParameter("receiver", Kind.Object); - XirParameter addr = asm.createConstantInputParameter("addr", target.wordKind); - XirOperand temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.rax); - XirLabel stub = asm.createOutOfLineLabel("call stub"); - - if (is(NULL_CHECK, flags)) { - asm.mark(MARK_IMPLICIT_NULL); - asm.pload(target.wordKind, temp, receiver, true); - } - asm.mark(MARK_INVOKESPECIAL); - - // -- out of line ------------------------------------------------------- - asm.bindOutOfLine(stub); - XirOperand method = asm.createRegisterTemp("method", target.wordKind, AMD64.rbx); - asm.mark(MARK_STATIC_CALL_STUB, XirMark.CALLSITE); - asm.mov(method, wordConst(asm, 0)); - XirLabel dummy = asm.createOutOfLineLabel("dummy"); - asm.jmp(dummy); - asm.bindOutOfLine(dummy); - - return asm.finishTemplate(addr, "invokespecial"); - } - }; - - private SimpleTemplates invokeStaticTemplates = new SimpleTemplates() { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { - asm.restart(); - XirParameter addr = asm.createConstantInputParameter("addr", target.wordKind); - - XirLabel stub = asm.createOutOfLineLabel("call stub"); - asm.mark(MARK_INVOKESTATIC); - - // -- out of line ------------------------------------------------------- - asm.bindOutOfLine(stub); - XirOperand method = asm.createRegisterTemp("method", target.wordKind, AMD64.rbx); - asm.mark(MARK_STATIC_CALL_STUB, XirMark.CALLSITE); - asm.mov(method, wordConst(asm, 0)); - XirLabel dummy = asm.createOutOfLineLabel("dummy"); - asm.jmp(dummy); - asm.bindOutOfLine(dummy); - - return asm.finishTemplate(addr, "invokestatic"); - } - }; - - private SimpleTemplates monitorEnterTemplates = new SimpleTemplates(NULL_CHECK) { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { - asm.restart(Kind.Void); - XirParameter object = asm.createInputParameter("object", Kind.Object); - XirParameter lock = asm.createInputParameter("lock", target.wordKind); - - if (is(NULL_CHECK, flags)) { - asm.mark(MARK_IMPLICIT_NULL); - asm.pload(target.wordKind, asm.createTemp("temp", target.wordKind), object, true); - } - - - // (thomaswue) It is important to use for this runtime call the debug info AFTER the monitor enter. Otherwise the monitor object - // is not correctly garbage collected. - final boolean useInfoAfter = true; - - if (config.useFastLocking) { - useRegisters(asm, AMD64.rax, AMD64.rbx); - useRegisters(asm, getGeneralParameterRegister(0)); - useRegisters(asm, getGeneralParameterRegister(1)); - asm.callRuntime(config.fastMonitorEnterStub, null, useInfoAfter, object, lock); - } else { - asm.reserveOutgoingStack(target.wordSize * 2); - XirOperand rsp = asm.createRegister("rsp", target.wordKind, asRegister(AMD64.RSP)); - asm.pstore(Kind.Object, rsp, asm.i(target.wordSize), object, false); - asm.pstore(target.wordKind, rsp, asm.i(0), lock, false); - asm.callRuntime(config.monitorEnterStub, null, useInfoAfter); - } - - return asm.finishTemplate("monitorEnter"); - } - }; - - private Register getGeneralParameterRegister(int index) { - return registerConfig.getCallingConventionRegisters(CallingConvention.Type.RuntimeCall, RegisterFlag.CPU)[index]; - } - - private SimpleTemplates monitorExitTemplates = new SimpleTemplates(NULL_CHECK) { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { - asm.restart(Kind.Void); - XirParameter object = asm.createInputParameter("object", Kind.Object); - XirParameter lock = asm.createInputParameter("lock", target.wordKind); - - if (config.useFastLocking) { - useRegisters(asm, AMD64.rax, AMD64.rbx); - useRegisters(asm, getGeneralParameterRegister(0)); - useRegisters(asm, getGeneralParameterRegister(1)); - asm.callRuntime(config.fastMonitorExitStub, null, object, lock); - } else { - asm.reserveOutgoingStack(target.wordSize); - asm.pstore(target.wordKind, asm.createRegister("rsp", target.wordKind, asRegister(AMD64.RSP)), asm.i(0), lock, false); - asm.callRuntime(config.monitorExitStub, null); - } - - return asm.finishTemplate("monitorExit"); - } - }; - - private final IndexTemplates newInstanceTemplates = new IndexTemplates() { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags, int size) { - XirOperand result = asm.restart(target.wordKind); - XirOperand hub = asm.createInputParameter("hub", Kind.Object); - - XirOperand temp1 = asm.createRegisterTemp("temp1", target.wordKind, AMD64.rcx); - XirOperand temp1o = asm.createRegister("temp1o", Kind.Object, AMD64.rcx); - XirOperand temp2 = asm.createRegisterTemp("temp2", target.wordKind, AMD64.rbx); - XirOperand temp2i = asm.createRegister("temp2i", Kind.Int, AMD64.rbx); - useRegisters(asm, AMD64.rsi); - XirLabel tlabFull = asm.createOutOfLineLabel("tlab full"); - XirLabel resume = asm.createInlineLabel("resume"); - - // check if the class is already initialized - asm.pload(Kind.Int, temp2i, hub, asm.i(config.klassStateOffset), false); - asm.jneq(tlabFull, temp2i, asm.i(config.klassStateFullyInitialized)); - - XirOperand thread = asm.createRegisterTemp("thread", target.wordKind, AMD64.r15); - asm.pload(target.wordKind, result, thread, asm.i(config.threadTlabTopOffset), false); - asm.add(temp1, result, wordConst(asm, size)); - asm.pload(target.wordKind, temp2, thread, asm.i(config.threadTlabEndOffset), false); - - asm.jgt(tlabFull, temp1, temp2); - asm.pstore(target.wordKind, thread, asm.i(config.threadTlabTopOffset), temp1, false); - - asm.bindInline(resume); - - asm.pload(target.wordKind, temp1, hub, asm.i(config.instanceHeaderPrototypeOffset), false); - asm.pstore(target.wordKind, result, temp1, false); - asm.mov(temp1o, hub); // need a temporary register since Intel cannot store 64-bit constants to memory - asm.pstore(Kind.Object, result, asm.i(config.hubOffset), temp1o, false); - - if (size > 2 * target.wordSize) { - asm.mov(temp1, wordConst(asm, 0)); - for (int offset = 2 * target.wordSize; offset < size; offset += target.wordSize) { - asm.pstore(target.wordKind, result, asm.i(offset), temp1, false); - } - } - - // -- out of line ------------------------------------------------------- - asm.bindOutOfLine(tlabFull); - XirOperand arg = asm.createRegisterTemp("runtime call argument", Kind.Object, AMD64.rdx); - asm.mov(arg, hub); - useRegisters(asm, AMD64.rax); - asm.callRuntime(config.newInstanceStub, result); - asm.jmp(resume); - - return asm.finishTemplate("new instance"); - } - }; - - private SimpleTemplates newObjectArrayTemplates = new SimpleTemplates() { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { - emitNewTypeArray(asm, Kind.Object, config.useFastNewObjectArray, config.newObjectArrayStub); - return asm.finishTemplate("newObjectArray"); - } - }; - - private void emitNewTypeArray(CiXirAssembler asm, Kind kind, boolean useFast, long slowPathStub) { - XirOperand result = asm.restart(target.wordKind); - - XirParameter lengthParam = asm.createInputParameter("length", Kind.Int, true); - - XirOperand length = asm.createRegisterTemp("length", Kind.Int, AMD64.rbx); - XirOperand hub = asm.createRegisterTemp("hub", Kind.Object, AMD64.rdx); - - // Registers rsi, rcx, rdi, and rax are needed by the runtime call. - // Hub needs to be on rdx, length on rbx. - XirOperand temp1 = asm.createRegisterTemp("temp1", target.wordKind, AMD64.rcx); - XirOperand temp1o = asm.createRegister("temp1o", Kind.Object, AMD64.rcx); - XirOperand temp2 = asm.createRegisterTemp("temp2", target.wordKind, AMD64.rax); - XirOperand temp3 = asm.createRegisterTemp("temp3", target.wordKind, AMD64.rdi); - XirOperand size = asm.createRegisterTemp("size", Kind.Int, AMD64.rsi); - - asm.mov(hub, asm.createConstantInputParameter("hub", Kind.Object)); - asm.mov(length, lengthParam); - - if (useFast) { - - XirLabel slowPath = asm.createOutOfLineLabel("slowPath"); - - XirLabel done = asm.createInlineLabel("done"); - - // Check for negative array size. - // TODO: Also check for upper bound - asm.jlt(slowPath, length, asm.i(0)); - - final int aligning = target.wordSize; - final int arrayLengthOffset = target.wordSize * 2; - final int arrayElementOffset = config.getArrayOffset(kind); - - // Calculate aligned size - asm.mov(size, length); - int scale = CodeUtil.log2(target.sizeInBytes(kind)); - if (scale != 0) { - asm.shl(size, size, asm.i(scale)); - } - asm.add(size, size, asm.i(arrayElementOffset + aligning - 1)); - long mask = 0xFFFFFFFFL; - mask <<= CodeUtil.log2(aligning); - asm.and(size, size, asm.i((int) mask)); - - // Try tlab allocation - XirOperand thread = asm.createRegisterTemp("thread", target.wordKind, AMD64.r15); - asm.pload(target.wordKind, result, thread, asm.i(config.threadTlabTopOffset), false); - asm.add(temp1, result, size); - asm.pload(target.wordKind, temp2, thread, asm.i(config.threadTlabEndOffset), false); - asm.jgt(slowPath, temp1, temp2); - asm.pstore(target.wordKind, thread, asm.i(config.threadTlabTopOffset), temp1, false); - - // Now the new object is in result, store mark word and klass - asm.pload(target.wordKind, temp1, hub, asm.i(config.instanceHeaderPrototypeOffset), false); - asm.pstore(target.wordKind, result, temp1, false); - asm.mov(temp1o, hub); // need a temporary register since Intel cannot store 64-bit constants to memory - asm.pstore(Kind.Object, result, asm.i(config.hubOffset), temp1o, false); - - // Store array length - asm.pstore(Kind.Int, result, asm.i(arrayLengthOffset), length, false); - - // Initialize with 0 - XirLabel top = asm.createInlineLabel("top"); - asm.sub(size, size, asm.i(arrayElementOffset)); - asm.shr(size, size, asm.i(Scale.Times8.log2)); - asm.jeq(done, size, asm.i(0)); - asm.xor(temp3, temp3, temp3); - asm.bindInline(top); - asm.pstore(target.wordKind, result, size, temp3, arrayElementOffset - target.wordSize, Scale.Times8, false); - asm.decAndJumpNotZero(top, size); - - asm.bindInline(done); - - // Slow path - asm.bindOutOfLine(slowPath); - asm.callRuntime(slowPathStub, result); - asm.jmp(done); - } else { - asm.callRuntime(slowPathStub, result); - } - } - - private KindTemplates newTypeArrayTemplates = new KindTemplates() { - @Override - protected XirTemplate create(CiXirAssembler asm, long flags, Kind kind) { - emitNewTypeArray(asm, kind, config.useFastNewTypeArray, config.newTypeArrayStub); - return asm.finishTemplate("newTypeArray<" + kind.toString() + ">"); - } - }; - - private final IndexTemplates multiNewArrayTemplate = new IndexTemplates() { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags, int dimensions) { - XirOperand result = asm.restart(Kind.Object); - - XirOperand hub = asm.createRegisterTemp("hub", Kind.Object, AMD64.rax); - XirOperand rank = asm.createRegisterTemp("rank", Kind.Int, AMD64.rbx); - XirOperand sizes = asm.createRegisterTemp("sizes", Kind.Long, AMD64.rcx); - XirOperand thread = asm.createRegisterTemp("thread", Kind.Long, AMD64.r15); - asm.add(sizes, thread, asm.l(config.threadMultiNewArrayStorage)); - for (int i = 0; i < dimensions; i++) { - XirParameter length = asm.createInputParameter("length" + i, Kind.Int, true); - asm.pstore(Kind.Int, sizes, asm.i(i * target.sizeInBytes(Kind.Int)), length, false); - } - - asm.mov(hub, asm.createConstantInputParameter("hub", Kind.Object)); - - asm.mov(rank, asm.i(dimensions)); - // not necessary because we already have a temp in rax: useRegisters(asm, AMD64.rax); - asm.callRuntime(config.newMultiArrayStub, result); - return asm.finishTemplate("multiNewArray" + dimensions); - } - }; - - enum CheckcastCounter { - hintsHit("hit a hint type"), - hintsMissed("missed the hint types"), - exact("tested type is (statically) final"), - noHints_class("profile information is not used (test type is a class)"), - noHints_iface("profile information is not used (test type is an interface)"), - noHints_unknown("test type is not a compile-time constant"), - isNull("object tested is null"), - exception("type test failed with a ClassCastException"); - - public final String desc; - - private CheckcastCounter(String desc) { - this.desc = desc; - } - - static final CheckcastCounter[] VALUES = values(); - } - - private static final long[] checkcastCounters = new long[CheckcastCounter.VALUES.length]; - - private IndexTemplates checkCastTemplates = new IndexTemplates(NULL_CHECK, EXACT_HINTS) { - - private void incCounter(CiXirAssembler asm, XirOperand counter, XirParameter counters, CheckcastCounter offset) { - int disp = Unsafe.getUnsafe().arrayBaseOffset(long[].class); - Scale scale = Scale.fromInt(Unsafe.getUnsafe().arrayIndexScale(long[].class)); - XirConstant index = asm.i(offset.ordinal()); - asm.pload(Kind.Long, counter, counters, index, disp, scale, false); - asm.add(counter, counter, asm.i(1)); - asm.pstore(Kind.Long, counters, index, counter, disp, scale, false); - } - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags, int hintCount) { - asm.restart(Kind.Void); - boolean exact = is(EXACT_HINTS, flags); - XirParameter counters = GraalOptions.CheckcastCounters ? asm.createConstantInputParameter("counters", Kind.Object) : null; - XirParameter object = asm.createInputParameter("object", Kind.Object); - final XirOperand hub = exact ? null : asm.createConstantInputParameter("hub", Kind.Object); - - XirOperand objHub = asm.createTemp("objHub", Kind.Object); - XirOperand counter = counters != null ? asm.createTemp("counter", Kind.Long) : null; - - XirLabel success = asm.createInlineLabel("success"); - XirLabel slowPath = asm.createOutOfLineLabel("slow path"); - - if (is(NULL_CHECK, flags)) { - // null can be cast to anything - if (counters != null) { - XirLabel isNotNull = asm.createInlineLabel("isNull"); - asm.jneq(isNotNull, object, asm.o(null)); - incCounter(asm, counter, counters, CheckcastCounter.isNull); - asm.jmp(success); - asm.bindInline(isNotNull); - } else { - asm.jeq(success, object, asm.o(null)); - } - - } - - asm.pload(Kind.Object, objHub, object, asm.i(config.hubOffset), false); - if (hintCount == 0) { - assert !exact; - if (counters != null) { - CheckcastCounter cc; - if (is(NULL_TYPE, flags)) { - cc = CheckcastCounter.noHints_unknown; - } else if (is(INTERFACE_TYPE, flags)) { - cc = CheckcastCounter.noHints_iface; - } else { - cc = CheckcastCounter.noHints_class; - } - incCounter(asm, counter, counters, cc); - } - - checkSubtype(asm, objHub, objHub, hub); - asm.jeq(slowPath, objHub, asm.o(null)); - asm.bindInline(success); - - // -- out of line ------------------------------------------------------- - asm.bindOutOfLine(slowPath); - } else { - XirLabel hintsSuccess = counters == null ? success : asm.createInlineLabel("hintsSuccess"); - XirOperand scratchObject = asm.createRegisterTemp("scratch", Kind.Object, AMD64.r10); - // if we get an exact match: succeed immediately - for (int i = 0; i < hintCount; i++) { - XirParameter hintHub = asm.createConstantInputParameter("hintHub" + i, Kind.Object); - asm.mov(scratchObject, hintHub); - if (i < hintCount - 1) { - asm.jeq(hintsSuccess, objHub, scratchObject); - } else { - asm.jneq(slowPath, objHub, scratchObject); - } - } - - if (counters != null) { - asm.bindInline(hintsSuccess); - incCounter(asm, counter, counters, exact ? CheckcastCounter.exact : CheckcastCounter.hintsHit); - } - - asm.bindInline(success); - - // -- out of line ------------------------------------------------------- - asm.bindOutOfLine(slowPath); - if (!exact) { - if (counters != null) { - incCounter(asm, counter, counters, CheckcastCounter.hintsMissed); - } - checkSubtype(asm, objHub, objHub, hub); - asm.jneq(success, objHub, asm.o(null)); - } - } - - if (counters != null) { - incCounter(asm, counter, counters, CheckcastCounter.exception); - } - DeoptimizationReason deoptReason = exact ? DeoptimizationReason.OptimizedTypeCheckViolated : DeoptimizationReason.ClassCastException; - XirOperand scratch = asm.createRegisterTemp("scratch", target.wordKind, AMD64.r10); - asm.mov(scratch, wordConst(asm, compiler.getRuntime().encodeDeoptActionAndReason(DeoptimizationAction.InvalidateReprofile, deoptReason))); - asm.callRuntime(RuntimeCall.Deoptimize, null); - asm.shouldNotReachHere(); - - return asm.finishTemplate("checkcast"); - } - }; - - private IndexTemplates instanceOfTemplates = new IndexTemplates(NULL_CHECK, EXACT_HINTS) { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags, int hintCount) { - asm.restart(Kind.Void); - XirParameter object = asm.createInputParameter("object", Kind.Object); - final XirOperand hub = is(EXACT_HINTS, flags) ? null : asm.createConstantInputParameter("hub", Kind.Object); - - XirOperand objHub = asm.createTemp("objHub", Kind.Object); - - XirLabel trueSucc = asm.createInlineLabel(XirLabel.TrueSuccessor); - XirLabel falseSucc = asm.createInlineLabel(XirLabel.FalseSuccessor); - - if (is(NULL_CHECK, flags)) { - // null isn't "instanceof" anything - asm.jeq(falseSucc, object, asm.o(null)); - } - - asm.pload(Kind.Object, objHub, object, asm.i(config.hubOffset), false); - if (hintCount == 0) { - assert !is(EXACT_HINTS, flags); - checkSubtype(asm, objHub, objHub, hub); - asm.jeq(falseSucc, objHub, asm.o(null)); - asm.jmp(trueSucc); - } else { - XirLabel slowPath = null; - XirOperand scratchObject = asm.createRegisterTemp("scratch", Kind.Object, AMD64.r10); - - // if we get an exact match: succeed immediately - for (int i = 0; i < hintCount; i++) { - XirParameter hintHub = asm.createConstantInputParameter("hintHub" + i, Kind.Object); - asm.mov(scratchObject, hintHub); - if (i < hintCount - 1) { - asm.jeq(trueSucc, objHub, scratchObject); - } else { - if (is(EXACT_HINTS, flags)) { - asm.jneq(falseSucc, objHub, scratchObject); - asm.jmp(trueSucc); - } else { - slowPath = asm.createOutOfLineLabel("slow path"); - asm.jneq(slowPath, objHub, scratchObject); - asm.jmp(trueSucc); - } - } - } - - // -- out of line ------------------------------------------------------- - if (slowPath != null) { - asm.bindOutOfLine(slowPath); - checkSubtype(asm, objHub, objHub, hub); - asm.jeq(falseSucc, objHub, asm.o(null)); - asm.jmp(trueSucc); - } - } - - return asm.finishTemplate("instanceof"); - } - }; - - private IndexTemplates materializeInstanceOfTemplates = new IndexTemplates(NULL_CHECK, EXACT_HINTS) { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags, int hintCount) { - XirOperand result = asm.restart(Kind.Int); - XirParameter object = asm.createInputParameter("object", Kind.Object); - final XirOperand hub = is(EXACT_HINTS, flags) ? null : asm.createConstantInputParameter("hub", Kind.Object); - XirOperand trueValue = asm.createInputParameter("trueValue", Kind.Int); - XirOperand falseValue = asm.createInputParameter("falseValue", Kind.Int); - - XirOperand objHub = asm.createTemp("objHub", Kind.Object); - - XirLabel end = asm.createInlineLabel("end"); - XirLabel falseSucc = asm.createInlineLabel("ko"); - - if (is(NULL_CHECK, flags)) { - // null isn't "instanceof" anything - asm.jeq(falseSucc, object, asm.o(null)); - } - - asm.pload(Kind.Object, objHub, object, asm.i(config.hubOffset), false); - asm.mov(result, trueValue); - - if (hintCount == 0) { - assert !is(EXACT_HINTS, flags); - checkSubtype(asm, objHub, objHub, hub); - asm.jneq(end, objHub, asm.o(null)); - asm.bindInline(falseSucc); - asm.mov(result, falseValue); - asm.bindInline(end); - } else { - XirLabel slowPath = null; - XirOperand scratchObject = asm.createRegisterTemp("scratch", Kind.Object, AMD64.r10); - - // if we get an exact match: succeed immediately - for (int i = 0; i < hintCount; i++) { - XirParameter hintHub = asm.createConstantInputParameter("hintHub" + i, Kind.Object); - asm.mov(scratchObject, hintHub); - if (i < hintCount - 1) { - asm.jeq(end, objHub, scratchObject); - } else { - if (is(EXACT_HINTS, flags)) { - asm.jeq(end, objHub, scratchObject); - } else { - slowPath = asm.createOutOfLineLabel("slow path"); - asm.jeq(end, objHub, scratchObject); - asm.jmp(slowPath); - } - } - } - asm.bindInline(falseSucc); - asm.mov(result, falseValue); - asm.bindInline(end); - - // -- out of line ------------------------------------------------------- - if (slowPath != null) { - asm.bindOutOfLine(slowPath); - checkSubtype(asm, objHub, objHub, hub); - asm.jeq(falseSucc, objHub, asm.o(null)); - asm.jmp(end); - } - } - - return asm.finishTemplate("instanceof"); - } - }; - - private SimpleTemplates typeCheckTemplates = new SimpleTemplates(NULL_CHECK) { - @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { - asm.restart(Kind.Void); - XirParameter objHub = asm.createInputParameter("objectHub", Kind.Object); - XirOperand hub = asm.createConstantInputParameter("hub", Kind.Object); - XirLabel falseSucc = asm.createInlineLabel(XirLabel.FalseSuccessor); - - XirOperand checkHub = asm.createTemp("checkHub", Kind.Object); - - if (is(NULL_CHECK, flags)) { - asm.mark(MARK_IMPLICIT_NULL); - } - - asm.mov(checkHub, hub); - // if we get an exact match: continue. - asm.jneq(falseSucc, objHub, checkHub); - - return asm.finishTemplate("typeCheck"); - } - }; - - @Override - public XirSnippet genInvokeInterface(XirSite site, XirArgument receiver, JavaMethod method) { - return new XirSnippet(invokeInterfaceTemplates.get(site), receiver, wordArg(0)); - } - - @Override - public XirSnippet genInvokeVirtual(XirSite site, XirArgument receiver, JavaMethod method, boolean megamorph) { - int vtableEntryOffset = 0; - - if (GraalOptions.InlineVTableStubs && (GraalOptions.AlwaysInlineVTableStubs || megamorph)) { - HotSpotMethodResolved hsMethod = (HotSpotMethodResolved) method; - if (!hsMethod.holder().isInterface()) { - vtableEntryOffset = hsMethod.vtableEntryOffset(); - } - } - if (vtableEntryOffset > 0) { - return new XirSnippet(inlinedInvokeVirtualTemplates.get(site, vtableEntryOffset), receiver); - } else { - return new XirSnippet(invokeVirtualTemplates.get(site), receiver, wordArg(0)); - } - } - - @Override - public XirSnippet genInvokeSpecial(XirSite site, XirArgument receiver, JavaMethod method) { - return new XirSnippet(invokeSpecialTemplates.get(site), receiver, wordArg(0)); - } - - @Override - public XirSnippet genInvokeStatic(XirSite site, JavaMethod method) { - return new XirSnippet(invokeStaticTemplates.get(site), wordArg(0)); - } - - @Override - public XirSnippet genMonitorEnter(XirSite site, XirArgument receiver, XirArgument lockAddress) { - return new XirSnippet(monitorEnterTemplates.get(site), receiver, lockAddress); - } - - @Override - public XirSnippet genMonitorExit(XirSite site, XirArgument receiver, XirArgument lockAddress) { - return new XirSnippet(monitorExitTemplates.get(site), receiver, lockAddress); - } - - @Override - public XirSnippet genNewInstance(XirSite site, JavaType type) { - HotSpotTypeResolved resolvedType = (HotSpotTypeResolved) type; - int instanceSize = resolvedType.instanceSize(); - return new XirSnippet(newInstanceTemplates.get(site, instanceSize), XirArgument.forObject(resolvedType.klassOop())); - } - - @Override - public XirSnippet genNewArray(XirSite site, XirArgument length, Kind elementKind, JavaType componentType, JavaType arrayType) { - if (elementKind == Kind.Object) { - assert arrayType instanceof ResolvedJavaType; - return new XirSnippet(newObjectArrayTemplates.get(site), length, XirArgument.forObject(((HotSpotType) arrayType).klassOop())); - } else { - assert arrayType == null; - JavaType primitiveArrayType = compiler.getCompilerToVM().getPrimitiveArrayType(elementKind); - return new XirSnippet(newTypeArrayTemplates.get(site, elementKind), length, XirArgument.forObject(((HotSpotType) primitiveArrayType).klassOop())); - } - } - - @Override - public XirSnippet genNewMultiArray(XirSite site, XirArgument[] lengths, JavaType type) { - XirArgument[] params = Arrays.copyOf(lengths, lengths.length + 1); - params[lengths.length] = XirArgument.forObject(((HotSpotType) type).klassOop()); - return new XirSnippet(multiNewArrayTemplate.get(site, lengths.length), params); - } - - @Override - public XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, ResolvedJavaType type, JavaTypeProfile profile) { - final boolean useCounters = GraalOptions.CheckcastCounters; - TypeCheckHints hints = new TypeCheckHints(type, profile, site.assumptions(), GraalOptions.CheckcastMinHintHitProbability, GraalOptions.CheckcastMaxHints); - int hintsLength = hints.types.length; - if (hintsLength == 0) { - if (useCounters) { - if (type == null) { - return new XirSnippet(checkCastTemplates.get(site, 0, NULL_TYPE), XirArgument.forObject(checkcastCounters), receiver, hub); - } else if (type.isInterface()) { - return new XirSnippet(checkCastTemplates.get(site, 0, INTERFACE_TYPE), XirArgument.forObject(checkcastCounters), receiver, hub); - } else { - return new XirSnippet(checkCastTemplates.get(site, 0), XirArgument.forObject(checkcastCounters), receiver, hub); - } - } else { - return new XirSnippet(checkCastTemplates.get(site, 0), receiver, hub); - } - } else { - XirArgument[] params = new XirArgument[(useCounters ? 1 : 0) + hintsLength + (hints.exact ? 1 : 2)]; - int i = 0; - if (useCounters) { - params[i++] = XirArgument.forObject(checkcastCounters); - } - params[i++] = receiver; - if (!hints.exact) { - params[i++] = hub; - } - for (ResolvedJavaType hint : hints.types) { - params[i++] = XirArgument.forObject(((HotSpotType) hint).klassOop()); - } - XirTemplate template = hints.exact ? checkCastTemplates.get(site, hintsLength, EXACT_HINTS) : checkCastTemplates.get(site, hintsLength); - return new XirSnippet(template, params); - } - } - - @Override - public XirSnippet genInstanceOf(XirSite site, XirArgument object, XirArgument hub, ResolvedJavaType type, JavaTypeProfile profile) { - TypeCheckHints hints = new TypeCheckHints(type, profile, site.assumptions(), GraalOptions.InstanceOfMinHintHitProbability, GraalOptions.InstanceOfMaxHints); - int hintsLength = hints.types.length; - if (hintsLength == 0) { - return new XirSnippet(instanceOfTemplates.get(site, 0), object, hub); - } else { - XirArgument[] params = new XirArgument[hintsLength + (hints.exact ? 1 : 2)]; - int i = 0; - params[i++] = object; - if (!hints.exact) { - params[i++] = hub; - } - for (ResolvedJavaType hint : hints.types) { - params[i++] = XirArgument.forObject(((HotSpotType) hint).klassOop()); - } - XirTemplate template = hints.exact ? instanceOfTemplates.get(site, hintsLength, EXACT_HINTS) : instanceOfTemplates.get(site, hintsLength); - return new XirSnippet(template, params); - } - } - - @Override - public XirSnippet genMaterializeInstanceOf(XirSite site, XirArgument object, XirArgument hub, XirArgument trueValue, XirArgument falseValue, ResolvedJavaType type, JavaTypeProfile profile) { - TypeCheckHints hints = new TypeCheckHints(type, profile, site.assumptions(), GraalOptions.InstanceOfMinHintHitProbability, GraalOptions.InstanceOfMaxHints); - int hintsLength = hints.types.length; - if (hintsLength == 0) { - return new XirSnippet(materializeInstanceOfTemplates.get(site, 0), object, hub, trueValue, falseValue); - } else { - XirArgument[] params = new XirArgument[hintsLength + (hints.exact ? 3 : 4)]; - int i = 0; - params[i++] = object; - if (!hints.exact) { - params[i++] = hub; - } - params[i++] = trueValue; - params[i++] = falseValue; - for (ResolvedJavaType hint : hints.types) { - params[i++] = XirArgument.forObject(((HotSpotType) hint).klassOop()); - } - XirTemplate template = hints.exact ? materializeInstanceOfTemplates.get(site, hintsLength, EXACT_HINTS) : materializeInstanceOfTemplates.get(site, hintsLength); - return new XirSnippet(template, params); - } - } - - @Override - public XirSnippet genTypeBranch(XirSite site, XirArgument thisHub, XirArgument otherHub, JavaType type) { - assert type instanceof ResolvedJavaType; - return new XirSnippet(typeCheckTemplates.get(site), thisHub, otherHub); - } - - @Override - public void initialize(CiXirAssembler asm) { - this.globalAsm = asm; - } - - private void checkSubtype(CiXirAssembler asm, XirOperand result, XirOperand objHub, XirOperand hub) { - asm.push(objHub); - asm.push(hub); - asm.callRuntime(config.instanceofStub, null); - asm.pop(result); - asm.pop(result); - } - - private static void useRegisters(CiXirAssembler asm, Register... registers) { - if (registers != null) { - for (Register register : registers) { - asm.createRegisterTemp("reg", Kind.Illegal, register); - } - } - } - - public boolean is(TemplateFlag check, long flags) { - return (flags & check.bits()) == check.bits(); - } - - /** - * Base class for all the ondemand template generators. It is not normally subclassed directly, but through one of - * its subclasses (SimpleTemplates, KindTemplates, IndexTemplates). - */ - private abstract class Templates { - - private ConcurrentHashMap templates = new ConcurrentHashMap<>(); - private final long mask; - - /** - * Each flag passed to this method will cause templates with and without it to be generated. - */ - public Templates(TemplateFlag... flags) { - this.mask = getBits((int) INDEX_MASK, null, flags); - } - - protected abstract XirTemplate create(CiXirAssembler asm, long flags); - - protected long getBits(int index, XirSite site, TemplateFlag... flags) { - long bits = index; - if (site != null) { - bits |= site.requiresNullCheck() ? NULL_CHECK.bits() : 0; - bits |= site.requiresReadBarrier() ? READ_BARRIER.bits() : 0; - bits |= site.requiresWriteBarrier() ? WRITE_BARRIER.bits() : 0; - bits |= site.requiresArrayStoreCheck() ? STORE_CHECK.bits() : 0; - bits |= site.requiresBoundsCheck() ? BOUNDS_CHECK.bits() : 0; - } - if (flags != null) { - for (TemplateFlag flag : flags) { - bits |= flag.bits(); - } - } - return bits; - } - - protected XirTemplate getInternal(long flags) { - long maskedFlags = flags & mask; - XirTemplate template = templates.get(maskedFlags); - if (template == null) { - template = create(HotSpotXirGenerator.this.globalAsm.copy(), maskedFlags); - templates.put(maskedFlags, template); - } - return template; - } - } - - private abstract class SimpleTemplates extends Templates { - - public SimpleTemplates(TemplateFlag... flags) { - super(flags); - } - - public XirTemplate get(XirSite site, TemplateFlag... flags) { - return getInternal(getBits(0, site, flags)); - } - } - - private abstract class IndexTemplates extends Templates { - - public IndexTemplates(TemplateFlag... flags) { - super(flags); - } - - @Override - protected final XirTemplate create(CiXirAssembler asm, long flags) { - return create(asm, flags & FLAGS_MASK, (int) (flags & INDEX_MASK)); - } - - protected abstract XirTemplate create(CiXirAssembler asm, long flags, int index); - - public XirTemplate get(XirSite site, int size, TemplateFlag... flags) { - return getInternal(getBits(size, site, flags)); - } - } - - private abstract class KindTemplates extends Templates { - - public KindTemplates(TemplateFlag... flags) { - super(flags); - } - - @Override - protected final XirTemplate create(CiXirAssembler asm, long flags) { - return create(asm, flags & FLAGS_MASK, Kind.VALUES[(int) (flags & INDEX_MASK)]); - } - - protected abstract XirTemplate create(CiXirAssembler asm, long flags, Kind kind); - - public XirTemplate get(XirSite site, Kind kind, TemplateFlag... flags) { - return getInternal(getBits(kind.ordinal(), site, flags)); - } - } - - private static void printCounter(PrintStream out, CheckcastCounter name, long count, long total) { - double percent = total == 0D ? 0D : ((double) (count * 100)) / total; - out.println(String.format("%16s: %5.2f%%%10d // %s", name, percent, count, name.desc)); - } - - public static void printCheckcastCounters(PrintStream out) { - class Count implements Comparable { - long c; - CheckcastCounter name; - Count(long c, CheckcastCounter name) { - this.c = c; - this.name = name; - } - public int compareTo(Count o) { - return (int) (o.c - c); - } - } - - long total = 0; - Count[] counters = new Count[checkcastCounters.length]; - for (int i = 0; i < counters.length; i++) { - counters[i] = new Count(checkcastCounters[i], CheckcastCounter.VALUES[i]); - total += checkcastCounters[i]; - } - Arrays.sort(counters); - - out.println(); - out.println("** XIR checkcast counters **"); - for (Count c : counters) { - printCounter(out, c.name, c.c, total); - } - } - - public static void printCounters(PrintStream out) { - if (GraalOptions.CheckcastCounters) { - printCheckcastCounters(out); - } - } -} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/TemplateFlag.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/TemplateFlag.java Sat Jun 09 20:10:05 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -/* - * 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.hotspot.ri; - -enum TemplateFlag { - NULL_CHECK, - READ_BARRIER, - WRITE_BARRIER, - STORE_CHECK, - BOUNDS_CHECK, - GIVEN_LENGTH, - INPUTS_DIFFERENT, - INPUTS_SAME, - STATIC_METHOD, - SYNCHRONIZED, - INTERFACE_TYPE, - NULL_TYPE, - EXACT_HINTS; - - private static final long FIRST_FLAG = 0x0000000100000000L; - public static final long FLAGS_MASK = 0x0000FFFF00000000L; - public static final long INDEX_MASK = 0x00000000FFFFFFFFL; - - public long bits() { - assert ((FIRST_FLAG << ordinal()) & FLAGS_MASK) != 0; - return FIRST_FLAG << ordinal(); - } -} diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java Sat Jun 09 20:10:05 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java Sat Jun 09 20:32:31 2012 +0200 @@ -40,7 +40,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.Fold; import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.ri.*; +import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64SafepointOp.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64SafepointOp.java Sat Jun 09 20:10:05 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64SafepointOp.java Sat Jun 09 20:32:31 2012 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.hotspot.target.amd64; -import static com.oracle.graal.hotspot.ri.HotSpotXirGenerator.*; +import static com.oracle.graal.hotspot.meta.HotSpotXirGenerator.*; import static com.oracle.max.asm.target.amd64.AMD64.*; import java.util.*; diff -r b6617d13ea44 -r 8872bc0eebdf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/HotSpotAMD64Backend.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/HotSpotAMD64Backend.java Sat Jun 09 20:10:05 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/HotSpotAMD64Backend.java Sat Jun 09 20:32:31 2012 +0200 @@ -24,7 +24,7 @@ import static com.oracle.graal.api.code.CallingConvention.Type.*; import static com.oracle.graal.api.code.ValueUtil.*; -import static com.oracle.graal.hotspot.ri.HotSpotXirGenerator.*; +import static com.oracle.graal.hotspot.meta.HotSpotXirGenerator.*; import static com.oracle.max.asm.target.amd64.AMD64.*; import java.lang.reflect.*; @@ -38,7 +38,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.counters.*; -import com.oracle.graal.hotspot.ri.*; +import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.asm.*; diff -r b6617d13ea44 -r 8872bc0eebdf src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Sat Jun 09 20:10:05 2012 +0200 +++ b/src/share/vm/classfile/vmSymbols.hpp Sat Jun 09 20:32:31 2012 +0200 @@ -270,16 +270,16 @@ \ /* Support for Graal */ \ template(com_oracle_graal_hotspot_bridge_VMToCompiler, "com/oracle/graal/hotspot/bridge/VMToCompiler") \ - template(com_oracle_graal_hotspot_ri_HotSpotMethodResolved, "com/oracle/graal/hotspot/ri/HotSpotMethodResolvedImpl") \ + template(com_oracle_graal_hotspot_ri_HotSpotMethodResolved, "com/oracle/graal/hotspot/meta/HotSpotMethodResolvedImpl") \ template(com_oracle_graal_hotspot_HotSpotTargetMethod, "com/oracle/graal/hotspot/HotSpotTargetMethod") \ - template(com_oracle_graal_hotspot_ri_HotSpotMethodData, "com/oracle/graal/hotspot/ri/HotSpotMethodData") \ - template(com_oracle_graal_hotspot_HotSpotCodeInfo, "com/oracle/graal/hotspot/ri/HotSpotCodeInfo") \ - template(com_oracle_graal_hotspot_HotSpotField, "com/oracle/graal/hotspot/ri/HotSpotField") \ - template(com_oracle_graal_hotspot_HotSpotCompiledMethod, "com/oracle/graal/hotspot/ri/HotSpotCompiledMethod") \ + template(com_oracle_graal_hotspot_ri_HotSpotMethodData, "com/oracle/graal/hotspot/meta/HotSpotMethodData") \ + template(com_oracle_graal_hotspot_HotSpotCodeInfo, "com/oracle/graal/hotspot/meta/HotSpotCodeInfo") \ + template(com_oracle_graal_hotspot_HotSpotField, "com/oracle/graal/hotspot/meta/HotSpotField") \ + template(com_oracle_graal_hotspot_HotSpotCompiledMethod, "com/oracle/graal/hotspot/meta/HotSpotCompiledMethod") \ template(com_oracle_graal_hotspot_HotSpotOptions, "com/oracle/graal/hotspot/HotSpotOptions") \ - template(com_oracle_graal_hotspot_HotSpotTypeResolved, "com/oracle/graal/hotspot/ri/HotSpotTypeResolvedImpl") \ - template(com_oracle_graal_hotspot_HotSpotType, "com/oracle/graal/hotspot/ri/HotSpotType") \ - template(com_oracle_graal_hotspot_HotSpotKlassOop, "com/oracle/graal/hotspot/ri/HotSpotKlassOop") \ + template(com_oracle_graal_hotspot_HotSpotTypeResolved, "com/oracle/graal/hotspot/meta/HotSpotTypeResolvedImpl") \ + template(com_oracle_graal_hotspot_HotSpotType, "com/oracle/graal/hotspot/meta/HotSpotType") \ + template(com_oracle_graal_hotspot_HotSpotKlassOop, "com/oracle/graal/hotspot/meta/HotSpotKlassOop") \ template(com_oracle_graal_hotspot_HotSpotProxy, "com/oracle/graal/hotspot/HotSpotProxy") \ template(com_oracle_graal_hotspot_CompilerImpl, "com/oracle/graal/hotspot/HotSpotGraalRuntime") \ template(com_oracle_max_cri_ri_RiMethod, "com/oracle/graal/api/meta/JavaMethod") \ @@ -316,7 +316,7 @@ template(bootstrap_name, "bootstrap") \ template(shutdownCompiler_name, "shutdownCompiler") \ template(compileMethod_name, "compileMethod") \ - template(compileMethod_signature, "(Lcom/oracle/graal/hotspot/ri/HotSpotMethodResolved;IZI)Z") \ + template(compileMethod_signature, "(Lcom/oracle/graal/hotspot/meta/HotSpotMethodResolved;IZI)Z") \ template(setOption_name, "setOption") \ template(setDefaultOptions_name, "setDefaultOptions") \ template(setOption_signature, "(Ljava/lang/String;)Z") \ diff -r b6617d13ea44 -r 8872bc0eebdf src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Sat Jun 09 20:10:05 2012 +0200 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Sat Jun 09 20:32:31 2012 +0200 @@ -1122,9 +1122,9 @@ #define PROXY "J" #define TYPE "Lcom/oracle/graal/api/meta/JavaType;" -#define RESOLVED_TYPE "Lcom/oracle/graal/hotspot/ri/HotSpotTypeResolved;" +#define RESOLVED_TYPE "Lcom/oracle/graal/hotspot/meta/HotSpotTypeResolved;" #define METHOD "Lcom/oracle/graal/api/meta/JavaMethod;" -#define RESOLVED_METHOD "Lcom/oracle/graal/hotspot/ri/HotSpotMethodResolved;" +#define RESOLVED_METHOD "Lcom/oracle/graal/hotspot/meta/HotSpotMethodResolved;" #define REFLECT_METHOD "Ljava/lang/reflect/Method;" #define SIGNATURE "Lcom/oracle/graal/api/meta/Signature;" #define FIELD "Lcom/oracle/graal/api/meta/JavaField;" @@ -1133,10 +1133,10 @@ #define EXCEPTION_HANDLERS "[Lcom/oracle/graal/api/meta/ExceptionHandler;" #define TARGET_METHOD "Lcom/oracle/graal/hotspot/HotSpotTargetMethod;" #define CONFIG "Lcom/oracle/graal/hotspot/HotSpotVMConfig;" -#define HS_METHOD "Lcom/oracle/graal/hotspot/ri/HotSpotMethod;" -#define HS_COMP_METHOD "Lcom/oracle/graal/hotspot/ri/HotSpotCompiledMethod;" -#define HS_CODE_INFO "Lcom/oracle/graal/hotspot/ri/HotSpotCodeInfo;" -#define METHOD_DATA "Lcom/oracle/graal/hotspot/ri/HotSpotMethodData;" +#define HS_METHOD "Lcom/oracle/graal/hotspot/meta/HotSpotMethod;" +#define HS_COMP_METHOD "Lcom/oracle/graal/hotspot/meta/HotSpotCompiledMethod;" +#define HS_CODE_INFO "Lcom/oracle/graal/hotspot/meta/HotSpotCodeInfo;" +#define METHOD_DATA "Lcom/oracle/graal/hotspot/meta/HotSpotMethodData;" #define CI_CONSTANT "Lcom/oracle/graal/api/meta/Constant;" #define CI_KIND "Lcom/oracle/graal/api/meta/Kind;" #define CI_RUNTIME_CALL "Lcom/oracle/graal/api/code/RuntimeCall;" diff -r b6617d13ea44 -r 8872bc0eebdf src/share/vm/graal/graalJavaAccess.hpp --- a/src/share/vm/graal/graalJavaAccess.hpp Sat Jun 09 20:10:05 2012 +0200 +++ b/src/share/vm/graal/graalJavaAccess.hpp Sat Jun 09 20:32:31 2012 +0200 @@ -96,7 +96,7 @@ end_class \ start_class(HotSpotTargetMethod) \ oop_field(HotSpotTargetMethod, targetMethod, "Lcom/oracle/graal/api/code/CompilationResult;") \ - oop_field(HotSpotTargetMethod, method, "Lcom/oracle/graal/hotspot/ri/HotSpotMethodResolved;") \ + oop_field(HotSpotTargetMethod, method, "Lcom/oracle/graal/hotspot/meta/HotSpotMethodResolved;") \ oop_field(HotSpotTargetMethod, name, "Ljava/lang/String;") \ oop_field(HotSpotTargetMethod, sites, "[Lcom/oracle/graal/api/code/CompilationResult$Site;") \ oop_field(HotSpotTargetMethod, exceptionHandlers, "[Lcom/oracle/graal/api/code/CompilationResult$ExceptionHandler;") \