# HG changeset patch # User Christos Kotselidis # Date 1365806017 -7200 # Node ID 0c8ec85fa01343de519805ecde93e511ab836505 # Parent 2cae919cd3af0ad6cbeb44e7b4f4083cfedcb5b4# Parent d766fd8eede09e4fede9e0a020d728c574ecce13 Merge diff -r 2cae919cd3af -r 0c8ec85fa013 .hgignore --- a/.hgignore Fri Apr 12 23:29:45 2013 +0200 +++ b/.hgignore Sat Apr 13 00:33:37 2013 +0200 @@ -4,6 +4,7 @@ ^mx/ecj.jar ^mx/includes ^build/ +^build-nograal/ ^dist/ ^java/ ^lib/ diff -r 2cae919cd3af -r 0c8ec85fa013 .hgtags --- a/.hgtags Fri Apr 12 23:29:45 2013 +0200 +++ b/.hgtags Sat Apr 13 00:33:37 2013 +0200 @@ -330,3 +330,6 @@ 8d0f263a370c5f3e61791bb06054560804117288 hs25-b25 af788b85010ebabbc1e8f52c6766e08c7a95cf99 jdk8-b84 a947f40fb536e5b9e0aa210cf26abb430f80887a hs25-b26 +42fe530cd478744a4d12a0cbf803f0fc804bab1a jdk8-b85 +09b0d3e9ba6cdf7da07d4010d2d1df14596f6864 hs25-b27 +6d88a566d369f6a1f86912cad7d0912686b2fda1 hs25-b28 diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Assumptions.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Assumptions.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Assumptions.java Sat Apr 13 00:33:37 2013 +0200 @@ -45,6 +45,40 @@ private static final long serialVersionUID = -1936652569665112915L; } + public static final class NoFinalizableSubclass extends Assumption { + + private static final long serialVersionUID = 6451169735564055081L; + + private ResolvedJavaType receiverType; + + public NoFinalizableSubclass(ResolvedJavaType receiverType) { + this.receiverType = receiverType; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + receiverType.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof NoFinalizableSubclass) { + NoFinalizableSubclass other = (NoFinalizableSubclass) obj; + return other.receiverType == receiverType; + } + return false; + } + + @Override + public String toString() { + return "NoFinalizableSubclass[receiverType=" + toJavaName(receiverType) + "]"; + } + + } + /** * An assumption about a unique subtype of a given type. */ @@ -273,12 +307,10 @@ * Records an assumption that the specified type has no finalizable subclasses. * * @param receiverType the type that is assumed to have no finalizable subclasses - * @return {@code true} if the assumption was recorded and can be assumed; {@code false} - * otherwise */ - public boolean recordNoFinalizableSubclassAssumption(ResolvedJavaType receiverType) { + public void recordNoFinalizableSubclassAssumption(ResolvedJavaType receiverType) { assert useOptimisticAssumptions; - return false; + record(new NoFinalizableSubclass(receiverType)); } /** diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java Sat Apr 13 00:33:37 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2013, 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 @@ -52,42 +52,45 @@ } /** - * Represents a safepoint with associated debug info. + * Represents an infopoint with associated debug info. Note that safepoints are also infopoints. */ - public static class Safepoint extends Site implements Comparable { + public static class Infopoint extends Site implements Comparable { private static final long serialVersionUID = 2479806696381720162L; public final DebugInfo debugInfo; - public Safepoint(int pcOffset, DebugInfo debugInfo) { + public final InfopointReason reason; + + public Infopoint(int pcOffset, DebugInfo debugInfo, InfopointReason reason) { super(pcOffset); this.debugInfo = debugInfo; + this.reason = reason; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append(pcOffset); - sb.append("[]"); + sb.append("[]"); appendDebugInfo(sb, debugInfo); return sb.toString(); } @Override - public int compareTo(Safepoint o) { + public int compareTo(Infopoint o) { if (pcOffset < o.pcOffset) { return -1; } else if (pcOffset > o.pcOffset) { return 1; } - return 0; + return this.reason.compareTo(o.reason); } } /** * Represents a call in the code. */ - public static final class Call extends Safepoint { + public static final class Call extends Infopoint { private static final long serialVersionUID = 1440741241631046954L; @@ -109,7 +112,7 @@ public final boolean direct; public Call(InvokeTarget target, int pcOffset, int size, boolean direct, DebugInfo debugInfo) { - super(pcOffset, debugInfo); + super(pcOffset, debugInfo, InfopointReason.CALL); this.size = size; this.target = target; this.direct = direct; @@ -284,7 +287,7 @@ } } - private final List safepoints = new ArrayList<>(); + private final List infopoints = new ArrayList<>(); private final List dataReferences = new ArrayList<>(); private final List exceptionHandlers = new ArrayList<>(); private final List marks = new ArrayList<>(); @@ -377,7 +380,7 @@ */ public void recordCall(int codePos, int size, InvokeTarget target, DebugInfo debugInfo, boolean direct) { final Call call = new Call(target, codePos, size, direct, debugInfo); - addSafepoint(call); + addInfopoint(call); } /** @@ -391,22 +394,22 @@ } /** - * Records a safepoint in the code array. + * Records an infopoint in the code array. * - * @param codePos the position of the safepoint in the code array - * @param debugInfo the debug info for the safepoint + * @param codePos the position of the infopoint in the code array + * @param debugInfo the debug info for the infopoint */ - public void recordSafepoint(int codePos, DebugInfo debugInfo) { - addSafepoint(new Safepoint(codePos, debugInfo)); + public void recordInfopoint(int codePos, DebugInfo debugInfo, InfopointReason reason) { + addInfopoint(new Infopoint(codePos, debugInfo, reason)); } - private void addSafepoint(Safepoint safepoint) { - // The safepoints list must always be sorted - if (!getSafepoints().isEmpty() && getSafepoints().get(getSafepoints().size() - 1).pcOffset >= safepoint.pcOffset) { + private void addInfopoint(Infopoint infopoint) { + // The infopoints list must always be sorted + if (!getInfopoints().isEmpty() && getInfopoints().get(getInfopoints().size() - 1).pcOffset >= infopoint.pcOffset) { // This re-sorting should be very rare - Collections.sort(getSafepoints()); + Collections.sort(getInfopoints()); } - getSafepoints().add(safepoint); + getInfopoints().add(infopoint); } /** @@ -522,10 +525,10 @@ } /** - * @return the list of safepoints, sorted by {@link Site#pcOffset} + * @return the list of infopoints, sorted by {@link Site#pcOffset} */ - public List getSafepoints() { - return safepoints; + public List getInfopoints() { + return infopoints; } /** diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InfopointReason.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InfopointReason.java Sat Apr 13 00:33:37 2013 +0200 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2013, 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.api.code; + +/** + * A reason for infopoint insertion. + */ +public enum InfopointReason { + + UNKNOWN, SAFEPOINT, CALL, IMPLICIT_EXCEPTION, METHOD_START, METHOD_END, LINE_NUMBER; + +} diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InstalledCode.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InstalledCode.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InstalledCode.java Sat Apr 13 00:33:37 2013 +0200 @@ -31,14 +31,6 @@ public interface InstalledCode { /** - * Exception thrown by the runtime in case an invalidated machine code is called. - */ - public abstract class MethodInvalidatedException extends RuntimeException { - - private static final long serialVersionUID = -3540232440794244844L; - } - - /** * Returns the method (if any) to which the installed code belongs. */ ResolvedJavaMethod getMethod(); @@ -61,6 +53,12 @@ boolean isValid(); /** + * Invalidates this installed code such that any subsequent invocation will throw an + * {@link InvalidInstalledCodeException}. + */ + void invalidate(); + + /** * Executes the installed code with three object arguments. * * @param arg1 the first argument @@ -68,7 +66,7 @@ * @param arg3 the third argument * @return the value returned by the executed code */ - Object execute(Object arg1, Object arg2, Object arg3); + Object execute(Object arg1, Object arg2, Object arg3) throws InvalidInstalledCodeException; /** * Executes the installed code with a variable number of arguments. @@ -76,5 +74,5 @@ * @param args the array of object arguments * @return the value returned by the executed code */ - Object executeVarargs(Object... args); + Object executeVarargs(Object... args) throws InvalidInstalledCodeException; } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InvalidInstalledCodeException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InvalidInstalledCodeException.java Sat Apr 13 00:33:37 2013 +0200 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2013, 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.api.code; + +/** + * Exception thrown by the runtime in case an invalidated machine code is called. + */ +public final class InvalidInstalledCodeException extends Exception { + + private static final long serialVersionUID = -3540232440794244844L; +} diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ValueUtil.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ValueUtil.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ValueUtil.java Sat Apr 13 00:33:37 2013 +0200 @@ -89,13 +89,19 @@ } public static Register asIntReg(Value value) { - assert value.getKind() == Kind.Int; - return asRegister(value); + if (value.getKind() != Kind.Int) { + throw new InternalError("needed Int got: " + value.getKind()); + } else { + return asRegister(value); + } } public static Register asLongReg(Value value) { - assert value.getKind() == Kind.Long : value.getKind(); - return asRegister(value); + if (value.getKind() != Kind.Long) { + throw new InternalError("needed Long got: " + value.getKind()); + } else { + return asRegister(value); + } } public static Register asObjectReg(Value value) { diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ConstantPool.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ConstantPool.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ConstantPool.java Sat Apr 13 00:33:37 2013 +0200 @@ -98,7 +98,9 @@ * Looks up the appendix at the specified index. * * @param cpi the constant pool index - * @return the appendix if resolved or {@code null}. + * @param opcode the opcode of the instruction for which the lookup is being performed or + * {@code -1} + * @return the appendix if it exists and is resolved or {@code null} */ - Object lookupAppendix(int cpi); + Object lookupAppendix(int cpi, int opcode); } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.api.runtime/src/com/oracle/graal/api/runtime/ServiceProvider.java --- a/graal/com.oracle.graal.api.runtime/src/com/oracle/graal/api/runtime/ServiceProvider.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.api.runtime/src/com/oracle/graal/api/runtime/ServiceProvider.java Sat Apr 13 00:33:37 2013 +0200 @@ -24,7 +24,7 @@ import java.lang.annotation.*; -@Retention(RetentionPolicy.SOURCE) +@Retention(RetentionPolicy.CLASS) @Target(ElementType.TYPE) public @interface ServiceProvider { diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java --- a/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java Sat Apr 13 00:33:37 2013 +0200 @@ -26,8 +26,7 @@ public class PTXAssembler extends AbstractPTXAssembler { - @SuppressWarnings("unused") - public PTXAssembler(TargetDescription target, RegisterConfig registerConfig) { + public PTXAssembler(TargetDescription target, @SuppressWarnings("unused") RegisterConfig registerConfig) { super(target); } @@ -35,6 +34,18 @@ emitString("@%p" + " " + ""); } + public final void atq() { + emitString("@%q" + " " + ""); + } + + public final void add_f32(Register d, Register a, Register b) { + emitString("add.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void add_f64(Register d, Register a, Register b) { + emitString("add.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + public final void add_s16(Register d, Register a, Register b) { emitString("add.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); } @@ -59,6 +70,14 @@ emitString("add.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s64 + ";" + ""); } + public final void add_f32(Register d, Register a, float f32) { + emitString("add.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f32 + ";" + ""); + } + + public final void add_f64(Register d, Register a, double f64) { + emitString("add.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f64 + ";" + ""); + } + public final void add_u16(Register d, Register a, Register b) { emitString("add.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); } @@ -123,7 +142,63 @@ emitString("bra.uni" + " " + tgt + ";" + ""); } - public final void div_s16(Register d, Register a, Register b) { + public final void cvt_s32_f32(Register d, Register a) { + emitString("cvt.s32.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void cvt_s64_f32(Register d, Register a) { + emitString("cvt.s64.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void cvt_f64_f32(Register d, Register a) { + emitString("cvt.f64.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void cvt_f32_f64(Register d, Register a) { + emitString("cvt.f32.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void cvt_s32_f64(Register d, Register a) { + emitString("cvt.s32.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void cvt_s64_f64(Register d, Register a) { + emitString("cvt.s64.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void cvt_f32_s32(Register d, Register a) { + emitString("cvt.f32.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void cvt_f64_s32(Register d, Register a) { + emitString("cvt.f64.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void cvt_s8_s32(Register d, Register a) { + emitString("cvt.s8.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void cvt_b16_s32(Register d, Register a) { + emitString("cvt.b16.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void cvt_s64_s32(Register d, Register a) { + emitString("cvt.s64.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void cvt_s32_s64(Register d, Register a) { + emitString("cvt.s32.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void div_f32(Register d, Register a, Register b) { + emitString("div.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void div_f64(Register d, Register a, Register b) { + emitString("div.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void div_s16(Register d, Register a, Register b) { emitString("div.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); } @@ -143,10 +218,30 @@ emitString("div.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + ""); } + public final void div_s32(Register d, int s32, Register b) { + emitString("div.s32" + " " + "%r" + d.encoding() + ", " + s32 + ", %r" + b.encoding() + ";" + ""); + } + + public final void div_f32(Register d, float f32, Register b) { + emitString("div.f32" + " " + "%r" + d.encoding() + ", " + f32 + ", %r" + b.encoding() + ";" + ""); + } + + public final void div_f64(Register d, double f64, Register b) { + emitString("div.f64" + " " + "%r" + d.encoding() + ", " + f64 + ", %r" + b.encoding() + ";" + ""); + } + public final void div_s64(Register d, Register a, long s64) { emitString("div.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s64 + ";" + ""); } + public final void div_f32(Register d, Register a, float f32) { + emitString("div.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f32 + ";" + ""); + } + + public final void div_f64(Register d, Register a, double f64) { + emitString("div.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f64 + ";" + ""); + } + public final void div_u16(Register d, Register a, Register b) { emitString("div.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); } @@ -255,6 +350,11 @@ emitString("mov.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); } + public final void mov_u64(@SuppressWarnings("unused") Register d, + @SuppressWarnings("unused") AbstractAddress a) { + // emitString("mov.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + public final void mov_s16(Register d, Register a) { emitString("mov.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); } @@ -319,6 +419,14 @@ emitString("mov.f64" + " " + "%r" + d.encoding() + ", " + f64 + ";" + ""); } + public final void mul_f32(Register d, Register a, Register b) { + emitString("mul.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void mul_f64(Register d, Register a, Register b) { + emitString("smul.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + public final void mul_s16(Register d, Register a, Register b) { emitString("mul.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); } @@ -343,6 +451,14 @@ emitString("mul.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s64 + ";" + ""); } + public final void mul_f32(Register d, Register a, float f32) { + emitString("mul.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f32 + ";" + ""); + } + + public final void mul_f64(Register d, Register a, double f64) { + emitString("mul.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f64 + ";" + ""); + } + public final void mul_u16(Register d, Register a, Register b) { emitString("mul.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); } @@ -367,6 +483,14 @@ emitString("mul.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u64 + ";" + ""); } + public final void neg_f32(Register d, Register a) { + emitString("neg.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void neg_f64(Register d, Register a) { + emitString("neg.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + public final void neg_s16(Register d, Register a) { emitString("neg.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); } @@ -379,6 +503,42 @@ emitString("neg.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); } + public final void not_s16(Register d, Register a) { + emitString("not.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void not_s32(Register d, Register a) { + emitString("not.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void not_s64(Register d, Register a) { + emitString("not.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + } + + public final void or_b16(Register d, Register a, Register b) { + emitString("or.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void or_b32(Register d, Register a, Register b) { + emitString("or.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void or_b64(Register d, Register a, Register b) { + emitString("or.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void or_b16(Register d, Register a, short b16) { + emitString("or.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b16 + ";" + ""); + } + + public final void or_b32(Register d, Register a, int b32) { + emitString("or.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b32 + ";" + ""); + } + + public final void or_b64(Register d, Register a, long b64) { + emitString("or.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b64 + ";" + ""); + } + public final void popc_b32(Register d, Register a) { emitString("popc.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); } @@ -443,6 +603,86 @@ emitString("ret.uni;" + " " + ""); } + public final void setp_eq_f32(Register a, Register b) { + emitString("setp.eq.f32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_ne_f32(Register a, Register b) { + emitString("setp.ne.f32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_lt_f32(Register a, Register b) { + emitString("setp.lt.f32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_le_f32(Register a, Register b) { + emitString("setp.le.f32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_gt_f32(Register a, Register b) { + emitString("setp.gt.f32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_ge_f32(Register a, Register b) { + emitString("setp.ge.f32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_eq_f32(float f32, Register b) { + emitString("setp.eq.f32" + " " + "%p" + ", " + f32 + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_ne_f32(float f32, Register b) { + emitString("setp.ne.f32" + " " + "%p" + ", " + f32 + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_lt_f32(float f32, Register b) { + emitString("setp.lt.f32" + " " + "%p" + ", " + f32 + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_le_f32(float f32, Register b) { + emitString("setp.le.f32" + " " + "%p" + ", " + f32 + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_gt_f32(float f32, Register b) { + emitString("setp.gt.f32" + " " + "%p" + ", " + f32 + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_ge_f32(float f32, Register b) { + emitString("setp.ge.f32" + " " + "%p" + ", " + f32 + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_eq_f64(double f64, Register b) { + emitString("setp.eq.f64" + " " + "%p" + ", " + f64 + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_ne_f64(double f64, Register b) { + emitString("setp.ne.f64" + " " + "%p" + ", " + f64 + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_lt_f64(double f64, Register b) { + emitString("setp.lt.f64" + " " + "%p" + ", " + f64 + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_le_f64(double f64, Register b) { + emitString("setp.le.f64" + " " + "%p" + ", " + f64 + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_gt_f64(double f64, Register b) { + emitString("setp.gt.f64" + " " + "%p" + ", " + f64 + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_ge_f64(double f64, Register b) { + emitString("setp.ge.f64" + " " + "%p" + ", " + f64 + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_eq_s64(Register a, Register b) { + emitString("setp.eq.s64" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void setp_eq_s64(long s64, Register b) { + emitString("setp.eq.s64" + " " + "%p" + ", " + s64 + ", %r" + b.encoding() + ";" + ""); + } + public final void setp_eq_s32(Register a, Register b) { emitString("setp.eq.s32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); } @@ -587,6 +827,54 @@ emitString("setp.ge.u32" + " " + "%p" + ", " + u32 + ", %r" + b.encoding() + ";" + ""); } + public final void shl_s16(Register d, Register a, Register b) { + emitString("shl.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void shl_s32(Register d, Register a, Register b) { + emitString("shl.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void shl_s64(Register d, Register a, Register b) { + emitString("shl.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void shl_s16(Register d, Register a, int u32) { + emitString("shl.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + ""); + } + + public final void shl_s32(Register d, Register a, int u32) { + emitString("shl.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + ""); + } + + public final void shl_s64(Register d, Register a, int u32) { + emitString("shl.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + ""); + } + + public final void shl_u16(Register d, Register a, Register b) { + emitString("shl.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void shl_u32(Register d, Register a, Register b) { + emitString("shl.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void shl_u64(Register d, Register a, Register b) { + emitString("shl.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void shl_u16(Register d, Register a, int u32) { + emitString("shl.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + ""); + } + + public final void shl_u32(Register d, Register a, int u32) { + emitString("shl.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + ""); + } + + public final void shl_u64(Register d, Register a, int u32) { + emitString("shl.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + ""); + } + public final void shr_s16(Register d, Register a, Register b) { emitString("shr.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); } @@ -631,8 +919,8 @@ emitString("shr.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + ""); } - public final void shr_u64(Register d, Register a, int u32) { - emitString("shr.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + ""); + public final void shr_u64(Register d, Register a, long u64) { + emitString("shr.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u64 + ";" + ""); } public final void st_global_b8(Register a, long immOff, Register b) { @@ -691,6 +979,14 @@ emitString("st.global.f64" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + ""); } + public final void sub_f32(Register d, Register a, Register b) { + emitString("sub.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void sub_f64(Register d, Register a, Register b) { + emitString("sub.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + public final void sub_s16(Register d, Register a, Register b) { emitString("sub.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); } @@ -711,10 +1007,22 @@ emitString("sub.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + ""); } + public final void sub_s64(Register d, Register a, int s32) { + emitString("sub.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + ""); + } + public final void sub_s64(Register d, Register a, long s64) { emitString("sub.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s64 + ";" + ""); } + public final void sub_f32(Register d, Register a, float f32) { + emitString("sub.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f32 + ";" + ""); + } + + public final void sub_f64(Register d, Register a, double f64) { + emitString("sub.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f64 + ";" + ""); + } + public final void sub_s16(Register d, short s16, Register b) { emitString("sub.s16" + " " + "%r" + d.encoding() + ", " + s16 + ", %r" + b.encoding() + ";" + ""); } @@ -727,6 +1035,14 @@ emitString("sub.s64" + " " + "%r" + d.encoding() + ", " + s64 + ", %r" + b.encoding() + ";" + ""); } + public final void sub_f32(Register d, float f32, Register b) { + emitString("sub.f32" + " " + "%r" + d.encoding() + ", %r" + b.encoding() + ", " + f32 + ";" + ""); + } + + public final void sub_f64(Register d, double f64, Register b) { + emitString("sub.f64" + " " + "%r" + d.encoding() + ", %r" + b.encoding() + ", " + f64 + ";" + ""); + } + public final void sub_sat_s32(Register d, Register a, Register b) { emitString("sub.sat.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); } @@ -739,6 +1055,30 @@ emitString("sub.sat.s32" + " " + "%r" + d.encoding() + ", " + s32 + ", %r" + b.encoding() + ";" + ""); } + public final void xor_b16(Register d, Register a, Register b) { + emitString("xor.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void xor_b32(Register d, Register a, Register b) { + emitString("xor.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void xor_b64(Register d, Register a, Register b) { + emitString("xor.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + } + + public final void xor_b16(Register d, Register a, short b16) { + emitString("xor.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b16 + ";" + ""); + } + + public final void xor_b32(Register d, Register a, int b32) { + emitString("xor.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b32 + ";" + ""); + } + + public final void xor_b64(Register d, Register a, long b64) { + emitString("xor.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b64 + ";" + ""); + } + @Override public PTXAddress makeAddress(Register base, int displacement) { return new PTXAddress(base, displacement); diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java --- a/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -67,7 +67,11 @@ protected Object runTest(String methodName, CodeGenTest test, Object... args) { Method method = getMethod(methodName); InstalledCode code = assembleMethod(method, test); - return code.executeVarargs(args); + try { + return code.executeVarargs(args); + } catch (InvalidInstalledCodeException e) { + throw new RuntimeException(e); + } } protected void assertReturn(String methodName, CodeGenTest test, Object expected, Object... args) { diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java --- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Sat Apr 13 00:33:37 2013 +0200 @@ -926,4 +926,9 @@ Value[] parameters = visitInvokeArguments(cc, node.arguments); append(new AMD64BreakpointOp(parameters)); } + + @Override + public void visitInfopointNode(InfopointNode i) { + append(new InfopointOp(stateFor(i.stateAfter(), DeoptimizationReason.None), i.reason)); + } } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ArrayTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ArrayTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.ptx.test; + +import java.lang.reflect.Method; + +import org.junit.Test; + +public class ArrayTest extends PTXTestBase { + + @Test + public void testArray() { + compile("testArray1I"); + compile("testArray1J"); + compile("testArray1B"); + compile("testArray1S"); + compile("testArray1C"); + compile("testArray1F"); + compile("testArray1D"); + compile("testArray1L"); + compile("testStoreArray1I"); + compile("testStoreArray1J"); + compile("testStoreArray1B"); + compile("testStoreArray1S"); + compile("testStoreArray1F"); + compile("testStoreArray1D"); + } + + public static int testArray1I(int[] array, int i) { + return array[i]; + } + + public static long testArray1J(long[] array, int i) { + return array[i]; + } + + public static byte testArray1B(byte[] array, int i) { + return array[i]; + } + + public static short testArray1S(short[] array, int i) { + return array[i]; + } + + public static char testArray1C(char[] array, int i) { + return array[i]; + } + + public static float testArray1F(float[] array, int i) { + return array[i]; + } + + public static double testArray1D(double[] array, int i) { + return array[i]; + } + + public static Object testArray1L(Object[] array, int i) { + return array[i]; + } + + public static void testStoreArray1I(int[] array, int i, int val) { + array[i] = val; + } + + public static void testStoreArray1B(byte[] array, int i, byte val) { + array[i] = val; + } + + public static void testStoreArray1S(short[] array, int i, short val) { + array[i] = val; + } + + public static void testStoreArray1J(long[] array, int i, long val) { + array[i] = val; + } + + public static void testStoreArray1F(float[] array, int i, float val) { + array[i] = val; + } + + public static void testStoreArray1D(double[] array, int i, double val) { + array[i] = val; + } + + public static void main(String[] args) { + ArrayTest test = new ArrayTest(); + for (Method m : ArrayTest.class.getMethods()) { + String name = m.getName(); + if (m.getAnnotation(Test.class) == null && name.startsWith("test")) { + // CheckStyle: stop system..print check + System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode())); + // CheckStyle: resume system..print check + } + } + } +} diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java --- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -22,82 +22,32 @@ */ package com.oracle.graal.compiler.ptx.test; -import java.lang.reflect.*; - -import org.junit.*; +import java.lang.reflect.Method; -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.runtime.*; -import com.oracle.graal.compiler.*; -import com.oracle.graal.compiler.ptx.*; -import com.oracle.graal.compiler.test.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.java.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; -import com.oracle.graal.phases.*; -import com.oracle.graal.phases.PhasePlan.PhasePosition; -import com.oracle.graal.ptx.*; +import org.junit.Test; /** * Test class for small Java methods compiled to PTX kernels. */ -public class BasicPTXTest extends GraalCompilerTest { +public class BasicPTXTest extends PTXTestBase { @Test public void testAdd() { - test("testAddSnippet"); + compile("testAddConst1I"); } - public static int testAddSnippet(int a) { + public static int testAddConst1I(int a) { return a + 1; } - @Test - public void testArray() { - test("testArraySnippet"); - } - - public static int testArraySnippet(int[] array) { - return array[0]; - } - - private CompilationResult test(String snippet) { - StructuredGraph graph = parse(snippet); - Debug.dump(graph, "Graph"); - TargetDescription target = new TargetDescription(new PTX(), true, 1, 0, true); - PTXBackend ptxBackend = new PTXBackend(Graal.getRequiredCapability(CodeCacheProvider.class), target); - PhasePlan phasePlan = new PhasePlan(); - GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.NONE); - phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); - phasePlan.addPhase(PhasePosition.AFTER_PARSING, new PTXPhase()); - new PTXPhase().apply(graph); - CompilationResult result = GraalCompiler.compileMethod(runtime, replacements, ptxBackend, target, graph.method(), graph, null, phasePlan, OptimisticOptimizations.NONE, new SpeculationLog()); - return result; - } - - private static class PTXPhase extends Phase { - - @Override - protected void run(StructuredGraph graph) { - for (LocalNode local : graph.getNodes(LocalNode.class)) { - if (local.kind() == Kind.Object) { - local.setStamp(StampFactory.declaredNonNull(local.objectStamp().type())); - } - } - } - - } - public static void main(String[] args) { - BasicPTXTest basicPTXTest = new BasicPTXTest(); + BasicPTXTest test = new BasicPTXTest(); Method[] methods = BasicPTXTest.class.getMethods(); for (Method m : methods) { - if (m.getAnnotation(Test.class) != null) { - String name = m.getName() + "Snippet"; + String name = m.getName(); + if (m.getAnnotation(Test.class) == null && name.startsWith("test")) { // CheckStyle: stop system..print check - System.out.println(name + ": \n" + new String(basicPTXTest.test(name).getTargetCode())); + System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode())); // CheckStyle: resume system..print check } } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ControlTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ControlTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.ptx.test; + +import org.junit.Test; + +import java.lang.reflect.Method; + +public class ControlTest extends PTXTestBase { + + @Test + public void testControl() { + compile("testSwitch1I"); + compile("testStatic"); + compile("testCall"); + compile("testLookupSwitch1I"); + } + + public static int testSwitch1I(int a) { + switch (a) { + case 1: + return 2; + case 2: + return 3; + default: + return 4; + } + } + + public static int testLookupSwitch1I(int a) { + switch (a) { + case 0: return 1; + case 1: return 2; + case 2: return 3; + case 3: return 1; + case 4: return 2; + case 5: return 3; + case 6: return 1; + case 7: return 2; + case 8: return 3; + case 9: return 1; + case 10: return 2; + case 11: return 3; + default: return -1; + } + } + + @SuppressWarnings("unused") + private static Object foo = null; + + public static boolean testStatic(Object o) { + foo = o; + return true; + } + + private static int method(int a, int b) { + return a + b; + } + + public static int testCall(@SuppressWarnings("unused") Object o, int a, int b) { + return method(a, b); + } + + public static void main(String[] args) { + ControlTest test = new ControlTest(); + for (Method m : ControlTest.class.getMethods()) { + String name = m.getName(); + if (m.getAnnotation(Test.class) == null && name.startsWith("test")) { + // CheckStyle: stop system..print check + System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode())); + // CheckStyle: resume system..print check + } + } + } +} diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/FloatPTXTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/FloatPTXTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.ptx.test; + +import java.lang.reflect.Method; + +import org.junit.*; + + +/* PTX ISA 3.1 - 8.7.3 Floating-Point Instructions */ +public class FloatPTXTest extends PTXTestBase { + + @Test + public void testAdd() { + compile("testAdd2F"); + compile("testAdd2D"); + compile("testAddFConst"); + compile("testAddConstF"); + compile("testAddDConst"); + compile("testAddConstD"); + } + + public static float testAdd2F(float a, float b) { + return a + b; + } + + public static double testAdd2D(double a, double b) { + return a + b; + } + + public static float testAddFConst(float a) { + return a + 32.0F; + } + + public static float testAddConstF(float a) { + return 32.0F + a; + } + + public static double testAddDConst(double a) { + return a + 32.0; + } + + public static double testAddConstD(double a) { + return 32.0 + a; + } + + @Test + public void testSub() { + compile("testSub2F"); + compile("testSub2D"); + compile("testSubFConst"); + compile("testSubConstF"); + compile("testSubDConst"); + compile("testSubConstD"); + } + + public static float testSub2F(float a, float b) { + return a - b; + } + + public static double testSub2D(double a, double b) { + return a - b; + } + + public static float testSubFConst(float a) { + return a - 32.0F; + } + + public static float testSubConstF(float a) { + return 32.0F - a; + } + + public static double testSubDConst(double a) { + return a - 32.0; + } + + public static double testSubConstD(double a) { + return 32.0 - a; + } + + @Test + public void testMul() { + compile("testMul2F"); + compile("testMul2D"); + compile("testMulFConst"); + compile("testMulConstF"); + compile("testMulDConst"); + compile("testMulConstD"); + } + + public static float testMul2F(float a, float b) { + return a * b; + } + + public static double testMul2D(double a, double b) { + return a * b; + } + + public static float testMulFConst(float a) { + return a * 32.0F; + } + + public static float testMulConstF(float a) { + return 32.0F * a; + } + + public static double testMulDConst(double a) { + return a * 32.0; + } + + public static double testMulConstD(double a) { + return 32.0 * a; + } + + @Test + public void testDiv() { + compile("testDiv2F"); + compile("testDiv2D"); + compile("testDivFConst"); + compile("testDivConstF"); + compile("testDivDConst"); + compile("testDivConstD"); + } + + public static float testDiv2F(float a, float b) { + return a / b; + } + + public static double testDiv2D(double a, double b) { + return a / b; + } + + public static float testDivFConst(float a) { + return a / 32.0F; + } + + public static float testDivConstF(float a) { + return 32.0F / a; + } + + public static double testDivDConst(double a) { + return a / 32.0; + } + + public static double testDivConstD(double a) { + return 32.0 / a; + } + + @Test + public void testNeg() { + compile("testNeg2F"); + compile("testNeg2D"); + } + + public static float testNeg2F(float a) { + return -a; + } + + public static double testNeg2D(double a) { + return -a; + } + + @Test + public void testRem() { + // need linkage to PTX remainder() + // compile("testRem2F"); + // compile("testRem2D"); + } + + public static float testRem2F(float a, float b) { + return a % b; + } + + public static double testRem2D(double a, double b) { + return a % b; + } + + @Test + public void testFloatConversion() { + compile("testF2I"); + compile("testF2L"); + compile("testF2D"); + compile("testD2I"); + compile("testD2L"); + compile("testD2F"); + } + + public static int testF2I(float a) { + return (int) a; + } + + public static long testF2L(float a) { + return (long) a; + } + + public static double testF2D(float a) { + return a; + } + + public static int testD2I(double a) { + return (int) a; + } + + public static long testD2L(double a) { + return (long) a; + } + + public static float testD2F(double a) { + return (float) a; + } + + public static void main(String[] args) { + FloatPTXTest test = new FloatPTXTest(); + for (Method m : FloatPTXTest.class.getMethods()) { + String name = m.getName(); + if (m.getAnnotation(Test.class) == null && + name.startsWith("test") && + name.startsWith("testRem") == false) { + // CheckStyle: stop system..print check + System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode())); + // CheckStyle: resume system..print check + } + } + } +} diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/IntegerPTXTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/IntegerPTXTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.ptx.test; + +import org.junit.Test; + +import java.lang.reflect.Method; + + +public class IntegerPTXTest extends PTXTestBase { + + @Test + public void testAdd() { + compile("testAdd2I"); + compile("testAdd2L"); + compile("testAdd2B"); + compile("testAddIConst"); + compile("testAddConstI"); + } + + public static int testAdd2I(int a, int b) { + return a + b; + } + + public static long testAdd2L(long a, long b) { + return a + b; + } + + public static int testAdd2B(byte a, byte b) { + return a + b; + } + + public static int testAddIConst(int a) { + return a + 32; + } + + public static int testAddConstI(int a) { + return 32 + a; + } + + @Test + public void testSub() { + compile("testSub2I"); + compile("testSub2L"); + compile("testSubIConst"); + compile("testSubConstI"); + } + + public static int testSub2I(int a, int b) { + return a - b; + } + + public static long testSub2L(long a, long b) { + return a - b; + } + + public static int testSubIConst(int a) { + return a - 32; + } + + public static int testSubConstI(int a) { + return 32 - a; + } + + @Test + public void testMul() { + compile("testMul2I"); + compile("testMul2L"); + compile("testMulIConst"); + compile("testMulConstI"); + } + + public static int testMul2I(int a, int b) { + return a * b; + } + + public static long testMul2L(long a, long b) { + return a * b; + } + + public static int testMulIConst(int a) { + return a * 32; + } + + public static int testMulConstI(int a) { + return 32 * a; + } + + @Test + public void testDiv() { + compile("testDiv2I"); + compile("testDiv2L"); + compile("testDivIConst"); + compile("testDivConstI"); + } + + public static int testDiv2I(int a, int b) { + return a / b; + } + + public static long testDiv2L(long a, long b) { + return a / b; + } + + public static int testDivIConst(int a) { + return a / 32; + } + + public static int testDivConstI(int a) { + return 32 / a; + } + + @Test + public void testRem() { + compile("testRem2I"); + compile("testRem2L"); + } + + public static int testRem2I(int a, int b) { + return a % b; + } + + public static long testRem2L(long a, long b) { + return a % b; + } + + @Test + public void testIntConversion() { + compile("testI2L"); + compile("testL2I"); + compile("testI2C"); + compile("testI2B"); + compile("testI2F"); + compile("testI2D"); + } + + public static long testI2L(int a) { + return a; + } + + public static char testI2C(int a) { + return (char) a; + } + + public static byte testI2B(int a) { + return (byte) a; + } + + public static float testI2F(int a) { + return a; + } + + public static double testI2D(int a) { + return a; + } + + public static int testL2I(long a) { + return (int) a; + } + + public static void main(String[] args) { + IntegerPTXTest test = new IntegerPTXTest(); + for (Method m : IntegerPTXTest.class.getMethods()) { + String name = m.getName(); + if (m.getAnnotation(Test.class) == null && name.startsWith("test")) { + // CheckStyle: stop system..print check + System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode())); + // CheckStyle: resume system..print check + } + } + } +} diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/LogicPTXTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/LogicPTXTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.ptx.test; + +import java.lang.reflect.Method; + +import org.junit.Test; + + +/* PTX ISA 3.1 - 8.7.5 Logic and Shift Instructions */ +public class LogicPTXTest extends PTXTestBase { + + @Test + public void testAnd() { + compile("testAnd2I"); + compile("testAnd2L"); + } + + public static int testAnd2I(int a, int b) { + return a & b; + } + + public static long testAnd2L(long a, long b) { + return a & b; + } + + @Test + public void testOr() { + compile("testOr2I"); + compile("testOr2L"); + } + + public static int testOr2I(int a, int b) { + return a | b; + } + + public static long testOr2L(long a, long b) { + return a | b; + } + + @Test + public void testXor() { + compile("testXor2I"); + compile("testXor2L"); + } + + public static int testXor2I(int a, int b) { + return a ^ b; + } + + public static long testXor2L(long a, long b) { + return a ^ b; + } + + @Test + public void testNot() { + compile("testNot1I"); + compile("testNot1L"); + } + + public static int testNot1I(int a) { + return ~a; + } + + public static long testNot1L(long a) { + return ~a; + } + + @Test + public void testShiftLeft() { + compile("testShiftLeft2I"); + compile("testShiftLeft2L"); + } + + public static int testShiftLeft2I(int a, int b) { + return a << b; + } + + public static long testShiftLeft2L(long a, int b) { + return a << b; + } + + @Test + public void testShiftRight() { + compile("testShiftRight2I"); + compile("testShiftRight2L"); + compile("testUnsignedShiftRight2I"); + compile("testUnsignedShiftRight2L"); + } + + public static int testShiftRight2I(int a, int b) { + return a >> b; + } + + public static long testShiftRight2L(long a, int b) { + return a >> b; + } + + public static int testUnsignedShiftRight2I(int a, int b) { + return a >>> b; + } + + public static long testUnsignedShiftRight2L(long a, long b) { + return a >>> b; + } + + public static void main(String[] args) { + LogicPTXTest test = new LogicPTXTest(); + for (Method m : LogicPTXTest.class.getMethods()) { + String name = m.getName(); + if (m.getAnnotation(Test.class) == null && name.startsWith("test")) { + // CheckStyle: stop system..print check + System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode())); + // CheckStyle: resume system..print check + } + } + } +} diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXPhase.java Sat Apr 13 00:33:37 2013 +0200 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.ptx.test; + +import com.oracle.graal.api.meta.Kind; +import com.oracle.graal.nodes.LocalNode; +import com.oracle.graal.nodes.StructuredGraph; +import com.oracle.graal.nodes.type.StampFactory; +import com.oracle.graal.phases.Phase; + + +public class PTXPhase extends Phase { + @Override + protected void run(StructuredGraph graph) { + /* + * Assume that null checks would be done on the CPU caller side prior + * to copying data onto the GPU. + */ + for (LocalNode local : graph.getNodes(LocalNode.class)) { + if (local.kind() == Kind.Object) { + local.setStamp(StampFactory.declaredNonNull(local.objectStamp().type())); + } + } + } +} diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXTestBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXTestBase.java Sat Apr 13 00:33:37 2013 +0200 @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.ptx.test; + +import com.oracle.graal.api.code.CodeCacheProvider; +import com.oracle.graal.api.code.CompilationResult; +import com.oracle.graal.api.code.SpeculationLog; +import com.oracle.graal.api.code.TargetDescription; +import com.oracle.graal.api.runtime.Graal; +import com.oracle.graal.compiler.GraalCompiler; +import com.oracle.graal.compiler.ptx.PTXBackend; +import com.oracle.graal.compiler.test.GraalCompilerTest; +import com.oracle.graal.debug.Debug; +import com.oracle.graal.java.GraphBuilderConfiguration; +import com.oracle.graal.java.GraphBuilderPhase; +import com.oracle.graal.hotspot.HotSpotGraalRuntime; +import com.oracle.graal.nodes.StructuredGraph; +import com.oracle.graal.phases.OptimisticOptimizations; +import com.oracle.graal.phases.PhasePlan; +import com.oracle.graal.phases.PhasePlan.PhasePosition; +import com.oracle.graal.ptx.PTX; + +public abstract class PTXTestBase extends GraalCompilerTest { + + protected CompilationResult compile(String test) { + StructuredGraph graph = parse(test); + Debug.dump(graph, "Graph"); + TargetDescription target = new TargetDescription(new PTX(), true, 1, 0, true); + PTXBackend ptxBackend = new PTXBackend(Graal.getRequiredCapability(CodeCacheProvider.class), target); + PhasePlan phasePlan = new PhasePlan(); + GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), + OptimisticOptimizations.NONE); + phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); + phasePlan.addPhase(PhasePosition.AFTER_PARSING, new PTXPhase()); + new PTXPhase().apply(graph); + CompilationResult result = GraalCompiler.compileMethod(runtime, HotSpotGraalRuntime.getInstance().getReplacements(), + ptxBackend, target, graph.method(), graph, null, phasePlan, + OptimisticOptimizations.NONE, new SpeculationLog()); + return result; + } + +} diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXBackend.java --- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXBackend.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXBackend.java Sat Apr 13 00:33:37 2013 +0200 @@ -94,7 +94,7 @@ codeBuffer.emitString(""); // XXX For now declare one predicate and all registers - codeBuffer.emitString(" .reg .pred %p;"); + codeBuffer.emitString(" .reg .pred %p,%q;"); codeBuffer.emitString(" .reg .u32 %r<16>;"); // Emit code for the LIR diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java --- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java Sat Apr 13 00:33:37 2013 +0200 @@ -28,35 +28,59 @@ import static com.oracle.graal.lir.ptx.PTXBitManipulationOp.IntrinsicOpcode.*; import static com.oracle.graal.lir.ptx.PTXCompare.*; -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.asm.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.lir.*; +import com.oracle.graal.api.code.AllocatableValue; +import com.oracle.graal.api.code.CodeCacheProvider; +import com.oracle.graal.api.code.DeoptimizationAction; +import com.oracle.graal.api.code.RuntimeCallTarget; +import com.oracle.graal.api.code.StackSlot; +import com.oracle.graal.api.code.TargetDescription; +import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; +import com.oracle.graal.api.meta.Constant; +import com.oracle.graal.api.meta.Kind; +import com.oracle.graal.api.meta.ResolvedJavaMethod; +import com.oracle.graal.api.meta.Value; +import com.oracle.graal.asm.NumUtil; +import com.oracle.graal.compiler.gen.LIRGenerator; +import com.oracle.graal.compiler.target.LIRGenLowerable; +import com.oracle.graal.graph.GraalInternalError; +import com.oracle.graal.lir.FrameMap; +import com.oracle.graal.lir.LIR; +import com.oracle.graal.lir.LIRFrameState; +import com.oracle.graal.lir.LIRInstruction; +import com.oracle.graal.lir.LIRValueUtil; +import com.oracle.graal.lir.LabelRef; import com.oracle.graal.lir.StandardOp.JumpOp; -import com.oracle.graal.lir.ptx.*; +import com.oracle.graal.lir.Variable; +import com.oracle.graal.lir.ptx.PTXAddressValue; import com.oracle.graal.lir.ptx.PTXArithmetic.Op1Stack; import com.oracle.graal.lir.ptx.PTXArithmetic.Op2Reg; import com.oracle.graal.lir.ptx.PTXArithmetic.Op2Stack; import com.oracle.graal.lir.ptx.PTXArithmetic.ShiftOp; +import com.oracle.graal.lir.ptx.PTXBitManipulationOp; import com.oracle.graal.lir.ptx.PTXCompare.CompareOp; import com.oracle.graal.lir.ptx.PTXControlFlow.BranchOp; +import com.oracle.graal.lir.ptx.PTXControlFlow.CondMoveOp; +import com.oracle.graal.lir.ptx.PTXControlFlow.FloatCondMoveOp; import com.oracle.graal.lir.ptx.PTXControlFlow.ReturnOp; +import com.oracle.graal.lir.ptx.PTXControlFlow.SequentialSwitchOp; +import com.oracle.graal.lir.ptx.PTXControlFlow.TableSwitchOp; import com.oracle.graal.lir.ptx.PTXMove.LoadOp; import com.oracle.graal.lir.ptx.PTXMove.MoveFromRegOp; import com.oracle.graal.lir.ptx.PTXMove.MoveToRegOp; import com.oracle.graal.lir.ptx.PTXMove.StoreOp; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.calc.Condition; +import com.oracle.graal.nodes.calc.ConvertNode; +import com.oracle.graal.nodes.java.CompareAndSwapNode; /** * This class implements the PTX specific portion of the LIR generator. */ public class PTXLIRGenerator extends LIRGenerator { + public static final Descriptor ARITHMETIC_FREM = new Descriptor("arithmeticFrem", false, float.class, float.class, float.class); + public static final Descriptor ARITHMETIC_DREM = new Descriptor("arithmeticDrem", false, double.class, double.class, double.class); + public static class PTXSpillMoveFactory implements LIR.SpillMoveFactory { @Override @@ -131,7 +155,7 @@ baseRegister = asAllocatable(base); } - if (index != Value.ILLEGAL) { + if (index != Value.ILLEGAL && scale != 0) { if (isConstant(index)) { finalDisp += asConstant(index).asLong() * scale; } else { @@ -145,6 +169,9 @@ if (baseRegister == AllocatableValue.UNUSED) { baseRegister = asAllocatable(indexRegister); } else { + Variable newBase = newVariable(Kind.Int); + emitMove(newBase, baseRegister); + baseRegister = newBase; baseRegister = emitAdd(baseRegister, indexRegister); } } @@ -190,6 +217,18 @@ append(new CompareOp(ICMP, cond, left, right)); append(new BranchOp(cond, label)); break; + case Long: + append(new CompareOp(LCMP, cond, left, right)); + append(new BranchOp(cond, label)); + break; + case Float: + append(new CompareOp(FCMP, cond, left, right)); + append(new BranchOp(cond, label)); + break; + case Double: + append(new CompareOp(DCMP, cond, left, right)); + append(new BranchOp(cond, label)); + break; case Object: append(new CompareOp(ACMP, cond, left, right)); append(new BranchOp(cond, label)); @@ -211,7 +250,67 @@ @Override public Variable emitConditionalMove(Value left, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) { - throw new InternalError("NYI"); + boolean mirrored = emitCompare(cond, left, right); + Condition finalCondition = mirrored ? cond.mirror() : cond; + + Variable result = newVariable(trueValue.getKind()); + switch (left.getKind().getStackKind()) { + case Int: + case Long: + case Object: + append(new CondMoveOp(result, finalCondition, load(trueValue), loadNonConst(falseValue))); + break; + case Float: + case Double: + append(new FloatCondMoveOp(result, finalCondition, unorderedIsTrue, load(trueValue), load(falseValue))); + break; + default: + throw GraalInternalError.shouldNotReachHere("missing: " + left.getKind()); + } + return result; + } + + /** + * This method emits the compare instruction, and may reorder the operands. It returns true if + * it did so. + * + * @param a the left operand of the comparison + * @param b the right operand of the comparison + * @return true if the left and right operands were switched, false otherwise + */ + private boolean emitCompare(Condition cond, Value a, Value b) { + Variable left; + Value right; + boolean mirrored; + if (LIRValueUtil.isVariable(b)) { + left = load(b); + right = loadNonConst(a); + mirrored = true; + } else { + left = load(a); + right = loadNonConst(b); + mirrored = false; + } + switch (left.getKind().getStackKind()) { + case Int: + append(new CompareOp(ICMP, cond, left, right)); + break; + case Long: + append(new CompareOp(LCMP, cond, left, right)); + break; + case Object: + append(new CompareOp(ACMP, cond, left, right)); + break; + case Float: + append(new CompareOp(FCMP, cond, left, right)); + break; + case Double: + append(new CompareOp(DCMP, cond, left, right)); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + return mirrored; } @Override @@ -226,6 +325,12 @@ case Int: append(new Op1Stack(INEG, result, input)); break; + case Float: + append(new Op1Stack(FNEG, result, input)); + break; + case Double: + append(new Op1Stack(DNEG, result, input)); + break; default: throw GraalInternalError.shouldNotReachHere(); } @@ -239,8 +344,17 @@ case Int: append(new Op2Stack(IADD, result, a, loadNonConst(b))); break; + case Long: + append(new Op2Stack(LADD, result, a, loadNonConst(b))); + break; + case Float: + append(new Op2Stack(FADD, result, a, loadNonConst(b))); + break; + case Double: + append(new Op2Stack(DADD, result, a, loadNonConst(b))); + break; default: - throw GraalInternalError.shouldNotReachHere(); + throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind() + " prim: " + a.getKind().isPrimitive()); } return result; } @@ -252,8 +366,17 @@ case Int: append(new Op2Stack(ISUB, result, a, loadNonConst(b))); break; + case Long: + append(new Op2Stack(LSUB, result, a, loadNonConst(b))); + break; + case Float: + append(new Op2Stack(FSUB, result, a, loadNonConst(b))); + break; + case Double: + append(new Op2Stack(DSUB, result, a, loadNonConst(b))); + break; default: - throw GraalInternalError.shouldNotReachHere(); + throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind()); } return result; } @@ -265,8 +388,17 @@ case Int: append(new Op2Reg(IMUL, result, a, loadNonConst(b))); break; + case Long: + append(new Op2Reg(LMUL, result, a, loadNonConst(b))); + break; + case Float: + append(new Op2Stack(FMUL, result, a, loadNonConst(b))); + break; + case Double: + append(new Op2Stack(DMUL, result, a, loadNonConst(b))); + break; default: - throw GraalInternalError.shouldNotReachHere(); + throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind()); } return result; } @@ -279,12 +411,40 @@ @Override public Value emitDiv(Value a, Value b, DeoptimizingNode deopting) { - throw new InternalError("NYI"); + Variable result = newVariable(a.getKind()); + switch (a.getKind()) { + case Int: + append(new Op2Reg(IDIV, result, a, loadNonConst(b))); + break; + case Long: + append(new Op2Reg(LDIV, result, a, loadNonConst(b))); + break; + case Float: + append(new Op2Stack(FDIV, result, a, loadNonConst(b))); + break; + case Double: + append(new Op2Stack(DDIV, result, a, loadNonConst(b))); + break; + default: + throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind()); + } + return result; } @Override public Value emitRem(Value a, Value b, DeoptimizingNode deopting) { - throw new InternalError("NYI"); + Variable result = newVariable(a.getKind()); + switch (a.getKind()) { + case Int: + append(new Op2Reg(IREM, result, a, loadNonConst(b))); + break; + case Long: + append(new Op2Reg(LREM, result, a, loadNonConst(b))); + break; + default: + throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind()); + } + return result; } @Override @@ -304,6 +464,42 @@ case Int: append(new Op2Stack(IAND, result, a, loadNonConst(b))); break; + case Long: + append(new Op2Stack(LAND, result, a, loadNonConst(b))); + break; + + default: + throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind()); + } + return result; + } + + @Override + public Variable emitOr(Value a, Value b) { + Variable result = newVariable(a.getKind()); + switch (a.getKind()) { + case Int: + append(new Op2Stack(IOR, result, a, loadNonConst(b))); + break; + case Long: + append(new Op2Stack(LOR, result, a, loadNonConst(b))); + break; + default: + throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind()); + } + return result; + } + + @Override + public Variable emitXor(Value a, Value b) { + Variable result = newVariable(a.getKind()); + switch (a.getKind()) { + case Int: + append(new Op2Stack(IXOR, result, a, loadNonConst(b))); + break; + case Long: + append(new Op2Stack(LXOR, result, a, loadNonConst(b))); + break; default: throw GraalInternalError.shouldNotReachHere(); } @@ -311,23 +507,35 @@ } @Override - public Variable emitOr(Value a, Value b) { - throw new InternalError("NYI"); - } - - @Override - public Variable emitXor(Value a, Value b) { - throw new InternalError("NYI"); - } - - @Override public Variable emitShl(Value a, Value b) { - throw new InternalError("NYI"); + Variable result = newVariable(a.getKind()); + switch (a.getKind()) { + case Int: + append(new Op2Stack(ISHL, result, a, loadNonConst(b))); + break; + case Long: + append(new Op1Stack(LSHL, result, loadNonConst(b))); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + return result; } @Override public Variable emitShr(Value a, Value b) { - throw new InternalError("NYI"); + Variable result = newVariable(a.getKind()); + switch (a.getKind()) { + case Int: + append(new Op2Stack(ISHR, result, a, loadNonConst(b))); + break; + case Long: + append(new Op1Stack(LSHR, result, loadNonConst(b))); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + return result; } @Override @@ -337,15 +545,87 @@ case Int: append(new ShiftOp(IUSHR, result, a, b)); break; + case Long: + append(new ShiftOp(LUSHR, result, a, b)); + break; default: - GraalInternalError.shouldNotReachHere(); + throw GraalInternalError.shouldNotReachHere(); } return result; } @Override public Variable emitConvert(ConvertNode.Op opcode, Value inputVal) { - throw new InternalError("NYI"); + Variable input = load(inputVal); + Variable result = newVariable(opcode.to); + switch (opcode) { + case I2L: + append(new Unary2Op(I2L, result, input)); + break; + case L2I: + append(new Unary1Op(L2I, result, input)); + break; + case I2B: + append(new Unary2Op(I2B, result, input)); + break; + case I2C: + append(new Unary1Op(I2C, result, input)); + break; + case I2S: + append(new Unary2Op(I2S, result, input)); + break; + case F2D: + append(new Unary2Op(F2D, result, input)); + break; + case D2F: + append(new Unary2Op(D2F, result, input)); + break; + case I2F: + append(new Unary2Op(I2F, result, input)); + break; + case I2D: + append(new Unary2Op(I2D, result, input)); + break; + case F2I: + append(new Unary2Op(F2I, result, input)); + break; + case D2I: + append(new Unary2Op(D2I, result, input)); + break; + case L2F: + append(new Unary2Op(L2F, result, input)); + break; + case L2D: + append(new Unary2Op(L2D, result, input)); + break; + case F2L: + append(new Unary2Op(F2L, result, input)); + break; + case D2L: + append(new Unary2Op(D2L, result, input)); + break; + case MOV_I2F: + append(new Unary2Op(MOV_I2F, result, input)); + break; + case MOV_L2D: + append(new Unary2Op(MOV_L2D, result, input)); + break; + case MOV_F2I: + append(new Unary2Op(MOV_F2I, result, input)); + break; + case MOV_D2L: + append(new Unary2Op(MOV_D2L, result, input)); + break; + case UNSIGNED_I2L: + // Instructions that move or generate 32-bit register values also set the upper 32 + // bits of the register to zero. + // Consequently, there is no need for a special zero-extension move. + emitMove(result, input); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + return result; } @Override @@ -434,7 +714,14 @@ @Override protected void emitSequentialSwitch(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key) { - throw new InternalError("NYI"); + // Making a copy of the switch value is necessary because jump table destroys the input + // value + if (key.getKind() == Kind.Int || key.getKind() == Kind.Long) { + append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key, Value.ILLEGAL)); + } else { + assert key.getKind() == Kind.Object : key.getKind(); + append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key, newVariable(Kind.Object))); + } } @Override @@ -444,7 +731,10 @@ @Override protected void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key) { - throw new InternalError("NYI"); + // Making a copy of the switch value is necessary because jump table destroys the input + // value + Variable tmp = emitMove(key); + append(new TableSwitchOp(lowKey, defaultTarget, targets, tmp, newVariable(target.wordKind))); } @Override @@ -459,17 +749,23 @@ @Override public void visitSafepointNode(SafepointNode i) { + // LIRFrameState info = state(); + // append(new PTXSafepointOp(info, runtime().config, this)); throw new InternalError("NYI"); } @Override public void emitUnwind(Value operand) { - // TODO Auto-generated method stub - + throw new InternalError("NYI"); } @Override public void emitNullCheck(ValueNode v, DeoptimizingNode deopting) { throw new InternalError("NYI"); } + + @Override + public void visitInfopointNode(InfopointNode i) { + throw new InternalError("NYI"); + } } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java --- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Sat Apr 13 00:33:37 2013 +0200 @@ -368,4 +368,10 @@ // SPARC: Auto-generated method stub } + + @Override + public void visitInfopointNode(InfopointNode i) { + // SPARC: Auto-generated method stub + + } } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -30,6 +30,7 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; import com.oracle.graal.virtual.nodes.*; import com.oracle.graal.virtual.phases.ea.*; @@ -307,8 +308,9 @@ graph = parse(snippet); new ComputeProbabilityPhase().apply(graph); Assumptions assumptions = new Assumptions(false); + HighTierContext context = new HighTierContext(runtime(), assumptions); new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); - new PartialEscapeAnalysisPhase(runtime(), assumptions, false, false).apply(graph); + new PartialEscapeAnalysisPhase(false, false).apply(graph, context); new CullFrameStatesPhase().apply(graph); } @@ -325,13 +327,14 @@ new ComputeProbabilityPhase().apply(graph); Assumptions assumptions = new Assumptions(false); + HighTierContext context = new HighTierContext(runtime(), assumptions); new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); if (loopPeeling) { new LoopTransformHighPhase().apply(graph); } new DeadCodeEliminationPhase().apply(graph); - new CanonicalizerPhase(runtime(), assumptions).apply(graph); - new PartialEscapeAnalysisPhase(runtime(), assumptions, false, false).apply(graph); + new CanonicalizerPhase().apply(graph, context); + new PartialEscapeAnalysisPhase(false, false).apply(graph, context); for (MaterializeObjectNode materialize : graph.getNodes(MaterializeObjectNode.class)) { materialize.getVirtualObject().materializeAt(materialize, materialize.getValues(), false, materialize.getLockCount()); @@ -339,12 +342,12 @@ new CullFrameStatesPhase().apply(graph); new DeadCodeEliminationPhase().apply(graph); - new CanonicalizerPhase(runtime(), assumptions).apply(graph); + new CanonicalizerPhase().apply(graph, context); StructuredGraph referenceGraph = parse(referenceSnippet); new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(referenceGraph); new DeadCodeEliminationPhase().apply(referenceGraph); - new CanonicalizerPhase(runtime(), assumptions).apply(referenceGraph); + new CanonicalizerPhase().apply(referenceGraph, context); assertEquals(referenceGraph, graph, excludeVirtual); } }); diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -35,7 +35,7 @@ private StructuredGraph getCanonicalizedGraph(String name) { StructuredGraph graph = parse(name); - new CanonicalizerPhase(runtime(), null).apply(graph); + new CanonicalizerPhase.Instance(runtime(), null).apply(graph); return graph; } @@ -53,7 +53,7 @@ assertEquals(referenceGraph, graph); } Assumptions assumptions = new Assumptions(false); - new CanonicalizerPhase(runtime(), assumptions).apply(referenceGraph); + new CanonicalizerPhase.Instance(runtime(), assumptions).apply(referenceGraph); for (int i = 1; i < 4; i++) { StructuredGraph graph = getCanonicalizedGraph("canonicalCompare" + i); assertEquals(referenceGraph, graph); diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -82,7 +82,7 @@ public void run() { StructuredGraph graph = parse(snippet); new InliningPhase(runtime(), null, replacements, new Assumptions(false), null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); - new CanonicalizerPhase(runtime(), new Assumptions(false)).apply(graph); + new CanonicalizerPhase.Instance(runtime(), new Assumptions(false)).apply(graph); Debug.dump(graph, "Graph"); StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET); Debug.dump(referenceGraph, "ReferenceGraph"); diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -405,6 +405,7 @@ } long start = System.currentTimeMillis(); PhasePlan phasePlan = new PhasePlan(); + StructuredGraph graphCopy = graph.copy(); GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL); phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); phasePlan.addPhase(PhasePosition.LOW_LEVEL, new WriteBarrierAdditionPhase()); @@ -414,7 +415,7 @@ if (printCompilation) { TTY.println(String.format("@%-6d Graal %-70s %-45s %-50s | %4dms %5dB", id, "", "", "", System.currentTimeMillis() - start, compResult.getTargetCodeSize())); } - return addMethod(method, compResult); + return addMethod(method, compResult, graphCopy); } }); @@ -424,12 +425,12 @@ return installedCode; } - protected InstalledCode addMethod(final ResolvedJavaMethod method, final CompilationResult compResult) { + protected InstalledCode addMethod(final ResolvedJavaMethod method, final CompilationResult compResult, final StructuredGraph graph) { return Debug.scope("CodeInstall", new Object[]{runtime, method}, new Callable() { @Override public InstalledCode call() throws Exception { - InstalledCode installedCode = runtime.addMethod(method, compResult); + InstalledCode installedCode = runtime.addMethod(method, compResult, graph); if (Debug.isDumpEnabled()) { Debug.dump(new Object[]{compResult, installedCode}, "After code installation"); } @@ -452,25 +453,41 @@ * Parses a Java method to produce a graph. */ protected StructuredGraph parse(Method m) { - ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(m); - StructuredGraph graph = new StructuredGraph(javaMethod); - new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph); - return graph; + return parse0(m, GraphBuilderConfiguration.getEagerDefault()); } /** * Parses a Java method to produce a graph. */ protected StructuredGraph parseProfiled(Method m) { + return parse0(m, GraphBuilderConfiguration.getDefault()); + } + + /** + * Parses a Java method in debug mode to produce a graph with extra infopoints. + */ + protected StructuredGraph parseDebug(Method m) { + GraphBuilderConfiguration gbConf = GraphBuilderConfiguration.getEagerDefault(); + gbConf.setEagerInfopointMode(true); + return parse0(m, gbConf); + } + + private StructuredGraph parse0(Method m, GraphBuilderConfiguration conf) { ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(m); StructuredGraph graph = new StructuredGraph(javaMethod); - new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL).apply(graph); + new GraphBuilderPhase(runtime, conf, OptimisticOptimizations.ALL).apply(graph); return graph; } protected PhasePlan getDefaultPhasePlan() { + return getDefaultPhasePlan(false); + } + + protected PhasePlan getDefaultPhasePlan(boolean eagerInfopointMode) { PhasePlan plan = new PhasePlan(); - plan.addPhase(PhasePosition.AFTER_PARSING, new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL)); + GraphBuilderConfiguration gbConf = GraphBuilderConfiguration.getEagerDefault(); + gbConf.setEagerInfopointMode(eagerInfopointMode); + plan.addPhase(PhasePosition.AFTER_PARSING, new GraphBuilderPhase(runtime, gbConf, OptimisticOptimizations.ALL)); return plan; } } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -144,7 +144,7 @@ n.replaceFirstInput(local, constant); } Debug.dump(graph, "Graph"); - new CanonicalizerPhase(runtime(), new Assumptions(false)).apply(graph); + new CanonicalizerPhase.Instance(runtime(), new Assumptions(false)).apply(graph); StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET); assertEquals(referenceGraph, graph); } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.test; + +import static org.junit.Assert.*; + +import java.lang.reflect.*; + +import org.junit.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.CompilationResult.Call; +import com.oracle.graal.api.code.CompilationResult.Infopoint; +import com.oracle.graal.compiler.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.test.*; + +/** + * Test that infopoints in {@link CompilationResult}s have correctly assigned reasons. + */ +public class InfopointReasonTest extends GraalCompilerTest { + + public static final String[] STRINGS = new String[]{"world", "everyone", "you"}; + + public String testMethod() { + StringBuilder sb = new StringBuilder("Hello "); + for (String s : STRINGS) { + sb.append(s).append(", "); + } + sb.replace(sb.length() - 2, sb.length(), "!"); + return sb.toString(); + } + + @Test + public void callInfopoints() { + final Method method = getMethod("testMethod"); + final StructuredGraph graph = parse(method); + final CompilationResult cr = GraalCompiler.compileMethod(runtime, replacements, backend, runtime.getTarget(), runtime.lookupJavaMethod(method), graph, null, getDefaultPhasePlan(), + OptimisticOptimizations.ALL, new SpeculationLog()); + for (Infopoint sp : cr.getInfopoints()) { + assertNotNull(sp.reason); + if (sp instanceof Call) { + assertEquals(InfopointReason.CALL, sp.reason); + } + } + } + + @LongTest + public void lineInfopoints() { + final Method method = getMethod("testMethod"); + final StructuredGraph graph = parseDebug(method); + int graphLineSPs = 0; + for (InfopointNode ipn : graph.getNodes(InfopointNode.class)) { + if (ipn.reason == InfopointReason.LINE_NUMBER) { + ++graphLineSPs; + } + } + assertTrue(graphLineSPs > 0); + final CompilationResult cr = GraalCompiler.compileMethod(runtime, replacements, backend, runtime.getTarget(), runtime.lookupJavaMethod(method), graph, null, getDefaultPhasePlan(true), + OptimisticOptimizations.ALL, new SpeculationLog()); + int lineSPs = 0; + for (Infopoint sp : cr.getInfopoints()) { + assertNotNull(sp.reason); + if (sp.reason == InfopointReason.LINE_NUMBER) { + ++lineSPs; + } + } + assertTrue(lineSPs > 0); + } + +} diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -66,7 +66,7 @@ } Assumptions assumptions = new Assumptions(false); new InliningPhase(runtime(), hints, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); - new CanonicalizerPhase(runtime(), assumptions).apply(graph); + new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph); new DeadCodeEliminationPhase().apply(graph); } } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -77,7 +77,7 @@ Assumptions assumptions = new Assumptions(false); new InliningPhase(runtime(), hints, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); - new CanonicalizerPhase(runtime(), assumptions).apply(graph); + new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph); new DeadCodeEliminationPhase().apply(graph); StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET); assertEquals(referenceGraph, graph); diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -133,8 +133,8 @@ } Assumptions assumptions = new Assumptions(false); - new CanonicalizerPhase(runtime(), assumptions).apply(graph); - new CanonicalizerPhase(runtime(), assumptions).apply(referenceGraph); + new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph); + new CanonicalizerPhase.Instance(runtime(), assumptions).apply(referenceGraph); Debug.scope("Test", new DebugDumpScope("Test:" + snippet), new Runnable() { @Override diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -94,7 +94,7 @@ } Assumptions assumptions = new Assumptions(false); new InliningPhase(runtime(), hints, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); - new CanonicalizerPhase(runtime(), assumptions).apply(graph); + new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph); new DeadCodeEliminationPhase().apply(graph); return graph; } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -83,9 +83,9 @@ private StructuredGraph compileTestSnippet(final String snippet) { StructuredGraph graph = parse(snippet); new LoweringPhase(null, runtime(), replacements, new Assumptions(false)).apply(graph); - new CanonicalizerPhase(runtime(), null).apply(graph); + new CanonicalizerPhase.Instance(runtime(), null).apply(graph); new PushThroughPiPhase().apply(graph); - new CanonicalizerPhase(runtime(), null).apply(graph); + new CanonicalizerPhase.Instance(runtime(), null).apply(graph); return graph; } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCast.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCast.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCast.java Sat Apr 13 00:33:37 2013 +0200 @@ -89,7 +89,7 @@ new FloatingReadPhase().apply(graph); new EliminatePartiallyRedundantGuardsPhase(true, false).apply(graph); new ReadEliminationPhase().apply(graph); - new CanonicalizerPhase(runtime(), null).apply(graph); + new CanonicalizerPhase.Instance(runtime(), null).apply(graph); Debug.dump(graph, "After lowering"); diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -244,9 +244,9 @@ private void test(String test, String ref) { StructuredGraph testGraph = parse(test); Assumptions assumptions = new Assumptions(false); - new CanonicalizerPhase(runtime(), assumptions).apply(testGraph); + new CanonicalizerPhase.Instance(runtime(), assumptions).apply(testGraph); StructuredGraph refGraph = parse(ref); - new CanonicalizerPhase(runtime(), assumptions).apply(refGraph); + new CanonicalizerPhase.Instance(runtime(), assumptions).apply(refGraph); assertEquals(testGraph, refGraph); } } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -166,9 +166,9 @@ StructuredGraph graph = parse(snippet); Debug.dump(graph, "Graph"); Assumptions assumptions = new Assumptions(false); - new CanonicalizerPhase(runtime(), assumptions).apply(graph); + new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph); new ConditionalEliminationPhase(runtime()).apply(graph); - new CanonicalizerPhase(runtime(), assumptions).apply(graph); + new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph); StructuredGraph referenceGraph = parse(referenceSnippet); assertEquals(referenceGraph, graph); } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -98,7 +98,7 @@ private void testZeroReturn(String methodName) { StructuredGraph graph = parse(methodName); - new CanonicalizerPhase(runtime(), new Assumptions(false)).apply(graph); + new CanonicalizerPhase.Instance(runtime(), new Assumptions(false)).apply(graph); new DeadCodeEliminationPhase().apply(graph); assertConstantReturn(graph, 0); } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -89,7 +89,7 @@ // No debug scope to reduce console noise for @Test(expected = ...) tests StructuredGraph graph = parse(snippet); Debug.dump(graph, "Graph"); - new CanonicalizerPhase(runtime(), new Assumptions(false)).apply(graph); + new CanonicalizerPhase.Instance(runtime(), new Assumptions(false)).apply(graph); StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET); assertEquals(referenceGraph, graph); } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -186,13 +186,13 @@ StructuredGraph graph = parse(snippet); Debug.dump(graph, "Graph"); Assumptions assumptions = new Assumptions(false); - new CanonicalizerPhase(runtime(), assumptions).apply(graph); + new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph); new ConditionalEliminationPhase(runtime()).apply(graph); - new CanonicalizerPhase(runtime(), assumptions).apply(graph); + new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph); // a second canonicalizer is needed to process nested MaterializeNodes - new CanonicalizerPhase(runtime(), assumptions).apply(graph); + new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph); StructuredGraph referenceGraph = parse(referenceSnippet); - new CanonicalizerPhase(runtime(), assumptions).apply(referenceGraph); + new CanonicalizerPhase.Instance(runtime(), assumptions).apply(referenceGraph); assertEquals(referenceGraph, graph); } @@ -244,9 +244,9 @@ StructuredGraph graph = parse(snippet); Debug.dump(graph, "Graph"); Assumptions assumptions = new Assumptions(false); - new CanonicalizerPhase(runtime(), assumptions).apply(graph); + new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph); new ConditionalEliminationPhase(runtime()).apply(graph); - new CanonicalizerPhase(runtime(), assumptions).apply(graph); + new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph); Debug.dump(graph, "Graph"); Assert.assertFalse("shouldn't have nodes of type " + clazz, graph.getNodes(clazz).iterator().hasNext()); } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -27,13 +27,10 @@ import org.junit.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.InstalledCode.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.graph.*; -import com.oracle.graal.java.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.test.*; @@ -58,7 +55,7 @@ public void test1() { Method method = getMethod("testMethod"); final StructuredGraph graph = parse(method); - new CanonicalizerPhase(runtime(), new Assumptions(false)).apply(graph); + new CanonicalizerPhase.Instance(runtime(), new Assumptions(false)).apply(graph); new DeadCodeEliminationPhase().apply(graph); for (Node node : graph.getNodes()) { @@ -75,7 +72,7 @@ try { Object result = compiledMethod.execute("1", "2", "3"); Assert.assertEquals("1-2-3", result); - } catch (MethodInvalidatedException t) { + } catch (InvalidInstalledCodeException t) { Assert.fail("method invalidated"); } } @@ -89,7 +86,7 @@ try { Object result = compiledMethod.executeVarargs("1", "2", "3"); Assert.assertEquals("1 2 3", result); - } catch (MethodInvalidatedException t) { + } catch (InvalidInstalledCodeException t) { Assert.fail("method invalidated"); } } @@ -104,98 +101,8 @@ f1 = "0"; Object result = compiledMethod.executeVarargs(this, "1", "2", "3"); Assert.assertEquals("0 1 2 3", result); - } catch (MethodInvalidatedException t) { + } catch (InvalidInstalledCodeException t) { Assert.fail("method invalidated"); } } - - @LongTest - public void test2() throws NoSuchMethodException, SecurityException { - Method method = CompilableObjectImpl.class.getDeclaredMethod("executeHelper", ObjectCompiler.class, String.class); - ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(method); - StructuredGraph graph = new StructuredGraph(javaMethod); - new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.NONE).apply(graph); - new CanonicalizerPhase(runtime, new Assumptions(false)).apply(graph); - new DeadCodeEliminationPhase().apply(graph); - - for (Node node : graph.getNodes()) { - if (node instanceof ConstantNode) { - ConstantNode constant = (ConstantNode) node; - if (constant.kind() == Kind.Object && "1 ".equals(constant.value.asObject())) { - graph.replaceFloating(constant, ConstantNode.forObject("1-", runtime, graph)); - } - } - } - - InstalledCode compiledMethod = getCode(javaMethod, graph); - final CompilableObject compilableObject = new CompilableObjectImpl(0); - - Object result; - result = compilableObject.execute(new ObjectCompilerImpl(compiledMethod), "3"); - Assert.assertEquals("1-3", result); - } - - public abstract class CompilableObject { - - private CompiledObject compiledObject; - private final int compileThreshold; - private int counter; - - public CompilableObject(int compileThreshold) { - this.compileThreshold = compileThreshold; - } - - public final Object execute(ObjectCompiler compiler, String args) { - if (counter++ < compileThreshold || compiler == null) { - return executeHelper(compiler, args); - } else { - compiledObject = compiler.compile(this); - return compiledObject.execute(compiler, args); - } - } - - protected abstract Object executeHelper(ObjectCompiler context, String args); - } - - private final class CompilableObjectImpl extends CompilableObject { - - private CompilableObjectImpl(int compileThreshold) { - super(compileThreshold); - } - - @Override - protected Object executeHelper(ObjectCompiler compiler, String args) { - return "1 " + args; - } - } - - public interface CompiledObject { - - Object execute(ObjectCompiler context, String args); - } - - public interface ObjectCompiler { - - CompiledObject compile(CompilableObject node); - } - - private final class ObjectCompilerImpl implements ObjectCompiler { - - private final InstalledCode compiledMethod; - - private ObjectCompilerImpl(InstalledCode compiledMethod) { - this.compiledMethod = compiledMethod; - } - - @Override - public CompiledObject compile(final CompilableObject node) { - return new CompiledObject() { - - @Override - public Object execute(ObjectCompiler compiler, String args) { - return compiledMethod.execute(node, compiler, args); - } - }; - } - } } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/SynchronizedMethodDeoptimizationTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/SynchronizedMethodDeoptimizationTest.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/SynchronizedMethodDeoptimizationTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -27,7 +27,6 @@ import org.junit.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.InstalledCode.MethodInvalidatedException; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.nodes.*; @@ -59,7 +58,7 @@ try { Object result = compiledMethod.executeVarargs(testString); Assert.assertEquals(testString, result); - } catch (MethodInvalidatedException t) { + } catch (InvalidInstalledCodeException t) { Assert.fail("method invalidated"); } @@ -67,7 +66,7 @@ Object result = compiledMethod.executeVarargs(new Object[]{null}); Assert.assertEquals(null, result); Assert.assertFalse(compiledMethod.isValid()); - } catch (MethodInvalidatedException t) { + } catch (InvalidInstalledCodeException t) { Assert.fail("method invalidated"); } } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -37,6 +37,7 @@ import com.oracle.graal.nodes.java.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; import com.oracle.graal.virtual.nodes.*; import com.oracle.graal.virtual.phases.ea.*; @@ -222,9 +223,10 @@ } Assumptions assumptions = new Assumptions(false); + HighTierContext context = new HighTierContext(runtime(), assumptions); new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); new DeadCodeEliminationPhase().apply(graph); - new PartialEscapeAnalysisPhase(runtime(), assumptions, iterativeEscapeAnalysis, false).apply(graph); + new PartialEscapeAnalysisPhase(iterativeEscapeAnalysis, false).apply(graph, context); Assert.assertEquals(1, graph.getNodes(ReturnNode.class).count()); ReturnNode returnNode = graph.getNodes(ReturnNode.class).first(); if (expectedConstantResult != null) { diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -34,6 +34,7 @@ import com.oracle.graal.nodes.java.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; import com.oracle.graal.virtual.phases.ea.*; public class IterativeInliningTest extends GraalCompilerTest { @@ -102,6 +103,7 @@ graph = parse(snippet); new ComputeProbabilityPhase().apply(graph); GraalOptions.OptEarlyReadElimination = true; - new IterativeInliningPhase(runtime(), replacements, new Assumptions(false), null, getDefaultPhasePlan(), OptimisticOptimizations.ALL, false).apply(graph); + HighTierContext context = new HighTierContext(runtime(), new Assumptions(false)); + new IterativeInliningPhase(replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL, false).apply(graph, context); } } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -34,6 +34,7 @@ import com.oracle.graal.nodes.java.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; import com.oracle.graal.virtual.phases.ea.*; public class PEAReadEliminationTest extends GraalCompilerTest { @@ -222,7 +223,8 @@ graph = parse(snippet); new ComputeProbabilityPhase().apply(graph); Assumptions assumptions = new Assumptions(false); + HighTierContext context = new HighTierContext(runtime(), assumptions); new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); - new PartialEscapeAnalysisPhase(runtime(), assumptions, false, true).apply(graph); + new PartialEscapeAnalysisPhase(false, true).apply(graph, context); } } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -24,7 +24,7 @@ import java.util.concurrent.*; -import junit.framework.*; +import junit.framework.Assert; import org.junit.Test; @@ -36,6 +36,7 @@ import com.oracle.graal.nodes.java.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; import com.oracle.graal.virtual.nodes.*; import com.oracle.graal.virtual.phases.ea.*; @@ -157,17 +158,18 @@ StructuredGraph graph = parse(snippet); new ComputeProbabilityPhase().apply(graph); for (Invoke n : graph.getInvokes()) { - n.node().setProbability(100000); + n.asNode().setProbability(100000); } Assumptions assumptions = new Assumptions(false); + HighTierContext context = new HighTierContext(runtime(), assumptions); new InliningPhase(runtime(), null, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); new DeadCodeEliminationPhase().apply(graph); - new CanonicalizerPhase(runtime(), assumptions).apply(graph); - new PartialEscapeAnalysisPhase(runtime(), assumptions, false, false).apply(graph); + new CanonicalizerPhase().apply(graph, context); + new PartialEscapeAnalysisPhase(false, false).apply(graph, context); new CullFrameStatesPhase().apply(graph); new DeadCodeEliminationPhase().apply(graph); - new CanonicalizerPhase(runtime(), assumptions).apply(graph); + new CanonicalizerPhase().apply(graph, context); return graph; } }); diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -24,6 +24,7 @@ import static org.junit.Assert.*; +import java.lang.reflect.*; import java.util.concurrent.*; import org.junit.*; @@ -35,14 +36,15 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.test.*; @SuppressWarnings("unused") public class InliningTest extends GraalCompilerTest { @Test public void testInvokeStaticInlining() { - assertInlined(getGraph("invokeStaticSnippet")); - assertInlined(getGraph("invokeStaticOnInstanceSnippet")); + assertInlined(getGraph("invokeStaticSnippet", false)); + assertInlined(getGraph("invokeStaticOnInstanceSnippet", false)); } @SuppressWarnings("all") @@ -57,9 +59,16 @@ @Test public void testStaticBindableInlining() { - assertInlined(getGraph("invokeConstructorSnippet")); - assertInlined(getGraph("invokeFinalMethodSnippet")); - assertInlined(getGraph("invokeMethodOnFinalClassSnippet")); + assertInlined(getGraph("invokeConstructorSnippet", false)); + assertInlined(getGraph("invokeFinalMethodSnippet", false)); + assertInlined(getGraph("invokeMethodOnFinalClassSnippet", false)); + } + + @LongTest + public void testStaticBindableInliningIP() { + assertManyMethodInfopoints(assertInlined(getGraph("invokeConstructorSnippet", true))); + assertManyMethodInfopoints(assertInlined(getGraph("invokeFinalMethodSnippet", true))); + assertManyMethodInfopoints(assertInlined(getGraph("invokeMethodOnFinalClassSnippet", true))); } @SuppressWarnings("all") @@ -81,14 +90,28 @@ @Test public void testClassHierarchyAnalysis() { - assertInlined(getGraph("invokeLeafClassMethodSnippet")); - assertInlined(getGraph("invokeConcreteMethodSnippet")); - assertInlined(getGraph("invokeSingleImplementorInterfaceSnippet")); - // assertInlined(getGraph("invokeConcreteInterfaceMethodSnippet")); + assertInlined(getGraph("invokeLeafClassMethodSnippet", false)); + assertInlined(getGraph("invokeConcreteMethodSnippet", false)); + assertInlined(getGraph("invokeSingleImplementorInterfaceSnippet", false)); + // assertInlined(getGraph("invokeConcreteInterfaceMethodSnippet", false)); + + assertNotInlined(getGraph("invokeOverriddenPublicMethodSnippet", false)); + assertNotInlined(getGraph("invokeOverriddenProtectedMethodSnippet", false)); + assertNotInlined(getGraph("invokeOverriddenInterfaceMethodSnippet", false)); + } - assertNotInlined(getGraph("invokeOverriddenPublicMethodSnippet")); - assertNotInlined(getGraph("invokeOverriddenProtectedMethodSnippet")); - assertNotInlined(getGraph("invokeOverriddenInterfaceMethodSnippet")); + @LongTest + public void testClassHierarchyAnalysisIP() { + assertManyMethodInfopoints(assertInlined(getGraph("invokeLeafClassMethodSnippet", true))); + assertManyMethodInfopoints(assertInlined(getGraph("invokeConcreteMethodSnippet", true))); + assertManyMethodInfopoints(assertInlined(getGraph("invokeSingleImplementorInterfaceSnippet", true))); + //@formatter:off + // assertInlineInfopoints(assertInlined(getGraph("invokeConcreteInterfaceMethodSnippet", true))); + //@formatter:on + + assertFewMethodInfopoints(assertNotInlined(getGraph("invokeOverriddenPublicMethodSnippet", true))); + assertFewMethodInfopoints(assertNotInlined(getGraph("invokeOverriddenProtectedMethodSnippet", true))); + assertFewMethodInfopoints(assertNotInlined(getGraph("invokeOverriddenInterfaceMethodSnippet", true))); } @SuppressWarnings("all") @@ -126,19 +149,20 @@ return superClass.protectedOverriddenMethod(); } - private StructuredGraph getGraph(final String snippet) { + private StructuredGraph getGraph(final String snippet, final boolean eagerInfopointMode) { return Debug.scope("InliningTest", new DebugDumpScope(snippet), new Callable() { @Override public StructuredGraph call() { - StructuredGraph graph = parse(snippet); - PhasePlan phasePlan = getDefaultPhasePlan(); + Method method = getMethod(snippet); + StructuredGraph graph = eagerInfopointMode ? parseDebug(method) : parse(method); + PhasePlan phasePlan = getDefaultPhasePlan(eagerInfopointMode); Assumptions assumptions = new Assumptions(true); new ComputeProbabilityPhase().apply(graph); Debug.dump(graph, "Graph"); new InliningPhase(runtime(), null, replacements, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph); Debug.dump(graph, "Graph"); - new CanonicalizerPhase(runtime(), assumptions).apply(graph); + new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph); new DeadCodeEliminationPhase().apply(graph); return graph; } @@ -172,6 +196,35 @@ return graph; } + private static int[] countMethodInfopoints(StructuredGraph graph) { + int start = 0; + int end = 0; + for (InfopointNode ipn : graph.getNodes(InfopointNode.class)) { + if (ipn.reason == InfopointReason.METHOD_START) { + ++start; + } else if (ipn.reason == InfopointReason.METHOD_END) { + ++end; + } + } + return new int[]{start, end}; + } + + private static StructuredGraph assertManyMethodInfopoints(StructuredGraph graph) { + int[] counts = countMethodInfopoints(graph); + if (counts[0] <= 1 || counts[1] <= 1) { + fail(String.format("Graph contains too few required method boundary infopoints: %d starts, %d ends.", counts[0], counts[1])); + } + return graph; + } + + private static StructuredGraph assertFewMethodInfopoints(StructuredGraph graph) { + int[] counts = countMethodInfopoints(graph); + if (counts[0] > 1 || counts[1] > 1) { + fail(String.format("Graph contains too many method boundary infopoints: %d starts, %d ends.", counts[0], counts[1])); + } + return graph; + } + // some interfaces and classes for testing private interface MultipleImplementorsInterface { diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Sat Apr 13 00:33:37 2013 +0200 @@ -31,11 +31,11 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.alloc.*; import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.phases.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.debug.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; -import com.oracle.graal.loop.phases.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.spi.*; @@ -43,6 +43,7 @@ import com.oracle.graal.phases.PhasePlan.PhasePosition; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.schedule.*; +import com.oracle.graal.phases.tiers.*; import com.oracle.graal.virtual.phases.ea.*; public class GraalCompiler { @@ -118,18 +119,20 @@ } if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(runtime, assumptions).apply(graph); + new CanonicalizerPhase.Instance(runtime, assumptions).apply(graph); } + HighTierContext highTierContext = new HighTierContext(runtime, assumptions); + if (GraalOptions.Inline && !plan.isPhaseDisabled(InliningPhase.class)) { if (GraalOptions.IterativeInlining) { - new IterativeInliningPhase(runtime, replacements, assumptions, cache, plan, optimisticOpts, GraalOptions.OptEarlyReadElimination).apply(graph); + new IterativeInliningPhase(replacements, cache, plan, optimisticOpts, GraalOptions.OptEarlyReadElimination).apply(graph, highTierContext); } else { new InliningPhase(runtime, null, replacements, assumptions, cache, plan, optimisticOpts).apply(graph); new DeadCodeEliminationPhase().apply(graph); if (GraalOptions.ConditionalElimination && GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(runtime, assumptions).apply(graph); + new CanonicalizerPhase.Instance(runtime, assumptions).apply(graph); new IterativeConditionalEliminationPhase(runtime, assumptions).apply(graph); } } @@ -137,57 +140,21 @@ plan.runPhases(PhasePosition.HIGH_LEVEL, graph); - if (GraalOptions.FullUnroll) { - new LoopFullUnrollPhase(runtime, assumptions).apply(graph); - if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(runtime, assumptions).apply(graph); - } - } - - if (GraalOptions.OptTailDuplication) { - new TailDuplicationPhase().apply(graph); - if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(runtime, assumptions).apply(graph); - } - } - - if (GraalOptions.PartialEscapeAnalysis && !plan.isPhaseDisabled(PartialEscapeAnalysisPhase.class)) { - new PartialEscapeAnalysisPhase(runtime, assumptions, true, GraalOptions.OptEarlyReadElimination).apply(graph); - } - - if (GraalOptions.OptConvertDeoptsToGuards) { - new ConvertDeoptimizeToGuardPhase().apply(graph); - } - - new LockEliminationPhase().apply(graph); - - if (GraalOptions.OptLoopTransform) { - new LoopTransformHighPhase().apply(graph); - new LoopTransformLowPhase().apply(graph); - } - new RemoveValueProxyPhase().apply(graph); - - if (GraalOptions.CullFrameStates) { - new CullFrameStatesPhase().apply(graph); - } - - if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(runtime, assumptions).apply(graph); - } + Suites.HIGH_TIER.apply(graph, highTierContext); new LoweringPhase(target, runtime, replacements, assumptions).apply(graph); if (GraalOptions.OptPushThroughPi) { new PushThroughPiPhase().apply(graph); if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(runtime, assumptions).apply(graph); + new CanonicalizerPhase.Instance(runtime, assumptions).apply(graph); } } if (GraalOptions.OptFloatingReads) { int mark = graph.getMark(); new FloatingReadPhase().apply(graph); - new CanonicalizerPhase(runtime, assumptions, mark, null).apply(graph); + new CanonicalizerPhase.Instance(runtime, assumptions, mark, null).apply(graph); if (GraalOptions.OptReadElimination) { new ReadEliminationPhase().apply(graph); } @@ -195,7 +162,7 @@ new RemoveValueProxyPhase().apply(graph); if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(runtime, assumptions).apply(graph); + new CanonicalizerPhase.Instance(runtime, assumptions).apply(graph); } if (GraalOptions.OptEliminatePartiallyRedundantGuards) { @@ -211,7 +178,7 @@ } if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(runtime, assumptions).apply(graph); + new CanonicalizerPhase.Instance(runtime, assumptions).apply(graph); } plan.runPhases(PhasePosition.MID_LEVEL, graph); diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java Sat Apr 13 00:33:37 2013 +0200 @@ -122,7 +122,7 @@ if (state.outerFrameState() != null) { caller = computeFrameForState(state.outerFrameState()); } - assert state.bci >= 0 || state.bci == FrameState.BEFORE_BCI : "bci == " + state.bci; + assert state.bci != FrameState.UNKNOWN_BCI : "bci == " + state.bci; return new BytecodeFrame(caller, state.method(), state.bci, state.rethrowException(), state.duringCall(), values, numLocals, numStack, numLocks); } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Sat Apr 13 00:33:37 2013 +0200 @@ -335,7 +335,7 @@ TTY.println("LIRGen for " + instr); } FrameState stateAfter = null; - if (instr instanceof StateSplit) { + if (instr instanceof StateSplit && !(instr instanceof InfopointNode)) { stateAfter = ((StateSplit) instr).stateAfter(); } if (instr instanceof ValueNode) { @@ -599,7 +599,7 @@ @Override public void emitInvoke(Invoke x) { AbstractCallTargetNode callTarget = (AbstractCallTargetNode) x.callTarget(); - CallingConvention cc = frameMap.registerConfig.getCallingConvention(callTarget.callType(), x.node().stamp().javaType(runtime), callTarget.signature(), target(), false); + CallingConvention cc = frameMap.registerConfig.getCallingConvention(callTarget.callType(), x.asNode().stamp().javaType(runtime), callTarget.signature(), target(), false); frameMap.callsMethod(cc); Value[] parameters = visitInvokeArguments(cc, callTarget.arguments()); @@ -620,7 +620,7 @@ } if (isLegal(result)) { - setResult(x.node(), emitMove(result)); + setResult(x.asNode(), emitMove(result)); } } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/Suites.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/Suites.java Sat Apr 13 00:33:37 2013 +0200 @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.phases; + +import java.util.*; + +import com.oracle.graal.loop.phases.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; +import com.oracle.graal.virtual.phases.ea.*; + +public class Suites { + + public static final PhaseSuite HIGH_TIER = createHighTier(); + + private static PhaseSuite createHighTier() { + ArrayList> phases = new ArrayList<>(); + + if (GraalOptions.FullUnroll) { + phases.add(new LoopFullUnrollPhase()); + if (GraalOptions.OptCanonicalizer) { + phases.add(new CanonicalizerPhase()); + } + } + + if (GraalOptions.OptTailDuplication) { + phases.add(new TailDuplicationPhase()); + if (GraalOptions.OptCanonicalizer) { + phases.add(new CanonicalizerPhase()); + } + } + + if (GraalOptions.PartialEscapeAnalysis) { + phases.add(new PartialEscapeAnalysisPhase(true, GraalOptions.OptEarlyReadElimination)); + } + + if (GraalOptions.OptConvertDeoptsToGuards) { + phases.add(new ConvertDeoptimizeToGuardPhase()); + } + + phases.add(new LockEliminationPhase()); + + if (GraalOptions.OptLoopTransform) { + phases.add(new LoopTransformHighPhase()); + phases.add(new LoopTransformLowPhase()); + } + phases.add(new RemoveValueProxyPhase()); + + if (GraalOptions.CullFrameStates) { + phases.add(new CullFrameStatesPhase()); + } + + if (GraalOptions.OptCanonicalizer) { + phases.add(new CanonicalizerPhase()); + } + + return new PhaseSuite<>("HighTier", phases); + } +} diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64SafepointOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64SafepointOp.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64SafepointOp.java Sat Apr 13 00:33:37 2013 +0200 @@ -63,11 +63,11 @@ if (config.isPollingPageFar) { asm.movq(scratch.getRegister(), config.safepointPollingAddress + offset); tasm.recordMark(Marks.MARK_POLL_FAR); - tasm.recordSafepoint(pos, state); + tasm.recordInfopoint(pos, state, InfopointReason.SAFEPOINT); asm.movq(scratch.getRegister(), new AMD64Address(scratch.getRegister())); } else { tasm.recordMark(Marks.MARK_POLL_NEAR); - tasm.recordSafepoint(pos, state); + tasm.recordInfopoint(pos, state, InfopointReason.SAFEPOINT); // The C++ code transforms the polling page offset into an RIP displacement // to the real address at that offset in the polling page. asm.movq(scratch.getRegister(), new AMD64Address(rip, offset)); diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotInstalledCodeTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotInstalledCodeTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2013, 2013, 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.test; + +import org.junit.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.nodes.*; + +public class HotSpotInstalledCodeTest extends GraalCompilerTest { + + private static final int ITERATION_COUNT = 100000; + + @Test + public void testInstallCodeInvalidation() { + final ResolvedJavaMethod testJavaMethod = runtime.lookupJavaMethod(getMethod("foo")); + final StructuredGraph graph = parse("otherFoo"); + final HotSpotInstalledCode installedCode = (HotSpotInstalledCode) getCode(testJavaMethod, graph); + Assert.assertTrue(installedCode.isValid()); + Object result; + try { + result = installedCode.execute("a", "b", "c"); + assertEquals(43, result); + } catch (InvalidInstalledCodeException e) { + Assert.fail("Code was invalidated"); + } + Assert.assertTrue(installedCode.isValid()); + installedCode.invalidate(); + Assert.assertFalse(installedCode.isValid()); + try { + result = installedCode.execute(null, null, null); + Assert.fail("Code was not invalidated"); + } catch (InvalidInstalledCodeException e) { + } + Assert.assertFalse(installedCode.isValid()); + } + + @Test + public void testInstalledCodeCalledFromCompiledCode() { + final ResolvedJavaMethod testJavaMethod = runtime.lookupJavaMethod(getMethod("foo")); + final StructuredGraph graph = parse("otherFoo"); + final HotSpotInstalledCode installedCode = (HotSpotInstalledCode) getCode(testJavaMethod, graph); + Assert.assertTrue(installedCode.isValid()); + try { + for (int i = 0; i < ITERATION_COUNT; ++i) { + installedCode.execute("a", "b", "c"); + } + } catch (InvalidInstalledCodeException e) { + Assert.fail("Code was invalidated"); + } + } + + @SuppressWarnings("unused") + public static Object foo(Object a1, Object a2, Object a3) { + return 42; + } + + @SuppressWarnings("unused") + public static Object otherFoo(Object a1, Object a2, Object a3) { + return 43; + } +} diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -22,64 +22,77 @@ */ package com.oracle.graal.hotspot.test; +import static com.oracle.graal.api.meta.MetaUtil.*; +import static java.lang.reflect.Modifier.*; + import java.lang.reflect.*; +import org.junit.*; + +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.*; public class InstalledCodeExecuteHelperTest extends GraalCompilerTest { - private static final int ITERATIONS = 100000000; + private static final int ITERATIONS = 100000; + private final MetaAccessProvider metaAccessProvider; + Object[] argsToBind; - // TODO this is not a test, move it somewhere else - // CheckStyle: stop system..print check - public void test1() throws NoSuchMethodException, SecurityException { - - final Method benchrMethod = InstalledCodeExecuteHelperTest.class.getMethod("bench", long.class, long.class); - final ResolvedJavaMethod benchJavaMethod = Graal.getRequiredCapability(GraalCodeCacheProvider.class).lookupJavaMethod(benchrMethod); - HotSpotInstalledCode benchCode = (HotSpotInstalledCode) getCode(benchJavaMethod, parse(benchrMethod)); + public InstalledCodeExecuteHelperTest() { + this.metaAccessProvider = Graal.getRequiredCapability(MetaAccessProvider.class); + } - final Method wrapperMethod = InstalledCodeExecuteHelperTest.class.getMethod("executeWrapper", long.class, long.class, Object.class, Object.class, Object.class); - final ResolvedJavaMethod wrapperJavaMethod = Graal.getRequiredCapability(GraalCodeCacheProvider.class).lookupJavaMethod(wrapperMethod); - HotSpotInstalledCode wrapperCode = (HotSpotInstalledCode) getCode(wrapperJavaMethod, parse(wrapperMethod)); + @Test + public void test1() throws NoSuchMethodException, SecurityException, InvalidInstalledCodeException { + final Method fooMethod = InstalledCodeExecuteHelperTest.class.getMethod("foo", Object.class, Object.class, Object.class); + final HotSpotResolvedJavaMethod fooJavaMethod = (HotSpotResolvedJavaMethod) metaAccessProvider.lookupJavaMethod(fooMethod); + final HotSpotInstalledCode fooCode = (HotSpotInstalledCode) getCode(fooJavaMethod, parse(fooMethod)); - final Method fooMethod = InstalledCodeExecuteHelperTest.class.getMethod("foo", Object.class, Object.class, Object.class); - final HotSpotResolvedJavaMethod fooJavaMethod = (HotSpotResolvedJavaMethod) Graal.getRequiredCapability(GraalCodeCacheProvider.class).lookupJavaMethod(fooMethod); - HotSpotInstalledCode fooCode = (HotSpotInstalledCode) getCode(fooJavaMethod, parse(fooMethod)); + argsToBind = new Object[]{fooCode}; - System.out.println(wrapperCode.executeVarargs(fooCode.getnmethod(), fooJavaMethod.getMetaspaceMethod(), null, null, null)); + final Method benchmarkMethod = InstalledCodeExecuteHelperTest.class.getMethod("benchmark", HotSpotInstalledCode.class); + final ResolvedJavaMethod benchmarkJavaMethod = metaAccessProvider.lookupJavaMethod(benchmarkMethod); + final HotSpotInstalledCode installedBenchmarkCode = (HotSpotInstalledCode) getCode(benchmarkJavaMethod, parse(benchmarkMethod)); - long nmethod = fooCode.getnmethod(); - long metaspacemethod = fooJavaMethod.getMetaspaceMethod(); + Assert.assertEquals(Integer.valueOf(42), benchmark(fooCode)); - System.out.println("Without replaced InstalledCode.execute:" + bench(nmethod, metaspacemethod)); - - System.out.println("WITH replaced InstalledCode.execute:" + benchCode.executeVarargs(nmethod, metaspacemethod)); + Assert.assertEquals(Integer.valueOf(42), installedBenchmarkCode.executeVarargs(argsToBind[0])); } - // CheckStyle: resume system..print check - - public static Long bench(long nmethod, long metaspacemethod) { - long start = System.currentTimeMillis(); - - for (int i = 0; i < ITERATIONS; i++) { - HotSpotInstalledCode.executeHelper(nmethod, metaspacemethod, null, null, null); + public static Integer benchmark(HotSpotInstalledCode code) throws InvalidInstalledCodeException { + int val = 0; + for (int j = 0; j < 100; j++) { + for (int i = 0; i < ITERATIONS; i++) { + val = (Integer) code.execute(null, null, null); + } } - - long end = System.currentTimeMillis(); - return (end - start); + return val; } - public static Object foo(@SuppressWarnings("unused") Object a1, @SuppressWarnings("unused") Object a2, @SuppressWarnings("unused") Object a3) { + public static Integer foo(@SuppressWarnings("unused") Object a1, @SuppressWarnings("unused") Object a2, @SuppressWarnings("unused") Object a3) { return 42; } - public static Object executeWrapper(long nmethod, long metaspaceMethod, Object arg1, Object arg2, Object arg3) { - return HotSpotInstalledCode.executeHelper(nmethod, metaspaceMethod, arg1, arg2, arg3); + @Override + protected StructuredGraph parse(Method m) { + StructuredGraph graph = super.parse(m); + if (argsToBind != null) { + Object receiver = isStatic(m.getModifiers()) ? null : this; + Object[] args = argsWithReceiver(receiver, argsToBind); + JavaType[] parameterTypes = signatureToTypes(runtime.lookupJavaMethod(m)); + assert parameterTypes.length == args.length; + for (int i = 0; i < argsToBind.length; i++) { + LocalNode local = graph.getLocal(i); + Constant c = Constant.forBoxed(parameterTypes[i].getKind(), argsToBind[i]); + ConstantNode replacement = ConstantNode.forConstant(c, runtime, graph); + local.replaceAtUsages(replacement); + } + } + return graph; } - } diff -r 2cae919cd3af -r 0c8ec85fa013 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 Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Sat Apr 13 00:33:37 2013 +0200 @@ -25,6 +25,7 @@ import static com.oracle.graal.nodes.StructuredGraph.*; import static com.oracle.graal.phases.common.InliningUtil.*; +import java.lang.reflect.Modifier; import java.util.concurrent.*; import com.oracle.graal.api.code.*; @@ -32,6 +33,7 @@ import com.oracle.graal.compiler.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.internal.*; +import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -133,6 +135,9 @@ TTY.println(String.format("%-6d Graal %-70s %-45s %-50s %s...", id, method.getDeclaringClass().getName(), method.getName(), method.getSignature(), entryBCI == StructuredGraph.INVOCATION_ENTRY_BCI ? "" : "(OSR@" + entryBCI + ") ")); } + if (GraalOptions.HotSpotPrintCompilation) { + printCompilation(); + } CompilationResult result = null; TTY.Filter filter = new TTY.Filter(GraalOptions.PrintFilter, method); @@ -163,7 +168,7 @@ } } - installMethod(result); + installMethod(result, null); } catch (BailoutException bailout) { Debug.metric("Bailouts").increment(); if (GraalOptions.ExitVMOnBailout) { @@ -183,12 +188,22 @@ stats.finish(method); } - private void installMethod(final CompilationResult compResult) { + /** + * Print a HotSpot-style compilation message to the console. + */ + private void printCompilation() { + final boolean isOSR = entryBCI != StructuredGraph.INVOCATION_ENTRY_BCI; + final int mod = method.getModifiers(); + TTY.println(String.format("%7d %4d %c%c%c%c%c %s %s(%d bytes)", 0, id, isOSR ? '%' : ' ', Modifier.isSynchronized(mod) ? 's' : ' ', ' ', ' ', Modifier.isNative(mod) ? 'n' : ' ', + MetaUtil.format("%H::%n(%p)", method), isOSR ? "@ " + entryBCI + " " : "", method.getCodeSize())); + } + + private void installMethod(final CompilationResult compResult, final Graph graph) { Debug.scope("CodeInstall", new Object[]{new DebugDumpScope(String.valueOf(id), true), graalRuntime.getRuntime(), method}, new Runnable() { @Override public void run() { - HotSpotInstalledCode installedCode = graalRuntime.getRuntime().installMethod(method, entryBCI, compResult); + HotSpotInstalledCode installedCode = graalRuntime.getRuntime().installMethod(method, graph, entryBCI, compResult); if (Debug.isDumpEnabled()) { Debug.dump(new Object[]{compResult, installedCode}, "After code installation"); } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompilationResult.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompilationResult.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompilationResult.java Sat Apr 13 00:33:37 2013 +0200 @@ -67,7 +67,7 @@ } private static Site[] getSortedSites(CompilationResult target) { - List[] lists = new List[]{target.getSafepoints(), target.getDataReferences(), target.getMarks()}; + List[] lists = new List[]{target.getInfopoints(), target.getDataReferences(), target.getMarks()}; int count = 0; for (List list : lists) { count += list.size(); diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Sat Apr 13 00:33:37 2013 +0200 @@ -139,6 +139,10 @@ compilerToVm.initializeConfiguration(config); config.check(); + // Set some global options: + GraalOptions.HotSpotPrintCompilation = config.printCompilation; + GraalOptions.HotSpotPrintInlining = config.printInlining; + if (Boolean.valueOf(System.getProperty("graal.printconfig"))) { printConfig(config); } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java Sat Apr 13 00:33:37 2013 +0200 @@ -28,6 +28,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.replacements.*; +import com.oracle.graal.nodes.*; import com.oracle.graal.replacements.*; /** @@ -62,4 +63,24 @@ } return super.registerMethodSubstitution(originalMethod, substituteMethod); } + + @Override + public Class getMacroSubstitution(ResolvedJavaMethod method) { + HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) method; + int intrinsicId = hsMethod.intrinsicId(); + if (intrinsicId != 0) { + if (intrinsicId == config.vmIntrinsicInvokeBasic) { + return MethodHandleInvokeBasicNode.class; + } else if (intrinsicId == config.vmIntrinsicLinkToInterface) { + return MethodHandleLinkToInterfaceNode.class; + } else if (intrinsicId == config.vmIntrinsicLinkToSpecial) { + return MethodHandleLinkToSpecialNode.class; + } else if (intrinsicId == config.vmIntrinsicLinkToStatic) { + return MethodHandleLinkToStaticNode.class; + } else if (intrinsicId == config.vmIntrinsicLinkToVirtual) { + return MethodHandleLinkToVirtualNode.class; + } + } + return super.getMacroSubstitution(method); + } } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Sat Apr 13 00:33:37 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, 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 @@ -37,6 +37,8 @@ public int codeEntryAlignment; public boolean verifyOops; public boolean ciTime; + public boolean printCompilation; + public boolean printInlining; public boolean useFastLocking; public boolean useTLAB; public boolean useBiasedLocking; @@ -185,6 +187,11 @@ public int methodAccessFlagsOffset; /** + * Offset of _intrinsic_id in a metaspace Method object. + */ + public int methodIntrinsicIdOffset; + + /** * Offset of _max_locals in a metaspace Method object. */ public int methodMaxLocalsOffset; @@ -376,6 +383,12 @@ public int deoptActionMakeNotEntrant; public int deoptActionMakeNotCompilable; + public int vmIntrinsicInvokeBasic; + public int vmIntrinsicLinkToVirtual; + public int vmIntrinsicLinkToStatic; + public int vmIntrinsicLinkToSpecial; + public int vmIntrinsicLinkToInterface; + public void check() { assert codeEntryAlignment > 0; assert stackShadowPages > 0; diff -r 2cae919cd3af -r 0c8ec85fa013 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 Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Sat Apr 13 00:33:37 2013 +0200 @@ -138,6 +138,8 @@ void lookupReferencedTypeInPool(HotSpotResolvedObjectType pool, int cpi, byte opcode); + Object lookupAppendixInPool(HotSpotResolvedObjectType pool, int cpi, byte opcode); + // Must be kept in sync with enum in graalEnv.hpp public enum CodeInstallResult { OK, DEPENDENCIES_FAILED, CACHE_FULL @@ -199,9 +201,9 @@ StackTraceElement getStackTraceElement(long metaspaceMethod, int bci); - Object executeCompiledMethod(long metaspaceMethod, long nmethod, Object arg1, Object arg2, Object arg3); + Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, long nativeMethod) throws InvalidInstalledCodeException; - Object executeCompiledMethodVarargs(long metaspaceMethod, long nmethod, Object... args); + Object executeCompiledMethodVarargs(Object[] args, long nativeMethod) throws InvalidInstalledCodeException; int getVtableEntryOffset(long metaspaceMethod); @@ -222,5 +224,7 @@ */ void reprofile(long metaspaceMethod); - Object lookupAppendixInPool(HotSpotResolvedObjectType pool, int cpi); + void invalidateInstalledCode(long nativeMethod); + + boolean isInstalledCodeValid(long nativeMethod); } diff -r 2cae919cd3af -r 0c8ec85fa013 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 Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Sat Apr 13 00:33:37 2013 +0200 @@ -133,10 +133,7 @@ public native StackTraceElement getStackTraceElement(long metaspaceMethod, int bci); @Override - public native Object executeCompiledMethod(long metaspaceMethod, long nmethod, Object arg1, Object arg2, Object arg3); - - @Override - public native Object executeCompiledMethodVarargs(long metaspaceMethod, long nmethod, Object... args); + public native Object executeCompiledMethodVarargs(Object[] args, long nativeMethod); @Override public native int getVtableEntryOffset(long metaspaceMethod); @@ -160,5 +157,25 @@ public native void reprofile(long metaspaceMethod); @Override - public native Object lookupAppendixInPool(HotSpotResolvedObjectType pool, int cpi); + public native Object lookupAppendixInPool(HotSpotResolvedObjectType pool, int cpi, byte opcode); + + @Override + public native void invalidateInstalledCode(long nativeMethod); + + @Override + public native boolean isInstalledCodeValid(long nativeMethod); + + @Override + public Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, long nativeMethod) throws InvalidInstalledCodeException { + return executeCompiledMethodIntrinsic(arg1, arg2, arg3, nativeMethod); + } + + /** + * Direct call to the given nativeMethod with three object arguments and an object return value. + * This method does not have an implementation on the C++ side, but its entry points (from + * interpreter and from compiled code) are directly pointing to a manually generated assembly + * stub that does the necessary argument shuffling and a tail call via an indirect jump to the + * verified entry point of the given native method. + */ + private static native Object executeCompiledMethodIntrinsic(Object arg1, Object arg2, Object arg3, long nativeMethod); } diff -r 2cae919cd3af -r 0c8ec85fa013 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 Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Sat Apr 13 00:33:37 2013 +0200 @@ -37,6 +37,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.internal.*; +import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.debug.*; import com.oracle.graal.hotspot.meta.*; @@ -152,7 +153,8 @@ @Override public void run() { - for (ReplacementsProvider provider : ServiceLoader.loadInstalled(ReplacementsProvider.class)) { + ServiceLoader serviceLoader = ServiceLoader.loadInstalled(ReplacementsProvider.class); + for (ReplacementsProvider provider : serviceLoader) { provider.registerReplacements(replacements); } runtime.registerReplacements(replacements); @@ -204,9 +206,22 @@ t.start(); } - if (GraalOptions.BenchmarkDynamicCounters) { - System.setErr(new PrintStream(new BenchmarkCountersOutputStream(System.err, " starting =====", " PASSED in ", "\n"))); - System.setOut(new PrintStream(new BenchmarkCountersOutputStream(System.out, "Iteration ~ (~s) begins: ", "Iteration ~ (~s) ends: ", "\n"))); + if (GraalOptions.BenchmarkDynamicCounters != null) { + String[] arguments = GraalOptions.BenchmarkDynamicCounters.split(","); + if (arguments.length == 0 || (arguments.length % 3) != 0) { + throw new GraalInternalError("invalid arguments to BenchmarkDynamicCounters: (err|out),start,end,(err|out),start,end,... (~ matches multiple digits)"); + } + for (int i = 0; i < arguments.length; i += 3) { + if (arguments[i].equals("err")) { + System.setErr(new PrintStream(new BenchmarkCountersOutputStream(System.err, arguments[i + 1], arguments[i + 2]))); + } else if (arguments[i].equals("out")) { + System.setOut(new PrintStream(new BenchmarkCountersOutputStream(System.out, arguments[i + 1], arguments[i + 2]))); + } else { + throw new GraalInternalError("invalid arguments to BenchmarkDynamicCounters: err|out"); + } + // dacapo: "err, starting =====, PASSED in " + // specjvm2008: "out,Iteration ~ (~s) begins: ,Iteration ~ (~s) ends: " + } DynamicCounterNode.excludedClassPrefix = "Lcom/oracle/graal/"; DynamicCounterNode.enabled = true; } @@ -221,8 +236,8 @@ private long startTime; private boolean waitingForEnd; - private BenchmarkCountersOutputStream(PrintStream delegate, String... patterns) { - super(delegate, patterns); + private BenchmarkCountersOutputStream(PrintStream delegate, String start, String end) { + super(delegate, new String[]{start, end, "\n"}); } @Override diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java Sat Apr 13 00:33:37 2013 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.hotspot.meta; import com.oracle.graal.api.meta.*; +import com.oracle.graal.bytecode.*; import com.oracle.graal.hotspot.*; /** @@ -51,10 +52,9 @@ } @Override - public Object lookupAppendix(int cpi) { - assert cpi != 0; - Object constant = HotSpotGraalRuntime.getInstance().getCompilerToVM().lookupAppendixInPool(type, cpi); - return constant; + public Object lookupAppendix(int cpi, int opcode) { + assert Bytecodes.isInvoke(opcode); + return HotSpotGraalRuntime.getInstance().getCompilerToVM().lookupAppendixInPool(type, cpi, (byte) opcode); } @Override diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java Sat Apr 13 00:33:37 2013 +0200 @@ -26,6 +26,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; /** @@ -39,11 +40,13 @@ private final HotSpotResolvedJavaMethod method; private final boolean isDefault; + private final Graph graph; long nmethod; long start; - public HotSpotInstalledCode(HotSpotResolvedJavaMethod method, boolean isDefault) { + public HotSpotInstalledCode(HotSpotResolvedJavaMethod method, Graph graph, boolean isDefault) { this.method = method; + this.graph = graph; this.isDefault = isDefault; } @@ -51,10 +54,14 @@ return isDefault; } - public long getnmethod() { + public long getMethodAddress() { return nmethod; } + public Graph getGraph() { + return graph; + } + @Override public ResolvedJavaMethod getMethod() { return method; @@ -62,7 +69,12 @@ @Override public boolean isValid() { - return nmethod != 0; + return HotSpotGraalRuntime.getInstance().getCompilerToVM().isInstalledCodeValid(nmethod); + } + + @Override + public void invalidate() { + HotSpotGraalRuntime.getInstance().getCompilerToVM().invalidateInstalledCode(nmethod); } @Override @@ -71,12 +83,12 @@ } @Override - public Object execute(Object arg1, Object arg2, Object arg3) { + public Object execute(Object arg1, Object arg2, Object arg3) throws InvalidInstalledCodeException { assert method.getSignature().getParameterCount(!Modifier.isStatic(method.getModifiers())) == 3; assert method.getSignature().getParameterKind(0) == Kind.Object; assert method.getSignature().getParameterKind(1) == Kind.Object; assert !Modifier.isStatic(method.getModifiers()) || method.getSignature().getParameterKind(2) == Kind.Object; - return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethod(method.metaspaceMethod, nmethod, arg1, arg2, arg3); + return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethod(arg1, arg2, arg3, nmethod); } private boolean checkArgs(Object... args) { @@ -94,9 +106,9 @@ } @Override - public Object executeVarargs(Object... args) { + public Object executeVarargs(Object... args) throws InvalidInstalledCodeException { assert checkArgs(args); - return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethodVarargs(method.metaspaceMethod, nmethod, args); + return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethodVarargs(args, nmethod); } @Override @@ -108,8 +120,4 @@ public byte[] getCode() { return HotSpotGraalRuntime.getInstance().getCompilerToVM().getCode(nmethod); } - - public static Object executeHelper(long nmethod, long metaspaceMethod, Object arg1, Object arg2, Object arg3) { - return HotSpotGraalRuntime.getInstance().getCompilerToVM().executeCompiledMethod(metaspaceMethod, nmethod, arg1, arg2, arg3); - } } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Sat Apr 13 00:33:37 2013 +0200 @@ -362,4 +362,9 @@ } return speculationLog; } + + public int intrinsicId() { + HotSpotVMConfig config = HotSpotGraalRuntime.getInstance().getConfig(); + return unsafe.getByte(metaspaceMethod + config.methodIntrinsicIdOffset) & 0xff; + } } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Sat Apr 13 00:33:37 2013 +0200 @@ -48,7 +48,7 @@ import com.oracle.graal.api.code.CompilationResult.Call; import com.oracle.graal.api.code.CompilationResult.DataPatch; import com.oracle.graal.api.code.CompilationResult.Mark; -import com.oracle.graal.api.code.CompilationResult.Safepoint; +import com.oracle.graal.api.code.CompilationResult.Infopoint; import com.oracle.graal.api.code.Register.RegisterFlag; import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.api.meta.*; @@ -328,17 +328,6 @@ replacements.registerSubstitutions(AESCryptSubstitutions.class); replacements.registerSubstitutions(CipherBlockChainingSubstitutions.class); } - if (GraalOptions.IntrinsifyArrayCopy) { - replacements.registerSnippets(ArrayCopySnippets.class); - } - if (GraalOptions.IntrinsifyObjectClone) { - replacements.registerSnippets(ObjectCloneSnippets.class); - } - - replacements.registerSnippets(BoxingSnippets.class); - for (Class clazz : BoxingSubstitutions.getClasses()) { - replacements.registerSubstitutions(clazz); - } checkcastSnippets = new CheckCastSnippets.Templates(this, replacements, graalRuntime.getTarget()); instanceofSnippets = new InstanceOfSnippets.Templates(this, replacements, graalRuntime.getTarget()); @@ -382,18 +371,18 @@ addExceptionHandlersComment(compResult, hcf); Register fp = regConfig.getFrameRegister(); RefMapFormatter slotFormatter = new RefMapFormatter(target.arch, target.wordSize, fp, 0); - for (Safepoint safepoint : compResult.getSafepoints()) { - if (safepoint instanceof Call) { - Call call = (Call) safepoint; + for (Infopoint infopoint : compResult.getInfopoints()) { + if (infopoint instanceof Call) { + Call call = (Call) infopoint; 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()); + if (infopoint.debugInfo != null) { + hcf.addComment(infopoint.pcOffset, CodeUtil.append(new StringBuilder(100), infopoint.debugInfo, slotFormatter).toString()); } - addOperandComment(hcf, safepoint.pcOffset, "{safepoint}"); + addOperandComment(hcf, infopoint.pcOffset, "{infopoint: " + infopoint.reason + "}"); } } for (DataPatch site : compResult.getDataReferences()) { @@ -517,7 +506,7 @@ NodeInputList parameters = callTarget.arguments(); ValueNode receiver = parameters.size() <= 0 ? null : parameters.get(0); if (!callTarget.isStatic() && receiver.kind() == Kind.Object && !receiver.objectStamp().nonNull()) { - invoke.node().dependencies().add(tool.createNullCheckGuard(receiver)); + invoke.asNode().dependencies().add(tool.createNullCheckGuard(receiver)); } JavaType[] signature = MetaUtil.signatureToTypes(callTarget.targetMethod().getSignature(), callTarget.isStatic() ? null : callTarget.targetMethod().getDeclaringClass()); @@ -537,10 +526,10 @@ ReadNode compiledEntry = graph.add(new ReadNode(metaspaceMethod, LocationNode.create(LocationNode.ANY_LOCATION, wordKind, config.methodCompiledEntryOffset, graph), StampFactory.forKind(wordKind()))); - loweredCallTarget = graph.add(new HotSpotIndirectCallTargetNode(metaspaceMethod, compiledEntry, parameters, invoke.node().stamp(), signature, callTarget.targetMethod(), + loweredCallTarget = graph.add(new HotSpotIndirectCallTargetNode(metaspaceMethod, compiledEntry, parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(), CallingConvention.Type.JavaCall)); - graph.addBeforeFixed(invoke.node(), hub); + graph.addBeforeFixed(invoke.asNode(), hub); graph.addAfterFixed(hub, metaspaceMethod); graph.addAfterFixed(metaspaceMethod, compiledEntry); } @@ -548,7 +537,7 @@ } if (loweredCallTarget == null) { - loweredCallTarget = graph.add(new HotSpotDirectCallTargetNode(parameters, invoke.node().stamp(), signature, callTarget.targetMethod(), CallingConvention.Type.JavaCall, + loweredCallTarget = graph.add(new HotSpotDirectCallTargetNode(parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(), CallingConvention.Type.JavaCall, callTarget.invokeKind())); } callTarget.replaceAndDelete(loweredCallTarget); @@ -698,7 +687,7 @@ } else if (n instanceof IntegerDivNode || n instanceof IntegerRemNode || n instanceof UnsignedDivNode || n instanceof UnsignedRemNode) { // Nothing to do for division nodes. The HotSpot signal handler catches divisions by // zero and the MIN_VALUE / -1 cases. - } else if (n instanceof UnwindNode) { + } else if (n instanceof UnwindNode || n instanceof DeoptimizeNode) { // Nothing to do, using direct LIR lowering for these nodes. } else if (n instanceof BoxNode) { boxingSnippets.lower((BoxNode) n); @@ -807,16 +796,21 @@ return graalRuntime.getCompilerToVM().getJavaField(reflectionField); } - public HotSpotInstalledCode installMethod(HotSpotResolvedJavaMethod method, int entryBCI, CompilationResult compResult) { - HotSpotInstalledCode installedCode = new HotSpotInstalledCode(method, true); + public HotSpotInstalledCode installMethod(HotSpotResolvedJavaMethod method, Graph graph, int entryBCI, CompilationResult compResult) { + HotSpotInstalledCode installedCode = new HotSpotInstalledCode(method, graph, true); graalRuntime.getCompilerToVM().installCode(new HotSpotCompilationResult(method, entryBCI, compResult), installedCode, method.getSpeculationLog()); return installedCode; } @Override public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult) { + return addMethod(method, compResult, null); + } + + @Override + public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, Graph graph) { HotSpotResolvedJavaMethod hotspotMethod = (HotSpotResolvedJavaMethod) method; - HotSpotInstalledCode code = new HotSpotInstalledCode(hotspotMethod, false); + HotSpotInstalledCode code = new HotSpotInstalledCode(hotspotMethod, graph, false); CodeInstallResult result = graalRuntime.getCompilerToVM().installCode(new HotSpotCompilationResult(hotspotMethod, -1, compResult), code, null); if (result != CodeInstallResult.OK) { return null; @@ -935,7 +929,7 @@ public String disassemble(InstalledCode code) { if (code.isValid()) { - long nmethod = ((HotSpotInstalledCode) code).nmethod; + long nmethod = ((HotSpotInstalledCode) code).getMethodAddress(); return graalRuntime.getCompilerToVM().disassembleNMethod(nmethod); } return null; diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotInstalledCodeExecuteNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotInstalledCodeExecuteNode.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotInstalledCodeExecuteNode.java Sat Apr 13 00:33:37 2013 +0200 @@ -24,22 +24,24 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.word.*; +import com.oracle.graal.phases.common.*; public class HotSpotInstalledCodeExecuteNode extends AbstractCallNode implements Lowerable { - @Input private final ValueNode targetAddress; - @Input private final ValueNode metaspaceObject; + @Input private final ValueNode code; private final Class[] signature; - public HotSpotInstalledCodeExecuteNode(Kind kind, ValueNode targetAddress, ValueNode metaspaceObject, Class[] signature, ValueNode arg1, ValueNode arg2, ValueNode arg3) { + public HotSpotInstalledCodeExecuteNode(Kind kind, Class[] signature, ValueNode code, ValueNode arg1, ValueNode arg2, ValueNode arg3) { super(StampFactory.forKind(kind), new ValueNode[]{arg1, arg2, arg3}); - this.targetAddress = targetAddress; - this.metaspaceObject = metaspaceObject; + this.code = code; this.signature = signature; } @@ -50,30 +52,57 @@ @Override public void lower(LoweringTool tool) { - replaceWithInvoke(tool); + if (code.isConstant() && code.asConstant().asObject() instanceof HotSpotInstalledCode) { + HotSpotInstalledCode hsCode = (HotSpotInstalledCode) code.asConstant().asObject(); + InvokeNode invoke = replaceWithInvoke(tool.getRuntime()); + StructuredGraph graph = (StructuredGraph) hsCode.getGraph(); + if (graph != null) { + InliningUtil.inline(invoke, (StructuredGraph) hsCode.getGraph(), false); + } + } else { + replaceWithInvoke(tool.getRuntime()); + } } - private InvokeNode replaceWithInvoke(LoweringTool tool) { - InvokeNode invoke = createInvoke(tool); - ((StructuredGraph) graph()).replaceFixedWithFixed(this, invoke); - return invoke; - } - - protected InvokeNode createInvoke(LoweringTool tool) { + protected InvokeNode replaceWithInvoke(MetaAccessProvider tool) { ResolvedJavaMethod method = null; + ResolvedJavaField methodField = null; + ResolvedJavaField metaspaceMethodField = null; + ResolvedJavaField nmethodField = null; try { - method = tool.getRuntime().lookupJavaMethod(HotSpotInstalledCodeExecuteNode.class.getMethod("placeholder", Object.class, Object.class, Object.class)); - } catch (NoSuchMethodException | SecurityException e) { - throw new IllegalStateException(); + method = tool.lookupJavaMethod(HotSpotInstalledCodeExecuteNode.class.getMethod("placeholder", Object.class, Object.class, Object.class)); + methodField = tool.lookupJavaField(HotSpotInstalledCode.class.getDeclaredField("method")); + nmethodField = tool.lookupJavaField(HotSpotInstalledCode.class.getDeclaredField("nmethod")); + metaspaceMethodField = tool.lookupJavaField(HotSpotResolvedJavaMethod.class.getDeclaredField("metaspaceMethod")); + } catch (NoSuchMethodException | SecurityException | NoSuchFieldException e) { + throw new IllegalStateException(e); } ResolvedJavaType[] signatureTypes = new ResolvedJavaType[signature.length]; for (int i = 0; i < signature.length; i++) { - signatureTypes[i] = tool.getRuntime().lookupJavaType(signature[i]); + signatureTypes[i] = tool.lookupJavaType(signature[i]); } - HotSpotIndirectCallTargetNode callTarget = graph().add( - new HotSpotIndirectCallTargetNode(metaspaceObject, targetAddress, arguments, stamp(), signatureTypes, method, CallingConvention.Type.JavaCall)); - InvokeNode invoke = graph().add(new InvokeNode(callTarget, 0)); + final int verifiedEntryPointOffset = HotSpotSnippetUtils.verifiedEntryPointOffset(); + + StructuredGraph g = (StructuredGraph) graph(); + + LoadFieldNode loadnmethod = g.add(new LoadFieldNode(code, nmethodField)); + UnsafeLoadNode load = g.add(new UnsafeLoadNode(loadnmethod, verifiedEntryPointOffset, ConstantNode.forLong(0, graph()), HotSpotGraalRuntime.getInstance().getTarget().wordKind)); + + LoadFieldNode loadMethod = g.add(new LoadFieldNode(code, methodField)); + LoadFieldNode loadmetaspaceMethod = g.add(new LoadFieldNode(loadMethod, metaspaceMethodField)); + + HotSpotIndirectCallTargetNode callTarget = g.add(new HotSpotIndirectCallTargetNode(loadmetaspaceMethod, load, arguments, stamp(), signatureTypes, method, CallingConvention.Type.JavaCall)); + + InvokeNode invoke = g.add(new InvokeNode(callTarget, 0)); + invoke.setStateAfter(stateAfter()); + g.replaceFixedWithFixed(this, invoke); + + g.addBeforeFixed(invoke, loadmetaspaceMethod); + g.addBeforeFixed(loadmetaspaceMethod, loadMethod); + g.addBeforeFixed(invoke, load); + g.addBeforeFixed(load, loadnmethod); + return invoke; } @@ -82,6 +111,6 @@ } @NodeIntrinsic - public static native T call(@ConstantNodeParameter Kind kind, Word targetAddress, long metaspaceObject, @ConstantNodeParameter Class[] signature, Object arg1, Object arg2, Object arg3); + public static native T call(@ConstantNodeParameter Kind kind, @ConstantNodeParameter Class[] signature, Object code, Object arg1, Object arg2, Object arg3); } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java Sat Apr 13 00:33:37 2013 +0200 @@ -31,6 +31,7 @@ import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; import com.oracle.graal.replacements.nodes.*; public class ArrayCopyNode extends MacroNode implements Virtualizable, IterableNodeType, Lowerable { @@ -81,9 +82,10 @@ } // the canonicalization before loop unrolling is needed to propagate the length into // additions, etc. - new CanonicalizerPhase(tool.getRuntime(), tool.assumptions()).apply(snippetGraph); - new LoopFullUnrollPhase(tool.getRuntime(), tool.assumptions()).apply(snippetGraph); - new CanonicalizerPhase(tool.getRuntime(), tool.assumptions()).apply(snippetGraph); + HighTierContext context = new HighTierContext(tool.getRuntime(), tool.assumptions()); + new CanonicalizerPhase().apply(snippetGraph, context); + new LoopFullUnrollPhase().apply(snippetGraph, context); + new CanonicalizerPhase().apply(snippetGraph, context); } @Override diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java Sat Apr 13 00:33:37 2013 +0200 @@ -37,7 +37,6 @@ import com.oracle.graal.nodes.java.*; import com.oracle.graal.phases.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.Snippet.*; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*; @@ -75,7 +74,7 @@ private static final Kind VECTOR_KIND = Kind.Long; private static final long VECTOR_SIZE = arrayIndexScale(Kind.Long); - public static void vectorizedCopy(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter("baseKind") Kind baseKind) { + private static void vectorizedCopy(Object src, int srcPos, Object dest, int destPos, int length, Kind baseKind) { checkNonNull(src); checkNonNull(dest); checkLimits(src, srcPos, dest, destPos, length); diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/BoxingSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/BoxingSnippets.java Fri Apr 12 23:29:45 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,252 +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.replacements; - -import static com.oracle.graal.replacements.SnippetTemplate.*; - -import java.lang.reflect.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.graph.Node.NodeIntrinsic; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; -import com.oracle.graal.phases.*; -import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.Snippet.Fold; -import com.oracle.graal.replacements.Snippet.Parameter; -import com.oracle.graal.replacements.Snippet.SnippetInliningPolicy; -import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; -import com.oracle.graal.replacements.SnippetTemplate.Arguments; -import com.oracle.graal.replacements.SnippetTemplate.Key; -import com.oracle.graal.word.*; - -public class BoxingSnippets implements Snippets { - - /** - * This snippet inlining policy differs from the default one in that it does normal inlining of - * boxing methods like {@link Integer#valueOf(int)} (as opposed to method substitution). - */ - public static class BoxingSnippetInliningPolicy implements SnippetInliningPolicy { - - @Override - public boolean shouldInline(ResolvedJavaMethod method, ResolvedJavaMethod caller) { - if (Modifier.isNative(method.getModifiers())) { - return false; - } - if (method.getAnnotation(Fold.class) != null) { - return false; - } - if (method.getAnnotation(NodeIntrinsic.class) != null) { - return false; - } - if (method.getAnnotation(Word.Operation.class) != null) { - return false; - } - return true; - } - - @Override - public boolean shouldUseReplacement(ResolvedJavaMethod callee, ResolvedJavaMethod methodToParse) { - return false; - } - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static Boolean valueOf(@Parameter("value") boolean value) { - valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Boolean.valueOf(value), StampFactory.forNodeIntrinsic()); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static Byte valueOf(@Parameter("value") byte value) { - valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Byte.valueOf(value), StampFactory.forNodeIntrinsic()); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static Character valueOf(@Parameter("value") char value) { - valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Character.valueOf(value), StampFactory.forNodeIntrinsic()); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static Double valueOf(@Parameter("value") double value) { - valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Double.valueOf(value), StampFactory.forNodeIntrinsic()); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static Float valueOf(@Parameter("value") float value) { - valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Float.valueOf(value), StampFactory.forNodeIntrinsic()); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static Integer valueOf(@Parameter("value") int value) { - valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Integer.valueOf(value), StampFactory.forNodeIntrinsic()); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static Long valueOf(@Parameter("value") long value) { - valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Long.valueOf(value), StampFactory.forNodeIntrinsic()); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static Short valueOf(@Parameter("value") short value) { - valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Short.valueOf(value), StampFactory.forNodeIntrinsic()); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static boolean booleanValue(@Parameter("value") Boolean value) { - valueOfCounter.inc(); - return value.booleanValue(); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static byte byteValue(@Parameter("value") Byte value) { - valueOfCounter.inc(); - return value.byteValue(); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static char charValue(@Parameter("value") Character value) { - valueOfCounter.inc(); - return value.charValue(); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static double doubleValue(@Parameter("value") Double value) { - valueOfCounter.inc(); - return value.doubleValue(); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static float floatValue(@Parameter("value") Float value) { - valueOfCounter.inc(); - return value.floatValue(); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static int intValue(@Parameter("value") Integer value) { - valueOfCounter.inc(); - return value.intValue(); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static long longValue(@Parameter("value") Long value) { - valueOfCounter.inc(); - return value.longValue(); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static short shortValue(@Parameter("value") Short value) { - valueOfCounter.inc(); - return value.shortValue(); - } - - public static FloatingNode canonicalizeBoxing(BoxNode box, MetaAccessProvider runtime) { - ValueNode value = box.getValue(); - if (value.isConstant()) { - Constant sourceConstant = value.asConstant(); - switch (box.getBoxingKind()) { - case Boolean: - return ConstantNode.forObject(Boolean.valueOf(sourceConstant.asInt() != 0), runtime, box.graph()); - case Byte: - return ConstantNode.forObject(Byte.valueOf((byte) sourceConstant.asInt()), runtime, box.graph()); - case Char: - return ConstantNode.forObject(Character.valueOf((char) sourceConstant.asInt()), runtime, box.graph()); - case Short: - return ConstantNode.forObject(Short.valueOf((short) sourceConstant.asInt()), runtime, box.graph()); - case Int: - return ConstantNode.forObject(Integer.valueOf(sourceConstant.asInt()), runtime, box.graph()); - case Long: - return ConstantNode.forObject(Long.valueOf(sourceConstant.asLong()), runtime, box.graph()); - case Float: - return ConstantNode.forObject(Float.valueOf(sourceConstant.asFloat()), runtime, box.graph()); - case Double: - return ConstantNode.forObject(Double.valueOf(sourceConstant.asDouble()), runtime, box.graph()); - default: - assert false : "Unexpected source kind for boxing"; - break; - } - } - return null; - } - - public static class Templates extends AbstractTemplates { - - private final ResolvedJavaMethod[] valueOfMethods = new ResolvedJavaMethod[Kind.values().length]; - private final ResolvedJavaMethod[] unboxMethods = new ResolvedJavaMethod[Kind.values().length]; - - public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) { - super(runtime, replacements, target, BoxingSnippets.class); - for (Kind kind : new Kind[]{Kind.Boolean, Kind.Byte, Kind.Char, Kind.Double, Kind.Float, Kind.Int, Kind.Long, Kind.Short}) { - valueOfMethods[kind.ordinal()] = snippet("valueOf", kind.toJavaClass()); - unboxMethods[kind.ordinal()] = snippet(kind.getJavaName() + "Value", kind.toBoxedJavaClass()); - } - } - - private ResolvedJavaMethod getValueOf(Kind kind) { - assert valueOfMethods[kind.ordinal()] != null; - return valueOfMethods[kind.ordinal()]; - } - - private ResolvedJavaMethod getUnbox(Kind kind) { - assert unboxMethods[kind.ordinal()] != null; - return unboxMethods[kind.ordinal()]; - } - - public void lower(BoxNode box) { - FloatingNode canonical = canonicalizeBoxing(box, runtime); - if (canonical != null) { - ((StructuredGraph) box.graph()).replaceFixedWithFloating(box, canonical); - } else { - Key key = new Key(getValueOf(box.getBoxingKind())); - Arguments arguments = new Arguments().add("value", box.getValue()); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering integerValueOf in %s: node=%s, template=%s, arguments=%s", box.graph(), box, template, arguments); - template.instantiate(runtime, box, DEFAULT_REPLACER, arguments); - } - } - - public void lower(UnboxNode unbox) { - Key key = new Key(getUnbox(unbox.getBoxingKind())); - Arguments arguments = new Arguments().add("value", unbox.getValue()); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering integerValueOf in %s: node=%s, template=%s, arguments=%s", unbox.graph(), unbox, template, arguments); - template.instantiate(runtime, unbox, DEFAULT_REPLACER, arguments); - } - } - - private static final SnippetCounter.Group integerCounters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("Integer intrinsifications") : null; - private static final SnippetCounter valueOfCounter = new SnippetCounter(integerCounters, "valueOf", "valueOf intrinsification"); - -} diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/BoxingSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/BoxingSubstitutions.java Fri Apr 12 23:29:45 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,147 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.hotspot.replacements; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.replacements.*; -import com.oracle.graal.nodes.extended.*; - -public class BoxingSubstitutions { - - @ClassSubstitution(Boolean.class) - private static class BooleanSubstitutions { - - @MethodSubstitution(forced = true) - public static Boolean valueOf(boolean value) { - return BoxNode.box(value, Boolean.class, Kind.Boolean); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static boolean booleanValue(Boolean value) { - return UnboxNode.unbox(value, Kind.Boolean); - } - } - - @ClassSubstitution(Byte.class) - private static class ByteSubstitutions { - - @MethodSubstitution(forced = true) - public static Byte valueOf(byte value) { - return BoxNode.box(value, Byte.class, Kind.Byte); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static byte byteValue(Byte value) { - return UnboxNode.unbox(value, Kind.Byte); - } - } - - @ClassSubstitution(Character.class) - private static class CharacterSubstitutions { - - @MethodSubstitution(forced = true) - public static Character valueOf(char value) { - return BoxNode.box(value, Character.class, Kind.Char); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static char charValue(Character value) { - return UnboxNode.unbox(value, Kind.Char); - } - } - - @ClassSubstitution(Double.class) - private static class DoubleSubstitutions { - - @MethodSubstitution(forced = true) - public static Double valueOf(double value) { - return BoxNode.box(value, Double.class, Kind.Double); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static double doubleValue(Double value) { - return UnboxNode.unbox(value, Kind.Double); - } - } - - @ClassSubstitution(Float.class) - private static class FloatSubstitutions { - - @MethodSubstitution(forced = true) - public static Float valueOf(float value) { - return BoxNode.box(value, Float.class, Kind.Float); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static float floatValue(Float value) { - return UnboxNode.unbox(value, Kind.Float); - } - } - - @ClassSubstitution(Integer.class) - private static class IntegerSubstitutions { - - @MethodSubstitution(forced = true) - public static Integer valueOf(int value) { - return BoxNode.box(value, Integer.class, Kind.Int); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static int intValue(Integer value) { - return UnboxNode.unbox(value, Kind.Int); - } - } - - @ClassSubstitution(Long.class) - private static class LongSubstitutions { - - @MethodSubstitution(forced = true) - public static Long valueOf(long value) { - return BoxNode.box(value, Long.class, Kind.Long); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static long longValue(Long value) { - return UnboxNode.unbox(value, Kind.Long); - } - } - - @ClassSubstitution(Short.class) - private static class ShortSubstitutions { - - @MethodSubstitution(forced = true) - public static Short valueOf(short value) { - return BoxNode.box(value, Short.class, Kind.Short); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static short shortValue(Short value) { - return UnboxNode.unbox(value, Kind.Short); - } - } - - public static Class[] getClasses() { - return new Class[]{BooleanSubstitutions.class, ByteSubstitutions.class, CharacterSubstitutions.class, DoubleSubstitutions.class, FloatSubstitutions.class, IntegerSubstitutions.class, - LongSubstitutions.class, ShortSubstitutions.class}; - } -} diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteSubstitutions.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteSubstitutions.java Sat Apr 13 00:33:37 2013 +0200 @@ -40,25 +40,25 @@ replacements.registerSubstitutions(VolatileCallSiteSubstitutions.class); } } -} + + @ClassSubstitution(ConstantCallSite.class) + private static class ConstantCallSiteSubstitutions { -@ClassSubstitution(ConstantCallSite.class) -class ConstantCallSiteSubstitutions { + @MacroSubstitution(isStatic = false, macro = CallSiteTargetNode.class) + public static native MethodHandle getTarget(ConstantCallSite callSite); + } - @MacroSubstitution(isStatic = false, macro = CallSiteTargetNode.class) - public static native MethodHandle getTarget(ConstantCallSite callSite); -} + @ClassSubstitution(MutableCallSite.class) + private static class MutableCallSiteSubstitutions { -@ClassSubstitution(MutableCallSite.class) -class MutableCallSiteSubstitutions { - - @MacroSubstitution(isStatic = false, macro = CallSiteTargetNode.class) - public static native MethodHandle getTarget(MutableCallSite callSite); -} + @MacroSubstitution(isStatic = false, macro = CallSiteTargetNode.class) + public static native MethodHandle getTarget(MutableCallSite callSite); + } -@ClassSubstitution(VolatileCallSite.class) -class VolatileCallSiteSubstitutions { + @ClassSubstitution(VolatileCallSite.class) + private static class VolatileCallSiteSubstitutions { - @MacroSubstitution(isStatic = false, macro = CallSiteTargetNode.class) - public static native MethodHandle getTarget(VolatileCallSite callSite); + @MacroSubstitution(isStatic = false, macro = CallSiteTargetNode.class) + public static native MethodHandle getTarget(VolatileCallSite callSite); + } } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java Sat Apr 13 00:33:37 2013 +0200 @@ -28,11 +28,9 @@ import static com.oracle.graal.hotspot.replacements.TypeCheckSnippetUtils.*; import static com.oracle.graal.nodes.extended.UnsafeCastNode.*; import static com.oracle.graal.replacements.SnippetTemplate.*; -import static com.oracle.graal.replacements.SnippetTemplate.Arguments.*; import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.hotspot.meta.*; @@ -42,7 +40,11 @@ import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.Snippet.*; +import com.oracle.graal.replacements.Snippet.ConstantParameter; +import com.oracle.graal.replacements.Snippet.VarargsParameter; +import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*; @@ -58,16 +60,11 @@ @NodeIntrinsic(BreakpointNode.class) static native void bkpt(Object object, Word hub, Word objectHub); - // @formatter:off - /** * Type test used when the type being tested against is a final type. */ @Snippet - public static Object checkcastExact( - @Parameter("object") Object object, - @Parameter("exactHub") Word exactHub, - @ConstantParameter("checkNull") boolean checkNull) { + public static Object checkcastExact(Object object, Word exactHub, @ConstantParameter boolean checkNull) { if (checkNull && object == null) { probability(NOT_FREQUENT_PROBABILITY); isNull.inc(); @@ -76,30 +73,25 @@ if (objectHub.notEqual(exactHub)) { probability(DEOPT_PATH_PROBABILITY); exactMiss.inc(); - //bkpt(object, exactHub, objectHub); DeoptimizeNode.deopt(InvalidateReprofile, ClassCastException); } exactHit.inc(); } - /* make sure that the unsafeCast is done *after* the check above, - * cf. ReadAfterCheckCast */ + /* + * make sure that the unsafeCast is done *after* the check above, cf. ReadAfterCheckCast + */ BeginNode anchorNode = BeginNode.anchor(StampFactory.forNodeIntrinsic()); return unsafeCast(verifyOop(object), StampFactory.forNodeIntrinsic(), anchorNode); } /** * Type test used when the type being tested against is a restricted primary type. - * - * This test ignores use of hints altogether as the display-based type check only - * involves one extra load where the second load should hit the same cache line as the - * first. + * + * This test ignores use of hints altogether as the display-based type check only involves one + * extra load where the second load should hit the same cache line as the first. */ @Snippet - public static Object checkcastPrimary( - @Parameter("hub") Word hub, - @Parameter("object") Object object, - @ConstantParameter("checkNull") boolean checkNull, - @ConstantParameter("superCheckOffset") int superCheckOffset) { + public static Object checkcastPrimary(Word hub, Object object, @ConstantParameter int superCheckOffset, @ConstantParameter boolean checkNull) { if (checkNull && object == null) { probability(NOT_FREQUENT_PROBABILITY); isNull.inc(); @@ -120,11 +112,7 @@ * Type test used when the type being tested against is a restricted secondary type. */ @Snippet - public static Object checkcastSecondary( - @Parameter("hub") Word hub, - @Parameter("object") Object object, - @VarargsParameter("hints") Word[] hints, - @ConstantParameter("checkNull") boolean checkNull) { + public static Object checkcastSecondary(Word hub, Object object, @VarargsParameter Word[] hints, @ConstantParameter boolean checkNull) { if (checkNull && object == null) { probability(NOT_FREQUENT_PROBABILITY); isNull.inc(); @@ -149,14 +137,11 @@ } /** - * Type test used when the type being tested against is not known at compile time (e.g. the type test - * in an object array store check). + * Type test used when the type being tested against is not known at compile time (e.g. the type + * test in an object array store check). */ @Snippet - public static Object checkcastDynamic( - @Parameter("hub") Word hub, - @Parameter("object") Object object, - @ConstantParameter("checkNull") boolean checkNull) { + public static Object checkcastDynamic(Word hub, Object object, @ConstantParameter boolean checkNull) { if (checkNull && object == null) { probability(NOT_FREQUENT_PROBABILITY); isNull.inc(); @@ -170,21 +155,15 @@ return unsafeCast(verifyOop(object), StampFactory.forNodeIntrinsic(), anchorNode); } - // @formatter:on - - public static class Templates extends AbstractTemplates { + public static class Templates extends AbstractTemplates { - private final ResolvedJavaMethod exact; - private final ResolvedJavaMethod primary; - private final ResolvedJavaMethod secondary; - private final ResolvedJavaMethod dynamic; + private final SnippetInfo exact = snippet(CheckCastSnippets.class, "checkcastExact"); + private final SnippetInfo primary = snippet(CheckCastSnippets.class, "checkcastPrimary"); + private final SnippetInfo secondary = snippet(CheckCastSnippets.class, "checkcastSecondary"); + private final SnippetInfo dynamic = snippet(CheckCastSnippets.class, "checkcastDynamic"); public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) { - super(runtime, replacements, target, CheckCastSnippets.class); - exact = snippet("checkcastExact", Object.class, Word.class, boolean.class); - primary = snippet("checkcastPrimary", Word.class, Object.class, boolean.class, int.class); - secondary = snippet("checkcastSecondary", Word.class, Object.class, Word[].class, boolean.class); - dynamic = snippet("checkcastDynamic", Word.class, Object.class, boolean.class); + super(runtime, replacements, target); } /** @@ -193,31 +172,34 @@ public void lower(CheckCastNode checkcast, LoweringTool tool) { StructuredGraph graph = (StructuredGraph) checkcast.graph(); ValueNode object = checkcast.object(); - final HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) checkcast.type(); + HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) checkcast.type(); TypeCheckHints hintInfo = new TypeCheckHints(checkcast.type(), checkcast.profile(), tool.assumptions(), GraalOptions.CheckcastMinHintHitProbability, GraalOptions.CheckcastMaxHints); ValueNode hub = ConstantNode.forConstant(type.klass(), runtime, checkcast.graph()); - boolean checkNull = !object.stamp().nonNull(); - Arguments arguments; - Key key; - assert type != null; + Arguments args; if (hintInfo.exact) { ConstantNode[] hints = createHints(hintInfo, runtime, true, graph).hubs; assert hints.length == 1; - key = new Key(exact).add("checkNull", checkNull); - arguments = arguments("object", object).add("exactHub", hints[0]); + args = new Arguments(exact); + args.add("object", object); + args.add("exactHub", hints[0]); } else if (type.isPrimaryType()) { - key = new Key(primary).add("checkNull", checkNull).add("superCheckOffset", type.superCheckOffset()); - arguments = arguments("hub", hub).add("object", object); + args = new Arguments(primary); + args.add("hub", hub); + args.add("object", object); + args.addConst("superCheckOffset", type.superCheckOffset()); } else { ConstantNode[] hints = createHints(hintInfo, runtime, true, graph).hubs; - key = new Key(secondary).add("hints", Varargs.vargargs(new Word[hints.length], StampFactory.forKind(wordKind()))).add("checkNull", checkNull); - arguments = arguments("hub", hub).add("object", object).add("hints", hints); + args = new Arguments(secondary); + args.add("hub", hub); + args.add("object", object); + args.addVarargs("hints", Word.class, StampFactory.forKind(wordKind()), hints); } + args.addConst("checkNull", !object.stamp().nonNull()); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering checkcast in %s: node=%s, template=%s, arguments=%s", graph, checkcast, template, arguments); - template.instantiate(runtime, checkcast, DEFAULT_REPLACER, arguments); + SnippetTemplate template = template(args); + Debug.log("Lowering checkcast in %s: node=%s, template=%s, arguments=%s", graph, checkcast, template, args); + template.instantiate(runtime, checkcast, DEFAULT_REPLACER, args); } /** @@ -225,16 +207,16 @@ */ public void lower(CheckCastDynamicNode checkcast) { StructuredGraph graph = (StructuredGraph) checkcast.graph(); - ValueNode hub = checkcast.type(); ValueNode object = checkcast.object(); - boolean checkNull = !object.stamp().nonNull(); - Key key = new Key(dynamic).add("checkNull", checkNull); - Arguments arguments = arguments("hub", hub).add("object", object); + Arguments args = new Arguments(dynamic); + args.add("hub", checkcast.type()); + args.add("object", object); + args.addConst("checkNull", !object.stamp().nonNull()); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering dynamic checkcast in %s: node=%s, template=%s, arguments=%s", graph, checkcast, template, arguments); - template.instantiate(runtime, checkcast, DEFAULT_REPLACER, arguments); + SnippetTemplate template = template(args); + Debug.log("Lowering dynamic checkcast in %s: node=%s, template=%s, arguments=%s", graph, checkcast, template, args); + template.instantiate(runtime, checkcast, DEFAULT_REPLACER, args); } } } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotInstalledCodeSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotInstalledCodeSubstitutions.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotInstalledCodeSubstitutions.java Sat Apr 13 00:33:37 2013 +0200 @@ -27,20 +27,18 @@ import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.replacements.Snippet.Fold; -import com.oracle.graal.word.*; @ClassSubstitution(HotSpotInstalledCode.class) public class HotSpotInstalledCodeSubstitutions { - @MethodSubstitution - public static Object executeHelper(long nmethod, long metaspaceMethod, final Object arg1, final Object arg2, final Object arg3) { - final int verifiedEntryPointOffset = HotSpotSnippetUtils.verifiedEntryPointOffset(); - final Word callTarget = Word.unsigned(nmethod).readWord(verifiedEntryPointOffset); - return HotSpotInstalledCodeExecuteNode.call(Kind.Object, callTarget, metaspaceMethod, getSignature(), arg1, arg2, arg3); + @MethodSubstitution(isStatic = false) + public static Object execute(HotSpotInstalledCode code, final Object arg1, final Object arg2, final Object arg3) { + return HotSpotInstalledCodeExecuteNode.call(Kind.Object, getSignature(), code, arg1, arg2, arg3); } @Fold private static Class[] getSignature() { return new Class[]{Object.class, Object.class, Object.class}; } + } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java Sat Apr 13 00:33:37 2013 +0200 @@ -24,21 +24,22 @@ import static com.oracle.graal.hotspot.replacements.HotSpotSnippetUtils.*; import static com.oracle.graal.hotspot.replacements.TypeCheckSnippetUtils.*; -import static com.oracle.graal.replacements.Snippet.Varargs.*; -import static com.oracle.graal.replacements.SnippetTemplate.Arguments.*; import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.replacements.TypeCheckSnippetUtils.Hints; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.Snippet.*; -import com.oracle.graal.replacements.SnippetTemplate.*; +import com.oracle.graal.replacements.Snippet.ConstantParameter; +import com.oracle.graal.replacements.Snippet.VarargsParameter; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*; @@ -52,18 +53,11 @@ */ public class InstanceOfSnippets implements Snippets { - // @formatter:off - /** * A test against a final type. */ @Snippet - public static Object instanceofExact( - @Parameter("object") Object object, - @Parameter("exactHub") Word exactHub, - @Parameter("trueValue") Object trueValue, - @Parameter("falseValue") Object falseValue, - @ConstantParameter("checkNull") boolean checkNull) { + public static Object instanceofExact(Object object, Word exactHub, Object trueValue, Object falseValue, @ConstantParameter boolean checkNull) { if (checkNull && object == null) { probability(NOT_FREQUENT_PROBABILITY); isNull.inc(); @@ -83,13 +77,7 @@ * A test against a primary type. */ @Snippet - public static Object instanceofPrimary( - @Parameter("hub") Word hub, - @Parameter("object") Object object, - @Parameter("trueValue") Object trueValue, - @Parameter("falseValue") Object falseValue, - @ConstantParameter("checkNull") boolean checkNull, - @ConstantParameter("superCheckOffset") int superCheckOffset) { + public static Object instanceofPrimary(Word hub, Object object, @ConstantParameter int superCheckOffset, Object trueValue, Object falseValue, @ConstantParameter boolean checkNull) { if (checkNull && object == null) { probability(NOT_FREQUENT_PROBABILITY); isNull.inc(); @@ -109,14 +97,8 @@ * A test against a restricted secondary type type. */ @Snippet - public static Object instanceofSecondary( - @Parameter("hub") Word hub, - @Parameter("object") Object object, - @Parameter("trueValue") Object trueValue, - @Parameter("falseValue") Object falseValue, - @VarargsParameter("hints") Word[] hints, - @VarargsParameter("hintIsPositive") boolean[] hintIsPositive, - @ConstantParameter("checkNull") boolean checkNull) { + public static Object instanceofSecondary(Word hub, Object object, @VarargsParameter Word[] hints, @VarargsParameter boolean[] hintIsPositive, Object trueValue, Object falseValue, + @ConstantParameter boolean checkNull) { if (checkNull && object == null) { probability(NOT_FREQUENT_PROBABILITY); isNull.inc(); @@ -144,12 +126,7 @@ * Type test used when the type being tested against is not known at compile time. */ @Snippet - public static Object instanceofDynamic( - @Parameter("mirror") Class mirror, - @Parameter("object") Object object, - @Parameter("trueValue") Object trueValue, - @Parameter("falseValue") Object falseValue, - @ConstantParameter("checkNull") boolean checkNull) { + public static Object instanceofDynamic(Class mirror, Object object, Object trueValue, Object falseValue, @ConstantParameter boolean checkNull) { if (checkNull && object == null) { probability(NOT_FREQUENT_PROBABILITY); isNull.inc(); @@ -164,65 +141,63 @@ return trueValue; } - // @formatter:on - - public static class Templates extends InstanceOfSnippetsTemplates { + public static class Templates extends InstanceOfSnippetsTemplates { - private final ResolvedJavaMethod instanceofExact; - private final ResolvedJavaMethod instanceofPrimary; - private final ResolvedJavaMethod instanceofSecondary; - private final ResolvedJavaMethod instanceofDynamic; + private final SnippetInfo instanceofExact = snippet(InstanceOfSnippets.class, "instanceofExact"); + private final SnippetInfo instanceofPrimary = snippet(InstanceOfSnippets.class, "instanceofPrimary"); + private final SnippetInfo instanceofSecondary = snippet(InstanceOfSnippets.class, "instanceofSecondary"); + private final SnippetInfo instanceofDynamic = snippet(InstanceOfSnippets.class, "instanceofDynamic"); public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) { - super(runtime, replacements, target, InstanceOfSnippets.class); - instanceofExact = snippet("instanceofExact", Object.class, Word.class, Object.class, Object.class, boolean.class); - instanceofPrimary = snippet("instanceofPrimary", Word.class, Object.class, Object.class, Object.class, boolean.class, int.class); - instanceofSecondary = snippet("instanceofSecondary", Word.class, Object.class, Object.class, Object.class, Word[].class, boolean[].class, boolean.class); - instanceofDynamic = snippet("instanceofDynamic", Class.class, Object.class, Object.class, Object.class, boolean.class); + super(runtime, replacements, target); } @Override - protected KeyAndArguments getKeyAndArguments(InstanceOfUsageReplacer replacer, LoweringTool tool) { + protected Arguments makeArguments(InstanceOfUsageReplacer replacer, LoweringTool tool) { if (replacer.instanceOf instanceof InstanceOfNode) { InstanceOfNode instanceOf = (InstanceOfNode) replacer.instanceOf; - ValueNode trueValue = replacer.trueValue; - ValueNode falseValue = replacer.falseValue; ValueNode object = instanceOf.object(); TypeCheckHints hintInfo = new TypeCheckHints(instanceOf.type(), instanceOf.profile(), tool.assumptions(), GraalOptions.InstanceOfMinHintHitProbability, GraalOptions.InstanceOfMaxHints); final HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) instanceOf.type(); ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, instanceOf.graph()); - boolean checkNull = !object.stamp().nonNull(); - Arguments arguments; - Key key; + + Arguments args; if (hintInfo.exact) { ConstantNode[] hints = createHints(hintInfo, runtime, true, hub.graph()).hubs; assert hints.length == 1; - key = new Key(instanceofExact).add("checkNull", checkNull); - arguments = arguments("object", object).add("exactHub", hints[0]).add("trueValue", trueValue).add("falseValue", falseValue); + args = new Arguments(instanceofExact); + args.add("object", object); + args.add("exactHub", hints[0]); } else if (type.isPrimaryType()) { - key = new Key(instanceofPrimary).add("checkNull", checkNull).add("superCheckOffset", type.superCheckOffset()); - arguments = arguments("hub", hub).add("object", object).add("trueValue", trueValue).add("falseValue", falseValue); + args = new Arguments(instanceofPrimary); + args.add("hub", hub); + args.add("object", object); + args.addConst("superCheckOffset", type.superCheckOffset()); } else { Hints hints = createHints(hintInfo, runtime, false, hub.graph()); - ConstantNode[] hintHubs = hints.hubs; - boolean[] hintIsPositive = hints.isPositive; - Varargs hintsParam = vargargs(new Word[hintHubs.length], StampFactory.forKind(wordKind())); - Varargs hintIsPositiveParam = vargargs(new boolean[hintIsPositive.length], StampFactory.forKind(Kind.Boolean)); - key = new Key(instanceofSecondary).add("hints", hintsParam).add("hintIsPositive", hintIsPositiveParam).add("checkNull", checkNull); - arguments = arguments("hub", hub).add("object", object).add("hints", hintHubs).add("hintIsPositive", hintIsPositive).add("trueValue", trueValue).add("falseValue", falseValue); + args = new Arguments(instanceofSecondary); + args.add("hub", hub); + args.add("object", object); + args.addVarargs("hints", Word.class, StampFactory.forKind(wordKind()), hints.hubs); + args.addVarargs("hintIsPositive", boolean.class, StampFactory.forKind(Kind.Boolean), hints.isPositive); } - return new KeyAndArguments(key, arguments); + args.add("trueValue", replacer.trueValue); + args.add("falseValue", replacer.falseValue); + args.addConst("checkNull", !object.stamp().nonNull()); + return args; + } else { assert replacer.instanceOf instanceof InstanceOfDynamicNode; InstanceOfDynamicNode instanceOf = (InstanceOfDynamicNode) replacer.instanceOf; - ValueNode trueValue = replacer.trueValue; - ValueNode falseValue = replacer.falseValue; ValueNode object = instanceOf.object(); - ValueNode mirror = instanceOf.mirror(); - boolean checkNull = !object.stamp().nonNull(); - Key key = new Key(instanceofDynamic).add("checkNull", checkNull); - Arguments arguments = arguments("mirror", mirror).add("object", object).add("trueValue", trueValue).add("falseValue", falseValue); - return new KeyAndArguments(key, arguments); + + Arguments args = new Arguments(instanceofDynamic); + args.add("mirror", instanceOf.mirror()); + args.add("object", object); + args.add("trueValue", replacer.trueValue); + args.add("falseValue", replacer.falseValue); + args.addConst("checkNull", !object.stamp().nonNull()); + return args; } } } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java Sat Apr 13 00:33:37 2013 +0200 @@ -27,16 +27,13 @@ import static com.oracle.graal.replacements.SnippetTemplate.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; import com.oracle.graal.replacements.SnippetTemplate.Arguments; -import com.oracle.graal.replacements.SnippetTemplate.Key; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; import com.oracle.graal.word.*; /** @@ -53,23 +50,17 @@ return unsafeCast(exception, StampFactory.forNodeIntrinsic()); } - public static class Templates extends AbstractTemplates { + public static class Templates extends AbstractTemplates { - private final ResolvedJavaMethod loadException; + private final SnippetInfo loadException = snippet(LoadExceptionObjectSnippets.class, "loadException"); public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) { - super(runtime, replacements, target, LoadExceptionObjectSnippets.class); - loadException = snippet("loadException"); + super(runtime, replacements, target); } public void lower(LoadExceptionObjectNode loadExceptionObject) { - StructuredGraph graph = (StructuredGraph) loadExceptionObject.graph(); - Arguments arguments = new Arguments(); - - Key key = new Key(loadException); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering exception object in %s: node=%s, template=%s, arguments=%s", graph, loadExceptionObject, template, arguments); - template.instantiate(runtime, loadExceptionObject, DEFAULT_REPLACER, arguments); + Arguments args = new Arguments(loadException); + template(args).instantiate(runtime, loadExceptionObject, DEFAULT_REPLACER, args); } } } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleInvokeBasicNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleInvokeBasicNode.java Sat Apr 13 00:33:37 2013 +0200 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013, 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.replacements; + +import java.lang.invoke.*; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.replacements.nodes.*; + +/** + * Macro node for {@link MethodHandle}{@code .invokeBasic(Object...)}. + */ +public class MethodHandleInvokeBasicNode extends MacroNode { + + public MethodHandleInvokeBasicNode(Invoke invoke) { + super(invoke); + } +} diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToInterfaceNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToInterfaceNode.java Sat Apr 13 00:33:37 2013 +0200 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013, 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.replacements; + +import java.lang.invoke.*; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.replacements.nodes.*; + +/** + * Macro node for {@link MethodHandle}{@code .linkToInterface(Object...)}. + */ +public class MethodHandleLinkToInterfaceNode extends MacroNode { + + public MethodHandleLinkToInterfaceNode(Invoke invoke) { + super(invoke); + } +} diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToSpecialNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToSpecialNode.java Sat Apr 13 00:33:37 2013 +0200 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013, 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.replacements; + +import java.lang.invoke.*; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.replacements.nodes.*; + +/** + * Macro node for {@link MethodHandle}{@code .linkToSpecial(Object...)}. + */ +public class MethodHandleLinkToSpecialNode extends MacroNode { + + public MethodHandleLinkToSpecialNode(Invoke invoke) { + super(invoke); + } +} diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToStaticNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToStaticNode.java Sat Apr 13 00:33:37 2013 +0200 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013, 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.replacements; + +import java.lang.invoke.*; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.replacements.nodes.*; + +/** + * Macro node for {@link MethodHandle}{@code .linkToStatic(Object...)}. + */ +public class MethodHandleLinkToStaticNode extends MacroNode { + + public MethodHandleLinkToStaticNode(Invoke invoke) { + super(invoke); + } +} diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToVirtualNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToVirtualNode.java Sat Apr 13 00:33:37 2013 +0200 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013, 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.replacements; + +import java.lang.invoke.*; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.replacements.nodes.*; + +/** + * Macro node for {@link MethodHandle}{@code .linkToVirtual(Object...)}. + */ +public class MethodHandleLinkToVirtualNode extends MacroNode { + + public MethodHandleLinkToVirtualNode(Invoke invoke) { + super(invoke); + } +} diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Sat Apr 13 00:33:37 2013 +0200 @@ -46,7 +46,10 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.Snippet.*; +import com.oracle.graal.replacements.Snippet.ConstantParameter; +import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; import com.oracle.graal.word.*; /** @@ -73,7 +76,7 @@ public static final boolean CHECK_BALANCED_MONITORS = Boolean.getBoolean("graal.monitors.checkBalanced"); @Snippet - public static void monitorenter(@Parameter("object") Object object, @ConstantParameter("checkNull") boolean checkNull, @ConstantParameter("trace") boolean trace) { + public static void monitorenter(Object object, @ConstantParameter boolean checkNull, @ConstantParameter boolean trace) { verifyOop(object); if (checkNull && object == null) { @@ -262,7 +265,7 @@ * Calls straight out to the monitorenter stub. */ @Snippet - public static void monitorenterStub(@Parameter("object") Object object, @ConstantParameter("checkNull") boolean checkNull, @ConstantParameter("trace") boolean trace) { + public static void monitorenterStub(Object object, @ConstantParameter boolean checkNull, @ConstantParameter boolean trace) { verifyOop(object); incCounter(); if (checkNull && object == null) { @@ -276,7 +279,7 @@ } @Snippet - public static void monitorexit(@Parameter("object") Object object, @ConstantParameter("trace") boolean trace) { + public static void monitorexit(Object object, @ConstantParameter boolean trace) { trace(trace, " object: 0x%016lx\n", Word.fromObject(object)); if (useBiasedLocking()) { // Check for biased locking unlock case, which is a no-op @@ -328,7 +331,7 @@ * Calls straight out to the monitorexit stub. */ @Snippet - public static void monitorexitStub(@Parameter("object") Object object, @ConstantParameter("trace") boolean trace) { + public static void monitorexitStub(Object object, @ConstantParameter boolean trace) { verifyOop(object); traceObject(trace, "-lock{stub}", object); MonitorExitStubCall.call(object); @@ -398,54 +401,45 @@ } } - public static class Templates extends AbstractTemplates { + public static class Templates extends AbstractTemplates { - private final ResolvedJavaMethod monitorenter; - private final ResolvedJavaMethod monitorexit; - private final ResolvedJavaMethod monitorenterStub; - private final ResolvedJavaMethod monitorexitStub; - private final ResolvedJavaMethod monitorenterEliminated; - private final ResolvedJavaMethod monitorexitEliminated; - private final ResolvedJavaMethod initCounter; - private final ResolvedJavaMethod checkCounter; + private final SnippetInfo monitorenter = snippet(MonitorSnippets.class, "monitorenter"); + private final SnippetInfo monitorexit = snippet(MonitorSnippets.class, "monitorexit"); + private final SnippetInfo monitorenterStub = snippet(MonitorSnippets.class, "monitorenterStub"); + private final SnippetInfo monitorexitStub = snippet(MonitorSnippets.class, "monitorexitStub"); + private final SnippetInfo monitorenterEliminated = snippet(MonitorSnippets.class, "monitorenterEliminated"); + private final SnippetInfo monitorexitEliminated = snippet(MonitorSnippets.class, "monitorexitEliminated"); + private final SnippetInfo initCounter = snippet(MonitorSnippets.class, "initCounter"); + private final SnippetInfo checkCounter = snippet(MonitorSnippets.class, "checkCounter"); + private final boolean useFastLocking; public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target, boolean useFastLocking) { - super(runtime, replacements, target, MonitorSnippets.class); - monitorenter = snippet("monitorenter", Object.class, boolean.class, boolean.class); - monitorexit = snippet("monitorexit", Object.class, boolean.class); - monitorenterStub = snippet("monitorenterStub", Object.class, boolean.class, boolean.class); - monitorexitStub = snippet("monitorexitStub", Object.class, boolean.class); - monitorenterEliminated = snippet("monitorenterEliminated"); - monitorexitEliminated = snippet("monitorexitEliminated"); - initCounter = snippet("initCounter"); - checkCounter = snippet("checkCounter", String.class); + super(runtime, replacements, target); this.useFastLocking = useFastLocking; } public void lower(MonitorEnterNode monitorenterNode, @SuppressWarnings("unused") LoweringTool tool) { StructuredGraph graph = (StructuredGraph) monitorenterNode.graph(); - checkBalancedMonitors(graph); - FrameState stateAfter = monitorenterNode.stateAfter(); - boolean eliminated = monitorenterNode.eliminated(); - ResolvedJavaMethod method = eliminated ? monitorenterEliminated : useFastLocking ? monitorenter : monitorenterStub; - boolean checkNull = !monitorenterNode.object().stamp().nonNull(); - Key key = new Key(method); - if (method != monitorenterEliminated) { - key.add("checkNull", checkNull); - } - if (!eliminated) { - key.add("trace", isTracingEnabledForType(monitorenterNode.object()) || isTracingEnabledForMethod(stateAfter.method()) || isTracingEnabledForMethod(graph.method())); + + Arguments args; + if (monitorenterNode.eliminated()) { + args = new Arguments(monitorenterEliminated); + } else { + if (useFastLocking) { + args = new Arguments(monitorenter); + } else { + args = new Arguments(monitorenterStub); + } + args.add("object", monitorenterNode.object()); + args.addConst("checkNull", !monitorenterNode.object().stamp().nonNull()); + args.addConst("trace", isTracingEnabledForType(monitorenterNode.object()) || isTracingEnabledForMethod(stateAfter.method()) || isTracingEnabledForMethod(graph.method())); } - Arguments arguments = new Arguments(); - if (!eliminated) { - arguments.add("object", monitorenterNode.object()); - } - SnippetTemplate template = cache.get(key); - Map nodes = template.instantiate(runtime, monitorenterNode, DEFAULT_REPLACER, arguments); + Map nodes = template(args).instantiate(runtime, monitorenterNode, DEFAULT_REPLACER, args); + for (Node n : nodes.values()) { if (n instanceof BeginLockScopeNode) { BeginLockScopeNode begin = (BeginLockScopeNode) n; @@ -460,18 +454,22 @@ public void lower(MonitorExitNode monitorexitNode, @SuppressWarnings("unused") LoweringTool tool) { StructuredGraph graph = (StructuredGraph) monitorexitNode.graph(); FrameState stateAfter = monitorexitNode.stateAfter(); - boolean eliminated = monitorexitNode.eliminated(); - ResolvedJavaMethod method = eliminated ? monitorexitEliminated : useFastLocking ? monitorexit : monitorexitStub; - Key key = new Key(method); - if (!eliminated) { - key.add("trace", isTracingEnabledForType(monitorexitNode.object()) || isTracingEnabledForMethod(stateAfter.method()) || isTracingEnabledForMethod(graph.method())); + + Arguments args; + if (monitorexitNode.eliminated()) { + args = new Arguments(monitorexitEliminated); + } else { + if (useFastLocking) { + args = new Arguments(monitorexit); + } else { + args = new Arguments(monitorexitStub); + } + args.add("object", monitorexitNode.object()); + args.addConst("trace", isTracingEnabledForType(monitorexitNode.object()) || isTracingEnabledForMethod(stateAfter.method()) || isTracingEnabledForMethod(graph.method())); } - Arguments arguments = new Arguments(); - if (!eliminated) { - arguments.add("object", monitorexitNode.object()); - } - SnippetTemplate template = cache.get(key); - Map nodes = template.instantiate(runtime, monitorexitNode, DEFAULT_REPLACER, arguments); + + Map nodes = template(args).instantiate(runtime, monitorexitNode, DEFAULT_REPLACER, args); + for (Node n : nodes.values()) { if (n instanceof EndLockScopeNode) { EndLockScopeNode end = (EndLockScopeNode) n; @@ -521,27 +519,27 @@ NodeIterable nodes = graph.getNodes().filter(MonitorCounterNode.class); if (nodes.isEmpty()) { // Only insert the nodes if this is the first monitorenter being lowered. - JavaType returnType = initCounter.getSignature().getReturnType(initCounter.getDeclaringClass()); - MethodCallTargetNode callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, initCounter, new ValueNode[0], returnType)); + JavaType returnType = initCounter.getMethod().getSignature().getReturnType(initCounter.getMethod().getDeclaringClass()); + MethodCallTargetNode callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, initCounter.getMethod(), new ValueNode[0], returnType)); InvokeNode invoke = graph.add(new InvokeNode(callTarget, 0)); invoke.setStateAfter(graph.start().stateAfter()); graph.addAfterFixed(graph.start(), invoke); - StructuredGraph inlineeGraph = replacements.getSnippet(initCounter); + StructuredGraph inlineeGraph = replacements.getSnippet(initCounter.getMethod()); InliningUtil.inline(invoke, inlineeGraph, false); List rets = graph.getNodes().filter(ReturnNode.class).snapshot(); for (ReturnNode ret : rets) { - returnType = checkCounter.getSignature().getReturnType(checkCounter.getDeclaringClass()); + returnType = checkCounter.getMethod().getSignature().getReturnType(checkCounter.getMethod().getDeclaringClass()); Object msg = ((HotSpotRuntime) runtime).registerGCRoot("unbalanced monitors in " + MetaUtil.format("%H.%n(%p)", graph.method()) + ", count = %d"); ConstantNode errMsg = ConstantNode.forObject(msg, runtime, graph); - callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, checkCounter, new ValueNode[]{errMsg}, returnType)); + callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, checkCounter.getMethod(), new ValueNode[]{errMsg}, returnType)); invoke = graph.add(new InvokeNode(callTarget, 0)); List stack = Collections.emptyList(); FrameState stateAfter = new FrameState(graph.method(), FrameState.AFTER_BCI, new ValueNode[0], stack, new ValueNode[0], false, false); invoke.setStateAfter(graph.add(stateAfter)); graph.addBeforeFixed(ret, invoke); - inlineeGraph = replacements.getSnippet(checkCounter); + inlineeGraph = replacements.getSnippet(checkCounter.getMethod()); InliningUtil.inline(invoke, inlineeGraph, false); } } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Sat Apr 13 00:33:37 2013 +0200 @@ -26,9 +26,7 @@ import static com.oracle.graal.hotspot.replacements.HotSpotSnippetUtils.*; import static com.oracle.graal.nodes.extended.UnsafeArrayCastNode.*; import static com.oracle.graal.nodes.extended.UnsafeCastNode.*; -import static com.oracle.graal.replacements.Snippet.Varargs.*; import static com.oracle.graal.replacements.SnippetTemplate.*; -import static com.oracle.graal.replacements.SnippetTemplate.Arguments.*; import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*; import static com.oracle.graal.replacements.nodes.ExplodeLoopNode.*; @@ -43,7 +41,11 @@ import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.Snippet.*; +import com.oracle.graal.replacements.Snippet.ConstantParameter; +import com.oracle.graal.replacements.Snippet.VarargsParameter; +import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*; @@ -52,15 +54,16 @@ */ public class NewObjectSnippets implements Snippets { - // @formatter:off - @Snippet - public static Word allocate(@Parameter("size") int size) { + public static Word allocate(int size) { Word thread = thread(); Word top = readTlabTop(thread); Word end = readTlabEnd(thread); Word newTop = top.add(size); - // this check might lead to problems if the TLAB is within 16GB of the address space end (checked in c++ code) + /* + * this check might lead to problems if the TLAB is within 16GB of the address space end + * (checked in c++ code) + */ if (newTop.belowOrEqual(end)) { probability(FAST_PATH_PROBABILITY); writeTlabTop(thread, newTop); @@ -70,13 +73,7 @@ } @Snippet - public static Object initializeObject( - @Parameter("memory") Word memory, - @Parameter("hub") Word hub, - @Parameter("prototypeMarkWord") Word prototypeMarkWord, - @ConstantParameter("size") int size, - @ConstantParameter("fillContents") boolean fillContents, - @ConstantParameter("locked") boolean locked) { + public static Object initializeObject(Word memory, Word hub, Word prototypeMarkWord, @ConstantParameter int size, @ConstantParameter boolean fillContents, @ConstantParameter boolean locked) { Object result; if (memory.equal(0)) { @@ -91,22 +88,17 @@ } result = memory.toObject(); } - /* make sure that the unsafeCast is anchored after initialization, - * see ReadAfterCheckCast and CheckCastSnippets */ + /* + * make sure that the unsafeCast is anchored after initialization, see ReadAfterCheckCast + * and CheckCastSnippets + */ BeginNode anchorNode = BeginNode.anchor(StampFactory.forNodeIntrinsic()); return unsafeCast(verifyOop(result), StampFactory.forNodeIntrinsic(), anchorNode); } @Snippet - public static Object initializeArray( - @Parameter("memory") Word memory, - @Parameter("hub") Word hub, - @Parameter("length") int length, - @Parameter("allocationSize") int allocationSize, - @Parameter("prototypeMarkWord") Word prototypeMarkWord, - @ConstantParameter("headerSize") int headerSize, - @ConstantParameter("fillContents") boolean fillContents, - @ConstantParameter("locked") boolean locked) { + public static Object initializeArray(Word memory, Word hub, int length, int allocationSize, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter boolean fillContents, + @ConstantParameter boolean locked) { if (locked) { return initializeArray(memory, hub, length, allocationSize, thread().or(biasedLockPattern()), headerSize, fillContents); } else { @@ -135,13 +127,8 @@ public static final int MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH = 0x00FFFFFF; @Snippet - public static Object allocateArrayAndInitialize( - @Parameter("length") int length, - @ConstantParameter("alignment") int alignment, - @ConstantParameter("headerSize") int headerSize, - @ConstantParameter("log2ElementSize") int log2ElementSize, - @ConstantParameter("fillContents") boolean fillContents, - @ConstantParameter("type") ResolvedJavaType type) { + public static Object allocateArrayAndInitialize(int length, @ConstantParameter int alignment, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize, + @ConstantParameter boolean fillContents, @ConstantParameter ResolvedJavaType type) { if (!belowThan(length, MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH)) { probability(DEOPT_PATH_PROBABILITY); // This handles both negative array sizes and very large array sizes @@ -153,9 +140,10 @@ } /** - * Computes the size of the memory chunk allocated for an array. This size accounts for the array - * header size, boy size and any padding after the last element to satisfy object alignment requirements. - * + * Computes the size of the memory chunk allocated for an array. This size accounts for the + * array header size, boy size and any padding after the last element to satisfy object + * alignment requirements. + * * @param length the number of elements in the array * @param alignment the object alignment requirement * @param headerSize the size of the array header @@ -171,10 +159,7 @@ * Calls the runtime stub for implementing MULTIANEWARRAY. */ @Snippet - public static Object newmultiarray( - @Parameter("hub") Word hub, - @ConstantParameter("rank") int rank, - @VarargsParameter("dimensions") int[] dimensions) { + public static Object newmultiarray(Word hub, @ConstantParameter int rank, @VarargsParameter int[] dimensions) { Word dims = DimensionsNode.allocaDimsArray(rank); ExplodeLoopNode.explodeLoop(); for (int i = 0; i < rank; i++) { @@ -184,9 +169,8 @@ } /** - * Maximum size of an object whose body is initialized by a sequence of - * zero-stores to its fields. Larger objects have their bodies initialized - * in a loop. + * Maximum size of an object whose body is initialized by a sequence of zero-stores to its + * fields. Larger objects have their bodies initialized in a loop. */ private static final int MAX_UNROLLED_OBJECT_ZEROING_SIZE = 10 * wordSize(); @@ -217,7 +201,10 @@ */ public static void formatArray(Word hub, int allocationSize, int length, int headerSize, Word memory, Word prototypeMarkWord, boolean fillContents) { memory.writeInt(arrayLengthOffset(), length, ANY_LOCATION); - // store hub last as the concurrent garbage collectors assume length is valid if hub field is not null + /* + * store hub last as the concurrent garbage collectors assume length is valid if hub field + * is not null + */ initializeObjectHeader(memory, prototypeMarkWord, hub); if (fillContents) { for (int offset = headerSize; offset < allocationSize; offset += wordSize()) { @@ -226,27 +213,19 @@ } } - // @formatter:on - - public static class Templates extends AbstractTemplates { + public static class Templates extends AbstractTemplates { - private final ResolvedJavaMethod allocate; - private final ResolvedJavaMethod initializeObject; - private final ResolvedJavaMethod initializeArray; - private final ResolvedJavaMethod allocateArrayAndInitialize; - private final ResolvedJavaMethod newmultiarray; - private final TargetDescription target; + private final SnippetInfo allocate = snippet(NewObjectSnippets.class, "allocate"); + private final SnippetInfo initializeObject = snippet(NewObjectSnippets.class, "initializeObject"); + private final SnippetInfo initializeArray = snippet(NewObjectSnippets.class, "initializeArray"); + private final SnippetInfo allocateArrayAndInitialize = snippet(NewObjectSnippets.class, "allocateArrayAndInitialize"); + private final SnippetInfo newmultiarray = snippet(NewObjectSnippets.class, "newmultiarray"); + private final boolean useTLAB; public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target, boolean useTLAB) { - super(runtime, replacements, target, NewObjectSnippets.class); - this.target = target; + super(runtime, replacements, target); this.useTLAB = useTLAB; - allocate = snippet("allocate", int.class); - initializeObject = snippet("initializeObject", Word.class, Word.class, Word.class, int.class, boolean.class, boolean.class); - initializeArray = snippet("initializeArray", Word.class, Word.class, int.class, int.class, Word.class, int.class, boolean.class, boolean.class); - allocateArrayAndInitialize = snippet("allocateArrayAndInitialize", int.class, int.class, int.class, int.class, boolean.class, ResolvedJavaType.class); - newmultiarray = snippet("newmultiarray", Word.class, int.class, int[].class); } /** @@ -289,9 +268,10 @@ int log2ElementSize = CodeUtil.log2(target.sizeInBytes(elementKind)); if (!useTLAB) { ConstantNode zero = ConstantNode.defaultForKind(target.wordKind, graph); - // value for 'size' doesn't matter as it isn't used since a stub call will be made - // anyway - // for both allocation and initialization - it just needs to be non-null + /* + * value for 'size' doesn't matter as it isn't used since a stub call will be made + * anyway for both allocation and initialization - it just needs to be non-null + */ ConstantNode size = ConstantNode.forInt(-1, graph); InitializeArrayNode initializeNode = graph.add(new InitializeArrayNode(zero, lengthNode, size, arrayType, newArrayNode.fillContents(), newArrayNode.locked())); graph.replaceFixedWithFixed(newArrayNode, initializeNode); @@ -304,12 +284,17 @@ InitializeArrayNode initializeNode = graph.add(new InitializeArrayNode(tlabAllocateNode, lengthNode, sizeNode, arrayType, newArrayNode.fillContents(), newArrayNode.locked())); graph.replaceFixedWithFixed(newArrayNode, initializeNode); } else { - Key key = new Key(allocateArrayAndInitialize).add("alignment", alignment).add("headerSize", headerSize).add("log2ElementSize", log2ElementSize).add("fillContents", - newArrayNode.fillContents()).add("type", arrayType); - Arguments arguments = new Arguments().add("length", lengthNode); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering allocateArrayAndInitialize in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, arguments); - template.instantiate(runtime, newArrayNode, DEFAULT_REPLACER, arguments); + Arguments args = new Arguments(allocateArrayAndInitialize); + args.add("length", lengthNode); + args.addConst("alignment", alignment); + args.addConst("headerSize", headerSize); + args.addConst("log2ElementSize", log2ElementSize); + args.addConst("fillContents", newArrayNode.fillContents()); + args.addConst("type", arrayType); + + SnippetTemplate template = template(args); + Debug.log("Lowering allocateArrayAndInitialize in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, args); + template.instantiate(runtime, newArrayNode, DEFAULT_REPLACER, args); } } @@ -317,11 +302,11 @@ public void lower(TLABAllocateNode tlabAllocateNode, LoweringTool tool) { StructuredGraph graph = (StructuredGraph) tlabAllocateNode.graph(); ValueNode size = tlabAllocateNode.size(); - Key key = new Key(allocate); - Arguments arguments = arguments("size", size); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering fastAllocate in %s: node=%s, template=%s, arguments=%s", graph, tlabAllocateNode, template, arguments); - template.instantiate(runtime, tlabAllocateNode, DEFAULT_REPLACER, arguments); + Arguments args = new Arguments(allocate).add("size", size); + + SnippetTemplate template = template(args); + Debug.log("Lowering fastAllocate in %s: node=%s, template=%s, arguments=%s", graph, tlabAllocateNode, template, args); + template.instantiate(runtime, tlabAllocateNode, DEFAULT_REPLACER, args); } @SuppressWarnings("unused") @@ -331,12 +316,18 @@ assert !type.isArray(); ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, graph); int size = instanceSize(type); - Key key = new Key(initializeObject).add("size", size).add("fillContents", initializeNode.fillContents()).add("locked", initializeNode.locked()); ValueNode memory = initializeNode.memory(); - Arguments arguments = arguments("memory", memory).add("hub", hub).add("prototypeMarkWord", type.prototypeMarkWord()); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering initializeObject in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, arguments); - template.instantiate(runtime, initializeNode, DEFAULT_REPLACER, arguments); + + Arguments args = new Arguments(initializeObject); + args.add("memory", memory); + args.add("hub", hub); + args.add("prototypeMarkWord", type.prototypeMarkWord()); + args.addConst("size", size).addConst("fillContents", initializeNode.fillContents()); + args.addConst("locked", initializeNode.locked()); + + SnippetTemplate template = template(args); + Debug.log("Lowering initializeObject in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, args); + template.instantiate(runtime, initializeNode, DEFAULT_REPLACER, args); } @SuppressWarnings("unused") @@ -348,13 +339,21 @@ ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, graph); Kind elementKind = elementType.getKind(); final int headerSize = HotSpotRuntime.getArrayBaseOffset(elementKind); - Key key = new Key(initializeArray).add("headerSize", headerSize).add("fillContents", initializeNode.fillContents()).add("locked", initializeNode.locked()); ValueNode memory = initializeNode.memory(); - Arguments arguments = arguments("memory", memory).add("hub", hub).add("prototypeMarkWord", type.prototypeMarkWord()).add("allocationSize", initializeNode.allocationSize()).add("length", - initializeNode.length()); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering initializeArray in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, arguments); - template.instantiate(runtime, initializeNode, DEFAULT_REPLACER, arguments); + + Arguments args = new Arguments(initializeArray); + args.add("memory", memory); + args.add("hub", hub); + args.add("length", initializeNode.length()); + args.add("allocationSize", initializeNode.allocationSize()); + args.add("prototypeMarkWord", type.prototypeMarkWord()); + args.addConst("headerSize", headerSize); + args.addConst("fillContents", initializeNode.fillContents()); + args.addConst("locked", initializeNode.locked()); + + SnippetTemplate template = template(args); + Debug.log("Lowering initializeArray in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, args); + template.instantiate(runtime, initializeNode, DEFAULT_REPLACER, args); } @SuppressWarnings("unused") @@ -367,10 +366,12 @@ } HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) newmultiarrayNode.type(); ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, graph); - Key key = new Key(newmultiarray).add("dimensions", vargargs(new int[rank], StampFactory.forKind(Kind.Int))).add("rank", rank); - Arguments arguments = arguments("dimensions", dims).add("hub", hub); - SnippetTemplate template = cache.get(key); - template.instantiate(runtime, newmultiarrayNode, DEFAULT_REPLACER, arguments); + + Arguments args = new Arguments(newmultiarray); + args.add("hub", hub); + args.addConst("rank", rank); + args.addVarargs("dimensions", int.class, StampFactory.forKind(Kind.Int), dims); + template(args).instantiate(runtime, newmultiarrayNode, DEFAULT_REPLACER, args); } private static int instanceSize(HotSpotResolvedObjectType type) { diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java Sat Apr 13 00:33:37 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -31,18 +31,17 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.replacements.Snippet.ConstantParameter; -import com.oracle.graal.replacements.Snippet.Parameter; import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; import com.oracle.graal.replacements.SnippetTemplate.Arguments; -import com.oracle.graal.replacements.SnippetTemplate.Key; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; +import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*; public class WriteBarrierSnippets implements Snippets { @Snippet - public static void serialArrayWriteBarrier(@Parameter("object") Object obj, @Parameter("location") Object location, @ConstantParameter("usePrecise") boolean usePrecise) { + public static void serialArrayWriteBarrier(Object obj, Object location, @ConstantParameter boolean usePrecise) { Object object = FixedValueAnchorNode.getObject(obj); Pointer oop; if (usePrecise) { @@ -62,7 +61,7 @@ } @Snippet - public static void serialArrayRangeWriteBarrier(@Parameter("object") Object object, @Parameter("startIndex") int startIndex, @Parameter("length") int length) { + public static void serialArrayRangeWriteBarrier(Object object, int startIndex, int length) { Object dest = FixedValueAnchorNode.getObject(object); int cardShift = cardTableShift(); long cardStart = cardTableStart(); @@ -77,37 +76,29 @@ } } - public static class Templates extends AbstractTemplates { + public static class Templates extends AbstractTemplates { - private final ResolvedJavaMethod serialArrayWriteBarrier; - private final ResolvedJavaMethod serialArrayRangeWriteBarrier; + private final SnippetInfo serialArrayWriteBarrier = snippet(WriteBarrierSnippets.class, "serialArrayWriteBarrier"); + private final SnippetInfo serialArrayRangeWriteBarrier = snippet(WriteBarrierSnippets.class, "serialArrayRangeWriteBarrier"); public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) { - super(runtime, replacements, target, WriteBarrierSnippets.class); - serialArrayWriteBarrier = snippet("serialArrayWriteBarrier", Object.class, Object.class, boolean.class); - serialArrayRangeWriteBarrier = snippet("serialArrayRangeWriteBarrier", Object.class, int.class, int.class); + super(runtime, replacements, target); } public void lower(SerialWriteBarrier arrayWriteBarrier, @SuppressWarnings("unused") LoweringTool tool) { - ResolvedJavaMethod method = serialArrayWriteBarrier; - Key key = new Key(method); - key.add("usePrecise", arrayWriteBarrier.usePrecise()); - Arguments arguments = new Arguments(); - arguments.add("object", arrayWriteBarrier.getObject()); - arguments.add("location", arrayWriteBarrier.getLocation()); - SnippetTemplate template = cache.get(key); - template.instantiate(runtime, arrayWriteBarrier, DEFAULT_REPLACER, arguments); + Arguments args = new Arguments(serialArrayWriteBarrier); + args.add("obj", arrayWriteBarrier.getObject()); + args.add("location", arrayWriteBarrier.getLocation()); + args.addConst("usePrecise", arrayWriteBarrier.usePrecise()); + template(args).instantiate(runtime, arrayWriteBarrier, DEFAULT_REPLACER, args); } public void lower(SerialArrayRangeWriteBarrier arrayRangeWriteBarrier, @SuppressWarnings("unused") LoweringTool tool) { - ResolvedJavaMethod method = serialArrayRangeWriteBarrier; - Key key = new Key(method); - Arguments arguments = new Arguments(); - arguments.add("object", arrayRangeWriteBarrier.getObject()); - arguments.add("startIndex", arrayRangeWriteBarrier.getStartIndex()); - arguments.add("length", arrayRangeWriteBarrier.getLength()); - SnippetTemplate template = cache.get(key); - template.instantiate(runtime, arrayRangeWriteBarrier, DEFAULT_REPLACER, arguments); + Arguments args = new Arguments(serialArrayRangeWriteBarrier); + args.add("object", arrayRangeWriteBarrier.getObject()); + args.add("startIndex", arrayRangeWriteBarrier.getStartIndex()); + args.add("length", arrayRangeWriteBarrier.getLength()); + template(args).instantiate(runtime, arrayRangeWriteBarrier, DEFAULT_REPLACER, args); } } } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Sat Apr 13 00:33:37 2013 +0200 @@ -27,15 +27,15 @@ import static com.oracle.graal.hotspot.stubs.NewInstanceStub.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.Snippet.*; -import com.oracle.graal.replacements.SnippetTemplate.*; +import com.oracle.graal.replacements.Snippet.ConstantParameter; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; import com.oracle.graal.word.*; /** @@ -47,14 +47,19 @@ public class NewArrayStub extends Stub { public NewArrayStub(final HotSpotRuntime runtime, Replacements replacements, TargetDescription target, HotSpotRuntimeCallTarget linkage) { - super(runtime, replacements, target, linkage); + super(runtime, replacements, target, linkage, "newArray"); } @Override - protected void populateKey(Key key) { + protected Arguments makeArguments(SnippetInfo stub) { HotSpotResolvedObjectType intArrayType = (HotSpotResolvedObjectType) runtime.lookupJavaType(int[].class); - Constant intArrayHub = intArrayType.klass(); - key.add("intArrayHub", intArrayHub).add("log", Boolean.getBoolean("graal.logNewArrayStub")); + + Arguments args = new Arguments(stub); + args.add("hub", null); + args.add("length", null); + args.addConst("intArrayHub", intArrayType.klass()); + args.addConst("log", Boolean.getBoolean("graal.logNewArrayStub")); + return args; } /** @@ -67,7 +72,7 @@ * @param log specifies if logging is enabled */ @Snippet - private static Object newArray(@Parameter("hub") Word hub, @Parameter("length") int length, @ConstantParameter("intArrayHub") Word intArrayHub, @ConstantParameter("log") boolean log) { + private static Object newArray(Word hub, int length, @ConstantParameter Word intArrayHub, @ConstantParameter boolean log) { int layoutHelper = hub.readInt(layoutHelperOffset(), FINAL_LOCATION); int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask(); int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift()) & layoutHelperHeaderSizeMask(); diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Sat Apr 13 00:33:37 2013 +0200 @@ -36,8 +36,8 @@ import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.Snippet.ConstantParameter; import com.oracle.graal.replacements.Snippet.Fold; -import com.oracle.graal.replacements.Snippet.Parameter; -import com.oracle.graal.replacements.SnippetTemplate.Key; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; import com.oracle.graal.word.*; /** @@ -49,14 +49,18 @@ public class NewInstanceStub extends Stub { public NewInstanceStub(final HotSpotRuntime runtime, Replacements replacements, TargetDescription target, HotSpotRuntimeCallTarget linkage) { - super(runtime, replacements, target, linkage); + super(runtime, replacements, target, linkage, "newInstance"); } @Override - protected void populateKey(Key key) { + protected Arguments makeArguments(SnippetInfo stub) { HotSpotResolvedObjectType intArrayType = (HotSpotResolvedObjectType) runtime.lookupJavaType(int[].class); - Constant intArrayHub = intArrayType.klass(); - key.add("intArrayHub", intArrayHub).add("log", Boolean.getBoolean("graal.logNewInstanceStub")); + + Arguments args = new Arguments(stub); + args.add("hub", null); + args.addConst("intArrayHub", intArrayType.klass()); + args.addConst("log", Boolean.getBoolean("graal.logNewInstanceStub")); + return args; } /** @@ -67,7 +71,7 @@ * @param intArrayHub the hub for {@code int[].class} */ @Snippet - private static Object newInstance(@Parameter("hub") Word hub, @ConstantParameter("intArrayHub") Word intArrayHub, @ConstantParameter("log") boolean log) { + private static Object newInstance(Word hub, @ConstantParameter Word intArrayHub, @ConstantParameter boolean log) { int sizeInBytes = hub.readInt(klassInstanceSizeOffset(), FINAL_LOCATION); if (!forceSlowPath() && inlineContiguousAllocationSupported()) { if (hub.readInt(klassStateOffset(), CLASS_STATE_LOCATION) == klassStateFullyInitialized()) { diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Sat Apr 13 00:33:37 2013 +0200 @@ -22,9 +22,6 @@ */ package com.oracle.graal.hotspot.stubs; -import static java.lang.reflect.Modifier.*; - -import java.lang.reflect.*; import java.util.concurrent.*; import com.oracle.graal.api.code.*; @@ -42,7 +39,8 @@ import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.Snippet.ConstantParameter; import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; -import com.oracle.graal.replacements.SnippetTemplate.Key; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; /** * Base class for implementing some low level code providing the out-of-line slow path for a @@ -56,7 +54,7 @@ /** * The method implementing the stub. */ - protected final HotSpotResolvedJavaMethod stubMethod; + protected final SnippetInfo stubInfo; /** * The linkage information for the stub. @@ -69,15 +67,14 @@ protected InstalledCode stubCode; /** - * Creates a new stub container. The new stub still needs to be {@linkplain #getAddress(Backend) - * installed}. + * Creates a new stub container. The new stub still needs to be + * {@linkplain #getAddress(Backend) installed}. * * @param linkage linkage details for a call to the stub */ - @SuppressWarnings("unchecked") - public Stub(HotSpotRuntime runtime, Replacements replacements, TargetDescription target, HotSpotRuntimeCallTarget linkage) { - super(runtime, replacements, target, null); - stubMethod = findStubMethod(runtime, getClass()); + public Stub(HotSpotRuntime runtime, Replacements replacements, TargetDescription target, HotSpotRuntimeCallTarget linkage, String methodName) { + super(runtime, replacements, target); + this.stubInfo = snippet(getClass(), methodName); this.linkage = linkage; } @@ -85,7 +82,7 @@ /** * Adds the {@linkplain ConstantParameter constant} arguments of this stub. */ - protected abstract void populateKey(Key key); + protected abstract Arguments makeArguments(SnippetInfo stub); protected HotSpotRuntime runtime() { return (HotSpotRuntime) runtime; @@ -95,7 +92,7 @@ * Gets the method implementing this stub. */ public ResolvedJavaMethod getMethod() { - return stubMethod; + return stubInfo.getMethod(); } public HotSpotRuntimeCallTarget getLinkage() { @@ -109,25 +106,22 @@ */ public synchronized long getAddress(Backend backend) { if (stubCode == null) { - StructuredGraph graph = replacements.getSnippet(stubMethod); - - Key key = new Key(stubMethod); - populateKey(key); - SnippetTemplate template = cache.get(key); - graph = template.copySpecializedGraph(); + Arguments args = makeArguments(stubInfo); + SnippetTemplate template = template(args); + StructuredGraph graph = template.copySpecializedGraph(); PhasePlan phasePlan = new PhasePlan(); GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL); phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); - final CompilationResult compResult = GraalCompiler.compileMethod(runtime(), replacements, backend, runtime().getTarget(), stubMethod, graph, null, phasePlan, - OptimisticOptimizations.ALL, new SpeculationLog()); + final CompilationResult compResult = GraalCompiler.compileMethod(runtime(), replacements, backend, runtime().getTarget(), getMethod(), graph, null, phasePlan, OptimisticOptimizations.ALL, + new SpeculationLog()); - stubCode = Debug.scope("CodeInstall", new Object[]{runtime(), stubMethod}, new Callable() { + stubCode = Debug.scope("CodeInstall", new Object[]{runtime(), getMethod()}, new Callable() { @Override public InstalledCode call() { - InstalledCode installedCode = runtime().addMethod(stubMethod, compResult); - assert installedCode != null : "error installing stub " + stubMethod; + InstalledCode installedCode = runtime().addMethod(getMethod(), compResult); + assert installedCode != null : "error installing stub " + getMethod(); if (Debug.isDumpEnabled()) { Debug.dump(new Object[]{compResult, installedCode}, "After code installation"); } @@ -135,24 +129,8 @@ } }); - assert stubCode != null : "error installing stub " + stubMethod; + assert stubCode != null : "error installing stub " + getMethod(); } return stubCode.getStart(); } - - /** - * Finds the static method annotated with {@link Snippet} in a given class of which there must - * be exactly one. - */ - private static HotSpotResolvedJavaMethod findStubMethod(HotSpotRuntime runtime, Class stubClass) { - HotSpotResolvedJavaMethod m = null; - for (Method candidate : stubClass.getDeclaredMethods()) { - if (isStatic(candidate.getModifiers()) && candidate.getAnnotation(Snippet.class) != null) { - assert m == null : "more than one method annotated with @" + Snippet.class.getSimpleName() + " in " + stubClass; - m = (HotSpotResolvedJavaMethod) runtime.lookupJavaMethod(candidate); - } - } - assert m != null : "no static method annotated with @" + Snippet.class.getSimpleName() + " in " + stubClass; - return m; - } } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java Sat Apr 13 00:33:37 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, 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 @@ -23,6 +23,7 @@ package com.oracle.graal.java; import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; public class GraphBuilderConfiguration { @@ -30,6 +31,13 @@ private final boolean omitAllExceptionEdges; private ResolvedJavaType[] skippedExceptionTypes; + /** + * When the graph builder is in eager infopoint mode, it inserts {@link InfopointNode}s in + * places where no safepoints would be inserted: inlining boundaries, and line number switches. + * This is relevant when code is to be generated for native, machine-code level debugging. + */ + private boolean eagerInfopointMode; + protected GraphBuilderConfiguration(boolean eagerResolving, boolean omitAllExceptionEdges) { this.eagerResolving = eagerResolving; this.omitAllExceptionEdges = omitAllExceptionEdges; @@ -39,6 +47,10 @@ this.skippedExceptionTypes = skippedExceptionTypes; } + public void setEagerInfopointMode(boolean eagerInfopointMode) { + this.eagerInfopointMode = eagerInfopointMode; + } + public ResolvedJavaType[] getSkippedExceptionTypes() { return skippedExceptionTypes; } @@ -51,6 +63,10 @@ return omitAllExceptionEdges; } + public boolean eagerInfopointMode() { + return eagerInfopointMode; + } + public static GraphBuilderConfiguration getDefault() { return new GraphBuilderConfiguration(false, false); } @@ -64,9 +80,9 @@ } /** - * Returns {@code true} if it is an error for a class/field/method resolution to fail. - * The default is the same result as returned by {@link #eagerResolving()}. - * However, it may be overridden to allow failure even when {@link #eagerResolving} is {@code true}. + * Returns {@code true} if it is an error for a class/field/method resolution to fail. The + * default is the same result as returned by {@link #eagerResolving()}. However, it may be + * overridden to allow failure even when {@link #eagerResolving} is {@code true}. */ public boolean unresolvedIsError() { return eagerResolving; diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Sat Apr 13 00:33:37 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2013, 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 @@ -75,6 +75,10 @@ */ public static final int TRACELEVEL_STATE = 2; + private LineNumberTable lnt; + private int previousLineNumber; + private int currentLineNumber; + protected StructuredGraph currentGraph; private final MetaAccessProvider runtime; @@ -141,6 +145,10 @@ @Override protected void run(StructuredGraph graph) { method = graph.method(); + if (graphBuilderConfig.eagerInfopointMode()) { + lnt = method.getLineNumberTable(); + previousLineNumber = -1; + } entryBCI = graph.getEntryBCI(); profilingInfo = method.getProfilingInfo(); assert method.getCode() != null : "method must contain bytecodes: " + method; @@ -193,6 +201,13 @@ } frameState.clearNonLiveLocals(blockMap.startBlock.localsLiveIn); + if (graphBuilderConfig.eagerInfopointMode()) { + ((StateSplit) lastInstr).setStateAfter(frameState.create(0)); + InfopointNode ipn = currentGraph.add(new InfopointNode(InfopointReason.METHOD_START)); + lastInstr.setNext(ipn); + lastInstr = ipn; + } + // finish the start block ((StateSplit) lastInstr).setStateAfter(frameState.create(0)); @@ -1056,7 +1071,7 @@ private void genInvokeDynamic(JavaMethod target) { if (target instanceof ResolvedJavaMethod) { - Object appendix = constantPool.lookupAppendix(stream.readCPI4()); + Object appendix = constantPool.lookupAppendix(stream.readCPI4(), Bytecodes.INVOKEDYNAMIC); if (appendix != null) { frameState.apush(ConstantNode.forObject(appendix, runtime, currentGraph)); } @@ -1069,8 +1084,20 @@ private void genInvokeVirtual(JavaMethod target) { if (target instanceof ResolvedJavaMethod) { - ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(true), target.getSignature().getParameterCount(true)); - genInvokeIndirect(InvokeKind.Virtual, (ResolvedJavaMethod) target, args); + // Special handling for runtimes that rewrite an invocation of MethodHandle.invoke(...) + // or MethodHandle.invokeExact(...) to a static adapter. HotSpot does this - see + // https://wikis.oracle.com/display/HotSpotInternals/Method+handles+and+invokedynamic + boolean hasReceiver = !isStatic(((ResolvedJavaMethod) target).getModifiers()); + Object appendix = constantPool.lookupAppendix(stream.readCPI(), Bytecodes.INVOKEVIRTUAL); + if (appendix != null) { + frameState.apush(ConstantNode.forObject(appendix, runtime, currentGraph)); + } + ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(hasReceiver), target.getSignature().getParameterCount(hasReceiver)); + if (hasReceiver) { + genInvokeIndirect(InvokeKind.Virtual, (ResolvedJavaMethod) target, args); + } else { + appendInvoke(InvokeKind.Static, (ResolvedJavaMethod) target, args); + } } else { handleUnresolvedInvoke(target, InvokeKind.Virtual); } @@ -1506,7 +1533,7 @@ } private void processBlock(Block block) { - // Ignore blocks that have no predecessors by the time it their bytecodes are parsed + // Ignore blocks that have no predecessors by the time their bytecodes are parsed if (block == null || block.firstInstruction == null) { Debug.log("Ignoring block %s", block); return; @@ -1587,6 +1614,12 @@ } ReturnNode returnNode = currentGraph.add(new ReturnNode(x)); + if (graphBuilderConfig.eagerInfopointMode()) { + InfopointNode ipn = currentGraph.add(new InfopointNode(InfopointReason.METHOD_END)); + ipn.setStateAfter(frameState.create(FrameState.AFTER_BCI)); + append(ipn); + } + append(returnNode); } @@ -1697,6 +1730,16 @@ BytecodesParsed.add(block.endBci - bci); while (bci < endBCI) { + if (graphBuilderConfig.eagerInfopointMode() && lnt != null) { + currentLineNumber = lnt.getLineNumber(bci); + if (currentLineNumber != previousLineNumber) { + InfopointNode ipn = currentGraph.add(new InfopointNode(InfopointReason.LINE_NUMBER)); + ipn.setStateAfter(frameState.create(bci)); + append(ipn); + previousLineNumber = currentLineNumber; + } + } + // read the opcode int opcode = stream.currentBC(); traceState(); diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXArithmetic.java --- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXArithmetic.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXArithmetic.java Sat Apr 13 00:33:37 2013 +0200 @@ -36,9 +36,9 @@ public enum PTXArithmetic { IADD, ISUB, IMUL, IDIV, IDIVREM, IREM, IUDIV, IUREM, IAND, IOR, IXOR, ISHL, ISHR, IUSHR, LADD, LSUB, LMUL, LDIV, LDIVREM, LREM, LUDIV, LUREM, LAND, LOR, LXOR, LSHL, LSHR, LUSHR, - FADD, FSUB, FMUL, FDIV, FAND, FOR, FXOR, - DADD, DSUB, DMUL, DDIV, DAND, DOR, DXOR, - INEG, LNEG, + FADD, FSUB, FMUL, FDIV, FREM, FAND, FOR, FXOR, + DADD, DSUB, DMUL, DDIV, DREM, DAND, DOR, DXOR, + INEG, LNEG, FNEG, DNEG, I2L, L2I, I2B, I2C, I2S, F2D, D2F, I2F, I2D, F2I, D2I, @@ -46,6 +46,47 @@ MOV_I2F, MOV_L2D, MOV_F2I, MOV_D2L; + /** + * Unary operation with separate source and destination operand. + */ + public static class Unary2Op extends PTXLIRInstruction { + @Opcode private final PTXArithmetic opcode; + @Def({REG}) protected AllocatableValue result; + @Use({REG, STACK}) protected AllocatableValue x; + + public Unary2Op(PTXArithmetic opcode, AllocatableValue result, AllocatableValue x) { + this.opcode = opcode; + this.result = result; + this.x = x; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { + PTXMove.move(tasm, masm, result, x); + emit(tasm, masm, opcode, result, x, null); + } + } + + /** + * Unary operation with single operand for source and destination. + */ + public static class Unary1Op extends PTXLIRInstruction { + @Opcode private final PTXArithmetic opcode; + @Def({REG, HINT}) protected AllocatableValue result; + @Use({REG, STACK}) protected AllocatableValue x; + + public Unary1Op(PTXArithmetic opcode, AllocatableValue result, AllocatableValue x) { + this.opcode = opcode; + this.result = result; + this.x = x; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { + emit(tasm, masm, opcode, result); + } + } + public static class Op1Reg extends PTXLIRInstruction { @Opcode private final PTXArithmetic opcode; @Def({REG, HINT}) protected Value result; @@ -213,23 +254,70 @@ } } - - @SuppressWarnings("unused") - protected static void emit(TargetMethodAssembler tasm, PTXAssembler masm, PTXArithmetic opcode, Value result) { + protected static void emit(@SuppressWarnings("unused") TargetMethodAssembler tasm, + PTXAssembler masm, PTXArithmetic opcode, Value result) { switch (opcode) { - default: throw GraalInternalError.shouldNotReachHere(); + case L2I: masm.and_b32(asIntReg(result), asIntReg(result), 0xFFFFFFFF); break; + case I2C: masm.and_b16(asIntReg(result), asIntReg(result), (short) 0xFFFF); break; + default: + throw GraalInternalError.shouldNotReachHere("missing: " + opcode); } } public static void emit(TargetMethodAssembler tasm, PTXAssembler masm, PTXArithmetic opcode, Value dst, Value src, LIRFrameState info) { int exceptionOffset = -1; if (isRegister(src)) { - Register a = asIntReg(src); - Register d = asIntReg(dst); switch (opcode) { - case INEG: masm.neg_s32(d, a); break; + case INEG: + masm.neg_s32(asIntReg(dst), asIntReg(src)); + break; + case I2L: + masm.cvt_s64_s32(asLongReg(dst), asIntReg(src)); + break; + case I2C: + masm.cvt_b16_s32(asIntReg(dst), asIntReg(src)); + break; + case I2B: + masm.cvt_s8_s32(asIntReg(dst), asIntReg(src)); + break; + case I2F: + masm.cvt_f32_s32(asFloatReg(dst), asIntReg(src)); + break; + case I2D: + masm.cvt_f64_s32(asDoubleReg(dst), asIntReg(src)); + break; + case FNEG: + masm.neg_f32(asFloatReg(dst), asFloatReg(src)); + break; + case DNEG: + masm.neg_f64(asDoubleReg(dst), asDoubleReg(src)); + break; + case F2I: + masm.cvt_s32_f32(asIntReg(dst), asFloatReg(src)); + break; + case F2L: + masm.cvt_s64_f32(asLongReg(dst), asFloatReg(src)); + break; + case F2D: + masm.cvt_f64_f32(asDoubleReg(dst), asFloatReg(src)); + break; + case D2I: + masm.cvt_s32_f64(asIntReg(dst), asDoubleReg(src)); + break; + case D2L: + masm.cvt_s64_f64(asLongReg(dst), asDoubleReg(src)); + break; + case D2F: + masm.cvt_f32_f64(asFloatReg(dst), asDoubleReg(src)); + break; + case LSHL: + masm.shl_s64(asLongReg(dst), asLongReg(dst), asIntReg(src)); + break; + case LSHR: + masm.shr_s64(asLongReg(dst), asLongReg(dst), asIntReg(src)); + break; default: - throw GraalInternalError.shouldNotReachHere(); + throw GraalInternalError.shouldNotReachHere("missing: " + opcode); } } else if (isConstant(src)) { switch (opcode) { @@ -252,33 +340,74 @@ public static void emit(TargetMethodAssembler tasm, PTXAssembler masm, PTXArithmetic opcode, Value dst, Value src1, Value src2, LIRFrameState info) { int exceptionOffset = -1; if (isConstant(src1)) { - int a = tasm.asIntConst(src1); - Register b = asIntReg(src2); - Register d = asIntReg(dst); switch (opcode) { - case ISUB: masm.sub_s32(d, a, b); break; - case IAND: masm.and_b32(d, b, a); break; - default: throw GraalInternalError.shouldNotReachHere(); + case ISUB: masm.sub_s32(asIntReg(dst), tasm.asIntConst(src1), asIntReg(src2)); break; + case IAND: masm.and_b32(asIntReg(dst), asIntReg(src2), tasm.asIntConst(src1)); break; + case IDIV: masm.div_s32(asIntReg(dst), tasm.asIntConst(src1), asIntReg(src2)); break; + case FSUB: masm.sub_f32(asFloatReg(dst), tasm.asFloatConst(src1), asFloatReg(src2)); break; + case FDIV: masm.div_f32(asFloatReg(dst), tasm.asFloatConst(src1), asFloatReg(src2)); break; + case DSUB: masm.sub_f64(asDoubleReg(dst), tasm.asDoubleConst(src1), asDoubleReg(src2)); break; + case DDIV: masm.div_f64(asDoubleReg(dst), tasm.asDoubleConst(src1), asDoubleReg(src2)); break; + default: + throw GraalInternalError.shouldNotReachHere(); } } else if (isConstant(src2)) { - Register a = asIntReg(src1); - int b = tasm.asIntConst(src2); - Register d = asIntReg(dst); switch (opcode) { - case IADD: masm.add_s32(d, a, b); break; - case IAND: masm.and_b32(d, a, b); break; - case IUSHR: masm.shr_u32(d, a, b); break; - default: throw GraalInternalError.shouldNotReachHere(); + case IADD: masm.add_s32(asIntReg(dst), asIntReg(src1), tasm.asIntConst(src2)); break; + case ISUB: masm.sub_s32(asIntReg(dst), asIntReg(src1), tasm.asIntConst(src2)); break; + case IMUL: masm.mul_s32(asIntReg(dst), asIntReg(src1), tasm.asIntConst(src2)); break; + case IAND: masm.and_b32(asIntReg(dst), asIntReg(src1), tasm.asIntConst(src2)); break; + case ISHL: masm.shl_s32(asIntReg(dst), asIntReg(src1), tasm.asIntConst(src2)); break; + case ISHR: masm.shr_s32(asIntReg(dst), asIntReg(src1), tasm.asIntConst(src2)); break; + case IUSHR: masm.shr_u32(asIntReg(dst), asIntReg(src1), tasm.asIntConst(src2)); break; + case IXOR: masm.xor_b32(asIntReg(dst), asIntReg(src1), tasm.asIntConst(src2)); break; + case LXOR: masm.xor_b64(asLongReg(dst), asLongReg(src1), tasm.asLongConst(src2)); break; + case LUSHR: masm.shr_u64(asLongReg(dst), asLongReg(src1), tasm.asLongConst(src2)); break; + case FADD: masm.add_f32(asFloatReg(dst), asFloatReg(src1), tasm.asFloatConst(src2)); break; + case FMUL: masm.mul_f32(asFloatReg(dst), asFloatReg(src1), tasm.asFloatConst(src2)); break; + case FDIV: masm.div_f32(asFloatReg(dst), asFloatReg(src1), tasm.asFloatConst(src2)); break; + case DADD: masm.add_f64(asDoubleReg(dst), asDoubleReg(src1), tasm.asDoubleConst(src2)); break; + case DMUL: masm.mul_f64(asDoubleReg(dst), asDoubleReg(src1), tasm.asDoubleConst(src2)); break; + case DDIV: masm.div_f64(asDoubleReg(dst), asDoubleReg(src1), tasm.asDoubleConst(src2)); break; + default: + throw GraalInternalError.shouldNotReachHere(); } } else { - Register a = asIntReg(src1); - Register b = asIntReg(src2); - Register d = asIntReg(dst); switch (opcode) { - case IADD: masm.add_s32(d, a, b); break; - case ISUB: masm.sub_s32(d, a, b); break; - case IMUL: masm.mul_s32(d, a, b); break; - default: throw GraalInternalError.shouldNotReachHere(); + case IADD: masm.add_s32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break; + case ISUB: masm.sub_s32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break; + case IMUL: masm.mul_s32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break; + case IDIV: masm.div_s32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break; + case IAND: masm.and_b32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break; + case IOR: masm.or_b32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break; + case IXOR: masm.xor_b32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break; + case ISHL: masm.shl_s32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break; + case ISHR: masm.shr_s32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break; + case IUSHR: masm.shr_u32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break; + case IREM: masm.rem_s32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break; + case LADD: masm.add_s64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break; + case LSUB: masm.sub_s64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break; + case LMUL: masm.mul_s64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break; + case LDIV: masm.div_s64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break; + case LAND: masm.and_b64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break; + case LOR: masm.or_b64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break; + case LXOR: masm.xor_b64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break; + case LSHL: masm.shl_s64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break; + case LSHR: masm.shr_s64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break; + case LUSHR: masm.shr_u64(asLongReg(dst), asLongReg(src1), asIntReg(src2)); break; + case LREM: masm.rem_s64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break; + case FADD: masm.add_f32(asFloatReg(dst), asFloatReg(src1), asFloatReg(src2)); break; + case FSUB: masm.sub_f32(asFloatReg(dst), asFloatReg(src1), asFloatReg(src2)); break; + case FMUL: masm.mul_f32(asFloatReg(dst), asFloatReg(src1), asFloatReg(src2)); break; + case FDIV: masm.div_f32(asFloatReg(dst), asFloatReg(src1), asFloatReg(src2)); break; + case FREM: masm.div_f32(asFloatReg(dst), asFloatReg(src1), asFloatReg(src2)); break; + case DADD: masm.add_f64(asDoubleReg(dst), asDoubleReg(src1), asDoubleReg(src2)); break; + case DSUB: masm.sub_f64(asDoubleReg(dst), asDoubleReg(src1), asDoubleReg(src2)); break; + case DMUL: masm.mul_f64(asDoubleReg(dst), asDoubleReg(src1), asDoubleReg(src2)); break; + case DDIV: masm.div_f64(asDoubleReg(dst), asDoubleReg(src1), asDoubleReg(src2)); break; + case DREM: masm.div_f64(asDoubleReg(dst), asDoubleReg(src1), asDoubleReg(src2)); break; + default: + throw GraalInternalError.shouldNotReachHere("missing: " + opcode); } } @@ -289,9 +418,11 @@ } private static void verifyKind(PTXArithmetic opcode, Value result, Value x, Value y) { - assert (opcode.name().startsWith("I") && result.getKind() == Kind.Int && x.getKind().getStackKind() == Kind.Int && y.getKind().getStackKind() == Kind.Int) + if (((opcode.name().startsWith("I") && result.getKind() == Kind.Int && x.getKind().getStackKind() == Kind.Int && y.getKind().getStackKind() == Kind.Int) || (opcode.name().startsWith("L") && result.getKind() == Kind.Long && x.getKind() == Kind.Long && y.getKind() == Kind.Long) || (opcode.name().startsWith("F") && result.getKind() == Kind.Float && x.getKind() == Kind.Float && y.getKind() == Kind.Float) - || (opcode.name().startsWith("D") && result.getKind() == Kind.Double && x.getKind() == Kind.Double && y.getKind() == Kind.Double); + || (opcode.name().startsWith("D") && result.getKind() == Kind.Double && x.getKind() == Kind.Double && y.getKind() == Kind.Double)) == false) { + throw GraalInternalError.shouldNotReachHere("opcode: " + opcode.name() + " x: " + x.getKind() + " y: " + y.getKind()); + } } } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXCompare.java --- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXCompare.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXCompare.java Sat Apr 13 00:33:37 2013 +0200 @@ -65,11 +65,15 @@ public static void emit(TargetMethodAssembler tasm, PTXAssembler masm, PTXCompare opcode, Condition condition, Value x, Value y) { if (isConstant(x)) { - int a = tasm.asIntConst(x); - Register b = asIntReg(y); switch (opcode) { case ICMP: - emitCompareConstReg(masm, condition, a, b); + emitCompareConstReg(masm, condition, tasm.asIntConst(x), asIntReg(y)); + break; + case FCMP: + emitCompareConstReg(masm, condition, tasm.asFloatConst(x), asFloatReg(y)); + break; + case DCMP: + emitCompareConstReg(masm, condition, tasm.asDoubleConst(x), asDoubleReg(y)); break; default: throw GraalInternalError.shouldNotReachHere(); @@ -101,18 +105,75 @@ throw GraalInternalError.shouldNotReachHere(); } } else { - Register a = asIntReg(x); - Register b = asIntReg(y); switch (opcode) { case ICMP: - emitCompareRegReg(masm, condition, a, b); + emitCompareRegReg(masm, condition, asIntReg(x), asIntReg(y)); + break; + case LCMP: + emitCompareRegReg(masm, condition, asLongReg(x), asLongReg(y)); + break; + case FCMP: + emitCompareRegReg(masm, condition, asFloatReg(x), asFloatReg(y)); + break; + case DCMP: + emitCompareRegReg(masm, condition, asDoubleReg(x), asDoubleReg(y)); break; default: - throw GraalInternalError.shouldNotReachHere(); + throw GraalInternalError.shouldNotReachHere("missing: " + opcode); } } } + private static void emitCompareConstReg(PTXAssembler masm, Condition condition, float a, Register b) { + switch (condition) { + case EQ: + masm.setp_eq_f32(a, b); + break; + case NE: + masm.setp_ne_f32(a, b); + break; + case LT: + masm.setp_lt_f32(a, b); + break; + case LE: + masm.setp_le_f32(a, b); + break; + case GT: + masm.setp_gt_f32(a, b); + break; + case GE: + masm.setp_ge_f32(a, b); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + private static void emitCompareConstReg(PTXAssembler masm, Condition condition, double a, Register b) { + switch (condition) { + case EQ: + masm.setp_eq_f64(a, b); + break; + case NE: + masm.setp_ne_f64(a, b); + break; + case LT: + masm.setp_lt_f64(a, b); + break; + case LE: + masm.setp_le_f64(a, b); + break; + case GT: + masm.setp_gt_f64(a, b); + break; + case GE: + masm.setp_ge_f64(a, b); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + private static void emitCompareConstReg(PTXAssembler masm, Condition condition, int a, Register b) { switch (condition) { case EQ: diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java --- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java Sat Apr 13 00:33:37 2013 +0200 @@ -22,14 +22,28 @@ */ package com.oracle.graal.lir.ptx; +import static com.oracle.graal.api.code.ValueUtil.asIntReg; +import static com.oracle.graal.api.code.ValueUtil.asLongReg; +import static com.oracle.graal.api.code.ValueUtil.asObjectReg; import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.asm.*; -import com.oracle.graal.asm.ptx.*; -import com.oracle.graal.lir.*; -import com.oracle.graal.lir.asm.*; -import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.api.code.Register; +import com.oracle.graal.api.code.CompilationResult.JumpTable; +import com.oracle.graal.api.meta.Constant; +import com.oracle.graal.api.meta.Kind; +import com.oracle.graal.api.meta.Value; +import com.oracle.graal.asm.Buffer; +import com.oracle.graal.asm.Label; +import com.oracle.graal.asm.NumUtil; +import com.oracle.graal.asm.ptx.AbstractPTXAssembler; +import com.oracle.graal.asm.ptx.PTXAssembler; +import com.oracle.graal.graph.GraalInternalError; +import com.oracle.graal.lir.LabelRef; +import com.oracle.graal.lir.StandardOp; +import com.oracle.graal.lir.StandardOp.FallThroughOp; +import com.oracle.graal.lir.Variable; +import com.oracle.graal.lir.asm.TargetMethodAssembler; +import com.oracle.graal.nodes.calc.Condition; public class PTXControlFlow { @@ -64,7 +78,7 @@ public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { masm.at(); Label l = destination.label(); - l.addPatchAt(tasm.asm.codeBuffer.position()); + // l.addPatchAt(tasm.asm.codeBuffer.position()); String target = l.isBound() ? "L" + l.toString() : AbstractPTXAssembler.UNBOUND_TARGET; masm.bra(target); } @@ -80,4 +94,176 @@ condition = condition.negate(); } } + + @SuppressWarnings("unused") + public static class CondMoveOp extends PTXLIRInstruction { + @Def({REG, HINT}) protected Value result; + @Alive({REG}) protected Value trueValue; + @Use({REG, STACK, CONST}) protected Value falseValue; + private final Condition condition; + + public CondMoveOp(Variable result, Condition condition, Variable trueValue, Value falseValue) { + this.result = result; + this.condition = condition; + this.trueValue = trueValue; + this.falseValue = falseValue; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { + // cmove(tasm, masm, result, false, condition, false, trueValue, falseValue); + // see 8.3 Predicated Execution p. 61 of PTX ISA 3.1 + throw new InternalError("NYI"); + } + } + + @SuppressWarnings("unused") + public static class FloatCondMoveOp extends PTXLIRInstruction { + @Def({REG}) protected Value result; + @Alive({REG}) protected Value trueValue; + @Alive({REG}) protected Value falseValue; + private final Condition condition; + private final boolean unorderedIsTrue; + + public FloatCondMoveOp(Variable result, Condition condition, boolean unorderedIsTrue, Variable trueValue, Variable falseValue) { + this.result = result; + this.condition = condition; + this.unorderedIsTrue = unorderedIsTrue; + this.trueValue = trueValue; + this.falseValue = falseValue; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { + // cmove(tasm, masm, result, true, condition, unorderedIsTrue, trueValue, falseValue); + // see 8.3 Predicated Execution p. 61 of PTX ISA 3.1 + throw new InternalError("NYI"); + } + } + + public static class SequentialSwitchOp extends PTXLIRInstruction implements FallThroughOp { + @Use({CONST}) protected Constant[] keyConstants; + private final LabelRef[] keyTargets; + private LabelRef defaultTarget; + @Alive({REG}) protected Value key; + @Temp({REG, ILLEGAL}) protected Value scratch; + + public SequentialSwitchOp(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, + Value key, Value scratch) { + assert keyConstants.length == keyTargets.length; + this.keyConstants = keyConstants; + this.keyTargets = keyTargets; + this.defaultTarget = defaultTarget; + this.key = key; + this.scratch = scratch; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { + if (key.getKind() == Kind.Int) { + Register intKey = asIntReg(key); + for (int i = 0; i < keyConstants.length; i++) { + if (tasm.runtime.needsDataPatch(keyConstants[i])) { + tasm.recordDataReferenceInCode(keyConstants[i], 0, true); + } + long lc = keyConstants[i].asLong(); + assert NumUtil.isInt(lc); + masm.setp_eq_s32((int) lc, intKey); + masm.at(); + Label l = keyTargets[i].label(); + l.addPatchAt(tasm.asm.codeBuffer.position()); + String target = l.isBound() ? "L" + l.toString() : AbstractPTXAssembler.UNBOUND_TARGET; + masm.bra(target); + } + } else if (key.getKind() == Kind.Long) { + Register longKey = asLongReg(key); + for (int i = 0; i < keyConstants.length; i++) { + masm.setp_eq_s64(tasm.asLongConst(keyConstants[i]), longKey); + masm.at(); + Label l = keyTargets[i].label(); + l.addPatchAt(tasm.asm.codeBuffer.position()); + String target = l.isBound() ? "L" + l.toString() : AbstractPTXAssembler.UNBOUND_TARGET; + masm.bra(target); + } + } else if (key.getKind() == Kind.Object) { + Register intKey = asObjectReg(key); + Register temp = asObjectReg(scratch); + for (int i = 0; i < keyConstants.length; i++) { + PTXMove.move(tasm, masm, temp.asValue(Kind.Object), keyConstants[i]); + masm.setp_eq_u32(intKey, temp); + masm.at(); + masm.bra(keyTargets[i].label().toString()); + } + } else { + throw new GraalInternalError("sequential switch only supported for int, long and object"); + } + if (defaultTarget != null) { + masm.jmp(defaultTarget.label()); + } else { + // masm.hlt(); + } + } + + @Override + public LabelRef fallThroughTarget() { + return defaultTarget; + } + + @Override + public void setFallThroughTarget(LabelRef target) { + defaultTarget = target; + } + } + + public static class TableSwitchOp extends PTXLIRInstruction { + private final int lowKey; + private final LabelRef defaultTarget; + private final LabelRef[] targets; + @Alive protected Value index; + @Temp protected Value scratch; + + public TableSwitchOp(final int lowKey, final LabelRef defaultTarget, final LabelRef[] targets, + Variable index, Variable scratch) { + this.lowKey = lowKey; + this.defaultTarget = defaultTarget; + this.targets = targets; + this.index = index; + this.scratch = scratch; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { + tableswitch(tasm, masm, lowKey, defaultTarget, targets, asIntReg(index), asLongReg(scratch)); + } + } + + @SuppressWarnings("unused") + private static void tableswitch(TargetMethodAssembler tasm, PTXAssembler masm, int lowKey, + LabelRef defaultTarget, LabelRef[] targets, + Register value, Register scratch) { + Buffer buf = masm.codeBuffer; + // Compare index against jump table bounds + int highKey = lowKey + targets.length - 1; + if (lowKey != 0) { + // subtract the low value from the switch value + masm.sub_s32(value, value, lowKey); + masm.setp_gt_s32(value, highKey - lowKey); + } else { + masm.setp_gt_s32(value, highKey); + } + + // Jump to default target if index is not within the jump table + if (defaultTarget != null) { + masm.at(); + masm.bra(defaultTarget.label().toString()); + } + + // address of jump table + int tablePos = buf.position(); + + JumpTable jt = new JumpTable(tablePos, lowKey, highKey, 4); + tasm.compilationResult.addAnnotation(jt); + + // PTX: unimp: tableswitch extract + } } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java --- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java Sat Apr 13 00:33:37 2013 +0200 @@ -133,9 +133,27 @@ public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { PTXAddress addr = address.toAddress(); switch (address.getKind()) { + case Byte: + masm.ld_global_s8(asRegister(result), addr.getBase(), addr.getDisplacement()); + break; + case Short: + masm.ld_global_s16(asRegister(result), addr.getBase(), addr.getDisplacement()); + break; + case Char: + masm.ld_global_u16(asRegister(result), addr.getBase(), addr.getDisplacement()); + break; case Int: masm.ld_global_s32(asRegister(result), addr.getBase(), addr.getDisplacement()); break; + case Long: + masm.ld_global_s64(asRegister(result), addr.getBase(), addr.getDisplacement()); + break; + case Float: + masm.ld_global_f32(asRegister(result), addr.getBase(), addr.getDisplacement()); + break; + case Double: + masm.ld_global_f64(asRegister(result), addr.getBase(), addr.getDisplacement()); + break; case Object: masm.ld_global_u32(asRegister(result), addr.getBase(), addr.getDisplacement()); break; @@ -162,11 +180,29 @@ assert isRegister(input); PTXAddress addr = address.toAddress(); switch (address.getKind()) { + case Byte: + masm.st_global_s8(addr.getBase(), addr.getDisplacement(), asRegister(input)); + break; + case Short: + masm.st_global_s8(addr.getBase(), addr.getDisplacement(), asRegister(input)); + break; case Int: masm.st_global_s32(addr.getBase(), addr.getDisplacement(), asRegister(input)); break; + case Long: + masm.st_global_s64(addr.getBase(), addr.getDisplacement(), asRegister(input)); + break; + case Float: + masm.st_global_f32(addr.getBase(), addr.getDisplacement(), asRegister(input)); + break; + case Double: + masm.st_global_f64(addr.getBase(), addr.getDisplacement(), asRegister(input)); + break; + case Object: + masm.st_global_s32(addr.getBase(), addr.getDisplacement(), asRegister(input)); + break; default: - throw GraalInternalError.shouldNotReachHere(); + throw GraalInternalError.shouldNotReachHere("missing: " + address.getKind()); } } } @@ -250,11 +286,20 @@ case Int: masm.mov_s32(asRegister(result), asRegister(input)); break; + case Long: + masm.mov_s64(asRegister(result), asRegister(input)); + break; + case Float: + masm.mov_f32(asRegister(result), asRegister(input)); + break; + case Double: + masm.mov_f64(asRegister(result), asRegister(input)); + break; case Object: masm.mov_u64(asRegister(result), asRegister(input)); break; default: - throw GraalInternalError.shouldNotReachHere("kind=" + result.getKind()); + throw GraalInternalError.shouldNotReachHere("missing: " + input.getKind()); } } @@ -266,8 +311,24 @@ } masm.mov_s32(asRegister(result), input.asInt()); break; + case Long: + if (tasm.runtime.needsDataPatch(input)) { + tasm.recordDataReferenceInCode(input, 0, true); + } + masm.mov_s64(asRegister(result), input.asLong()); + break; + case Object: + if (input.isNull()) { + masm.mov_u64(asRegister(result), 0x0L); + } else if (tasm.target.inlineObjects) { + tasm.recordDataReferenceInCode(input, 0, true); + masm.mov_u64(asRegister(result), 0xDEADDEADDEADDEADL); + } else { + masm.mov_u64(asRegister(result), tasm.recordDataReferenceInCode(input, 0, false)); + } + break; default: - throw GraalInternalError.shouldNotReachHere(); + throw GraalInternalError.shouldNotReachHere("missing: " + input.getKind()); } } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/InfopointOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/InfopointOp.java Sat Apr 13 00:33:37 2013 +0200 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2013, 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.lir; + +import static com.oracle.graal.lir.LIRInstruction.Opcode; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.lir.asm.*; + +/** + * Emits an infopoint (only mark the position). + */ +@Opcode("INFOPOINT") +public class InfopointOp extends LIRInstruction { + + @State protected LIRFrameState state; + + private final InfopointReason reason; + + public InfopointOp(LIRFrameState state, InfopointReason reason) { + this.state = state; + this.reason = reason; + } + + @Override + public void emitCode(TargetMethodAssembler tasm) { + tasm.recordInfopoint(tasm.asm.codeBuffer.position(), state, reason); + } +} diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java Sat Apr 13 00:33:37 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, 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 @@ -101,7 +101,7 @@ Debug.metric("TargetMethods").increment(); Debug.metric("CodeBytesEmitted").add(compilationResult.getTargetCodeSize()); - Debug.metric("SafepointsEmitted").add(compilationResult.getSafepoints().size()); + Debug.metric("SafepointsEmitted").add(compilationResult.getInfopoints().size()); Debug.metric("DataPatches").add(compilationResult.getDataReferences().size()); Debug.metric("ExceptionHandlersEmitted").add(compilationResult.getExceptionHandlers().size()); Debug.log("Finished target method %s, isStub %b", name, isStub); @@ -122,7 +122,7 @@ public void recordImplicitException(int pcOffset, LIRFrameState info) { // record an implicit exception point if (info != null) { - compilationResult.recordSafepoint(pcOffset, info.debugInfo()); + compilationResult.recordInfopoint(pcOffset, info.debugInfo(), InfopointReason.IMPLICIT_EXCEPTION); assert info.exceptionEdge == null; } } @@ -137,10 +137,10 @@ compilationResult.recordCall(posBefore, posAfter - posBefore, callTarget, debugInfo, false); } - public void recordSafepoint(int pos, LIRFrameState info) { - // safepoints always need debug info + public void recordInfopoint(int pos, LIRFrameState info, InfopointReason reason) { + // infopoints always need debug info DebugInfo debugInfo = info.debugInfo(); - compilationResult.recordSafepoint(pos, debugInfo); + compilationResult.recordInfopoint(pos, debugInfo, reason); } public AbstractAddress recordDataReferenceInCode(Constant data, int alignment, boolean inlined) { @@ -167,6 +167,36 @@ } /** + * Returns the float value of any constant that can be represented by a 32-bit float value. + */ + public float asFloatConst(Value value) { + assert (value.getKind().getStackKind() == Kind.Float && isConstant(value)); + Constant constant = (Constant) value; + assert !runtime.needsDataPatch(constant) : constant + " should be in a DataPatch"; + return constant.asFloat(); + } + + /** + * Returns the long value of any constant that can be represented by a 64-bit long value. + */ + public long asLongConst(Value value) { + assert (value.getKind().getStackKind() == Kind.Long && isConstant(value)); + Constant constant = (Constant) value; + assert !runtime.needsDataPatch(constant) : constant + " should be in a DataPatch"; + return constant.asLong(); + } + + /** + * Returns the double value of any constant that can be represented by a 64-bit float value. + */ + public double asDoubleConst(Value value) { + assert (value.getKind().getStackKind() == Kind.Double && isConstant(value)); + Constant constant = (Constant) value; + assert !runtime.needsDataPatch(constant) : constant + " should be in a DataPatch"; + return constant.asDouble(); + } + + /** * Returns the address of a float constant that is embedded as a data references into the code. */ public AbstractAddress asFloatConstRef(Value value) { diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java Sat Apr 13 00:33:37 2013 +0200 @@ -60,7 +60,7 @@ while (!loopBegin.isDeleted()) { int mark = graph.getMark(); peel(loop); - new CanonicalizerPhase(runtime, assumptions, mark, null).apply(graph); + new CanonicalizerPhase.Instance(runtime, assumptions, mark, null).apply(graph); if (iterations++ > UNROLL_LIMIT || graph.getNodeCount() > GraalOptions.MaximumDesiredSize * 3) { throw new BailoutException("FullUnroll : Graph seems to grow out of proportion"); } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopFullUnrollPhase.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopFullUnrollPhase.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopFullUnrollPhase.java Sat Apr 13 00:33:37 2013 +0200 @@ -22,31 +22,21 @@ */ package com.oracle.graal.loop.phases; -import com.oracle.graal.api.code.*; import com.oracle.graal.debug.*; import com.oracle.graal.loop.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; +import com.oracle.graal.phases.tiers.*; -public class LoopFullUnrollPhase extends Phase { +public class LoopFullUnrollPhase extends BasePhase { private static final DebugMetric FULLY_UNROLLED_LOOPS = Debug.metric("FullUnrolls"); - private final GraalCodeCacheProvider runtime; - private final Assumptions assumptions; - private int unrollCount; - public LoopFullUnrollPhase(GraalCodeCacheProvider runtime, Assumptions assumptions) { - this.runtime = runtime; - this.assumptions = assumptions; - } - - public int getUnrollCount() { - return unrollCount; + public LoopFullUnrollPhase() { } @Override - protected void run(StructuredGraph graph) { + protected void run(StructuredGraph graph, HighTierContext context) { if (graph.hasLoops()) { boolean peeled; do { @@ -56,11 +46,10 @@ for (LoopEx loop : dataCounted.countedLoops()) { if (LoopPolicies.shouldFullUnroll(loop)) { Debug.log("FullUnroll %s", loop); - LoopTransformations.fullUnroll(loop, runtime, assumptions); + LoopTransformations.fullUnroll(loop, context.getRuntime(), context.getAssumptions()); FULLY_UNROLLED_LOOPS.increment(); Debug.dump(graph, "After fullUnroll %s", loop); peeled = true; - unrollCount++; break; } } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java Sat Apr 13 00:33:37 2013 +0200 @@ -29,7 +29,7 @@ import com.oracle.graal.nodes.type.*; @NodeInfo(shortName = "Deopt", nameTemplate = "Deopt {p#reason/s}") -public class DeoptimizeNode extends ControlSinkNode implements Node.IterableNodeType, LIRLowerable, DeoptimizingNode { +public class DeoptimizeNode extends ControlSinkNode implements Node.IterableNodeType, Lowerable, LIRLowerable, DeoptimizingNode { @Input private FrameState deoptState; @@ -51,6 +51,11 @@ } @Override + public void lower(LoweringTool tool) { + tool.getRuntime().lower(this, tool); + } + + @Override public void generate(LIRGeneratorTool gen) { gen.emitDeoptimize(action, this); } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java Sat Apr 13 00:33:37 2013 +0200 @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2013, 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.nodes; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.graph.Node.IterableNodeType; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +/** + * Nodes of this type are inserted into the graph to denote points of interest to debugging. + */ +public class InfopointNode extends AbstractStateSplit implements LIRLowerable, IterableNodeType { + + public final InfopointReason reason; + + public InfopointNode(InfopointReason reason) { + super(StampFactory.forVoid()); + this.reason = reason; + } + + @Override + public void generate(LIRGeneratorTool generator) { + generator.visitInfopointNode(this); + } + + @Override + public boolean hasSideEffect() { + return false; + } + + @Override + public void setStateAfter(FrameState state) { + // shield this node from frame state removal + // TODO turn InfopointNode into a FixedWithNextNode subclass with a self-maintained + // FrameState that is correctly dealt with by scheduling and partial escape analysis + if (state != null) { + super.setStateAfter(state); + } + } + +} diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java Sat Apr 13 00:33:37 2013 +0200 @@ -41,7 +41,7 @@ int bci(); - FixedNode node(); + FixedNode asNode(); FrameState stateDuring(); diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java Sat Apr 13 00:33:37 2013 +0200 @@ -140,13 +140,16 @@ } @Override - public FixedNode node() { + public FixedNode asNode() { return this; } @Override public FrameState stateDuring() { FrameState stateAfter = stateAfter(); + if (stateAfter == null) { + return null; + } FrameState stateDuring = stateAfter.duplicateModified(bci(), stateAfter.rethrowException(), kind()); stateDuring.setDuringCall(true); return stateDuring; diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Sat Apr 13 00:33:37 2013 +0200 @@ -126,7 +126,7 @@ } @Override - public FixedNode node() { + public FixedNode asNode() { return this; } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java Sat Apr 13 00:33:37 2013 +0200 @@ -121,6 +121,9 @@ @Override public void lower(LoweringTool tool) { + if (!enabled) { + throw new GraalInternalError("counter nodes shouldn't exist when not enabled"); + } StructuredGraph graph = (StructuredGraph) graph(); if (excludedClassPrefix == null || !graph.method().getDeclaringClass().getName().startsWith(excludedClassPrefix)) { int index = addContext ? getIndex(name + " @ " + MetaUtil.format("%h.%n", ((StructuredGraph) graph()).method())) : getIndex(name); diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/Access.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/Access.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/Access.java Sat Apr 13 00:33:37 2013 +0200 @@ -33,5 +33,5 @@ void setNullCheck(boolean check); - Node node(); + Node asNode(); } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java Sat Apr 13 00:33:37 2013 +0200 @@ -79,7 +79,7 @@ } @Override - public Node node() { + public Node asNode() { return this; } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java Sat Apr 13 00:33:37 2013 +0200 @@ -76,7 +76,7 @@ } @Override - public Node node() { + public Node asNode() { return this; } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeArrayCastNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeArrayCastNode.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeArrayCastNode.java Sat Apr 13 00:33:37 2013 +0200 @@ -51,5 +51,5 @@ } @NodeIntrinsic - public static native T unsafeArrayCast(Object object, int length, @ConstantNodeParameter Stamp stamp, ValueNode anchor); + public static native T unsafeArrayCast(Object object, int length, @ConstantNodeParameter Stamp stamp, Object anchor); } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Sat Apr 13 00:33:37 2013 +0200 @@ -88,7 +88,7 @@ } @NodeIntrinsic - public static native void writeMemory(Object object, Object value, Object location); + public static native void writeMemory(Object object, Object value, Object location, @ConstantNodeParameter boolean usePreciseWriteBarriers); @Override public Object[] getLocationIdentities() { diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Sat Apr 13 00:33:37 2013 +0200 @@ -65,7 +65,8 @@ } else if (stamp.type() != null && !stamp.type().hasFinalizableSubclass()) { // if either the declared type of receiver or the holder // can be assumed to have no finalizers - if (tool.assumptions().useOptimisticAssumptions() && tool.assumptions().recordNoFinalizableSubclassAssumption(stamp.type())) { + if (tool.assumptions().useOptimisticAssumptions()) { + tool.assumptions().recordNoFinalizableSubclassAssumption(stamp.type()); needsCheck = false; } } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraalCodeCacheProvider.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraalCodeCacheProvider.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraalCodeCacheProvider.java Sat Apr 13 00:33:37 2013 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.nodes.spi; import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; /** @@ -30,5 +31,17 @@ */ public interface GraalCodeCacheProvider extends CodeCacheProvider { + /** + * Adds the given compilation result as an implementation of the given method without making it + * the default implementation. The graph might be inlined later on. + * + * @param method a method to which the executable code is begin added + * @param compResult the compilation result to be added + * @param graph the graph that represents the method + * @return a reference to the compiled and ready-to-run code or null if the code installation + * failed + */ + InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, Graph graph); + void lower(Node n, LoweringTool tool); } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java Sat Apr 13 00:33:37 2013 +0200 @@ -137,4 +137,6 @@ */ public void beforeRegisterAllocation() { } + + public abstract void visitInfopointNode(InfopointNode i); } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java Sat Apr 13 00:33:37 2013 +0200 @@ -63,11 +63,6 @@ Assumptions getAssumptions(); /** - * Registers all the snippet methods defined by a given class. - */ - void registerSnippets(Class snippets); - - /** * Registers all the {@linkplain MethodSubstitution method} and {@linkplain MacroSubstitution * macro} substitutions defined by a given class. */ diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Sat Apr 13 00:33:37 2013 +0200 @@ -202,7 +202,7 @@ while (n != null) { if (n instanceof MethodCallTargetNode) { elements.add(((MethodCallTargetNode) n).targetMethod().asStackTraceElement(-1)); - n = ((MethodCallTargetNode) n).invoke().node(); + n = ((MethodCallTargetNode) n).invoke().asNode(); } if (n instanceof StateSplit) { diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Sat Apr 13 00:33:37 2013 +0200 @@ -36,8 +36,9 @@ import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.*; +import com.oracle.graal.phases.tiers.*; -public class CanonicalizerPhase extends Phase { +public class CanonicalizerPhase extends BasePhase { private static final int MAX_ITERATION_PER_NODE = 10; private static final DebugMetric METRIC_CANONICALIZED_NODES = Debug.metric("CanonicalizedNodes"); @@ -47,155 +48,163 @@ private static final DebugMetric METRIC_SIMPLIFICATION_CONSIDERED_NODES = Debug.metric("SimplificationConsideredNodes"); public static final DebugMetric METRIC_GLOBAL_VALUE_NUMBERING_HITS = Debug.metric("GlobalValueNumberingHits"); - private final int newNodesMark; - private final Assumptions assumptions; - private final MetaAccessProvider runtime; - private final CustomCanonicalizer customCanonicalizer; - private final Iterable initWorkingSet; - - private NodeWorkList workList; - private Tool tool; - private List snapshotTemp; - public interface CustomCanonicalizer { ValueNode canonicalize(Node node); } - public CanonicalizerPhase(MetaAccessProvider runtime, Assumptions assumptions) { - this(runtime, assumptions, null, 0, null); - } - - /** - * @param runtime - * @param assumptions - * @param workingSet the initial working set of nodes on which the canonicalizer works, should - * be an auto-grow node bitmap - * @param customCanonicalizer - */ - public CanonicalizerPhase(MetaAccessProvider runtime, Assumptions assumptions, Iterable workingSet, CustomCanonicalizer customCanonicalizer) { - this(runtime, assumptions, workingSet, 0, customCanonicalizer); - } - - /** - * @param newNodesMark only the {@linkplain Graph#getNewNodes(int) new nodes} specified by this - * mark are processed otherwise all nodes in the graph are processed - */ - public CanonicalizerPhase(MetaAccessProvider runtime, Assumptions assumptions, int newNodesMark, CustomCanonicalizer customCanonicalizer) { - this(runtime, assumptions, null, newNodesMark, customCanonicalizer); - } - - public CanonicalizerPhase(MetaAccessProvider runtime, Assumptions assumptions, Iterable workingSet, int newNodesMark, CustomCanonicalizer customCanonicalizer) { - this.newNodesMark = newNodesMark; - this.assumptions = assumptions; - this.runtime = runtime; - this.customCanonicalizer = customCanonicalizer; - this.initWorkingSet = workingSet; - this.snapshotTemp = new ArrayList<>(); - } - @Override - protected void run(StructuredGraph graph) { - if (initWorkingSet == null) { - workList = graph.createNodeWorkList(newNodesMark == 0, MAX_ITERATION_PER_NODE); - } else { - workList = graph.createNodeWorkList(false, MAX_ITERATION_PER_NODE); - workList.addAll(initWorkingSet); - } - if (newNodesMark > 0) { - workList.addAll(graph.getNewNodes(newNodesMark)); - } - tool = new Tool(workList, runtime, assumptions); - processWorkSet(graph); - } - - private void processWorkSet(StructuredGraph graph) { - graph.trackInputChange(new InputChangedListener() { - - @Override - public void inputChanged(Node node) { - workList.addAgain(node); - } - }); - - for (Node n : workList) { - processNode(n, graph); - } - - graph.stopTrackingInputChange(); + protected void run(StructuredGraph graph, PhaseContext context) { + new Instance(context.getRuntime(), context.getAssumptions()).run(graph); } - private void processNode(Node node, StructuredGraph graph) { - if (node.isAlive()) { - METRIC_PROCESSED_NODES.increment(); + public static class Instance extends Phase { + + private final int newNodesMark; + private final Assumptions assumptions; + private final MetaAccessProvider runtime; + private final CustomCanonicalizer customCanonicalizer; + private final Iterable initWorkingSet; + + private NodeWorkList workList; + private Tool tool; + private List snapshotTemp; + + public Instance(MetaAccessProvider runtime, Assumptions assumptions) { + this(runtime, assumptions, null, 0, null); + } - if (tryGlobalValueNumbering(node, graph)) { - return; + /** + * @param runtime + * @param assumptions + * @param workingSet the initial working set of nodes on which the canonicalizer works, + * should be an auto-grow node bitmap + * @param customCanonicalizer + */ + public Instance(MetaAccessProvider runtime, Assumptions assumptions, Iterable workingSet, CustomCanonicalizer customCanonicalizer) { + this(runtime, assumptions, workingSet, 0, customCanonicalizer); + } + + /** + * @param newNodesMark only the {@linkplain Graph#getNewNodes(int) new nodes} specified by + * this mark are processed otherwise all nodes in the graph are processed + */ + public Instance(MetaAccessProvider runtime, Assumptions assumptions, int newNodesMark, CustomCanonicalizer customCanonicalizer) { + this(runtime, assumptions, null, newNodesMark, customCanonicalizer); + } + + public Instance(MetaAccessProvider runtime, Assumptions assumptions, Iterable workingSet, int newNodesMark, CustomCanonicalizer customCanonicalizer) { + super("Canonicalizer"); + this.newNodesMark = newNodesMark; + this.assumptions = assumptions; + this.runtime = runtime; + this.customCanonicalizer = customCanonicalizer; + this.initWorkingSet = workingSet; + this.snapshotTemp = new ArrayList<>(); + } + + @Override + protected void run(StructuredGraph graph) { + if (initWorkingSet == null) { + workList = graph.createNodeWorkList(newNodesMark == 0, MAX_ITERATION_PER_NODE); + } else { + workList = graph.createNodeWorkList(false, MAX_ITERATION_PER_NODE); + workList.addAll(initWorkingSet); } - int mark = graph.getMark(); - if (!tryKillUnused(node)) { - node.inputs().filter(GraphUtil.isFloatingNode()).snapshotTo(snapshotTemp); - if (!tryCanonicalize(node, graph)) { - tryInferStamp(node, graph); - } else { - for (Node in : snapshotTemp) { - if (in.isAlive() && in.usages().isEmpty()) { - GraphUtil.killWithUnusedFloatingInputs(in); + if (newNodesMark > 0) { + workList.addAll(graph.getNewNodes(newNodesMark)); + } + tool = new Tool(workList, runtime, assumptions); + processWorkSet(graph); + } + + private void processWorkSet(StructuredGraph graph) { + graph.trackInputChange(new InputChangedListener() { + + @Override + public void inputChanged(Node node) { + workList.addAgain(node); + } + }); + + for (Node n : workList) { + processNode(n, graph); + } + + graph.stopTrackingInputChange(); + } + + private void processNode(Node node, StructuredGraph graph) { + if (node.isAlive()) { + METRIC_PROCESSED_NODES.increment(); + + if (tryGlobalValueNumbering(node, graph)) { + return; + } + int mark = graph.getMark(); + if (!tryKillUnused(node)) { + node.inputs().filter(GraphUtil.isFloatingNode()).snapshotTo(snapshotTemp); + if (!tryCanonicalize(node, graph)) { + tryInferStamp(node, graph); + } else { + for (Node in : snapshotTemp) { + if (in.isAlive() && in.usages().isEmpty()) { + GraphUtil.killWithUnusedFloatingInputs(in); + } } } + snapshotTemp.clear(); } - snapshotTemp.clear(); - } - for (Node newNode : graph.getNewNodes(mark)) { - workList.add(newNode); + for (Node newNode : graph.getNewNodes(mark)) { + workList.add(newNode); + } } } - } - private static boolean tryKillUnused(Node node) { - if (node.isAlive() && GraphUtil.isFloatingNode().apply(node) && node.usages().isEmpty()) { - GraphUtil.killWithUnusedFloatingInputs(node); - return true; - } - return false; - } - - public static boolean tryGlobalValueNumbering(Node node, StructuredGraph graph) { - if (node.getNodeClass().valueNumberable()) { - Node newNode = graph.findDuplicate(node); - if (newNode != null) { - assert !(node instanceof FixedNode || newNode instanceof FixedNode); - node.replaceAtUsages(newNode); - node.safeDelete(); - METRIC_GLOBAL_VALUE_NUMBERING_HITS.increment(); - Debug.log("GVN applied and new node is %1s", newNode); + private static boolean tryKillUnused(Node node) { + if (node.isAlive() && GraphUtil.isFloatingNode().apply(node) && node.usages().isEmpty()) { + GraphUtil.killWithUnusedFloatingInputs(node); return true; } + return false; } - return false; - } - public boolean tryCanonicalize(final Node node, final StructuredGraph graph) { - boolean result = baseTryCanonicalize(node, graph); - if (!result && customCanonicalizer != null) { - ValueNode canonical = customCanonicalizer.canonicalize(node); - if (canonical == node && customCanonicalizer != null) { - canonical = customCanonicalizer.canonicalize(node); + public static boolean tryGlobalValueNumbering(Node node, StructuredGraph graph) { + if (node.getNodeClass().valueNumberable()) { + Node newNode = graph.findDuplicate(node); + if (newNode != null) { + assert !(node instanceof FixedNode || newNode instanceof FixedNode); + node.replaceAtUsages(newNode); + node.safeDelete(); + METRIC_GLOBAL_VALUE_NUMBERING_HITS.increment(); + Debug.log("GVN applied and new node is %1s", newNode); + return true; + } } - result = performReplacement(node, graph, canonical); + return false; } - return result; - } - public boolean baseTryCanonicalize(final Node node, final StructuredGraph graph) { - if (node instanceof Canonicalizable) { - assert !(node instanceof Simplifiable); - METRIC_CANONICALIZATION_CONSIDERED_NODES.increment(); - return Debug.scope("CanonicalizeNode", node, new Callable() { + public boolean tryCanonicalize(final Node node, final StructuredGraph graph) { + boolean result = baseTryCanonicalize(node, graph); + if (!result && customCanonicalizer != null) { + ValueNode canonical = customCanonicalizer.canonicalize(node); + if (canonical == node && customCanonicalizer != null) { + canonical = customCanonicalizer.canonicalize(node); + } + result = performReplacement(node, graph, canonical); + } + return result; + } - public Boolean call() { - ValueNode canonical = ((Canonicalizable) node).canonical(tool); + public boolean baseTryCanonicalize(final Node node, final StructuredGraph graph) { + if (node instanceof Canonicalizable) { + assert !(node instanceof Simplifiable); + METRIC_CANONICALIZATION_CONSIDERED_NODES.increment(); + return Debug.scope("CanonicalizeNode", node, new Callable() { + + public Boolean call() { + ValueNode canonical = ((Canonicalizable) node).canonical(tool); // @formatter:off // cases: original node: // |Floating|Fixed-unconnected|Fixed-connected| @@ -211,137 +220,139 @@ // X: must not happen (checked with assertions) // @formatter:on - return performReplacement(node, graph, canonical); - } - }); - } else if (node instanceof Simplifiable) { - Debug.log("Canonicalizer: simplifying %s", node); - METRIC_SIMPLIFICATION_CONSIDERED_NODES.increment(); - Debug.scope("SimplifyNode", node, new Runnable() { + return performReplacement(node, graph, canonical); + } + }); + } else if (node instanceof Simplifiable) { + Debug.log("Canonicalizer: simplifying %s", node); + METRIC_SIMPLIFICATION_CONSIDERED_NODES.increment(); + Debug.scope("SimplifyNode", node, new Runnable() { - public void run() { - ((Simplifiable) node).simplify(tool); - } - }); + public void run() { + ((Simplifiable) node).simplify(tool); + } + }); + } + return node.isDeleted(); } - return node.isDeleted(); - } - private boolean performReplacement(final Node node, final StructuredGraph graph, ValueNode canonical) { - if (canonical == node) { - Debug.log("Canonicalizer: work on %s", node); - return false; - } else { - Debug.log("Canonicalizer: replacing %s with %s", node, canonical); - METRIC_CANONICALIZED_NODES.increment(); - if (node instanceof FloatingNode) { - if (canonical == null) { - // case 1 - graph.removeFloating((FloatingNode) node); + private boolean performReplacement(final Node node, final StructuredGraph graph, ValueNode canonical) { + if (canonical == node) { + Debug.log("Canonicalizer: work on %s", node); + return false; + } else { + Debug.log("Canonicalizer: replacing %s with %s", node, canonical); + METRIC_CANONICALIZED_NODES.increment(); + if (node instanceof FloatingNode) { + if (canonical == null) { + // case 1 + graph.removeFloating((FloatingNode) node); + } else { + // case 2 + assert !(canonical instanceof FixedNode) || (canonical.predecessor() != null || canonical instanceof StartNode || canonical instanceof MergeNode) : node + " -> " + canonical + + " : replacement should be floating or fixed and connected"; + graph.replaceFloating((FloatingNode) node, canonical); + } } else { - // case 2 - assert !(canonical instanceof FixedNode) || (canonical.predecessor() != null || canonical instanceof StartNode || canonical instanceof MergeNode) : node + " -> " + canonical + - " : replacement should be floating or fixed and connected"; - graph.replaceFloating((FloatingNode) node, canonical); - } - } else { - assert node instanceof FixedWithNextNode && node.predecessor() != null : node + " -> " + canonical + " : node should be fixed & connected (" + node.predecessor() + ")"; - FixedWithNextNode fixedWithNext = (FixedWithNextNode) node; + assert node instanceof FixedWithNextNode && node.predecessor() != null : node + " -> " + canonical + " : node should be fixed & connected (" + node.predecessor() + ")"; + FixedWithNextNode fixedWithNext = (FixedWithNextNode) node; - // When removing a fixed node, new canonicalization opportunities for its successor - // may arise - assert fixedWithNext.next() != null; - tool.addToWorkList(fixedWithNext.next()); + // When removing a fixed node, new canonicalization opportunities for its +// successor + // may arise + assert fixedWithNext.next() != null; + tool.addToWorkList(fixedWithNext.next()); - if (canonical == null) { - // case 3 - graph.removeFixed(fixedWithNext); - } else if (canonical instanceof FloatingNode) { - // case 4 - graph.replaceFixedWithFloating(fixedWithNext, (FloatingNode) canonical); - } else { - assert canonical instanceof FixedNode; - if (canonical.predecessor() == null) { - assert !canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " shouldn't have successors"; - // case 5 - graph.replaceFixedWithFixed(fixedWithNext, (FixedWithNextNode) canonical); + if (canonical == null) { + // case 3 + graph.removeFixed(fixedWithNext); + } else if (canonical instanceof FloatingNode) { + // case 4 + graph.replaceFixedWithFloating(fixedWithNext, (FloatingNode) canonical); } else { - assert canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " should have successors"; - // case 6 - node.replaceAtUsages(canonical); - graph.removeFixed(fixedWithNext); + assert canonical instanceof FixedNode; + if (canonical.predecessor() == null) { + assert !canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " shouldn't have successors"; + // case 5 + graph.replaceFixedWithFixed(fixedWithNext, (FixedWithNextNode) canonical); + } else { + assert canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " should have successors"; + // case 6 + node.replaceAtUsages(canonical); + graph.removeFixed(fixedWithNext); + } } } + return true; } - return true; } - } - /** - * Calls {@link ValueNode#inferStamp()} on the node and, if it returns true (which means that - * the stamp has changed), re-queues the node's usages . If the stamp has changed then this - * method also checks if the stamp now describes a constant integer value, in which case the - * node is replaced with a constant. - */ - private void tryInferStamp(Node node, StructuredGraph graph) { - if (node.isAlive() && node instanceof ValueNode) { - ValueNode valueNode = (ValueNode) node; - METRIC_INFER_STAMP_CALLED.increment(); - if (valueNode.inferStamp()) { - METRIC_STAMP_CHANGED.increment(); - if (valueNode.stamp() instanceof IntegerStamp && valueNode.integerStamp().lowerBound() == valueNode.integerStamp().upperBound()) { - ValueNode replacement = ConstantNode.forIntegerKind(valueNode.kind(), valueNode.integerStamp().lowerBound(), graph); - Debug.log("Canonicalizer: replacing %s with %s (inferStamp)", valueNode, replacement); - valueNode.replaceAtUsages(replacement); - } else { - for (Node usage : valueNode.usages()) { - workList.addAgain(usage); + /** + * Calls {@link ValueNode#inferStamp()} on the node and, if it returns true (which means + * that the stamp has changed), re-queues the node's usages . If the stamp has changed then + * this method also checks if the stamp now describes a constant integer value, in which + * case the node is replaced with a constant. + */ + private void tryInferStamp(Node node, StructuredGraph graph) { + if (node.isAlive() && node instanceof ValueNode) { + ValueNode valueNode = (ValueNode) node; + METRIC_INFER_STAMP_CALLED.increment(); + if (valueNode.inferStamp()) { + METRIC_STAMP_CHANGED.increment(); + if (valueNode.stamp() instanceof IntegerStamp && valueNode.integerStamp().lowerBound() == valueNode.integerStamp().upperBound()) { + ValueNode replacement = ConstantNode.forIntegerKind(valueNode.kind(), valueNode.integerStamp().lowerBound(), graph); + Debug.log("Canonicalizer: replacing %s with %s (inferStamp)", valueNode, replacement); + valueNode.replaceAtUsages(replacement); + } else { + for (Node usage : valueNode.usages()) { + workList.addAgain(usage); + } } } } } - } - private static final class Tool implements SimplifierTool { + private static final class Tool implements SimplifierTool { - private final NodeWorkList nodeWorkSet; - private final MetaAccessProvider runtime; - private final Assumptions assumptions; + private final NodeWorkList nodeWorkSet; + private final MetaAccessProvider runtime; + private final Assumptions assumptions; - public Tool(NodeWorkList nodeWorkSet, MetaAccessProvider runtime, Assumptions assumptions) { - this.nodeWorkSet = nodeWorkSet; - this.runtime = runtime; - this.assumptions = assumptions; - } + public Tool(NodeWorkList nodeWorkSet, MetaAccessProvider runtime, Assumptions assumptions) { + this.nodeWorkSet = nodeWorkSet; + this.runtime = runtime; + this.assumptions = assumptions; + } - @Override - public void deleteBranch(FixedNode branch) { - branch.predecessor().replaceFirstSuccessor(branch, null); - GraphUtil.killCFG(branch); - } + @Override + public void deleteBranch(FixedNode branch) { + branch.predecessor().replaceFirstSuccessor(branch, null); + GraphUtil.killCFG(branch); + } - /** - * @return an object that can be used for recording assumptions or {@code null} if - * assumptions are not allowed in the current context. - */ - @Override - public Assumptions assumptions() { - return assumptions; - } + /** + * @return an object that can be used for recording assumptions or {@code null} if + * assumptions are not allowed in the current context. + */ + @Override + public Assumptions assumptions() { + return assumptions; + } - @Override - public MetaAccessProvider runtime() { - return runtime; - } + @Override + public MetaAccessProvider runtime() { + return runtime; + } - @Override - public void addToWorkList(Node node) { - nodeWorkSet.addAgain(node); - } + @Override + public void addToWorkList(Node node) { + nodeWorkSet.addAgain(node); + } - @Override - public void removeIfUnused(Node node) { - tryKillUnused(node); + @Override + public void removeIfUnused(Node node) { + tryKillUnused(node); + } } } } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java Sat Apr 13 00:33:37 2013 +0200 @@ -114,12 +114,12 @@ Access fixedAccess = access; if (access instanceof FloatingAccessNode) { fixedAccess = ((FloatingAccessNode) access).asFixedNode(); - replaceCurrent((FixedWithNextNode) fixedAccess.node()); + replaceCurrent((FixedWithNextNode) fixedAccess.asNode()); } assert fixedAccess instanceof FixedNode; fixedAccess.setNullCheck(true); LogicNode condition = guard.condition(); - guard.replaceAndDelete(fixedAccess.node()); + guard.replaceAndDelete(fixedAccess.asNode()); if (condition.usages().isEmpty()) { GraphUtil.killWithUnusedFloatingInputs(condition); } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java Sat Apr 13 00:33:37 2013 +0200 @@ -111,13 +111,13 @@ if (isWorthInlining) { int mark = graph.getMark(); try { - List invokeUsages = candidate.invoke().node().usages().snapshot(); + List invokeUsages = candidate.invoke().asNode().usages().snapshot(); candidate.inline(graph, runtime, replacements, this, assumptions); Debug.dump(graph, "after %s", candidate); Iterable newNodes = graph.getNewNodes(mark); inliningPolicy.scanInvokes(newNodes); if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(runtime, assumptions, invokeUsages, mark, customCanonicalizer).apply(graph); + new CanonicalizerPhase.Instance(runtime, assumptions, invokeUsages, mark, customCanonicalizer).apply(graph); } inliningCount++; metricInliningPerformed.increment(); @@ -161,7 +161,7 @@ new ComputeProbabilityPhase().apply(newGraph); } if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(runtime, assumptions).apply(newGraph); + new CanonicalizerPhase.Instance(runtime, assumptions).apply(newGraph); } if (GraalOptions.CullFrameStates) { new CullFrameStatesPhase().apply(newGraph); @@ -278,7 +278,7 @@ private static int countInvokeUsages(InlineInfo info) { // inlining calls with lots of usages simplifies the caller int usages = 0; - for (Node n : info.invoke().node().usages()) { + for (Node n : info.invoke().asNode().usages()) { if (!(n instanceof FrameState)) { usages++; } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Sat Apr 13 00:33:37 2013 +0200 @@ -73,13 +73,47 @@ boolean isWorthInlining(InlineInfo info); } + /** + * Print a HotSpot-style inlining message to the console. + */ + private static void printInlining(final InlineInfo info, final boolean success, final String msg, final Object... args) { + printInlining(info.methodAt(0), info.invoke(), success, msg, args); + } + + /** + * Print a HotSpot-style inlining message to the console. + */ + private static void printInlining(final ResolvedJavaMethod method, final Invoke invoke, final boolean success, final String msg, final Object... args) { + if (GraalOptions.HotSpotPrintInlining) { + final int mod = method.getModifiers(); + // 1234567 + TTY.print(" "); // print timestamp + // 1234 + TTY.print(" "); // print compilation number + // % s ! b n + TTY.print("%c%c%c%c%c ", ' ', Modifier.isSynchronized(mod) ? 's' : ' ', ' ', ' ', Modifier.isNative(mod) ? 'n' : ' '); + TTY.print(" "); // more indent + TTY.print(" "); // initial inlining indent + final int level = computeInliningLevel(invoke); + for (int i = 0; i < level; i++) { + TTY.print(" "); + } + TTY.println(String.format("@ %d %s %s%s", invoke.bci(), methodName(method, null), success ? "" : "not inlining ", String.format(msg, args))); + } + } + + public static boolean logInlinedMethod(InlineInfo info, String msg, Object... args) { + logInliningDecision(info, true, msg, args); + return true; + } + public static boolean logNotInlinedMethod(InlineInfo info, String msg, Object... args) { - logInliningDecision(info, false, msg, args); return false; } public static void logInliningDecision(InlineInfo info, boolean success, String msg, final Object... args) { + printInlining(info, success, msg, args); if (shouldLogInliningDecision()) { logInliningDecision(methodName(info), success, msg, args); } @@ -94,11 +128,6 @@ }); } - public static boolean logInlinedMethod(InlineInfo info, String string, Object... args) { - logInliningDecision(info, true, string, args); - return true; - } - private static boolean logNotInlinedMethodAndReturnFalse(Invoke invoke, String msg) { if (shouldLogInliningDecision()) { String methodString = invoke.toString() + (invoke.callTarget() == null ? " callTarget=null" : invoke.callTarget().targetName()); @@ -112,6 +141,7 @@ } private static InlineInfo logNotInlinedMethodAndReturnNull(Invoke invoke, ResolvedJavaMethod method, String msg, Object... args) { + printInlining(method, invoke, false, msg, args); if (shouldLogInliningDecision()) { String methodString = methodName(method, invoke); logInliningDecision(methodString, false, msg, args); @@ -120,6 +150,7 @@ } private static boolean logNotInlinedMethodAndReturnFalse(Invoke invoke, ResolvedJavaMethod method, String msg) { + printInlining(method, invoke, false, msg, new Object[0]); if (shouldLogInliningDecision()) { String methodString = methodName(method, invoke); logInliningDecision(methodString, false, msg, new Object[0]); @@ -227,9 +258,9 @@ try { macroNode = macroNodeClass.getConstructor(Invoke.class).newInstance(invoke); } catch (ReflectiveOperationException | IllegalArgumentException | SecurityException e) { - throw new GraalInternalError(e).addContext(invoke.node()).addContext("macroSubstitution", macroNodeClass); + throw new GraalInternalError(e).addContext(invoke.asNode()).addContext("macroSubstitution", macroNodeClass); } - macroNode.setProbability(invoke.node().probability()); + macroNode.setProbability(invoke.asNode().probability()); CallTargetNode callTarget = invoke.callTarget(); if (invoke instanceof InvokeNode) { graph.replaceFixedWithFixed((InvokeNode) invoke, graph.add(macroNode)); @@ -268,7 +299,7 @@ protected void replaceInvokeCallTarget(StructuredGraph graph, InvokeKind invokeKind, ResolvedJavaMethod targetMethod) { MethodCallTargetNode oldCallTarget = invoke.methodCallTarget(); MethodCallTargetNode newCallTarget = graph.add(new MethodCallTargetNode(invokeKind, targetMethod, oldCallTarget.arguments().toArray(new ValueNode[0]), oldCallTarget.returnType())); - invoke.node().replaceFirstInput(oldCallTarget, newCallTarget); + invoke.asNode().replaceFirstInput(oldCallTarget, newCallTarget); } } @@ -364,9 +395,9 @@ ValueNode anchoredReceiver = createAnchoredReceiver(graph, anchor, type, receiver, true); invoke.callTarget().replaceFirstInput(receiver, anchoredReceiver); - graph.addBeforeFixed(invoke.node(), receiverHub); - graph.addBeforeFixed(invoke.node(), guard); - graph.addBeforeFixed(invoke.node(), anchor); + graph.addBeforeFixed(invoke.asNode(), receiverHub); + graph.addBeforeFixed(invoke.asNode(), guard); + graph.addBeforeFixed(invoke.asNode(), anchor); } @Override @@ -439,8 +470,8 @@ returnMerge.setStateAfter(invoke.stateAfter().duplicate(invoke.stateAfter().bci)); PhiNode returnValuePhi = null; - if (invoke.node().kind() != Kind.Void) { - returnValuePhi = graph.unique(new PhiNode(invoke.node().kind(), returnMerge)); + if (invoke.asNode().kind() != Kind.Void) { + returnValuePhi = graph.unique(new PhiNode(invoke.asNode().kind(), returnMerge)); } MergeNode exceptionMerge = null; @@ -489,7 +520,7 @@ GraphUtil.killCFG(invokeWithExceptionNode.exceptionEdge()); } - assert invoke.node().isAlive(); + assert invoke.asNode().isAlive(); // replace the invoke with a switch on the type of the actual receiver createDispatchOnTypeBeforeInvoke(graph, successors, false); @@ -497,8 +528,8 @@ assert invoke.next() == continuation; invoke.setNext(null); returnMerge.setNext(continuation); - invoke.node().replaceAtUsages(returnValuePhi); - invoke.node().replaceAndDelete(null); + invoke.asNode().replaceAtUsages(returnValuePhi); + invoke.asNode().replaceAndDelete(null); ArrayList replacementNodes = new ArrayList<>(); @@ -586,7 +617,7 @@ BeginNode[] successors = new BeginNode[]{calleeEntryNode, unknownTypeSux}; createDispatchOnTypeBeforeInvoke(graph, successors, false); - calleeEntryNode.setNext(invoke.node()); + calleeEntryNode.setNext(invoke.asNode()); ResolvedJavaMethod concrete = concretes.get(0); inline(invoke, concrete, callback, replacements, assumptions, false); @@ -597,7 +628,7 @@ Kind hubKind = invoke.methodCallTarget().targetMethod().getDeclaringClass().getEncoding(Representation.ObjectHub).getKind(); LoadHubNode hub = graph.add(new LoadHubNode(invoke.methodCallTarget().receiver(), hubKind)); - graph.addBeforeFixed(invoke.node(), hub); + graph.addBeforeFixed(invoke.asNode(), hub); ResolvedJavaType[] keys = new ResolvedJavaType[ptypes.size()]; double[] keyProbabilities = new double[ptypes.size() + 1]; @@ -612,7 +643,7 @@ keySuccessors[keySuccessors.length - 1] = successors.length - 1; TypeSwitchNode typeSwitch = graph.add(new TypeSwitchNode(hub, successors, keys, keyProbabilities, keySuccessors)); - FixedWithNextNode pred = (FixedWithNextNode) invoke.node().predecessor(); + FixedWithNextNode pred = (FixedWithNextNode) invoke.asNode().predecessor(); pred.setNext(typeSwitch); } @@ -620,7 +651,7 @@ double probability, boolean useForInlining) { Invoke duplicatedInvoke = duplicateInvokeForInlining(graph, invoke, exceptionMerge, exceptionObjectPhi, useForInlining, probability); BeginNode calleeEntryNode = graph.add(new BeginNode()); - calleeEntryNode.setNext(duplicatedInvoke.node()); + calleeEntryNode.setNext(duplicatedInvoke.asNode()); calleeEntryNode.setProbability(probability); EndNode endNode = graph.add(new EndNode()); @@ -630,24 +661,24 @@ returnMerge.addForwardEnd(endNode); if (returnValuePhi != null) { - returnValuePhi.addInput(duplicatedInvoke.node()); + returnValuePhi.addInput(duplicatedInvoke.asNode()); } return calleeEntryNode; } private static Invoke duplicateInvokeForInlining(StructuredGraph graph, Invoke invoke, MergeNode exceptionMerge, PhiNode exceptionObjectPhi, boolean useForInlining, double probability) { - Invoke result = (Invoke) invoke.node().copyWithInputs(); + Invoke result = (Invoke) invoke.asNode().copyWithInputs(); Node callTarget = result.callTarget().copyWithInputs(); - result.node().replaceFirstInput(result.callTarget(), callTarget); + result.asNode().replaceFirstInput(result.callTarget(), callTarget); result.setUseForInlining(useForInlining); result.setProbability(probability); result.setInliningRelevance(invoke.inliningRelevance() * probability); - Kind kind = invoke.node().kind(); + Kind kind = invoke.asNode().kind(); if (kind != Kind.Void) { FrameState stateAfter = invoke.stateAfter(); stateAfter = stateAfter.duplicate(stateAfter.bci); - stateAfter.replaceFirstInput(invoke.node(), result.node()); + stateAfter.replaceFirstInput(invoke.asNode(), result.asNode()); result.setStateAfter(stateAfter); } @@ -712,7 +743,7 @@ BeginNode[] successors = new BeginNode[]{invocationEntry, unknownTypeSux}; createDispatchOnTypeBeforeInvoke(graph, successors, true); - invocationEntry.setNext(invoke.node()); + invocationEntry.setNext(invoke.asNode()); ValueNode receiver = invoke.methodCallTarget().receiver(); PiNode anchoredReceiver = createAnchoredReceiver(graph, invocationEntry, target.getDeclaringClass(), receiver, false); invoke.callTarget().replaceFirstInput(receiver, anchoredReceiver); @@ -935,7 +966,7 @@ } private static boolean checkInvokeConditions(Invoke invoke) { - if (invoke.predecessor() == null || !invoke.node().isAlive()) { + if (invoke.predecessor() == null || !invoke.asNode().isAlive()) { return logNotInlinedMethodAndReturnFalse(invoke, "the invoke is dead code"); } else if (!(invoke.callTarget() instanceof MethodCallTargetNode)) { return logNotInlinedMethodAndReturnFalse(invoke, "the invoke has already been lowered, or has been created as a low-level node"); @@ -1017,7 +1048,7 @@ */ public static Map inline(Invoke invoke, StructuredGraph inlineGraph, boolean receiverNullCheck) { NodeInputList parameters = invoke.callTarget().arguments(); - StructuredGraph graph = (StructuredGraph) invoke.node().graph(); + StructuredGraph graph = (StructuredGraph) invoke.asNode().graph(); FrameState stateAfter = invoke.stateAfter(); assert stateAfter.isAlive(); @@ -1045,17 +1076,17 @@ } } // ensure proper anchoring of things that were anchored to the StartNode - replacements.put(entryPointNode, BeginNode.prevBegin(invoke.node())); + replacements.put(entryPointNode, BeginNode.prevBegin(invoke.asNode())); - assert invoke.node().successors().first() != null : invoke; - assert invoke.node().predecessor() != null; + assert invoke.asNode().successors().first() != null : invoke; + assert invoke.asNode().predecessor() != null; Map duplicates = graph.addDuplicates(nodes, replacements); FixedNode firstCFGNodeDuplicate = (FixedNode) duplicates.get(firstCFGNode); if (receiverNullCheck) { receiverNullCheck(invoke); } - invoke.node().replaceAtPredecessor(firstCFGNodeDuplicate); + invoke.asNode().replaceAtPredecessor(firstCFGNodeDuplicate); FrameState stateAtExceptionEdge = null; if (invoke instanceof InvokeWithExceptionNode) { @@ -1094,7 +1125,7 @@ } FrameState outerFrameState = null; - double invokeProbability = invoke.node().probability(); + double invokeProbability = invoke.asNode().probability(); int callerLockDepth = stateAfter.nestedLockDepth(); for (Node node : duplicates.values()) { if (GraalOptions.ProbabilityAnalysis) { @@ -1117,7 +1148,7 @@ } if (node instanceof FrameState) { FrameState frameState = (FrameState) node; - assert frameState.bci != FrameState.BEFORE_BCI; + assert frameState.bci != FrameState.BEFORE_BCI : frameState; if (frameState.bci == FrameState.AFTER_BCI) { frameState.replaceAndDelete(stateAfter); } else if (frameState.bci == FrameState.AFTER_EXCEPTION_BCI) { @@ -1132,7 +1163,7 @@ if (frameState.outerFrameState() == null) { assert frameState.bci == FrameState.INVALID_FRAMESTATE_BCI || frameState.method() == inlineGraph.method(); if (outerFrameState == null) { - outerFrameState = stateAfter.duplicateModified(invoke.bci(), stateAfter.rethrowException(), invoke.node().kind()); + outerFrameState = stateAfter.duplicateModified(invoke.bci(), stateAfter.rethrowException(), invoke.asNode().kind()); outerFrameState.setDuringCall(true); } frameState.setOuterFrameState(outerFrameState); @@ -1152,7 +1183,7 @@ } else { returnValue = duplicates.get(returnNode.result()); } - invoke.node().replaceAtUsages(returnValue); + invoke.asNode().replaceAtUsages(returnValue); Node returnDuplicate = duplicates.get(returnNode); returnDuplicate.clearInputs(); Node n = invoke.next(); @@ -1160,8 +1191,8 @@ returnDuplicate.replaceAndDelete(n); } - invoke.node().replaceAtUsages(null); - GraphUtil.killCFG(invoke.node()); + invoke.asNode().replaceAtUsages(null); + GraphUtil.killCFG(invoke.asNode()); return duplicates; } @@ -1172,7 +1203,7 @@ NodeInputList parameters = callTarget.arguments(); ValueNode firstParam = parameters.size() <= 0 ? null : parameters.get(0); if (!callTarget.isStatic() && firstParam.kind() == Kind.Object && !firstParam.objectStamp().nonNull()) { - graph.addBeforeFixed(invoke.node(), + graph.addBeforeFixed(invoke.asNode(), graph.add(new FixedGuardNode(graph.unique(new IsNullNode(firstParam)), DeoptimizationReason.NullCheckException, DeoptimizationAction.InvalidateReprofile, true))); } } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java Sat Apr 13 00:33:37 2013 +0200 @@ -53,7 +53,7 @@ if (canonicalizationRoots.isEmpty()) { break; } - new CanonicalizerPhase(runtime, assumptions, canonicalizationRoots, null).apply(graph); + new CanonicalizerPhase.Instance(runtime, assumptions, canonicalizationRoots, null).apply(graph); canonicalizationRoots.clear(); } } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java Sat Apr 13 00:33:37 2013 +0200 @@ -151,7 +151,7 @@ deferred = false; processBlock(schedule.getCFG().getStartBlock(), graph.createNodeBitMap(), null, schedule, processed); Debug.dump(graph, "Lowering iteration %d", i++); - new CanonicalizerPhase(runtime, assumptions, mark, null).apply(graph); + new CanonicalizerPhase.Instance(runtime, assumptions, mark, null).apply(graph); if (!deferred && !containsLowerable(graph.getNewNodes(mark))) { // No new lowerable nodes - done! diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java Sat Apr 13 00:33:37 2013 +0200 @@ -127,21 +127,13 @@ } }; - private int tailDuplicationCount; - - public int getTailDuplicationCount() { - return tailDuplicationCount; - } - @Override protected void run(StructuredGraph graph) { // A snapshot is taken here, so that new MergeNode instances aren't considered for tail // duplication. for (MergeNode merge : graph.getNodes(MergeNode.class).snapshot()) { if (!(merge instanceof LoopBeginNode) && merge.probability() >= GraalOptions.TailDuplicationProbability) { - if (tailDuplicate(merge, DEFAULT_DECISION, null)) { - tailDuplicationCount++; - } + tailDuplicate(merge, DEFAULT_DECISION, null); } } } @@ -251,7 +243,6 @@ final HashSet duplicatedNodes = buildDuplicatedNodeSet(fixedNodes, stateAfter); mergeAfter.clearEnds(); expandDuplicated(duplicatedNodes, mergeAfter); - retargetDependencies(duplicatedNodes, anchor); List endSnapshot = merge.forwardEnds().snapshot(); List phiSnapshot = merge.phis().snapshot(); @@ -526,29 +517,6 @@ } /** - * Moves all depdendencies that point outside the duplicated area to the supplied value - * anchor node. - * - * @param duplicatedNodes The set of duplicated nodes. - * @param anchor The node that will be the new target for all dependencies that point - * outside the duplicated set of nodes. - */ - private static void retargetDependencies(HashSet duplicatedNodes, ValueAnchorNode anchor) { - for (Node node : duplicatedNodes) { - if (node instanceof ValueNode) { - NodeInputList dependencies = ((ValueNode) node).dependencies(); - for (int i = 0; i < dependencies.size(); i++) { - Node dependency = dependencies.get(i); - if (dependency != null && !duplicatedNodes.contains(dependency)) { - Debug.log("retargeting dependency %s to %s on %s", dependency, anchor, node); - dependencies.set(i, anchor); - } - } - } - } - } - - /** * Checks if the given node has usages that are not within the given set of nodes. * * @param node The node whose usages are checked. diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/BasePhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/BasePhase.java Sat Apr 13 00:33:37 2013 +0200 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2011, 2013, 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.phases; + +import com.oracle.graal.debug.*; +import com.oracle.graal.nodes.*; + +/** + * Base class for all compiler phases. Subclasses should be stateless. There will be one global + * instance for each compiler phase that is shared for all compilations. VM-, target- and + * compilation-specific data can be passed with a context object. + */ +public abstract class BasePhase { + + private String name; + private static final DebugMetric metricPhaseRuns = Debug.metric("Runs"); + protected static final DebugMetric METRIC_PROCESSED_NODES = Debug.metric("ProcessedNodes"); + + protected BasePhase() { + this.name = this.getClass().getSimpleName(); + if (name.endsWith("Phase")) { + name = name.substring(0, name.length() - "Phase".length()); + } + } + + protected BasePhase(String name) { + this.name = name; + } + + protected String getDetailedName() { + return getName(); + } + + public final void apply(final StructuredGraph graph, final C context) { + apply(graph, context, true); + } + + public final void apply(final StructuredGraph graph, final C context, final boolean dumpGraph) { + Debug.scope(name, this, new Runnable() { + + public void run() { + BasePhase.this.run(graph, context); + metricPhaseRuns.increment(); + if (dumpGraph) { + Debug.dump(graph, "After phase %s", name); + } + assert graph.verify(); + } + }); + } + + public final String getName() { + return name; + } + + protected abstract void run(StructuredGraph graph, C context); +} diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Sat Apr 13 00:33:37 2013 +0200 @@ -128,7 +128,7 @@ public static String MethodFilter = null; public static boolean DumpOnError = ____; public static boolean GenericDynamicCounters = ____; - public static boolean BenchmarkDynamicCounters = ____; + public static String BenchmarkDynamicCounters = null; // Ideal graph visualizer output settings public static boolean PrintBinaryGraphs = true; @@ -152,6 +152,10 @@ public static boolean ExitVMOnBailout = ____; public static boolean ExitVMOnException = true; + // HotSpot command line options + public static boolean HotSpotPrintCompilation = ____; + public static boolean HotSpotPrintInlining = ____; + // Register allocator debugging public static String RegisterPressure = null; diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/Phase.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/Phase.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/Phase.java Sat Apr 13 00:33:37 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, 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 @@ -22,28 +22,18 @@ */ package com.oracle.graal.phases; -import com.oracle.graal.debug.*; import com.oracle.graal.nodes.*; -public abstract class Phase { - - private String name; - private static final DebugMetric metricPhaseRuns = Debug.metric("Runs"); - protected static final DebugMetric METRIC_PROCESSED_NODES = Debug.metric("ProcessedNodes"); +/** + * Base class for compiler phases that don't need a context object. + */ +public abstract class Phase extends BasePhase { protected Phase() { - this.name = this.getClass().getSimpleName(); - if (name.endsWith("Phase")) { - name = name.substring(0, name.length() - "Phase".length()); - } } protected Phase(String name) { - this.name = name; - } - - protected String getDetailedName() { - return getName(); + super(name); } public final void apply(final StructuredGraph graph) { @@ -51,22 +41,13 @@ } public final void apply(final StructuredGraph graph, final boolean dumpGraph) { - Debug.scope(name, this, new Runnable() { - - public void run() { - Phase.this.run(graph); - metricPhaseRuns.increment(); - if (dumpGraph) { - Debug.dump(graph, "After phase %s", name); - } - assert graph.verify(); - } - }); - } - - public final String getName() { - return name; + apply(graph, null, dumpGraph); } protected abstract void run(StructuredGraph graph); + + @Override + protected final void run(StructuredGraph graph, Object context) { + run(graph); + } } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/PhaseSuite.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/PhaseSuite.java Sat Apr 13 00:33:37 2013 +0200 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013, 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.phases; + +import java.util.*; + +import com.oracle.graal.nodes.*; + +public class PhaseSuite extends BasePhase { + + private final List> phases; + + public PhaseSuite(String name, List> phases) { + super(name); + this.phases = phases; + } + + @Override + protected void run(StructuredGraph graph, C context) { + for (BasePhase phase : phases) { + phase.apply(graph, context); + } + } +} diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/PostOrderNodeIterator.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/PostOrderNodeIterator.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/PostOrderNodeIterator.java Sat Apr 13 00:33:37 2013 +0200 @@ -217,7 +217,7 @@ } protected void invoke(Invoke invoke) { - node(invoke.node()); + node(invoke.asNode()); } protected void finished() { diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/HighTierContext.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/HighTierContext.java Sat Apr 13 00:33:37 2013 +0200 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2013, 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.phases.tiers; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; + +public class HighTierContext extends PhaseContext { + + public HighTierContext(MetaAccessProvider runtime, Assumptions assumptions) { + super(runtime, assumptions); + } +} diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/PhaseContext.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/PhaseContext.java Sat Apr 13 00:33:37 2013 +0200 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2013, 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.phases.tiers; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; + +public class PhaseContext { + + private final MetaAccessProvider runtime; + private final Assumptions assumptions; + + public PhaseContext(MetaAccessProvider runtime, Assumptions assumptions) { + this.runtime = runtime; + this.assumptions = assumptions; + } + + public MetaAccessProvider getRuntime() { + return runtime; + } + + public Assumptions getAssumptions() { + return assumptions; + } +} diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java --- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java Sat Apr 13 00:33:37 2013 +0200 @@ -23,18 +23,20 @@ package com.oracle.graal.replacements.amd64; import static com.oracle.graal.replacements.SnippetTemplate.*; -import static com.oracle.graal.replacements.SnippetTemplate.Arguments.*; import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*; +import java.util.*; + import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.calc.ConvertNode.Op; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.Snippet.*; +import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; /** * Snippets used for conversion operations on AMD64 where the AMD64 instruction used does not match @@ -54,7 +56,7 @@ * @param result the result produced by the CVTTSS2SI instruction */ @Snippet - public static int f2i(@Parameter("input") float input, @Parameter("result") int result) { + public static int f2i(float input, int result) { if (result == Integer.MIN_VALUE) { probability(NOT_FREQUENT_PROBABILITY); if (Float.isNaN(input)) { @@ -80,7 +82,7 @@ * @param result the result produced by the CVTTSS2SI instruction */ @Snippet - public static long f2l(@Parameter("input") float input, @Parameter("result") long result) { + public static long f2l(float input, long result) { if (result == Long.MIN_VALUE) { probability(NOT_FREQUENT_PROBABILITY); if (Float.isNaN(input)) { @@ -106,7 +108,7 @@ * @param result the result produced by the CVTTSS2SI instruction */ @Snippet - public static int d2i(@Parameter("input") double input, @Parameter("result") int result) { + public static int d2i(double input, int result) { if (result == Integer.MIN_VALUE) { probability(NOT_FREQUENT_PROBABILITY); if (Double.isNaN(input)) { @@ -132,7 +134,7 @@ * @param result the result produced by the CVTTSS2SI instruction */ @Snippet - public static long d2l(@Parameter("input") double input, @Parameter("result") long result) { + public static long d2l(double input, long result) { if (result == Long.MIN_VALUE) { probability(NOT_FREQUENT_PROBABILITY); if (Double.isNaN(input)) { @@ -146,34 +148,26 @@ return result; } - public static class Templates extends AbstractTemplates { + public static class Templates extends AbstractTemplates { - private final ResolvedJavaMethod f2i; - private final ResolvedJavaMethod f2l; - private final ResolvedJavaMethod d2i; - private final ResolvedJavaMethod d2l; + private final EnumMap snippets; public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) { - super(runtime, replacements, target, AMD64ConvertSnippets.class); - f2i = snippet("f2i", float.class, int.class); - f2l = snippet("f2l", float.class, long.class); - d2i = snippet("d2i", double.class, int.class); - d2l = snippet("d2l", double.class, long.class); + super(runtime, replacements, target); + + snippets = new EnumMap<>(Op.class); + snippets.put(Op.F2I, snippet(AMD64ConvertSnippets.class, "f2i")); + snippets.put(Op.F2L, snippet(AMD64ConvertSnippets.class, "f2l")); + snippets.put(Op.D2I, snippet(AMD64ConvertSnippets.class, "d2i")); + snippets.put(Op.D2L, snippet(AMD64ConvertSnippets.class, "d2l")); } public void lower(ConvertNode convert, LoweringTool tool) { - if (convert.opcode == Op.F2I) { - lower0(convert, tool, f2i); - } else if (convert.opcode == Op.F2L) { - lower0(convert, tool, f2l); - } else if (convert.opcode == Op.D2I) { - lower0(convert, tool, d2i); - } else if (convert.opcode == Op.D2L) { - lower0(convert, tool, d2l); + SnippetInfo key = snippets.get(convert.opcode); + if (key == null) { + return; } - } - private void lower0(ConvertNode convert, LoweringTool tool, ResolvedJavaMethod snippet) { StructuredGraph graph = (StructuredGraph) convert.graph(); // Insert a unique placeholder node in place of the Convert node so that the @@ -183,11 +177,13 @@ LocalNode replacee = graph.add(new LocalNode(Integer.MAX_VALUE, convert.stamp())); convert.replaceAtUsages(replacee); - Key key = new Key(snippet); - Arguments arguments = arguments("input", convert.value()).add("result", convert); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering %s in %s: node=%s, template=%s, arguments=%s", convert.opcode, graph, convert, template, arguments); - template.instantiate(runtime, replacee, DEFAULT_REPLACER, tool, arguments); + Arguments args = new Arguments(key); + args.add("input", convert.value()); + args.add("result", convert); + + SnippetTemplate template = template(args); + Debug.log("Lowering %s in %s: node=%s, template=%s, arguments=%s", convert.opcode, graph, convert, template, args); + template.instantiate(runtime, replacee, DEFAULT_REPLACER, tool, args); } } } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -54,7 +54,7 @@ Debug.dump(graph, "Graph"); new InliningPhase(runtime(), null, replacements, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph); Debug.dump(graph, "Graph"); - new CanonicalizerPhase(runtime(), assumptions).apply(graph); + new CanonicalizerPhase.Instance(runtime(), assumptions).apply(graph); new DeadCodeEliminationPhase().apply(graph); assertNotInGraph(graph, Invoke.class); diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java Sat Apr 13 00:33:37 2013 +0200 @@ -0,0 +1,243 @@ +/* + * 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.replacements; + +import static com.oracle.graal.replacements.SnippetTemplate.*; + +import java.lang.reflect.*; +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.graph.Node.NodeIntrinsic; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.replacements.Snippet.Fold; +import com.oracle.graal.replacements.Snippet.SnippetInliningPolicy; +import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; +import com.oracle.graal.word.*; + +public class BoxingSnippets implements Snippets { + + /** + * This snippet inlining policy differs from the default one in that it does normal inlining of + * boxing methods like {@link Integer#valueOf(int)} (as opposed to method substitution). + */ + public static class BoxingSnippetInliningPolicy implements SnippetInliningPolicy { + + @Override + public boolean shouldInline(ResolvedJavaMethod method, ResolvedJavaMethod caller) { + if (Modifier.isNative(method.getModifiers())) { + return false; + } + if (method.getAnnotation(Fold.class) != null) { + return false; + } + if (method.getAnnotation(NodeIntrinsic.class) != null) { + return false; + } + if (method.getAnnotation(Word.Operation.class) != null) { + return false; + } + return true; + } + + @Override + public boolean shouldUseReplacement(ResolvedJavaMethod callee, ResolvedJavaMethod methodToParse) { + return false; + } + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static Boolean booleanValueOf(boolean value) { + valueOfCounter.inc(); + return UnsafeCastNode.unsafeCast(Boolean.valueOf(value), StampFactory.forNodeIntrinsic()); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static Byte byteValueOf(byte value) { + valueOfCounter.inc(); + return UnsafeCastNode.unsafeCast(Byte.valueOf(value), StampFactory.forNodeIntrinsic()); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static Character charValueOf(char value) { + valueOfCounter.inc(); + return UnsafeCastNode.unsafeCast(Character.valueOf(value), StampFactory.forNodeIntrinsic()); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static Double doubleValueOf(double value) { + valueOfCounter.inc(); + return UnsafeCastNode.unsafeCast(Double.valueOf(value), StampFactory.forNodeIntrinsic()); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static Float floatValueOf(float value) { + valueOfCounter.inc(); + return UnsafeCastNode.unsafeCast(Float.valueOf(value), StampFactory.forNodeIntrinsic()); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static Integer intValueOf(int value) { + valueOfCounter.inc(); + return UnsafeCastNode.unsafeCast(Integer.valueOf(value), StampFactory.forNodeIntrinsic()); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static Long longValueOf(long value) { + valueOfCounter.inc(); + return UnsafeCastNode.unsafeCast(Long.valueOf(value), StampFactory.forNodeIntrinsic()); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static Short shortValueOf(short value) { + valueOfCounter.inc(); + return UnsafeCastNode.unsafeCast(Short.valueOf(value), StampFactory.forNodeIntrinsic()); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static boolean booleanValue(Boolean value) { + valueOfCounter.inc(); + return value.booleanValue(); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static byte byteValue(Byte value) { + valueOfCounter.inc(); + return value.byteValue(); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static char charValue(Character value) { + valueOfCounter.inc(); + return value.charValue(); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static double doubleValue(Double value) { + valueOfCounter.inc(); + return value.doubleValue(); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static float floatValue(Float value) { + valueOfCounter.inc(); + return value.floatValue(); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static int intValue(Integer value) { + valueOfCounter.inc(); + return value.intValue(); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static long longValue(Long value) { + valueOfCounter.inc(); + return value.longValue(); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static short shortValue(Short value) { + valueOfCounter.inc(); + return value.shortValue(); + } + + public static FloatingNode canonicalizeBoxing(BoxNode box, MetaAccessProvider runtime) { + ValueNode value = box.getValue(); + if (value.isConstant()) { + Constant sourceConstant = value.asConstant(); + switch (box.getBoxingKind()) { + case Boolean: + return ConstantNode.forObject(Boolean.valueOf(sourceConstant.asInt() != 0), runtime, box.graph()); + case Byte: + return ConstantNode.forObject(Byte.valueOf((byte) sourceConstant.asInt()), runtime, box.graph()); + case Char: + return ConstantNode.forObject(Character.valueOf((char) sourceConstant.asInt()), runtime, box.graph()); + case Short: + return ConstantNode.forObject(Short.valueOf((short) sourceConstant.asInt()), runtime, box.graph()); + case Int: + return ConstantNode.forObject(Integer.valueOf(sourceConstant.asInt()), runtime, box.graph()); + case Long: + return ConstantNode.forObject(Long.valueOf(sourceConstant.asLong()), runtime, box.graph()); + case Float: + return ConstantNode.forObject(Float.valueOf(sourceConstant.asFloat()), runtime, box.graph()); + case Double: + return ConstantNode.forObject(Double.valueOf(sourceConstant.asDouble()), runtime, box.graph()); + default: + assert false : "Unexpected source kind for boxing"; + break; + } + } + return null; + } + + public static class Templates extends AbstractTemplates { + + private final EnumMap boxSnippets = new EnumMap<>(Kind.class); + private final EnumMap unboxSnippets = new EnumMap<>(Kind.class); + + public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) { + super(runtime, replacements, target); + for (Kind kind : new Kind[]{Kind.Boolean, Kind.Byte, Kind.Char, Kind.Double, Kind.Float, Kind.Int, Kind.Long, Kind.Short}) { + boxSnippets.put(kind, snippet(BoxingSnippets.class, kind.getJavaName() + "ValueOf")); + unboxSnippets.put(kind, snippet(BoxingSnippets.class, kind.getJavaName() + "Value")); + } + } + + public void lower(BoxNode box) { + FloatingNode canonical = canonicalizeBoxing(box, runtime); + if (canonical != null) { + ((StructuredGraph) box.graph()).replaceFixedWithFloating(box, canonical); + } else { + Arguments args = new Arguments(boxSnippets.get(box.getBoxingKind())); + args.add("value", box.getValue()); + + SnippetTemplate template = template(args); + Debug.log("Lowering integerValueOf in %s: node=%s, template=%s, arguments=%s", box.graph(), box, template, args); + template.instantiate(runtime, box, DEFAULT_REPLACER, args); + } + } + + public void lower(UnboxNode unbox) { + Arguments args = new Arguments(unboxSnippets.get(unbox.getBoxingKind())); + args.add("value", unbox.getValue()); + + SnippetTemplate template = template(args); + Debug.log("Lowering integerValueOf in %s: node=%s, template=%s, arguments=%s", unbox.graph(), unbox, template, args); + template.instantiate(runtime, unbox, DEFAULT_REPLACER, args); + } + } + + private static final SnippetCounter.Group integerCounters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("Integer intrinsifications") : null; + private static final SnippetCounter valueOfCounter = new SnippetCounter(integerCounters, "valueOf", "valueOf intrinsification"); + +} diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSubstitutions.java Sat Apr 13 00:33:37 2013 +0200 @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.replacements; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; +import com.oracle.graal.nodes.extended.*; + +public class BoxingSubstitutions { + + @ClassSubstitution(Boolean.class) + private static class BooleanSubstitutions { + + @MethodSubstitution(forced = true) + public static Boolean valueOf(boolean value) { + return BoxNode.box(value, Boolean.class, Kind.Boolean); + } + + @MethodSubstitution(isStatic = false, forced = true) + public static boolean booleanValue(Boolean value) { + return UnboxNode.unbox(value, Kind.Boolean); + } + } + + @ClassSubstitution(Byte.class) + private static class ByteSubstitutions { + + @MethodSubstitution(forced = true) + public static Byte valueOf(byte value) { + return BoxNode.box(value, Byte.class, Kind.Byte); + } + + @MethodSubstitution(isStatic = false, forced = true) + public static byte byteValue(Byte value) { + return UnboxNode.unbox(value, Kind.Byte); + } + } + + @ClassSubstitution(Character.class) + private static class CharacterSubstitutions { + + @MethodSubstitution(forced = true) + public static Character valueOf(char value) { + return BoxNode.box(value, Character.class, Kind.Char); + } + + @MethodSubstitution(isStatic = false, forced = true) + public static char charValue(Character value) { + return UnboxNode.unbox(value, Kind.Char); + } + } + + @ClassSubstitution(Double.class) + private static class DoubleSubstitutions { + + @MethodSubstitution(forced = true) + public static Double valueOf(double value) { + return BoxNode.box(value, Double.class, Kind.Double); + } + + @MethodSubstitution(isStatic = false, forced = true) + public static double doubleValue(Double value) { + return UnboxNode.unbox(value, Kind.Double); + } + } + + @ClassSubstitution(Float.class) + private static class FloatSubstitutions { + + @MethodSubstitution(forced = true) + public static Float valueOf(float value) { + return BoxNode.box(value, Float.class, Kind.Float); + } + + @MethodSubstitution(isStatic = false, forced = true) + public static float floatValue(Float value) { + return UnboxNode.unbox(value, Kind.Float); + } + } + + @ClassSubstitution(Integer.class) + private static class IntegerSubstitutions { + + @MethodSubstitution(forced = true) + public static Integer valueOf(int value) { + return BoxNode.box(value, Integer.class, Kind.Int); + } + + @MethodSubstitution(isStatic = false, forced = true) + public static int intValue(Integer value) { + return UnboxNode.unbox(value, Kind.Int); + } + } + + @ClassSubstitution(Long.class) + private static class LongSubstitutions { + + @MethodSubstitution(forced = true) + public static Long valueOf(long value) { + return BoxNode.box(value, Long.class, Kind.Long); + } + + @MethodSubstitution(isStatic = false, forced = true) + public static long longValue(Long value) { + return UnboxNode.unbox(value, Kind.Long); + } + } + + @ClassSubstitution(Short.class) + private static class ShortSubstitutions { + + @MethodSubstitution(forced = true) + public static Short valueOf(short value) { + return BoxNode.box(value, Short.class, Kind.Short); + } + + @MethodSubstitution(isStatic = false, forced = true) + public static short shortValue(Short value) { + return UnboxNode.unbox(value, Kind.Short); + } + } + + public static Class[] getClasses() { + return new Class[]{BooleanSubstitutions.class, ByteSubstitutions.class, CharacterSubstitutions.class, DoubleSubstitutions.class, FloatSubstitutions.class, IntegerSubstitutions.class, + LongSubstitutions.class, ShortSubstitutions.class}; + } +} diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java Sat Apr 13 00:33:37 2013 +0200 @@ -33,6 +33,10 @@ public class GraalMethodSubstitutions implements ReplacementsProvider { public void registerReplacements(Replacements replacements) { + for (Class clazz : BoxingSubstitutions.getClasses()) { + replacements.registerSubstitutions(clazz); + } + if (GraalOptions.Intrinsify) { replacements.registerSubstitutions(MathSubstitutionsX86.class); replacements.registerSubstitutions(DoubleSubstitutions.class); diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java Sat Apr 13 00:33:37 2013 +0200 @@ -34,7 +34,9 @@ import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.util.*; -import com.oracle.graal.replacements.SnippetTemplate.*; +import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.UsageReplacer; /** * Helper class for lowering {@link InstanceOfNode}s with snippets. The majority of the complexity @@ -49,31 +51,16 @@ * {@link IfNode}. This avoids materializing the instanceof test as a boolean which is then retested * by the {@link IfNode}. */ -public abstract class InstanceOfSnippetsTemplates extends AbstractTemplates { +public abstract class InstanceOfSnippetsTemplates extends AbstractTemplates { - public InstanceOfSnippetsTemplates(MetaAccessProvider runtime, Replacements replacements, TargetDescription target, Class snippetsClass) { - super(runtime, replacements, target, snippetsClass); + public InstanceOfSnippetsTemplates(MetaAccessProvider runtime, Replacements replacements, TargetDescription target) { + super(runtime, replacements, target); } /** - * The key and arguments used to retrieve and instantiate an instanceof snippet template. + * Gets the arguments used to retrieve and instantiate an instanceof snippet template. */ - public static class KeyAndArguments { - - public final Key key; - public final Arguments arguments; - - public KeyAndArguments(Key key, Arguments arguments) { - this.key = key; - this.arguments = arguments; - } - - } - - /** - * Gets the key and arguments used to retrieve and instantiate an instanceof snippet template. - */ - protected abstract KeyAndArguments getKeyAndArguments(InstanceOfUsageReplacer replacer, LoweringTool tool); + protected abstract Arguments makeArguments(InstanceOfUsageReplacer replacer, LoweringTool tool); public void lower(FloatingNode instanceOf, LoweringTool tool) { assert instanceOf instanceof InstanceOfNode || instanceOf instanceof InstanceOfDynamicNode; @@ -90,9 +77,8 @@ // No need to re-instantiate the snippet - just re-use its result replacer.replaceUsingInstantiation(); } else { - KeyAndArguments keyAndArguments = getKeyAndArguments(replacer, tool); - SnippetTemplate template = cache.get(keyAndArguments.key); - template.instantiate(runtime, instanceOf, replacer, tool, keyAndArguments.arguments); + Arguments args = makeArguments(replacer, tool); + template(args).instantiate(runtime, instanceOf, replacer, tool, args); } } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java Sat Apr 13 00:33:37 2013 +0200 @@ -104,7 +104,7 @@ Node newInstance = createNodeInstance(runtime, c, parameterTypes, returnType, intrinsic.setStampFromReturnType(), nodeConstructorArguments); // Replace the invoke with the new node. - invoke.node().graph().add(newInstance); + invoke.asNode().graph().add(newInstance); invoke.intrinsify(newInstance); // Clean up checkcast instructions inserted by javac if the return type is generic. @@ -130,7 +130,7 @@ if (constant != null) { // Replace the invoke with the result of the call - ConstantNode node = ConstantNode.forConstant(constant, runtime, invoke.node().graph()); + ConstantNode node = ConstantNode.forConstant(constant, runtime, invoke.asNode().graph()); invoke.intrinsify(node); // Clean up checkcast instructions inserted by javac if the return type is generic. diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Sat Apr 13 00:33:37 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, 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 @@ -60,7 +60,6 @@ // These data structures are all fully initialized during single-threaded // compiler startup and so do not need to be concurrent. private final Map registeredMethodSubstitutions; - private final Set registeredSnippets; private final Map> registerMacroSubstitutions; private final Set forcedSubstitutions; @@ -70,36 +69,20 @@ this.assumptions = assumptions; this.graphs = new ConcurrentHashMap<>(); this.registeredMethodSubstitutions = new HashMap<>(); - this.registeredSnippets = new HashSet<>(); this.registerMacroSubstitutions = new HashMap<>(); this.forcedSubstitutions = new HashSet<>(); } - public void registerSnippets(Class snippets) { - assert Snippets.class.isAssignableFrom(snippets); - for (Method method : snippets.getDeclaredMethods()) { - if (method.getAnnotation(Snippet.class) != null) { - int modifiers = method.getModifiers(); - if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) { - throw new RuntimeException("Snippet must not be abstract or native"); - } - ResolvedJavaMethod snippet = runtime.lookupJavaMethod(method); - registeredSnippets.add(snippet); - } - } - } + public StructuredGraph getSnippet(ResolvedJavaMethod method) { + assert method.getAnnotation(Snippet.class) != null : "Snippet must be annotated with @" + Snippet.class.getSimpleName(); + assert !Modifier.isAbstract(method.getModifiers()) && !Modifier.isNative(method.getModifiers()) : "Snippet must not be abstract or native"; - public StructuredGraph getSnippet(ResolvedJavaMethod method) { - if (!registeredSnippets.contains(method)) { - return null; - } StructuredGraph graph = graphs.get(method); if (graph == null) { graphs.putIfAbsent(method, makeGraph(method, null, inliningPolicy(method))); graph = graphs.get(method); } return graph; - } public StructuredGraph getMethodSubstitution(ResolvedJavaMethod original) { @@ -340,7 +323,7 @@ protected void afterInline(StructuredGraph caller, StructuredGraph callee) { if (GraalOptions.OptCanonicalizer) { new WordTypeRewriterPhase(runtime, target.wordKind).apply(caller); - new CanonicalizerPhase(runtime, assumptions).apply(caller); + new CanonicalizerPhase.Instance(runtime, assumptions).apply(caller); } } @@ -354,7 +337,7 @@ new DeadCodeEliminationPhase().apply(graph); if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(runtime, assumptions).apply(graph); + new CanonicalizerPhase.Instance(runtime, assumptions).apply(graph); } } @@ -488,7 +471,6 @@ @Override public Collection getAllReplacements() { HashSet result = new HashSet<>(); - result.addAll(registeredSnippets); result.addAll(registeredMethodSubstitutions.keySet()); result.addAll(registerMacroSubstitutions.keySet()); return result; diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Snippet.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Snippet.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Snippet.java Sat Apr 13 00:33:37 2013 +0200 @@ -27,7 +27,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.Node.NodeIntrinsic; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*; @@ -122,20 +121,6 @@ } /** - * Denotes a snippet parameter that will be bound during snippet template - * {@linkplain SnippetTemplate#instantiate instantiation}. - */ - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.PARAMETER) - public @interface Parameter { - - /** - * The name of this parameter. - */ - String value(); - } - - /** * Denotes a snippet parameter representing 0 or more arguments that will be bound during * snippet template {@linkplain SnippetTemplate#instantiate instantiation}. During snippet * template creation, its value must be an array whose length specifies the number of arguments @@ -149,11 +134,6 @@ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) public @interface VarargsParameter { - - /** - * The name of this parameter. - */ - String value(); } /** @@ -163,61 +143,5 @@ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) public @interface ConstantParameter { - - /** - * The name of this constant. - */ - String value(); - } - - /** - * Wrapper for the prototype value of a {@linkplain VarargsParameter varargs} parameter. - */ - public static class Varargs { - - private final Object args; - private final Class argType; - private final int length; - private final Stamp argStamp; - - public static Varargs vargargs(Object array, Stamp argStamp) { - return new Varargs(array, argStamp); - } - - public Varargs(Object array, Stamp argStamp) { - assert array != null; - this.argType = array.getClass().getComponentType(); - this.argStamp = argStamp; - assert this.argType != null; - this.length = java.lang.reflect.Array.getLength(array); - this.args = array; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof Varargs) { - Varargs other = (Varargs) obj; - return other.argType == argType && other.length == length; - } - return false; - } - - public Object getArray() { - return args; - } - - public Stamp getArgStamp() { - return argStamp; - } - - @Override - public int hashCode() { - return argType.hashCode() ^ length; - } - - @Override - public String toString() { - return argType.getName() + "[" + length + "]"; - } } } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Sat Apr 13 00:33:37 2013 +0200 @@ -22,11 +22,8 @@ */ package com.oracle.graal.replacements; -import static com.oracle.graal.api.meta.MetaUtil.*; - import java.lang.reflect.*; import java.util.*; -import java.util.Map.Entry; import java.util.concurrent.*; import com.oracle.graal.api.code.*; @@ -42,8 +39,6 @@ import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.replacements.Snippet.ConstantParameter; -import com.oracle.graal.replacements.Snippet.Parameter; -import com.oracle.graal.replacements.Snippet.Varargs; import com.oracle.graal.replacements.Snippet.VarargsParameter; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*; @@ -53,173 +48,274 @@ * A snippet template is a graph created by parsing a snippet method and then specialized by binding * constants to the snippet's {@link ConstantParameter} parameters. * - * Snippet templates can be managed in a {@link Cache}. + * Snippet templates can be managed in a cache maintained by {@link AbstractTemplates}. */ public class SnippetTemplate { /** - * A snippet template key encapsulates the method from which a snippet was built and the - * arguments used to specialize the snippet. - * - * @see Cache + * Holds the {@link ResolvedJavaMethod} of the snippet, together with some information about the + * method that needs to be computed only once. The {@link SnippetInfo} should be created once + * per snippet an then cached. */ - public static class Key implements Iterable> { + public static class SnippetInfo { + + protected final ResolvedJavaMethod method; + protected final ConstantParameter[] constantParameters; + protected final VarargsParameter[] varargsParameters; + + /** + * The parameter names, taken from the local variables table. Only used for assertion + * checking, so use only within an assert statement. + */ + protected final String[] names; + + protected SnippetInfo(ResolvedJavaMethod method) { + this.method = method; - public final ResolvedJavaMethod method; - private final HashMap map = new HashMap<>(); - private int hash; + assert Modifier.isStatic(method.getModifiers()) : "snippet method must be static: " + MetaUtil.format("%H.%n", method); + int count = method.getSignature().getParameterCount(false); + constantParameters = new ConstantParameter[count]; + varargsParameters = new VarargsParameter[count]; + for (int i = 0; i < count; i++) { + constantParameters[i] = MetaUtil.getParameterAnnotation(ConstantParameter.class, i, method); + varargsParameters[i] = MetaUtil.getParameterAnnotation(VarargsParameter.class, i, method); + + assert !isConstantParameter(i) || !isVarargsParameter(i) : "Parameter cannot be annotated with both @" + ConstantParameter.class.getSimpleName() + " and @" + + VarargsParameter.class.getSimpleName(); + } - public Key(ResolvedJavaMethod method) { - this.method = method; - this.hash = method.hashCode(); + names = new String[count]; + // Retrieve the names only when assertions are turned on. + assert initNames(); + } + + private boolean initNames() { + int slotIdx = 0; + for (int i = 0; i < names.length; i++) { + names[i] = method.getLocalVariableTable().getLocal(slotIdx, 0).getName(); + + Kind kind = method.getSignature().getParameterKind(i); + slotIdx += kind == Kind.Long || kind == Kind.Double ? 2 : 1; + } + return true; } - public Key add(String name, Object value) { - assert !map.containsKey(name); - map.put(name, value); - hash = hash ^ name.hashCode(); - if (value != null) { - hash *= (value.hashCode() + 1); - } + public ResolvedJavaMethod getMethod() { + return method; + } + + public int getParameterCount() { + return constantParameters.length; + } + + public boolean isConstantParameter(int paramIdx) { + return constantParameters[paramIdx] != null; + } + + public boolean isVarargsParameter(int paramIdx) { + return varargsParameters[paramIdx] != null; + } + } + + /** + * Values that are bound to the snippet method parameters. The methods {@link #add}, + * {@link #addConst}, and {@link #addVarargs} must be called in the same order as in the + * signature of the snippet method. The parameter name is passed to the add methods for + * assertion checking, i.e., to enforce that the order matches. Which method needs to be called + * depends on the annotation of the snippet method parameter: + *
    + *
  • Use {@link #add} for a parameter without an annotation. The value is bound when the + * {@link SnippetTemplate} is {@link SnippetTemplate#instantiate instantiated}. + *
  • Use {@link #addConst} for a parameter annotated with {@link ConstantParameter}. The value + * is bound when the {@link SnippetTemplate} is {@link SnippetTemplate#SnippetTemplate created}. + *
  • Use {@link #addVarargs} for an array parameter annotated with {@link VarargsParameter}. A + * separate {@link SnippetTemplate} is {@link SnippetTemplate#SnippetTemplate created} for every + * distinct array length. The actual values are bound when the {@link SnippetTemplate} is + * {@link SnippetTemplate#instantiate instantiated} + *
+ */ + public static class Arguments { + + protected final SnippetInfo info; + protected final CacheKey cacheKey; + protected final Object[] values; + + protected int nextParamIdx; + + public Arguments(SnippetInfo info) { + this.info = info; + this.cacheKey = new CacheKey(info); + this.values = new Object[info.getParameterCount()]; + } + + public Arguments add(String name, Object value) { + assert check(name, false, false); + values[nextParamIdx] = value; + nextParamIdx++; return this; } - public int length() { - return map.size(); + public Arguments addConst(String name, Object value) { + assert check(name, true, false); + values[nextParamIdx] = value; + cacheKey.setParam(nextParamIdx, value); + nextParamIdx++; + return this; } - public Object get(String name) { - return map.get(name); + public Arguments addVarargs(String name, Class componentType, Stamp argStamp, Object value) { + assert check(name, false, true); + Varargs varargs = new Varargs(componentType, argStamp, value); + values[nextParamIdx] = varargs; + // A separate template is necessary for every distinct array length + cacheKey.setParam(nextParamIdx, varargs.length); + nextParamIdx++; + return this; + } + + private boolean check(String name, boolean constParam, boolean varargsParam) { + assert nextParamIdx < info.getParameterCount() : "too many parameters: " + name + " " + this; + assert info.names[nextParamIdx].equals(name) : "wrong parameter name: " + name + " " + this; + assert constParam == info.isConstantParameter(nextParamIdx) : "Parameter " + (constParam ? "not " : "") + "annotated with @" + ConstantParameter.class.getSimpleName() + ": " + name + + " " + this; + assert varargsParam == info.isVarargsParameter(nextParamIdx) : "Parameter " + (varargsParam ? "not " : "") + "annotated with @" + VarargsParameter.class.getSimpleName() + ": " + name + + " " + this; + return true; } @Override - public Iterator> iterator() { - return map.entrySet().iterator(); + public String toString() { + StringBuilder result = new StringBuilder(); + result.append("Parameters<").append(MetaUtil.format("%H.%n", info.method)).append(" ["); + String sep = ""; + for (int i = 0; i < info.getParameterCount(); i++) { + result.append(sep); + if (info.isConstantParameter(i)) { + result.append("const "); + } else if (info.isVarargsParameter(i)) { + result.append("varargs "); + } + result.append(info.names[i]).append(" = ").append(values[i]); + sep = ", "; + } + result.append(">"); + return result.toString(); + } + } + + /** + * Wrapper for the prototype value of a {@linkplain VarargsParameter varargs} parameter. + */ + static class Varargs { + + protected final Class componentType; + protected final Stamp stamp; + protected final Object value; + protected final int length; + + protected Varargs(Class componentType, Stamp stamp, Object value) { + this.componentType = componentType; + this.stamp = stamp; + this.value = value; + if (value instanceof List) { + this.length = ((List) value).size(); + } else { + this.length = Array.getLength(value); + } + } + } + + static class CacheKey { + + private final ResolvedJavaMethod method; + private final Object[] values; + private int hash; + + protected CacheKey(SnippetInfo info) { + this.method = info.method; + this.values = new Object[info.getParameterCount()]; + this.hash = info.method.hashCode(); + } + + protected void setParam(int paramIdx, Object value) { + values[paramIdx] = value; + hash = (hash * 31) ^ (value == null ? 0 : value.hashCode()); } @Override public boolean equals(Object obj) { - if (obj instanceof Key) { - Key other = (Key) obj; - return other.method == method && other.map.equals(map); + if (!(obj instanceof CacheKey)) { + return false; + } + CacheKey other = (CacheKey) obj; + if (method != other.method) { + return false; } - return false; + for (int i = 0; i < values.length; i++) { + if (values[i] != null && !values[i].equals(other.values[i])) { + return false; + } + } + return true; } @Override public int hashCode() { return hash; } - - @Override - public String toString() { - return MetaUtil.format("%h.%n", method) + map.toString(); - } - - public Set names() { - return map.keySet(); - } } /** - * Arguments used to instantiate a template. + * Base class for snippet classes. It provides a cache for {@link SnippetTemplate}s. */ - public static class Arguments implements Iterable> { - - private final HashMap map = new HashMap<>(); - - public static Arguments arguments(String name, Object value) { - return new Arguments().add(name, value); - } - - public Arguments add(String name, Object value) { - assert !map.containsKey(name); - map.put(name, value); - return this; - } - - public int length() { - return map.size(); - } + public abstract static class AbstractTemplates { - @Override - public Iterator> iterator() { - return map.entrySet().iterator(); - } - - @Override - public String toString() { - return map.toString(); - } - } + protected final MetaAccessProvider runtime; + protected final Replacements replacements; + protected final TargetDescription target; + private final ConcurrentHashMap templates; - /** - * A collection of snippet templates accessed by a {@link Key} instance. - */ - public static class Cache { - - private final ConcurrentHashMap templates = new ConcurrentHashMap<>(); - private final MetaAccessProvider runtime; - private final TargetDescription target; - private final Replacements replacements; - - public Cache(MetaAccessProvider runtime, Replacements replacements, TargetDescription target) { + protected AbstractTemplates(MetaAccessProvider runtime, Replacements replacements, TargetDescription target) { this.runtime = runtime; this.replacements = replacements; this.target = target; + this.templates = new ConcurrentHashMap<>(); + } + + protected SnippetInfo snippet(Class declaringClass, String methodName) { + Method found = null; + for (Method method : declaringClass.getDeclaredMethods()) { + if (method.getAnnotation(Snippet.class) != null && method.getName().equals(methodName)) { + assert found == null : "found more than one @" + Snippet.class.getSimpleName() + " method " + methodName + " in " + declaringClass; + found = method; + } + } + assert found != null : "did not find @" + Snippet.class.getSimpleName() + " method " + methodName + " in " + declaringClass; + + return new SnippetInfo(runtime.lookupJavaMethod(found)); } /** * Gets a template for a given key, creating it first if necessary. */ - public SnippetTemplate get(final SnippetTemplate.Key key) { - SnippetTemplate template = templates.get(key); + protected SnippetTemplate template(final Arguments args) { + SnippetTemplate template = templates.get(args.cacheKey); if (template == null) { - template = Debug.scope("SnippetSpecialization", key.method, new Callable() { + template = Debug.scope("SnippetSpecialization", args.info.method, new Callable() { @Override public SnippetTemplate call() throws Exception { - return new SnippetTemplate(runtime, replacements, target, key); + return new SnippetTemplate(runtime, replacements, target, args); } }); - templates.put(key, template); + templates.put(args.cacheKey, template); } return template; } } - public abstract static class AbstractTemplates { - - protected final Cache cache; - protected final MetaAccessProvider runtime; - protected final Replacements replacements; - protected Class snippetsClass; - - public AbstractTemplates(MetaAccessProvider runtime, Replacements replacements, TargetDescription target, Class snippetsClass) { - this.runtime = runtime; - this.replacements = replacements; - if (snippetsClass == null) { - assert this instanceof Snippets; - this.snippetsClass = getClass(); - } else { - this.snippetsClass = snippetsClass; - } - this.cache = new Cache(runtime, replacements, target); - replacements.registerSnippets(this.snippetsClass); - } - - protected ResolvedJavaMethod snippet(String name, Class... parameterTypes) { - try { - ResolvedJavaMethod snippet = runtime.lookupJavaMethod(snippetsClass.getDeclaredMethod(name, parameterTypes)); - assert snippet.getAnnotation(Snippet.class) != null : "snippet is not annotated with @" + Snippet.class.getSimpleName(); - return snippet; - } catch (NoSuchMethodException e) { - throw new GraalInternalError(e); - } - } - } - private static final Object UNUSED_PARAMETER = "DEAD PARAMETER"; + private static final Object CONSTANT_PARAMETER = "CONSTANT"; /** * Determines if any parameter of a given method is annotated with {@link ConstantParameter}. @@ -236,31 +332,25 @@ /** * Creates a snippet template. */ - public SnippetTemplate(MetaAccessProvider runtime, Replacements replacements, TargetDescription target, SnippetTemplate.Key key) { - ResolvedJavaMethod method = key.method; - assert Modifier.isStatic(method.getModifiers()) : "snippet method must be static: " + method; + protected SnippetTemplate(MetaAccessProvider runtime, Replacements replacements, TargetDescription target, Arguments args) { + StructuredGraph snippetGraph = replacements.getSnippet(args.info.method); + + ResolvedJavaMethod method = snippetGraph.method(); Signature signature = method.getSignature(); // Copy snippet graph, replacing constant parameters with given arguments - StructuredGraph snippetGraph = replacements.getSnippet(method); - if (snippetGraph == null) { - throw new GraalInternalError("Snippet has not been registered: %s", format("%H.%n(%p)", method)); - } StructuredGraph snippetCopy = new StructuredGraph(snippetGraph.name, snippetGraph.method()); IdentityHashMap nodeReplacements = new IdentityHashMap<>(); nodeReplacements.put(snippetGraph.start(), snippetCopy.start()); - int parameterCount = signature.getParameterCount(false); - assert checkTemplate(runtime, key, parameterCount, method, signature); + assert checkTemplate(runtime, args, method, signature); - Parameter[] parameterAnnotations = new Parameter[parameterCount]; - VarargsParameter[] varargsParameterAnnotations = new VarargsParameter[parameterCount]; + int parameterCount = args.info.getParameterCount(); ConstantNode[] placeholders = new ConstantNode[parameterCount]; + for (int i = 0; i < parameterCount; i++) { - ConstantParameter c = MetaUtil.getParameterAnnotation(ConstantParameter.class, i, method); - if (c != null) { - String name = c.value(); - Object arg = key.get(name); + if (args.info.isConstantParameter(i)) { + Object arg = args.values[i]; Kind kind = signature.getParameterKind(i); Constant constantArg; if (arg instanceof Constant) { @@ -269,19 +359,12 @@ constantArg = Constant.forBoxed(kind, arg); } nodeReplacements.put(snippetGraph.getLocal(i), ConstantNode.forConstant(constantArg, runtime, snippetCopy)); - } else { - VarargsParameter vp = MetaUtil.getParameterAnnotation(VarargsParameter.class, i, method); - if (vp != null) { - String name = vp.value(); - Varargs varargs = (Varargs) key.get(name); - Object array = varargs.getArray(); - ConstantNode placeholder = ConstantNode.forObject(array, runtime, snippetCopy); - nodeReplacements.put(snippetGraph.getLocal(i), placeholder); - placeholders[i] = placeholder; - varargsParameterAnnotations[i] = vp; - } else { - parameterAnnotations[i] = MetaUtil.getParameterAnnotation(Parameter.class, i, method); - } + } else if (args.info.isVarargsParameter(i)) { + Varargs varargs = (Varargs) args.values[i]; + Object array = Array.newInstance(varargs.componentType, varargs.length); + ConstantNode placeholder = ConstantNode.forObject(array, runtime, snippetCopy); + nodeReplacements.put(snippetGraph.getLocal(i), placeholder); + placeholders[i] = placeholder; } } snippetCopy.addDuplicates(snippetGraph.getNodes(), nodeReplacements); @@ -292,28 +375,28 @@ new NodeIntrinsificationPhase(runtime).apply(snippetCopy); new WordTypeRewriterPhase(runtime, target.wordKind).apply(snippetCopy); - new CanonicalizerPhase(runtime, replacements.getAssumptions(), 0, null).apply(snippetCopy); + new CanonicalizerPhase.Instance(runtime, replacements.getAssumptions(), 0, null).apply(snippetCopy); } assert NodeIntrinsificationVerificationPhase.verify(snippetCopy); // Gather the template parameters - parameters = new HashMap<>(); + parameters = new Object[parameterCount]; for (int i = 0; i < parameterCount; i++) { - VarargsParameter vp = varargsParameterAnnotations[i]; - if (vp != null) { + if (args.info.isConstantParameter(i)) { + parameters[i] = CONSTANT_PARAMETER; + } else if (args.info.isVarargsParameter(i)) { assert snippetCopy.getLocal(i) == null; - Varargs varargs = (Varargs) key.get(vp.value()); - Object array = varargs.getArray(); - int length = Array.getLength(array); + Varargs varargs = (Varargs) args.values[i]; + int length = varargs.length; LocalNode[] locals = new LocalNode[length]; - Stamp stamp = varargs.getArgStamp(); + Stamp stamp = varargs.stamp; for (int j = 0; j < length; j++) { assert (parameterCount & 0xFFFF) == parameterCount; int idx = i << 16 | j; LocalNode local = snippetCopy.unique(new LocalNode(idx, stamp)); locals[j] = local; } - parameters.put(vp.value(), locals); + parameters[i] = locals; ConstantNode placeholder = placeholders[i]; assert placeholder != null; @@ -327,15 +410,12 @@ } } } else { - Parameter p = parameterAnnotations[i]; - if (p != null) { - LocalNode local = snippetCopy.getLocal(i); - if (local == null) { - // Parameter value was eliminated - parameters.put(p.value(), UNUSED_PARAMETER); - } else { - parameters.put(p.value(), local); - } + LocalNode local = snippetCopy.getLocal(i); + if (local == null) { + // Parameter value was eliminated + parameters[i] = UNUSED_PARAMETER; + } else { + parameters[i] = local; } } } @@ -352,7 +432,7 @@ LoopEx loop = new LoopsData(snippetCopy).loop(loopBegin); int mark = snippetCopy.getMark(); LoopTransformations.fullUnroll(loop, runtime, null); - new CanonicalizerPhase(runtime, replacements.getAssumptions(), mark, null).apply(snippetCopy); + new CanonicalizerPhase.Instance(runtime, replacements.getAssumptions(), mark, null).apply(snippetCopy); } FixedNode explodeLoopNext = explodeLoop.next(); explodeLoop.clearSuccessors(); @@ -434,11 +514,11 @@ return true; } - private static boolean checkVarargs(final ResolvedJavaMethod method, Signature signature, int i, String name, Varargs varargs) { - Object arg = varargs.getArray(); + private static boolean checkVarargs(MetaAccessProvider runtime, final ResolvedJavaMethod method, Signature signature, int i, String name, Varargs varargs) { ResolvedJavaType type = (ResolvedJavaType) signature.getParameterType(i, method.getDeclaringClass()); assert type.isArray() : "varargs parameter must be an array type"; - assert type.isInstance(Constant.forObject(arg)) : "value for " + name + " is not a " + MetaUtil.toJavaName(type) + " instance: " + arg; + assert type.getComponentType().isAssignableFrom(runtime.lookupJavaType(varargs.componentType)) : "componentType for " + name + " not matching " + MetaUtil.toJavaName(type) + " instance: " + + varargs.componentType; return true; } @@ -453,7 +533,7 @@ * {@link LocalNode} instance or a {@link LocalNode} array. For an eliminated parameter, the * value is identical to the key. */ - private final Map parameters; + private final Object[] parameters; /** * The return node (if any) of the snippet. @@ -481,33 +561,33 @@ * * @return the map that will be used to bind arguments to parameters when inlining this template */ - private IdentityHashMap bind(StructuredGraph replaceeGraph, MetaAccessProvider runtime, SnippetTemplate.Arguments args) { + private IdentityHashMap bind(StructuredGraph replaceeGraph, MetaAccessProvider runtime, Arguments args) { IdentityHashMap replacements = new IdentityHashMap<>(); - assert args.length() == parameters.size() : "number of args (" + args.length() + ") != number of parameters (" + parameters.size() + ")"; - for (Map.Entry e : args) { - String name = e.getKey(); - Object parameter = parameters.get(name); - assert parameter != null : this + " has no parameter named " + name; - Object argument = e.getValue(); + assert args.info.getParameterCount() == parameters.length : "number of args (" + args.info.getParameterCount() + ") != number of parameters (" + parameters.length + ")"; + for (int i = 0; i < parameters.length; i++) { + Object parameter = parameters[i]; + assert parameter != null : this + " has no parameter named " + args.info.names[i]; + Object argument = args.values[i]; if (parameter instanceof LocalNode) { if (argument instanceof ValueNode) { replacements.put((LocalNode) parameter, (ValueNode) argument); } else { Kind kind = ((LocalNode) parameter).kind(); - assert argument != null || kind == Kind.Object : this + " cannot accept null for non-object parameter named " + name; + assert argument != null || kind == Kind.Object : this + " cannot accept null for non-object parameter named " + args.info.names[i]; Constant constant = forBoxed(argument, kind); replacements.put((LocalNode) parameter, ConstantNode.forConstant(constant, runtime, replaceeGraph)); } } else if (parameter instanceof LocalNode[]) { LocalNode[] locals = (LocalNode[]) parameter; + Varargs varargs = (Varargs) argument; int length = locals.length; List list = null; Object array = null; - if (argument instanceof List) { - list = (List) argument; + if (varargs.value instanceof List) { + list = (List) varargs.value; assert list.size() == length : length + " != " + list.size(); } else { - array = argument; + array = varargs.value; assert array != null && array.getClass().isArray(); assert Array.getLength(array) == length : length + " != " + Array.getLength(array); } @@ -525,7 +605,7 @@ } } } else { - assert parameter == UNUSED_PARAMETER : "unexpected entry for parameter: " + name + " -> " + parameter; + assert parameter == CONSTANT_PARAMETER || parameter == UNUSED_PARAMETER : "unexpected entry for parameter: " + args.info.names[i] + " -> " + parameter; } } return replacements; @@ -592,7 +672,7 @@ * @param args the arguments to be bound to the flattened positional parameters of the snippet * @return the map of duplicated nodes (original -> duplicate) */ - public Map instantiate(MetaAccessProvider runtime, FixedNode replacee, UsageReplacer replacer, SnippetTemplate.Arguments args) { + public Map instantiate(MetaAccessProvider runtime, FixedNode replacee, UsageReplacer replacer, Arguments args) { // Inline the snippet nodes, replacing parameters with the given args in the process String name = snippet.name == null ? "{copy}" : snippet.name + "{copy}"; @@ -668,7 +748,7 @@ * @param replacer object that replaces the usages of {@code replacee} * @param args the arguments to be bound to the flattened positional parameters of the snippet */ - public void instantiate(MetaAccessProvider runtime, FloatingNode replacee, UsageReplacer replacer, LoweringTool tool, SnippetTemplate.Arguments args) { + public void instantiate(MetaAccessProvider runtime, FloatingNode replacee, UsageReplacer replacer, LoweringTool tool, Arguments args) { // Inline the snippet nodes, replacing parameters with the given args in the process String name = snippet.name == null ? "{copy}" : snippet.name + "{copy}"; @@ -727,13 +807,17 @@ public String toString() { StringBuilder buf = new StringBuilder(snippet.toString()).append('('); String sep = ""; - for (Map.Entry e : parameters.entrySet()) { - String name = e.getKey(); - Object value = e.getValue(); + for (int i = 0; i < parameters.length; i++) { + String name = "[" + i + "]"; + Object value = parameters[i]; buf.append(sep); sep = ", "; - if (value == UNUSED_PARAMETER) { + if (value == null) { + buf.append(" ").append(name); + } else if (value == UNUSED_PARAMETER) { buf.append(" ").append(name); + } else if (value == CONSTANT_PARAMETER) { + buf.append(" ").append(name); } else if (value instanceof LocalNode) { LocalNode local = (LocalNode) value; buf.append(local.kind().getJavaName()).append(' ').append(name); @@ -746,42 +830,18 @@ return buf.append(')').toString(); } - private static boolean checkTemplate(MetaAccessProvider runtime, SnippetTemplate.Key key, int parameterCount, ResolvedJavaMethod method, Signature signature) { - Set expected = new HashSet<>(); - for (int i = 0; i < parameterCount; i++) { - ConstantParameter c = MetaUtil.getParameterAnnotation(ConstantParameter.class, i, method); - VarargsParameter vp = MetaUtil.getParameterAnnotation(VarargsParameter.class, i, method); - Parameter p = MetaUtil.getParameterAnnotation(Parameter.class, i, method); - if (c != null) { - assert vp == null && p == null; - String name = c.value(); - expected.add(name); + private static boolean checkTemplate(MetaAccessProvider runtime, Arguments args, ResolvedJavaMethod method, Signature signature) { + for (int i = 0; i < args.info.getParameterCount(); i++) { + if (args.info.isConstantParameter(i)) { Kind kind = signature.getParameterKind(i); - assert key.names().contains(name) : "key for " + method + " is missing \"" + name + "\": " + key; - assert checkConstantArgument(runtime, method, signature, i, c.value(), key.get(name), kind); - } else if (vp != null) { - assert p == null; - String name = vp.value(); - expected.add(name); - assert key.names().contains(name) : "key for " + method + " is missing \"" + name + "\": " + key; - assert key.get(name) instanceof Varargs; - Varargs varargs = (Varargs) key.get(name); - assert checkVarargs(method, signature, i, name, varargs); - } else { - assert p != null : method + ": parameter " + i + " must be annotated with exactly one of " + "@" + ConstantParameter.class.getSimpleName() + " or " + "@" + - VarargsParameter.class.getSimpleName() + " or " + "@" + Parameter.class.getSimpleName(); + assert checkConstantArgument(runtime, method, signature, i, args.info.names[i], args.values[i], kind); + + } else if (args.info.isVarargsParameter(i)) { + assert args.values[i] instanceof Varargs; + Varargs varargs = (Varargs) args.values[i]; + assert checkVarargs(runtime, method, signature, i, args.info.names[i], varargs); } } - if (!key.names().containsAll(expected)) { - expected.removeAll(key.names()); - assert false : expected + " missing from key " + key; - } - if (!expected.containsAll(key.names())) { - Set namesCopy = new HashSet<>(key.names()); - namesCopy.removeAll(expected); - assert false : "parameter(s) " + namesCopy + " should be annotated with @" + ConstantParameter.class.getSimpleName() + " or @" + VarargsParameter.class.getSimpleName() + " in " + - MetaUtil.format("%H.%n(%p)", method); - } return true; } } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java Sat Apr 13 00:33:37 2013 +0200 @@ -41,7 +41,7 @@ private final JavaType returnType; protected MacroNode(Invoke invoke) { - super(invoke.node().stamp(), invoke.stateAfter()); + super(invoke.asNode().stamp(), invoke.stateAfter()); this.arguments = new NodeInputList<>(this, invoke.methodCallTarget().arguments()); this.bci = invoke.bci(); this.targetMethod = invoke.methodCallTarget().targetMethod(); diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java Sat Apr 13 00:33:37 2013 +0200 @@ -107,6 +107,8 @@ return ConstantNode.forDouble(Math.cos(value), graph()); case TAN: return ConstantNode.forDouble(Math.tan(value), graph()); + default: + throw GraalInternalError.shouldNotReachHere(); } } return this; diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.service.processor/src/com/oracle/graal/service/processor/ServiceProviderProcessor.java --- a/graal/com.oracle.graal.service.processor/src/com/oracle/graal/service/processor/ServiceProviderProcessor.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.service.processor/src/com/oracle/graal/service/processor/ServiceProviderProcessor.java Sat Apr 13 00:33:37 2013 +0200 @@ -29,6 +29,7 @@ import javax.lang.model.*; import javax.lang.model.element.*; import javax.lang.model.type.*; +import javax.lang.model.util.*; import javax.tools.Diagnostic.Kind; import javax.tools.*; @@ -81,27 +82,57 @@ return true; } + private void processElement(TypeElement serviceProvider) { + ServiceProvider annotation = serviceProvider.getAnnotation(ServiceProvider.class); + if (annotation != null) { + try { + annotation.value(); + } catch (MirroredTypeException ex) { + TypeMirror serviceInterface = ex.getTypeMirror(); + if (verifyAnnotation(serviceInterface, serviceProvider)) { + String interfaceName = ex.getTypeMirror().toString(); + addProvider(interfaceName, serviceProvider); + } + } + } + } + + private void processOldElements() { + Filer filer = processingEnv.getFiler(); + Elements elements = processingEnv.getElementUtils(); + for (String key : serviceMap.keySet()) { + String filename = "META-INF/services/" + key; + try { + FileObject servicesFile = filer.getResource(StandardLocation.CLASS_OUTPUT, "", filename); + BufferedReader reader = new BufferedReader(new InputStreamReader(servicesFile.openInputStream(), "UTF-8")); + String line; + while ((line = reader.readLine()) != null) { + TypeElement serviceProvider = elements.getTypeElement(line); + if (serviceProvider != null) { + processElement(serviceProvider); + } + } + reader.close(); + servicesFile.delete(); + } catch (IOException e) { + // old services file not found: do nothing + } + } + } + @Override public boolean process(Set annotations, RoundEnvironment roundEnv) { if (roundEnv.processingOver()) { + processOldElements(); generateServicesFiles(); return true; } for (Element element : roundEnv.getElementsAnnotatedWith(ServiceProvider.class)) { assert element.getKind().isClass(); - ServiceProvider annotation = element.getAnnotation(ServiceProvider.class); - try { - annotation.value(); - } catch (MirroredTypeException ex) { - TypeMirror serviceInterface = ex.getTypeMirror(); - TypeElement serviceProvider = (TypeElement) element; - if (verifyAnnotation(serviceInterface, serviceProvider)) { - String interfaceName = ex.getTypeMirror().toString(); - addProvider(interfaceName, serviceProvider); - } - } + processElement((TypeElement) element); } + return true; } } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/CyclicMaterializeStoreNode.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/CyclicMaterializeStoreNode.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/CyclicMaterializeStoreNode.java Sat Apr 13 00:33:37 2013 +0200 @@ -30,9 +30,6 @@ import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.virtual.*; -/** - * The {@code StoreFieldNode} represents a write to a static or instance field. - */ @NodeInfo(nameTemplate = "MaterializeStore#{p#target/s}") public final class CyclicMaterializeStoreNode extends FixedWithNextNode implements Lowerable, Virtualizable { diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java Sat Apr 13 00:33:37 2013 +0200 @@ -25,28 +25,24 @@ import java.util.*; import java.util.concurrent.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.debug.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; -public class IterativeInliningPhase extends Phase { +public class IterativeInliningPhase extends BasePhase { private final PhasePlan plan; - private final GraalCodeCacheProvider runtime; private final Replacements replacements; - private final Assumptions assumptions; private final GraphCache cache; private final OptimisticOptimizations optimisticOpts; private final boolean readElimination; - public IterativeInliningPhase(GraalCodeCacheProvider runtime, Replacements replacements, Assumptions assumptions, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts, boolean readElimination) { - this.runtime = runtime; + public IterativeInliningPhase(Replacements replacements, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts, boolean readElimination) { this.replacements = replacements; - this.assumptions = assumptions; this.cache = cache; this.plan = plan; this.optimisticOpts = optimisticOpts; @@ -60,12 +56,12 @@ } @Override - protected void run(final StructuredGraph graph) { - runIterations(graph, true); - runIterations(graph, false); + protected void run(final StructuredGraph graph, final HighTierContext context) { + runIterations(graph, true, context); + runIterations(graph, false, context); } - private void runIterations(final StructuredGraph graph, final boolean simple) { + private void runIterations(final StructuredGraph graph, final boolean simple, final HighTierContext context) { Boolean continueIteration = true; for (int iteration = 0; iteration < GraalOptions.EscapeAnalysisIterations && continueIteration; iteration++) { continueIteration = Debug.scope("iteration " + iteration, new Callable() { @@ -73,13 +69,13 @@ @Override public Boolean call() { boolean progress = false; - PartialEscapeAnalysisPhase ea = new PartialEscapeAnalysisPhase(runtime, assumptions, false, readElimination); - ea.apply(graph); - progress |= ea.hasChanged(); + PartialEscapeAnalysisPhase ea = new PartialEscapeAnalysisPhase(false, readElimination); + boolean eaResult = ea.runAnalysis(graph, context); + progress |= eaResult; Map hints = GraalOptions.PEAInliningHints ? PartialEscapeAnalysisPhase.getHints(graph) : null; - InliningPhase inlining = new InliningPhase(runtime, hints, replacements, assumptions, cache, plan, optimisticOpts); + InliningPhase inlining = new InliningPhase(context.getRuntime(), hints, replacements, context.getAssumptions(), cache, plan, optimisticOpts); inlining.setMaxMethodsPerInlining(simple ? 1 : Integer.MAX_VALUE); inlining.apply(graph); progress |= inlining.getInliningCount() > 0; @@ -87,8 +83,8 @@ new DeadCodeEliminationPhase().apply(graph); if (GraalOptions.ConditionalElimination && GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(runtime, assumptions).apply(graph); - new IterativeConditionalEliminationPhase(runtime, assumptions).apply(graph); + new CanonicalizerPhase().apply(graph, context); + new IterativeConditionalEliminationPhase(context.getRuntime(), context.getAssumptions()).apply(graph); } return progress; diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java Sat Apr 13 00:33:37 2013 +0200 @@ -25,12 +25,10 @@ import java.util.*; import java.util.concurrent.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.debug.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; @@ -38,33 +36,25 @@ import com.oracle.graal.phases.common.CanonicalizerPhase.CustomCanonicalizer; import com.oracle.graal.phases.graph.*; import com.oracle.graal.phases.schedule.*; +import com.oracle.graal.phases.tiers.*; import com.oracle.graal.virtual.nodes.*; -public class PartialEscapeAnalysisPhase extends Phase { +public class PartialEscapeAnalysisPhase extends BasePhase { - private final MetaAccessProvider runtime; - private final Assumptions assumptions; - private CustomCanonicalizer customCanonicalizer; + private final CustomCanonicalizer customCanonicalizer; private final boolean iterative; private final boolean readElimination; - private boolean changed; + public PartialEscapeAnalysisPhase(boolean iterative, boolean readElimination) { + this(null, iterative, readElimination); + } - public PartialEscapeAnalysisPhase(MetaAccessProvider runtime, Assumptions assumptions, boolean iterative, boolean readElimination) { - this.runtime = runtime; - this.assumptions = assumptions; + public PartialEscapeAnalysisPhase(CustomCanonicalizer customCanonicalizer, boolean iterative, boolean readElimination) { + this.customCanonicalizer = customCanonicalizer; this.iterative = iterative; this.readElimination = readElimination; } - public boolean hasChanged() { - return changed; - } - - public void setCustomCanonicalizer(CustomCanonicalizer customCanonicalizer) { - this.customCanonicalizer = customCanonicalizer; - } - public static final void trace(String format, Object... obj) { if (GraalOptions.TraceEscapeAnalysis) { Debug.log(format, obj); @@ -72,9 +62,13 @@ } @Override - protected void run(final StructuredGraph graph) { + protected void run(StructuredGraph graph, HighTierContext context) { + runAnalysis(graph, context); + } + + public boolean runAnalysis(final StructuredGraph graph, final HighTierContext context) { if (!matches(graph, GraalOptions.EscapeAnalyzeOnly)) { - return; + return false; } if (!readElimination) { @@ -86,26 +80,26 @@ } } if (!analyzableNodes) { - return; + return false; } } - Boolean continueIteration = true; + boolean continueIteration = true; + boolean changed = false; for (int iteration = 0; iteration < GraalOptions.EscapeAnalysisIterations && continueIteration; iteration++) { - continueIteration = Debug.scope("iteration " + iteration, new Callable() { + boolean currentChanged = Debug.scope("iteration " + iteration, new Callable() { @Override public Boolean call() { SchedulePhase schedule = new SchedulePhase(); schedule.apply(graph, false); - PartialEscapeClosure closure = new PartialEscapeClosure(graph.createNodeBitMap(), schedule, runtime, assumptions); + PartialEscapeClosure closure = new PartialEscapeClosure(graph.createNodeBitMap(), schedule, context.getRuntime(), context.getAssumptions()); ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock(), new BlockState(), null); if (!closure.hasChanged()) { return false; } - changed = true; // apply the effects collected during the escape analysis iteration List obsoleteNodes = closure.applyEffects(graph); @@ -116,21 +110,17 @@ new DeadCodeEliminationPhase().apply(graph); if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(runtime, assumptions, null, customCanonicalizer).apply(graph); + new CanonicalizerPhase.Instance(context.getRuntime(), context.getAssumptions(), null, customCanonicalizer).apply(graph); } - return iterative; + return true; } }); + continueIteration = currentChanged && iterative; + changed |= currentChanged; } - if (DynamicCounterNode.enabled && readElimination) { - for (Node node : graph.getNodes()) { - if (node instanceof LoadFieldNode) { - DynamicCounterNode.addCounterBefore("load non-elim", 1, false, (FixedNode) node); - } - } - } + return changed; } private static boolean matches(StructuredGraph graph, String filter) { diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Sat Apr 13 00:33:37 2013 +0200 @@ -162,7 +162,6 @@ state.killReadCache(store.field()); if (cachedValue == store.value()) { - effects.addCounterBefore("store elim", 1, false, lastFixedNode.next()); effects.deleteFixedNode(store); changed = true; } else { @@ -173,7 +172,6 @@ ValueNode cachedValue = state.getReadCache(load.object(), load.field()); if (cachedValue != null) { METRIC_LOADFIELD_ELIMINATED.increment(); - effects.addCounterBefore("load elim", 1, false, lastFixedNode.next()); effects.replaceAtUsages(load, cachedValue); state.addScalarAlias(load, cachedValue); changed = true; diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Sat Apr 13 00:33:37 2013 +0200 @@ -184,7 +184,7 @@ case TO_OBJECT: assert arguments.size() == 1; - replace(invoke, graph.unique(new UnsafeCastNode(arguments.get(0), invoke.node().stamp()))); + replace(invoke, graph.unique(new UnsafeCastNode(arguments.get(0), invoke.asNode().stamp()))); break; default: @@ -228,7 +228,7 @@ Constructor constructor = nodeClass.getConstructor(Kind.class, ValueNode.class, ValueNode.class); ValueNode result = graph.add(constructor.newInstance(wordKind, left, right)); if (result instanceof FixedWithNextNode) { - graph.addBeforeFixed(invoke.node(), (FixedWithNextNode) result); + graph.addBeforeFixed(invoke.asNode(), (FixedWithNextNode) result); } return result; } catch (Throwable ex) { @@ -268,11 +268,11 @@ private static ValueNode readOp(StructuredGraph graph, ValueNode base, ValueNode offset, Invoke invoke, Kind readKind, Object locationIdentity) { IndexedLocationNode location = IndexedLocationNode.create(locationIdentity, readKind, 0, offset, graph, 1); - ReadNode read = graph.add(new ReadNode(base, location, invoke.node().stamp())); - graph.addBeforeFixed(invoke.node(), read); + ReadNode read = graph.add(new ReadNode(base, location, invoke.asNode().stamp())); + graph.addBeforeFixed(invoke.asNode(), read); // The read must not float outside its block otherwise it may float above an explicit zero // check on its base address - read.dependencies().add(BeginNode.prevBegin(invoke.node())); + read.dependencies().add(BeginNode.prevBegin(invoke.asNode())); return read; } @@ -280,16 +280,16 @@ IndexedLocationNode location = IndexedLocationNode.create(locationIdentity, writeKind, 0, offset, graph, 1); WriteNode write = graph.add(new WriteNode(base, value, location, WriteBarrierType.NONE)); write.setStateAfter(invoke.stateAfter()); - graph.addBeforeFixed(invoke.node(), write); + graph.addBeforeFixed(invoke.asNode(), write); return write; } private static void replace(Invoke invoke, ValueNode value) { FixedNode next = invoke.next(); invoke.setNext(null); - invoke.node().replaceAtPredecessor(next); - invoke.node().replaceAtUsages(value); - GraphUtil.killCFG(invoke.node()); + invoke.asNode().replaceAtPredecessor(next); + invoke.asNode().replaceAtUsages(value); + GraphUtil.killCFG(invoke.asNode()); } public boolean isWord(ValueNode node) { diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java Sat Apr 13 00:33:37 2013 +0200 @@ -80,9 +80,9 @@ ValueNode receiver = arguments.get(argc); if (receiver == node && isWord(node)) { ResolvedJavaMethod resolvedMethod = wordAccess.getWordImplType().resolveMethod(method); - verify(resolvedMethod != null, node, invoke.node(), "cannot resolve method on Word class: " + MetaUtil.format("%H.%n(%P) %r", method)); + verify(resolvedMethod != null, node, invoke.asNode(), "cannot resolve method on Word class: " + MetaUtil.format("%H.%n(%P) %r", method)); Operation operation = resolvedMethod.getAnnotation(Word.Operation.class); - verify(operation != null, node, invoke.node(), "cannot dispatch on word value to non @Operation annotated method " + resolvedMethod); + verify(operation != null, node, invoke.asNode(), "cannot dispatch on word value to non @Operation annotated method " + resolvedMethod); } argc++; } @@ -91,7 +91,7 @@ ValueNode argument = arguments.get(argc); if (argument == node) { ResolvedJavaType type = (ResolvedJavaType) signature.getParameterType(i, method.getDeclaringClass()); - verify(isWord(type) == isWord(argument), node, invoke.node(), "cannot pass word value to non-word parameter " + i + " or vice-versa"); + verify(isWord(type) == isWord(argument), node, invoke.asNode(), "cannot pass word value to non-word parameter " + i + " or vice-versa"); } argc++; } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeElement.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeElement.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeElement.java Sat Apr 13 00:33:37 2013 +0200 @@ -103,19 +103,29 @@ return annotations; } - /* Support JDK8 langtools. */ - @SuppressWarnings("unused") + /** + * Support JDK8 langtools. + * + * @param annotationType + */ public A[] getAnnotationsByType(Class annotationType) { throw new UnsupportedOperationException(); } - /* Support for some JDK8 builds. (remove after jdk8 is released) */ - @SuppressWarnings("unused") + /** + * Support for some JDK8 builds. (remove after jdk8 is released) + * + * @param annotationType + */ public A[] getAnnotations(Class annotationType) { throw new UnsupportedOperationException(); } - @Override + /** + * Support for some JDK8 builds. (remove after jdk8 is released) + * + * @param annotationType + */ public A getAnnotation(Class annotationType) { throw new UnsupportedOperationException(); } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeExecutableElement.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeExecutableElement.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeExecutableElement.java Sat Apr 13 00:33:37 2013 +0200 @@ -225,4 +225,7 @@ return copy; } + public TypeMirror getReceiverType() { + throw new UnsupportedOperationException(); + } } diff -r 2cae919cd3af -r 0c8ec85fa013 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTypeMirror.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTypeMirror.java Fri Apr 12 23:29:45 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTypeMirror.java Sat Apr 13 00:33:37 2013 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.truffle.codegen.processor.ast; +import java.lang.annotation.*; import java.util.*; import javax.lang.model.element.*; @@ -92,4 +93,21 @@ } + public List getAnnotationMirrors() { + throw new UnsupportedOperationException(); + } + + /** + * @param annotationType + */ + public A getAnnotation(Class annotationType) { + throw new UnsupportedOperationException(); + } + + /** + * @param annotationType + */ + public A[] getAnnotationsByType(Class annotationType) { + throw new UnsupportedOperationException(); + } } diff -r 2cae919cd3af -r 0c8ec85fa013 make/bsd/makefiles/compiler1.make --- a/make/bsd/makefiles/compiler1.make Fri Apr 12 23:29:45 2013 +0200 +++ b/make/bsd/makefiles/compiler1.make Sat Apr 13 00:33:37 2013 +0200 @@ -32,4 +32,6 @@ ifndef OMIT_GRAAL CFLAGS += -DGRAAL +else + VM_SUBDIR = client-nograal endif \ No newline at end of file diff -r 2cae919cd3af -r 0c8ec85fa013 make/bsd/makefiles/compiler2.make --- a/make/bsd/makefiles/compiler2.make Fri Apr 12 23:29:45 2013 +0200 +++ b/make/bsd/makefiles/compiler2.make Sat Apr 13 00:33:37 2013 +0200 @@ -32,4 +32,6 @@ ifndef OMIT_GRAAL CFLAGS += -DGRAAL +else + VM_SUBDIR = server-nograal endif \ No newline at end of file diff -r 2cae919cd3af -r 0c8ec85fa013 make/bsd/makefiles/tiered.make --- a/make/bsd/makefiles/tiered.make Fri Apr 12 23:29:45 2013 +0200 +++ b/make/bsd/makefiles/tiered.make Sat Apr 13 00:33:37 2013 +0200 @@ -32,4 +32,6 @@ ifndef OMIT_GRAAL CFLAGS += -DGRAAL +else + VM_SUBDIR = server-nograal endif diff -r 2cae919cd3af -r 0c8ec85fa013 make/hotspot_version --- a/make/hotspot_version Fri Apr 12 23:29:45 2013 +0200 +++ b/make/hotspot_version Sat Apr 13 00:33:37 2013 +0200 @@ -35,7 +35,7 @@ HS_MAJOR_VER=25 HS_MINOR_VER=0 -HS_BUILD_NUMBER=26 +HS_BUILD_NUMBER=28 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 diff -r 2cae919cd3af -r 0c8ec85fa013 make/linux/makefiles/compiler1.make --- a/make/linux/makefiles/compiler1.make Fri Apr 12 23:29:45 2013 +0200 +++ b/make/linux/makefiles/compiler1.make Sat Apr 13 00:33:37 2013 +0200 @@ -32,4 +32,6 @@ ifndef OMIT_GRAAL CFLAGS += -DGRAAL +else + VM_SUBDIR = client-nograal endif \ No newline at end of file diff -r 2cae919cd3af -r 0c8ec85fa013 make/linux/makefiles/compiler2.make --- a/make/linux/makefiles/compiler2.make Fri Apr 12 23:29:45 2013 +0200 +++ b/make/linux/makefiles/compiler2.make Sat Apr 13 00:33:37 2013 +0200 @@ -32,4 +32,6 @@ ifndef OMIT_GRAAL CFLAGS += -DGRAAL +else + VM_SUBDIR = server-nograal endif \ No newline at end of file diff -r 2cae919cd3af -r 0c8ec85fa013 make/linux/makefiles/gcc.make --- a/make/linux/makefiles/gcc.make Fri Apr 12 23:29:45 2013 +0200 +++ b/make/linux/makefiles/gcc.make Sat Apr 13 00:33:37 2013 +0200 @@ -126,14 +126,12 @@ # Compiler warnings are treated as errors WARNINGS_ARE_ERRORS = -Werror -# Except for a few acceptable ones +WARNING_FLAGS = -Wpointer-arith -Wsign-compare -Wundef -Wunused-function + # Since GCC 4.3, -Wconversion has changed its meanings to warn these implicit -# conversions which might affect the values. To avoid that, we need to turn -# it off explicitly. -ifneq "$(shell expr \( $(CC_VER_MAJOR) \> 4 \) \| \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) \>= 3 \) \))" "0" -WARNING_FLAGS = -Wpointer-arith -Wsign-compare -Wundef -else -WARNING_FLAGS = -Wpointer-arith -Wconversion -Wsign-compare -Wundef +# conversions which might affect the values. Only enable it in earlier versions. +ifeq "$(shell expr \( $(CC_VER_MAJOR) \> 4 \) \| \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) \>= 3 \) \))" "0" +WARNING_FLAGS += -Wconversion endif CFLAGS_WARN/DEFAULT = $(WARNINGS_ARE_ERRORS) $(WARNING_FLAGS) diff -r 2cae919cd3af -r 0c8ec85fa013 make/linux/makefiles/tiered.make --- a/make/linux/makefiles/tiered.make Fri Apr 12 23:29:45 2013 +0200 +++ b/make/linux/makefiles/tiered.make Sat Apr 13 00:33:37 2013 +0200 @@ -32,4 +32,6 @@ ifndef OMIT_GRAAL CFLAGS += -DGRAAL +else + VM_SUBDIR = server-nograal endif \ No newline at end of file diff -r 2cae919cd3af -r 0c8ec85fa013 make/solaris/makefiles/compiler1.make --- a/make/solaris/makefiles/compiler1.make Fri Apr 12 23:29:45 2013 +0200 +++ b/make/solaris/makefiles/compiler1.make Sat Apr 13 00:33:37 2013 +0200 @@ -32,4 +32,6 @@ ifndef OMIT_GRAAL CFLAGS += -DGRAAL +else + VM_SUBDIR = client-nograal endif diff -r 2cae919cd3af -r 0c8ec85fa013 make/solaris/makefiles/compiler2.make --- a/make/solaris/makefiles/compiler2.make Fri Apr 12 23:29:45 2013 +0200 +++ b/make/solaris/makefiles/compiler2.make Sat Apr 13 00:33:37 2013 +0200 @@ -32,4 +32,6 @@ ifndef OMIT_GRAAL CFLAGS += -DGRAAL +else + VM_SUBDIR = server-nograal endif diff -r 2cae919cd3af -r 0c8ec85fa013 make/solaris/makefiles/tiered.make --- a/make/solaris/makefiles/tiered.make Fri Apr 12 23:29:45 2013 +0200 +++ b/make/solaris/makefiles/tiered.make Sat Apr 13 00:33:37 2013 +0200 @@ -32,4 +32,6 @@ ifndef OMIT_GRAAL CFLAGS += -DGRAAL +else + VM_SUBDIR = server-nograal endif diff -r 2cae919cd3af -r 0c8ec85fa013 mx/commands.py --- a/mx/commands.py Fri Apr 12 23:29:45 2013 +0200 +++ b/mx/commands.py Sat Apr 13 00:33:37 2013 +0200 @@ -38,13 +38,19 @@ """ Used to distinguish an exported GraalVM (see 'mx export'). """ _vmSourcesAvailable = exists(join(_graal_home, 'make')) and exists(join(_graal_home, 'src')) -""" The VM that will be run by the 'vm' command: graal(default), client or server. +""" The VMs that can be built and run - default is first in list """ +_vmChoices = ['graal', 'server', 'client', 'server-nograal', 'client-nograal', 'boot'] + +""" The VM that will be run by the 'vm' command and built by default by the 'build' command. This can be set via the global '--vm' option. """ -_vm = 'graal' +_vm = _vmChoices[0] -""" The VM build that will be run by the 'vm' command: product(default), fastdebug or debug. - This can be set via the global '--fastdebug' and '--debug' options. """ -_vmbuild = 'product' +""" The VM builds that will be run by the 'vm' command - default is first in list """ +_vmbuildChoices = ['product', 'fastdebug', 'debug'] + +""" The VM build that will be run by the 'vm' command. + This can be set via the global '--product', '--fastdebug' and '--debug' options. """ +_vmbuild = _vmbuildChoices[0] _jacoco = 'off' @@ -66,12 +72,16 @@ """clean the GraalVM source tree""" opts = mx.clean(args, parser=ArgumentParser(prog='mx clean')) if opts.native: - env = os.environ.copy() - env.update(ARCH_DATA_MODEL='64', LANG='C', HOTSPOT_BUILD_JOBS='16') - mx.run([mx.gmake_cmd(), 'clean'], cwd=join(_graal_home, 'make'), env=env) - jdks = join(_graal_home, 'jdk' + str(mx.java().version)) - if exists(jdks): - shutil.rmtree(jdks) + def rmIfExists(name): + if os.path.isdir(name): + shutil.rmtree(name) + elif os.path.isfile(name): + os.unlink(name) + + rmIfExists(join(_graal_home, 'build')) + rmIfExists(join(_graal_home, 'build-nograal')) + rmIfExists(join(_graal_home, 'jdk' + str(mx.java().version))) + rmIfExists(mx.distribution('GRAAL').path) def export(args): """create a GraalVM zip file for distribution""" @@ -329,14 +339,15 @@ assert len(parts) == 2, parts assert parts[1] == 'KNOWN', parts[1] defaultVM = parts[0][1:] - jvmCfgLines += ['-' + defaultVM + '0 KNOWN\n'] + jvmCfgLines += ['# boot VM is a copy of the unmodified ' + defaultVM + ' VM\n'] + jvmCfgLines += ['-boot KNOWN\n'] else: jvmCfgLines += [line] assert defaultVM is not None, 'Could not find default VM in ' + jvmCfg if mx.get_os() != 'windows': chmodRecursive(jdk, 0755) - shutil.move(join(_vmLibDirInJdk(jdk), defaultVM), join(_vmLibDirInJdk(jdk), defaultVM + '0')) + shutil.move(join(_vmLibDirInJdk(jdk), defaultVM), join(_vmLibDirInJdk(jdk), 'boot')) with open(jvmCfg, 'w') as fp: @@ -540,9 +551,9 @@ if vm is None: vm = _vm - if vm == 'server' or vm == 'server0': + if vm.startswith('server') or vm == 'boot': buildSuffix = '' - elif vm == 'client': + elif vm.startswith('client'): buildSuffix = '1' else: assert vm == 'graal', vm @@ -557,10 +568,12 @@ mx.log('[skipping build from IDE as IDE_BUILD_TARGET environment variable is ""]') continue - if vm == 'server0': - assert build == 'product', 'can not "build" a non-product server0' + jdk = _jdk(build, create=True) - jdk = _jdk(build, create=True) + if vm == 'boot': + if build != 'product': + mx.log('only product build of boot VM exists') + continue vmDir = join(_vmLibDirInJdk(jdk), vm) if not exists(vmDir): @@ -575,9 +588,7 @@ # Check if a build really needs to be done timestampFile = join(vmDir, '.build-timestamp') - if vm == 'server0': - mustBuild = False - elif opts2.force or not exists(timestampFile): + if opts2.force or not exists(timestampFile): mustBuild = True else: mustBuild = False @@ -627,7 +638,10 @@ env.setdefault('HOTSPOT_BUILD_JOBS', str(cpus)) env['ALT_BOOTDIR'] = mx.java().jdk env['JAVA_HOME'] = jdk - if not env.has_key('OMIT_GRAAL'): + if vm.endswith('nograal'): + env['OMIT_GRAAL'] = 'true' + env.setdefault('ALT_OUTPUTDIR', join(_graal_home, 'build-nograal', mx.get_os())) + else: env['GRAAL'] = join(_graal_home, 'graal') # needed for TEST_IN_BUILD env.setdefault('INSTALL', 'y') if mx.get_os() == 'solaris' : @@ -777,12 +791,14 @@ name = 'JUnitWrapper' javaSource = join(mxdir, name + '.java') javaClass = join(mxdir, name + '.class') - (_, testfile) = tempfile.mkstemp(".testclasses", "graal") + testfile = os.environ.get('MX_TESTFILE', None) + if testfile is None: + (_, testfile) = tempfile.mkstemp(".testclasses", "graal") def harness(projectscp, vmArgs): if not exists(javaClass) or getmtime(javaClass) < getmtime(javaSource): subprocess.check_call([mx.java().javac, '-cp', projectscp, '-d', mxdir, javaSource]) - if _vm == 'server0': + if _vm == 'boot' or _vm.endswith('nograal'): prefixArgs = ['-esa', '-ea'] else: prefixArgs = ['-XX:-BootstrapGraal', '-esa', '-ea'] @@ -791,7 +807,8 @@ try: _run_tests(args, harness, annotations, testfile) finally: - os.remove(testfile) + if os.environ.get('MX_TESTFILE') is None: + os.remove(testfile) def unittest(args): """run the JUnit tests (all testcases) @@ -823,9 +840,14 @@ def buildvms(args): """build one or more VMs in various configurations""" + vmsDefault = ','.join(_vmChoices) + vmbuildsDefault = ','.join(_vmbuildChoices) + parser = ArgumentParser(prog='mx buildvms'); - parser.add_argument('--vms', help='a comma separated list of VMs to build (default: server,client,graal)', default='server,client,graal') - parser.add_argument('--builds', help='a comma separated list of build types (default: product,fastdebug,debug)', default='product,fastdebug,debug') + parser.add_argument('--vms', help='a comma separated list of VMs to build (default: ' + vmsDefault + ')', metavar='', default=vmsDefault) + parser.add_argument('--builds', help='a comma separated list of build types (default: ' + vmbuildsDefault + ')', metavar='', default=vmbuildsDefault) + parser.add_argument('-n', '--no-check', action='store_true', help='omit running "java -version" after each build') + parser.add_argument('-c', '--console', action='store_true', help='send build output to console instead of log file') args = parser.parse_args(args) vms = args.vms.split(',') @@ -834,14 +856,26 @@ allStart = time.time() for v in vms: for vmbuild in builds: - logFile = join(v + '-' + vmbuild + '.log') - log = open(join(_graal_home, logFile), 'wb') - start = time.time() - mx.log('BEGIN: ' + v + '-' + vmbuild + '\t(see: ' + logFile + ')') - # Run as subprocess so that output can be directed to a file - subprocess.check_call([sys.executable, '-u', join('mxtool', 'mx.py'), '--vm', v, 'build', vmbuild], cwd=_graal_home, stdout=log, stderr=subprocess.STDOUT) - duration = datetime.timedelta(seconds=time.time() - start) - mx.log('END: ' + v + '-' + vmbuild + '\t[' + str(duration) + ']') + if v == 'boot' and vmbuild != 'product': + continue + if not args.console: + logFile = join(v + '-' + vmbuild + '.log') + log = open(join(_graal_home, logFile), 'wb') + start = time.time() + mx.log('BEGIN: ' + v + '-' + vmbuild + '\t(see: ' + logFile + ')') + # Run as subprocess so that output can be directed to a file + subprocess.check_call([sys.executable, '-u', join('mxtool', 'mx.py'), '--vm', v, 'build', vmbuild], cwd=_graal_home, stdout=log, stderr=subprocess.STDOUT) + duration = datetime.timedelta(seconds=time.time() - start) + mx.log('END: ' + v + '-' + vmbuild + '\t[' + str(duration) + ']') + else: + global _vm + _vm = v + build([vmbuild]) + if not args.no_check: + vmargs = ['-version'] + if v == 'graal': + vmargs.insert(0, '-XX:-BootstrapGraal') + vm(vmargs, vm=v, vmbuild=vmbuild) allDuration = datetime.timedelta(seconds=time.time() - allStart) mx.log('TOTAL TIME: ' + '[' + str(allDuration) + ']') @@ -1289,18 +1323,16 @@ mx.add_argument('--jacoco', help='instruments com.oracle.* classes using JaCoCo', default='off', choices=['off', 'on', 'append']) if (_vmSourcesAvailable): - mx.add_argument('--vm', action='store', dest='vm', default='graal', choices=['graal', 'server', 'client', 'server0'], help='the VM to build/run (default: graal)') - mx.add_argument('--product', action='store_const', dest='vmbuild', const='product', help='select the product build of the VM') - mx.add_argument('--debug', action='store_const', dest='vmbuild', const='debug', help='select the debug build of the VM') - mx.add_argument('--fastdebug', action='store_const', dest='vmbuild', const='fastdebug', help='select the fast debug build of the VM') + mx.add_argument('--vm', action='store', dest='vm', default='graal', choices=_vmChoices, help='the VM to build/run (default: ' + _vmChoices[0] + ')') + for c in _vmbuildChoices: + mx.add_argument('--' + c, action='store_const', dest='vmbuild', const=c, help='select the ' + c + ' build of the VM') mx.add_argument('--ecl', action='store_true', dest='make_eclipse_launch', help='create launch configuration for running VM execution(s) in Eclipse') mx.add_argument('--native-dbg', action='store', dest='native_dbg', help='Start the vm inside a debugger', metavar='') mx.add_argument('--gdb', action='store_const', const='/usr/bin/gdb --args', dest='native_dbg', help='alias for --native-dbg /usr/bin/gdb -- args') - commands.update({ 'export': [export, '[-options] [zipfile]'], - 'build': [build, '[-options] [product|debug|fastdebug]...'] + 'build': [build, '[-options] [' + '|'.join(_vmbuildChoices) + ']...'] }) mx.commands.update(commands) diff -r 2cae919cd3af -r 0c8ec85fa013 mxtool/mx.py --- a/mxtool/mx.py Fri Apr 12 23:29:45 2013 +0200 +++ b/mxtool/mx.py Sat Apr 13 00:33:37 2013 +0200 @@ -1344,7 +1344,7 @@ parser = parser if parser is not None else ArgumentParser(prog='mx build') parser.add_argument('-f', action='store_true', dest='force', help='force build (disables timestamp checking)') parser.add_argument('-c', action='store_true', dest='clean', help='removes existing build output') - parser.add_argument('--source', dest='compliance', help='Java compliance level', default=str(javaCompliance)) + parser.add_argument('--source', dest='compliance', help='Java compliance level for projects without an explicit one', default=str(javaCompliance)) parser.add_argument('--Wapi', action='store_true', dest='warnAPI', help='show warnings about using internal APIs') parser.add_argument('--projects', action='store', help='comma separated projects to build (omit to build all projects)') parser.add_argument('--only', action='store', help='comma separated projects to build, without checking their dependencies (omit to build all projects)') @@ -1502,16 +1502,17 @@ toBeDeleted = [argfileName] try: + compliance = str(p.javaCompliance) if p.javaCompliance is not None else args.compliance if jdtJar is None: log('Compiling Java sources for {0} with javac...'.format(p.name)) - javacCmd = [java().javac, '-g', '-J-Xmx1g', '-source', args.compliance, '-classpath', cp, '-d', outputDir] + javacArgs + ['@' + argfile.name] + javacCmd = [java().javac, '-g', '-J-Xmx1g', '-source', compliance, '-classpath', cp, '-d', outputDir] + javacArgs + ['@' + argfile.name] if not args.warnAPI: javacCmd.append('-XDignore.symbol.file') run(javacCmd) else: log('Compiling Java sources for {0} with JDT...'.format(p.name)) jdtArgs = [java().java, '-Xmx1g', '-jar', jdtJar, - '-' + args.compliance, + '-' + compliance, '-cp', cp, '-g', '-enableJavadoc', '-d', outputDir] + javacArgs jdtProperties = join(p.dir, '.settings', 'org.eclipse.jdt.core.prefs') @@ -1561,6 +1562,13 @@ args.eclipse_exe = os.environ.get('ECLIPSE_EXE') if args.eclipse_exe is None: abort('Could not find Eclipse executable. Use -e option or ensure ECLIPSE_EXE environment variable is set.') + + # Maybe an Eclipse installation dir was specified - look for the executable in it + if join(args.eclipse_exe, exe_suffix('eclipse')): + args.eclipse_exe = join(args.eclipse_exe, exe_suffix('eclipse')) + + if not os.path.isfile(args.eclipse_exe) or not os.access(args.eclipse_exe, os.X_OK): + abort('Not an executable file: ' + args.eclipse_exe) eclipseinit([], buildProcessorJars=False) @@ -3010,9 +3018,10 @@ if exists(tmpbase): shutil.rmtree(tmpbase) -def findclass(args): +def findclass(args, logToConsole=True): """find all classes matching a given substring""" + matches = [] for entry, filename in classpath_walk(includeBootClasspath=True): if filename.endswith('.class'): if isinstance(entry, zipfile.ZipFile): @@ -3022,20 +3031,19 @@ classname = classname[:-len('.class')] for a in args: if a in classname: - log(classname) + matches.append(classname) + if logToConsole: + log(classname) + return matches def javap(args): - """launch javap with a -classpath option denoting all available classes - - Run the JDK javap class file disassembler with the following prepended options: - - -private -verbose -classpath """ + """disassemble classes matching given pattern with javap""" javap = java().javap if not exists(javap): abort('The javap executable does not exists: ' + javap) else: - run([javap, '-private', '-verbose', '-classpath', classpath()] + args) + run([javap, '-private', '-verbose', '-classpath', classpath()] + findclass(args, logToConsole=False)) def show_projects(args): """show all loaded projects""" @@ -3073,7 +3081,7 @@ 'ideinit': [ideinit, ''], 'archive': [archive, '[options]'], 'projectgraph': [projectgraph, ''], - 'javap': [javap, ''], + 'javap': [javap, ''], 'javadoc': [javadoc, '[options]'], 'site': [site, '[options]'], 'netbeansinit': [netbeansinit, ''], diff -r 2cae919cd3af -r 0c8ec85fa013 src/cpu/sparc/vm/interpreter_sparc.cpp --- a/src/cpu/sparc/vm/interpreter_sparc.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/cpu/sparc/vm/interpreter_sparc.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -381,6 +381,9 @@ case Interpreter::zerolocals_synchronized: synchronized = true; break; case Interpreter::native : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(false); break; case Interpreter::native_synchronized : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(true); break; +#ifdef GRAAL + case Interpreter::execute_compiled_method: entry_point = ((InterpreterGenerator*)this)->generate_execute_compiled_method_entry(); break; +#endif case Interpreter::empty : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry(); break; case Interpreter::accessor : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry(); break; case Interpreter::abstract : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry(); break; diff -r 2cae919cd3af -r 0c8ec85fa013 src/cpu/sparc/vm/sharedRuntime_sparc.cpp diff -r 2cae919cd3af -r 0c8ec85fa013 src/cpu/x86/vm/assembler_x86.cpp --- a/src/cpu/x86/vm/assembler_x86.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/cpu/x86/vm/assembler_x86.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -214,14 +214,6 @@ return enc; } -static int encode(XMMRegister r) { - int enc = r->encoding(); - if (enc >= 8) { - enc -= 8; - } - return enc; -} - void Assembler::emit_arith_b(int op1, int op2, Register dst, int imm8) { assert(dst->has_byte_register(), "must have byte register"); assert(isByte(op1) && isByte(op2), "wrong opcode"); diff -r 2cae919cd3af -r 0c8ec85fa013 src/cpu/x86/vm/interpreterGenerator_x86.hpp --- a/src/cpu/x86/vm/interpreterGenerator_x86.hpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/cpu/x86/vm/interpreterGenerator_x86.hpp Sat Apr 13 00:33:37 2013 +0200 @@ -36,6 +36,9 @@ address generate_normal_entry(bool synchronized); address generate_native_entry(bool synchronized); +#ifdef GRAAL + address generate_execute_compiled_method_entry(); +#endif address generate_abstract_entry(void); address generate_math_entry(AbstractInterpreter::MethodKind kind); address generate_empty_entry(void); diff -r 2cae919cd3af -r 0c8ec85fa013 src/cpu/x86/vm/methodHandles_x86.cpp --- a/src/cpu/x86/vm/methodHandles_x86.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/cpu/x86/vm/methodHandles_x86.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -41,11 +41,6 @@ #define BIND(label) bind(label); BLOCK_COMMENT(#label ":") -// Workaround for C++ overloading nastiness on '0' for RegisterOrConstant. -static RegisterOrConstant constant(int value) { - return RegisterOrConstant(value); -} - void MethodHandles::load_klass_from_Class(MacroAssembler* _masm, Register klass_reg) { if (VerifyMethodHandles) verify_klass(_masm, klass_reg, SystemDictionary::WK_KLASS_ENUM_NAME(java_lang_Class), diff -r 2cae919cd3af -r 0c8ec85fa013 src/cpu/x86/vm/sharedRuntime_x86_64.cpp --- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -1670,6 +1670,17 @@ verify_oop_args(masm, method, sig_bt, regs); vmIntrinsics::ID iid = method->intrinsic_id(); +#ifdef GRAAL + if (iid == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod) { + // We are called from compiled code here. The three object arguments + // are already in the correct registers (j_rarg0, jrarg1, jrarg2). The + // fourth argument (j_rarg3) is a raw pointer to the nmethod. Make a tail + // call to its verified entry point. + __ jmp(Address(j_rarg3, nmethod::verified_entry_point_offset())); + return; + } +#endif + // Now write the args into the outgoing interpreter space bool has_receiver = false; Register receiver_reg = noreg; diff -r 2cae919cd3af -r 0c8ec85fa013 src/cpu/x86/vm/templateInterpreter_x86_64.cpp --- a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -873,6 +873,46 @@ return generate_accessor_entry(); } +#ifdef GRAAL + +// Interpreter stub for calling a compiled method with 3 object arguments +address InterpreterGenerator::generate_execute_compiled_method_entry() { + address entry_point = __ pc(); + + // Pick up the return address + __ movptr(rax, Address(rsp, 0)); + + // Must preserve original SP for loading incoming arguments because + // we need to align the outgoing SP for compiled code. + __ movptr(r11, rsp); + + // Ensure compiled code always sees stack at proper alignment + __ andptr(rsp, -16); + + // push the return address and misalign the stack that youngest frame always sees + // as far as the placement of the call instruction + __ push(rax); + + // Move first object argument from interpreter calling convention to compiled + // code calling convention. + __ movq(j_rarg0, Address(r11, Interpreter::stackElementSize*5)); + + // Move second object argument. + __ movq(j_rarg1, Address(r11, Interpreter::stackElementSize*4)); + + // Move third object argument. + __ movq(j_rarg2, Address(r11, Interpreter::stackElementSize*3)); + + // Load the raw pointer to the nmethod. + __ movq(j_rarg3, Address(r11, Interpreter::stackElementSize)); + + // Perform a tail call to the verified entry point of the nmethod. + __ jmp(Address(j_rarg3, nmethod::verified_entry_point_offset())); + + return entry_point; +} + +#endif // Interpreter stub for calling a native method. (asm interpreter) // This sets up a somewhat different looking stack for calling the @@ -1561,6 +1601,9 @@ switch (kind) { case Interpreter::zerolocals : break; case Interpreter::zerolocals_synchronized: synchronized = true; break; +#ifdef GRAAL + case Interpreter::execute_compiled_method: entry_point = ((InterpreterGenerator*)this)->generate_execute_compiled_method_entry(); break; +#endif case Interpreter::native : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(false); break; case Interpreter::native_synchronized : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(true); break; case Interpreter::empty : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry(); break; diff -r 2cae919cd3af -r 0c8ec85fa013 src/cpu/x86/vm/x86_64.ad --- a/src/cpu/x86/vm/x86_64.ad Fri Apr 12 23:29:45 2013 +0200 +++ b/src/cpu/x86/vm/x86_64.ad Sat Apr 13 00:33:37 2013 +0200 @@ -1693,17 +1693,6 @@ return PTR_RBP_REG_mask(); } -static Address build_address(int b, int i, int s, int d) { - Register index = as_Register(i); - Address::ScaleFactor scale = (Address::ScaleFactor)s; - if (index == rsp) { - index = noreg; - scale = Address::no_scale; - } - Address addr(as_Register(b), index, scale, d); - return addr; -} - %} //----------ENCODING BLOCK----------------------------------------------------- diff -r 2cae919cd3af -r 0c8ec85fa013 src/os/bsd/vm/os_bsd.cpp --- a/src/os/bsd/vm/os_bsd.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/os/bsd/vm/os_bsd.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -152,7 +152,6 @@ // utility functions static int SR_initialize(); -static int SR_finalize(); julong os::available_memory() { return Bsd::available_memory(); @@ -1200,6 +1199,9 @@ } else if (strchr(pname, *os::path_separator()) != NULL) { int n; char** pelements = split_path(pname, &n); + if (pelements == NULL) { + return false; + } for (int i = 0 ; i < n ; i++) { // Really shouldn't be NULL, but check can't hurt if (pelements[i] == NULL || strlen(pelements[i]) == 0) { @@ -2766,10 +2768,6 @@ return 0; } -static int SR_finalize() { - return 0; -} - // returns true on success and false on error - really an error is fatal // but this seems the normal response to library errors @@ -3578,16 +3576,6 @@ //////////////////////////////////////////////////////////////////////////////// // debug support -static address same_page(address x, address y) { - int page_bits = -os::vm_page_size(); - if ((intptr_t(x) & page_bits) == (intptr_t(y) & page_bits)) - return x; - else if (x > y) - return (address)(intptr_t(y) | ~page_bits) + 1; - else - return (address)(intptr_t(y) & page_bits); -} - bool os::find(address addr, outputStream* st) { Dl_info dlinfo; memset(&dlinfo, 0, sizeof(dlinfo)); @@ -3611,8 +3599,8 @@ if (Verbose) { // decode some bytes around the PC - address begin = same_page(addr-40, addr); - address end = same_page(addr+40, addr); + address begin = clamp_address_in_page(addr-40, addr, os::vm_page_size()); + address end = clamp_address_in_page(addr+40, addr, os::vm_page_size()); address lowest = (address) dlinfo.dli_sname; if (!lowest) lowest = (address) dlinfo.dli_fbase; if (begin < lowest) begin = lowest; diff -r 2cae919cd3af -r 0c8ec85fa013 src/os/bsd/vm/perfMemory_bsd.cpp --- a/src/os/bsd/vm/perfMemory_bsd.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/os/bsd/vm/perfMemory_bsd.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -672,15 +672,15 @@ RESTARTABLE(::open(filename, oflags), result); if (result == OS_ERR) { if (errno == ENOENT) { - THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), - "Process not found"); + THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), + "Process not found", OS_ERR); } else if (errno == EACCES) { - THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), - "Permission denied"); + THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), + "Permission denied", OS_ERR); } else { - THROW_MSG_0(vmSymbols::java_io_IOException(), strerror(errno)); + THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR); } } @@ -828,7 +828,7 @@ char* mapAddress; int result; int fd; - size_t size; + size_t size = 0; const char* luser = NULL; int mmap_prot; @@ -899,9 +899,12 @@ if (*sizep == 0) { size = sharedmem_filesize(fd, CHECK); - assert(size != 0, "unexpected size"); + } else { + size = *sizep; } + assert(size > 0, "unexpected size <= 0"); + mapAddress = (char*)::mmap((char*)0, size, mmap_prot, MAP_SHARED, fd, 0); // attempt to close the file - restart if it gets interrupted, diff -r 2cae919cd3af -r 0c8ec85fa013 src/os/linux/vm/os_linux.cpp --- a/src/os/linux/vm/os_linux.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/os/linux/vm/os_linux.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -176,7 +176,6 @@ // utility functions static int SR_initialize(); -static int SR_finalize(); julong os::available_memory() { return Linux::available_memory(); @@ -1633,6 +1632,9 @@ } else if (strchr(pname, *os::path_separator()) != NULL) { int n; char** pelements = split_path(pname, &n); + if (pelements == NULL) { + return false; + } for (int i = 0 ; i < n ; i++) { // Really shouldn't be NULL, but check can't hurt if (pelements[i] == NULL || strlen(pelements[i]) == 0) { @@ -3655,10 +3657,6 @@ return 0; } -static int SR_finalize() { - return 0; -} - // returns true on success and false on error - really an error is fatal // but this seems the normal response to library errors @@ -4500,16 +4498,6 @@ //////////////////////////////////////////////////////////////////////////////// // debug support -static address same_page(address x, address y) { - int page_bits = -os::vm_page_size(); - if ((intptr_t(x) & page_bits) == (intptr_t(y) & page_bits)) - return x; - else if (x > y) - return (address)(intptr_t(y) | ~page_bits) + 1; - else - return (address)(intptr_t(y) & page_bits); -} - bool os::find(address addr, outputStream* st) { Dl_info dlinfo; memset(&dlinfo, 0, sizeof(dlinfo)); @@ -4533,8 +4521,8 @@ if (Verbose) { // decode some bytes around the PC - address begin = same_page(addr-40, addr); - address end = same_page(addr+40, addr); + address begin = clamp_address_in_page(addr-40, addr, os::vm_page_size()); + address end = clamp_address_in_page(addr+40, addr, os::vm_page_size()); address lowest = (address) dlinfo.dli_sname; if (!lowest) lowest = (address) dlinfo.dli_fbase; if (begin < lowest) begin = lowest; diff -r 2cae919cd3af -r 0c8ec85fa013 src/os/linux/vm/perfMemory_linux.cpp --- a/src/os/linux/vm/perfMemory_linux.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/os/linux/vm/perfMemory_linux.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -672,15 +672,15 @@ RESTARTABLE(::open(filename, oflags), result); if (result == OS_ERR) { if (errno == ENOENT) { - THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), - "Process not found"); + THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), + "Process not found", OS_ERR); } else if (errno == EACCES) { - THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), - "Permission denied"); + THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), + "Permission denied", OS_ERR); } else { - THROW_MSG_0(vmSymbols::java_io_IOException(), strerror(errno)); + THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR); } } @@ -828,7 +828,7 @@ char* mapAddress; int result; int fd; - size_t size; + size_t size = 0; const char* luser = NULL; int mmap_prot; @@ -899,9 +899,12 @@ if (*sizep == 0) { size = sharedmem_filesize(fd, CHECK); - assert(size != 0, "unexpected size"); + } else { + size = *sizep; } + assert(size > 0, "unexpected size <= 0"); + mapAddress = (char*)::mmap((char*)0, size, mmap_prot, MAP_SHARED, fd, 0); // attempt to close the file - restart if it gets interrupted, diff -r 2cae919cd3af -r 0c8ec85fa013 src/os/solaris/vm/os_solaris.cpp --- a/src/os/solaris/vm/os_solaris.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/os/solaris/vm/os_solaris.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -1885,6 +1885,9 @@ } else if (strchr(pname, *os::path_separator()) != NULL) { int n; char** pelements = split_path(pname, &n); + if (pelements == NULL) { + return false; + } for (int i = 0 ; i < n ; i++) { // really shouldn't be NULL but what the heck, check can't hurt if (pelements[i] == NULL || strlen(pelements[i]) == 0) { @@ -5787,16 +5790,6 @@ //--------------------------------------------------------------------------------- -static address same_page(address x, address y) { - intptr_t page_bits = -os::vm_page_size(); - if ((intptr_t(x) & page_bits) == (intptr_t(y) & page_bits)) - return x; - else if (x > y) - return (address)(intptr_t(y) | ~page_bits) + 1; - else - return (address)(intptr_t(y) & page_bits); -} - bool os::find(address addr, outputStream* st) { Dl_info dlinfo; memset(&dlinfo, 0, sizeof(dlinfo)); @@ -5822,8 +5815,8 @@ if (Verbose) { // decode some bytes around the PC - address begin = same_page(addr-40, addr); - address end = same_page(addr+40, addr); + address begin = clamp_address_in_page(addr-40, addr, os::vm_page_size()); + address end = clamp_address_in_page(addr+40, addr, os::vm_page_size()); address lowest = (address) dlinfo.dli_sname; if (!lowest) lowest = (address) dlinfo.dli_fbase; if (begin < lowest) begin = lowest; diff -r 2cae919cd3af -r 0c8ec85fa013 src/os/solaris/vm/perfMemory_solaris.cpp --- a/src/os/solaris/vm/perfMemory_solaris.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/os/solaris/vm/perfMemory_solaris.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -687,15 +687,15 @@ RESTARTABLE(::open(filename, oflags), result); if (result == OS_ERR) { if (errno == ENOENT) { - THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), - "Process not found"); + THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), + "Process not found", OS_ERR); } else if (errno == EACCES) { - THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), - "Permission denied"); + THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), + "Permission denied", OS_ERR); } else { - THROW_MSG_0(vmSymbols::java_io_IOException(), strerror(errno)); + THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR); } } @@ -843,7 +843,7 @@ char* mapAddress; int result; int fd; - size_t size; + size_t size = 0; const char* luser = NULL; int mmap_prot; @@ -914,9 +914,12 @@ if (*sizep == 0) { size = sharedmem_filesize(fd, CHECK); - assert(size != 0, "unexpected size"); + } else { + size = *sizep; } + assert(size > 0, "unexpected size <= 0"); + mapAddress = (char*)::mmap((char*)0, size, mmap_prot, MAP_SHARED, fd, 0); // attempt to close the file - restart if it gets interrupted, diff -r 2cae919cd3af -r 0c8ec85fa013 src/os/windows/vm/os_windows.cpp --- a/src/os/windows/vm/os_windows.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/os/windows/vm/os_windows.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -1182,6 +1182,9 @@ } else if (strchr(pname, *os::path_separator()) != NULL) { int n; char** pelements = split_path(pname, &n); + if (pelements == NULL) { + return false; + } for (int i = 0 ; i < n ; i++) { char* path = pelements[i]; // Really shouldn't be NULL, but check can't hurt diff -r 2cae919cd3af -r 0c8ec85fa013 src/os/windows/vm/perfMemory_windows.cpp --- a/src/os/windows/vm/perfMemory_windows.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/os/windows/vm/perfMemory_windows.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -1581,7 +1581,7 @@ ResourceMark rm; void *mapAddress = 0; - size_t size; + size_t size = 0; HANDLE fmh; DWORD ofm_access; DWORD mv_access; @@ -1652,9 +1652,12 @@ if (*sizep == 0) { size = sharedmem_filesize(rfilename, CHECK); - assert(size != 0, "unexpected size"); + } else { + size = *sizep; } + assert(size > 0, "unexpected size <= 0"); + // Open the file mapping object with the given name fmh = open_sharedmem_object(robjectname, ofm_access, CHECK); diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/tools/launcher/wildcard.c --- a/src/share/tools/launcher/wildcard.c Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/tools/launcher/wildcard.c Sat Apr 13 00:33:37 2013 +0200 @@ -368,8 +368,10 @@ const char *basename; FileList fl = FileList_new(16); WildcardIterator it = WildcardIterator_for(wildcard); - if (it == NULL) + if (it == NULL) { + FileList_free(fl); return NULL; + } while ((basename = WildcardIterator_next(it)) != NULL) if (isJarFileName(basename)) FileList_add(fl, wildcardConcat(wildcard, basename)); diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/adlc/output_c.cpp --- a/src/share/vm/adlc/output_c.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/adlc/output_c.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -63,11 +63,10 @@ RegDef *reg_def = NULL; RegDef *next = NULL; registers->reset_RegDefs(); - for( reg_def = registers->iter_RegDefs(); reg_def != NULL; reg_def = next ) { + for (reg_def = registers->iter_RegDefs(); reg_def != NULL; reg_def = next) { next = registers->iter_RegDefs(); const char *comma = (next != NULL) ? "," : " // no trailing comma"; - fprintf(fp," \"%s\"%s\n", - reg_def->_regname, comma ); + fprintf(fp," \"%s\"%s\n", reg_def->_regname, comma); } // Finish defining enumeration @@ -79,10 +78,10 @@ reg_def = NULL; next = NULL; registers->reset_RegDefs(); - for( reg_def = registers->iter_RegDefs(); reg_def != NULL; reg_def = next ) { + for (reg_def = registers->iter_RegDefs(); reg_def != NULL; reg_def = next) { next = registers->iter_RegDefs(); const char *comma = (next != NULL) ? "," : " // no trailing comma"; - fprintf(fp,"\t%s%s\n", reg_def->_concrete, comma ); + fprintf(fp,"\t%s%s\n", reg_def->_concrete, comma); } // Finish defining array fprintf(fp,"\t};\n"); @@ -104,19 +103,17 @@ RegDef *reg_def = NULL; RegDef *next = NULL; registers->reset_RegDefs(); - for( reg_def = registers->iter_RegDefs(); reg_def != NULL; reg_def = next ) { + for (reg_def = registers->iter_RegDefs(); reg_def != NULL; reg_def = next) { next = registers->iter_RegDefs(); const char* register_encode = reg_def->register_encode(); const char *comma = (next != NULL) ? "," : " // no trailing comma"; int encval; if (!ADLParser::is_int_token(register_encode, encval)) { - fprintf(fp," %s%s // %s\n", - register_encode, comma, reg_def->_regname ); + fprintf(fp," %s%s // %s\n", register_encode, comma, reg_def->_regname); } else { // Output known constants in hex char format (backward compatibility). assert(encval < 256, "Exceeded supported width for register encoding"); - fprintf(fp," (unsigned char)'\\x%X'%s // %s\n", - encval, comma, reg_def->_regname ); + fprintf(fp," (unsigned char)'\\x%X'%s // %s\n", encval, comma, reg_def->_regname); } } // Finish defining enumeration @@ -133,9 +130,10 @@ fprintf(fp,"// Enumeration of register class names\n"); fprintf(fp, "enum machRegisterClass {\n"); registers->_rclasses.reset(); - for( const char *class_name = NULL; - (class_name = registers->_rclasses.iter()) != NULL; ) { - fprintf(fp," %s,\n", toUpper( class_name )); + for (const char *class_name = NULL; (class_name = registers->_rclasses.iter()) != NULL;) { + const char * class_name_to_upper = toUpper(class_name); + fprintf(fp," %s,\n", class_name_to_upper); + delete[] class_name_to_upper; } // Finish defining enumeration fprintf(fp, " _last_Mach_Reg_Class\n"); @@ -148,7 +146,7 @@ void ArchDesc::declare_register_masks(FILE *fp_hpp) { const char *rc_name; - if( _register ) { + if (_register) { // Build enumeration of user-defined register classes. defineRegClassEnum(fp_hpp, _register); @@ -156,24 +154,27 @@ fprintf(fp_hpp,"\n"); fprintf(fp_hpp,"// Register masks, one for each register class.\n"); _register->_rclasses.reset(); - for( rc_name = NULL; - (rc_name = _register->_rclasses.iter()) != NULL; ) { - const char *prefix = ""; - RegClass *reg_class = _register->getRegClass(rc_name); - assert( reg_class, "Using an undefined register class"); + for (rc_name = NULL; (rc_name = _register->_rclasses.iter()) != NULL;) { + const char *prefix = ""; + RegClass *reg_class = _register->getRegClass(rc_name); + assert(reg_class, "Using an undefined register class"); + + const char* rc_name_to_upper = toUpper(rc_name); if (reg_class->_user_defined == NULL) { - fprintf(fp_hpp, "extern const RegMask _%s%s_mask;\n", prefix, toUpper( rc_name ) ); - fprintf(fp_hpp, "inline const RegMask &%s%s_mask() { return _%s%s_mask; }\n", prefix, toUpper( rc_name ), prefix, toUpper( rc_name )); + fprintf(fp_hpp, "extern const RegMask _%s%s_mask;\n", prefix, rc_name_to_upper); + fprintf(fp_hpp, "inline const RegMask &%s%s_mask() { return _%s%s_mask; }\n", prefix, rc_name_to_upper, prefix, rc_name_to_upper); } else { - fprintf(fp_hpp, "inline const RegMask &%s%s_mask() { %s }\n", prefix, toUpper( rc_name ), reg_class->_user_defined); + fprintf(fp_hpp, "inline const RegMask &%s%s_mask() { %s }\n", prefix, rc_name_to_upper, reg_class->_user_defined); } - if( reg_class->_stack_or_reg ) { + if (reg_class->_stack_or_reg) { assert(reg_class->_user_defined == NULL, "no user defined reg class here"); - fprintf(fp_hpp, "extern const RegMask _%sSTACK_OR_%s_mask;\n", prefix, toUpper( rc_name ) ); - fprintf(fp_hpp, "inline const RegMask &%sSTACK_OR_%s_mask() { return _%sSTACK_OR_%s_mask; }\n", prefix, toUpper( rc_name ), prefix, toUpper( rc_name ) ); + fprintf(fp_hpp, "extern const RegMask _%sSTACK_OR_%s_mask;\n", prefix, rc_name_to_upper); + fprintf(fp_hpp, "inline const RegMask &%sSTACK_OR_%s_mask() { return _%sSTACK_OR_%s_mask; }\n", prefix, rc_name_to_upper, prefix, rc_name_to_upper); } + delete[] rc_name_to_upper; + } } } @@ -183,34 +184,41 @@ void ArchDesc::build_register_masks(FILE *fp_cpp) { const char *rc_name; - if( _register ) { + if (_register) { // Generate a list of register masks, one for each class. fprintf(fp_cpp,"\n"); fprintf(fp_cpp,"// Register masks, one for each register class.\n"); _register->_rclasses.reset(); - for( rc_name = NULL; - (rc_name = _register->_rclasses.iter()) != NULL; ) { - const char *prefix = ""; - RegClass *reg_class = _register->getRegClass(rc_name); - assert( reg_class, "Using an undefined register class"); - - if (reg_class->_user_defined != NULL) continue; + for (rc_name = NULL; (rc_name = _register->_rclasses.iter()) != NULL;) { + const char *prefix = ""; + RegClass *reg_class = _register->getRegClass(rc_name); + assert(reg_class, "Using an undefined register class"); + + if (reg_class->_user_defined != NULL) { + continue; + } int len = RegisterForm::RegMask_Size(); - fprintf(fp_cpp, "const RegMask _%s%s_mask(", prefix, toUpper( rc_name ) ); - { int i; - for( i = 0; i < len-1; i++ ) - fprintf(fp_cpp," 0x%x,",reg_class->regs_in_word(i,false)); - fprintf(fp_cpp," 0x%x );\n",reg_class->regs_in_word(i,false)); + const char* rc_name_to_upper = toUpper(rc_name); + fprintf(fp_cpp, "const RegMask _%s%s_mask(", prefix, rc_name_to_upper); + + { + int i; + for(i = 0; i < len - 1; i++) { + fprintf(fp_cpp," 0x%x,", reg_class->regs_in_word(i, false)); + } + fprintf(fp_cpp," 0x%x );\n", reg_class->regs_in_word(i, false)); } - if( reg_class->_stack_or_reg ) { + if (reg_class->_stack_or_reg) { int i; - fprintf(fp_cpp, "const RegMask _%sSTACK_OR_%s_mask(", prefix, toUpper( rc_name ) ); - for( i = 0; i < len-1; i++ ) - fprintf(fp_cpp," 0x%x,",reg_class->regs_in_word(i,true)); - fprintf(fp_cpp," 0x%x );\n",reg_class->regs_in_word(i,true)); + fprintf(fp_cpp, "const RegMask _%sSTACK_OR_%s_mask(", prefix, rc_name_to_upper); + for(i = 0; i < len - 1; i++) { + fprintf(fp_cpp," 0x%x,",reg_class->regs_in_word(i, true)); + } + fprintf(fp_cpp," 0x%x );\n",reg_class->regs_in_word(i, true)); } + delete[] rc_name_to_upper; } } } @@ -2676,7 +2684,9 @@ if (strcmp(first_reg_class, "stack_slots") == 0) { fprintf(fp," return &(Compile::current()->FIRST_STACK_mask());\n"); } else { - fprintf(fp," return &%s_mask();\n", toUpper(first_reg_class)); + const char* first_reg_class_to_upper = toUpper(first_reg_class); + fprintf(fp," return &%s_mask();\n", first_reg_class_to_upper); + delete[] first_reg_class_to_upper; } } else { // Build a switch statement to return the desired mask. @@ -2688,7 +2698,9 @@ if( !strcmp(reg_class, "stack_slots") ) { fprintf(fp, " case %d: return &(Compile::current()->FIRST_STACK_mask());\n", index); } else { - fprintf(fp, " case %d: return &%s_mask();\n", index, toUpper(reg_class)); + const char* reg_class_to_upper = toUpper(reg_class); + fprintf(fp, " case %d: return &%s_mask();\n", index, reg_class_to_upper); + delete[] reg_class_to_upper; } } fprintf(fp," }\n"); diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/adlc/output_h.cpp --- a/src/share/vm/adlc/output_h.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/adlc/output_h.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -2069,9 +2069,21 @@ void closing() { fprintf(_cpp, " _LAST_MACH_OPER\n"); OutputMap::closing(); } - void map(OpClassForm &opc) { fprintf(_cpp, " %s", _AD.machOperEnum(opc._ident) ); } - void map(OperandForm &oper) { fprintf(_cpp, " %s", _AD.machOperEnum(oper._ident) ); } - void map(char *name) { fprintf(_cpp, " %s", _AD.machOperEnum(name)); } + void map(OpClassForm &opc) { + const char* opc_ident_to_upper = _AD.machOperEnum(opc._ident); + fprintf(_cpp, " %s", opc_ident_to_upper); + delete[] opc_ident_to_upper; + } + void map(OperandForm &oper) { + const char* oper_ident_to_upper = _AD.machOperEnum(oper._ident); + fprintf(_cpp, " %s", oper_ident_to_upper); + delete[] oper_ident_to_upper; + } + void map(char *name) { + const char* name_to_upper = _AD.machOperEnum(name); + fprintf(_cpp, " %s", name_to_upper); + delete[] name_to_upper; + } bool do_instructions() { return false; } void map(InstructForm &inst){ assert( false, "ShouldNotCallThis()"); } diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/c1/c1_LIRGenerator.cpp --- a/src/share/vm/c1/c1_LIRGenerator.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/c1/c1_LIRGenerator.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -711,25 +711,6 @@ } } -static Value maxvalue(IfOp* ifop) { - switch (ifop->cond()) { - case If::eql: return NULL; - case If::neq: return NULL; - case If::lss: // x < y ? x : y - case If::leq: // x <= y ? x : y - if (ifop->x() == ifop->tval() && - ifop->y() == ifop->fval()) return ifop->y(); - return NULL; - - case If::gtr: // x > y ? y : x - case If::geq: // x >= y ? y : x - if (ifop->x() == ifop->tval() && - ifop->y() == ifop->fval()) return ifop->y(); - return NULL; - - } -} - static ciType* phi_declared_type(Phi* phi) { ciType* t = phi->operand_at(0)->declared_type(); if (t == NULL) { diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/c1/c1_ValueMap.cpp --- a/src/share/vm/c1/c1_ValueMap.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/c1/c1_ValueMap.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -316,6 +316,7 @@ ShortLoopOptimizer* _short_loop_optimizer; Instruction* _insertion_point; ValueStack * _state; + bool _insert_is_pred; void set_invariant(Value v) const { _gvn->set_processed(v); } bool is_invariant(Value v) const { return _gvn->is_processed(v); } @@ -339,6 +340,7 @@ assert(insertion_block->end()->as_Base() == NULL, "cannot insert into entry block"); _insertion_point = insertion_block->end()->prev(); + _insert_is_pred = loop_header->is_predecessor(insertion_block); BlockEnd *block_end = insertion_block->end(); _state = block_end->state_before(); @@ -379,13 +381,13 @@ } else if (cur->as_LoadField() != NULL) { LoadField* lf = (LoadField*)cur; // deoptimizes on NullPointerException - cur_invariant = !lf->needs_patching() && !lf->field()->is_volatile() && !_short_loop_optimizer->has_field_store(lf->field()->type()->basic_type()) && is_invariant(lf->obj()); + cur_invariant = !lf->needs_patching() && !lf->field()->is_volatile() && !_short_loop_optimizer->has_field_store(lf->field()->type()->basic_type()) && is_invariant(lf->obj()) && _insert_is_pred; } else if (cur->as_ArrayLength() != NULL) { ArrayLength *length = cur->as_ArrayLength(); cur_invariant = is_invariant(length->array()); } else if (cur->as_LoadIndexed() != NULL) { LoadIndexed *li = (LoadIndexed *)cur->as_LoadIndexed(); - cur_invariant = !_short_loop_optimizer->has_indexed_store(as_BasicType(cur->type())) && is_invariant(li->array()) && is_invariant(li->index()); + cur_invariant = !_short_loop_optimizer->has_indexed_store(as_BasicType(cur->type())) && is_invariant(li->array()) && is_invariant(li->index()) && _insert_is_pred; } if (cur_invariant) { diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/classfile/classFileParser.cpp --- a/src/share/vm/classfile/classFileParser.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/classfile/classFileParser.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -1723,9 +1723,6 @@ } else { coll->set_contended_group(0); // default contended group } - coll->set_contended(true); - } else { - coll->set_contended(false); } } } diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/classfile/classFileParser.hpp --- a/src/share/vm/classfile/classFileParser.hpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/classfile/classFileParser.hpp Sat Apr 13 00:33:37 2013 +0200 @@ -150,7 +150,6 @@ void set_contended_group(u2 group) { _contended_group = group; } u2 contended_group() { return _contended_group; } - void set_contended(bool contended) { set_annotation(_sun_misc_Contended); } bool is_contended() { return has_annotation(_sun_misc_Contended); } }; diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/classfile/classLoaderData.cpp --- a/src/share/vm/classfile/classLoaderData.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/classfile/classLoaderData.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -70,15 +70,19 @@ _is_anonymous(is_anonymous), _keep_alive(is_anonymous), // initially _metaspace(NULL), _unloading(false), _klasses(NULL), _claimed(0), _jmethod_ids(NULL), _handles(NULL), _deallocate_list(NULL), - _next(NULL), _dependencies(NULL), + _next(NULL), _dependencies(), _metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true)) { // empty } void ClassLoaderData::init_dependencies(TRAPS) { + _dependencies.init(CHECK); +} + +void ClassLoaderData::Dependencies::init(TRAPS) { // Create empty dependencies array to add to. CMS requires this to be // an oop so that it can track additions via card marks. We think. - _dependencies = (oop)oopFactory::new_objectArray(2, CHECK); + _list_head = oopFactory::new_objectArray(2, CHECK); } bool ClassLoaderData::claim() { @@ -95,13 +99,17 @@ } f->do_oop(&_class_loader); - f->do_oop(&_dependencies); + _dependencies.oops_do(f); _handles->oops_do(f); if (klass_closure != NULL) { classes_do(klass_closure); } } +void ClassLoaderData::Dependencies::oops_do(OopClosure* f) { + f->do_oop((oop*)&_list_head); +} + void ClassLoaderData::classes_do(KlassClosure* klass_closure) { for (Klass* k = _klasses; k != NULL; k = k->next_link()) { klass_closure->do_klass(k); @@ -154,14 +162,14 @@ // It's a dependency we won't find through GC, add it. This is relatively rare // Must handle over GC point. Handle dependency(THREAD, to); - from_cld->add_dependency(dependency, CHECK); + from_cld->_dependencies.add(dependency, CHECK); } -void ClassLoaderData::add_dependency(Handle dependency, TRAPS) { +void ClassLoaderData::Dependencies::add(Handle dependency, TRAPS) { // Check first if this dependency is already in the list. // Save a pointer to the last to add to under the lock. - objArrayOop ok = (objArrayOop)_dependencies; + objArrayOop ok = _list_head; objArrayOop last = NULL; while (ok != NULL) { last = ok; @@ -184,16 +192,17 @@ objArrayHandle new_dependency(THREAD, deps); // Add the dependency under lock - locked_add_dependency(last_handle, new_dependency); + locked_add(last_handle, new_dependency, THREAD); } -void ClassLoaderData::locked_add_dependency(objArrayHandle last_handle, - objArrayHandle new_dependency) { +void ClassLoaderData::Dependencies::locked_add(objArrayHandle last_handle, + objArrayHandle new_dependency, + Thread* THREAD) { // Have to lock and put the new dependency on the end of the dependency // array so the card mark for CMS sees that this dependency is new. // Can probably do this lock free with some effort. - MutexLockerEx ml(metaspace_lock(), Mutex::_no_safepoint_check_flag); + ObjectLocker ol(Handle(THREAD, _list_head), THREAD); oop loader_or_mirror = new_dependency->obj_at(0); diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/classfile/classLoaderData.hpp --- a/src/share/vm/classfile/classLoaderData.hpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/classfile/classLoaderData.hpp Sat Apr 13 00:33:37 2013 +0200 @@ -93,6 +93,18 @@ class ClassLoaderData : public CHeapObj { friend class VMStructs; private: + class Dependencies VALUE_OBJ_CLASS_SPEC { + objArrayOop _list_head; + void locked_add(objArrayHandle last, + objArrayHandle new_dependency, + Thread* THREAD); + public: + Dependencies() : _list_head(NULL) {} + void add(Handle dependency, TRAPS); + void init(TRAPS); + void oops_do(OopClosure* f); + }; + friend class ClassLoaderDataGraph; friend class ClassLoaderDataGraphMetaspaceIterator; friend class MetaDataFactory; @@ -100,10 +112,11 @@ static ClassLoaderData * _the_null_class_loader_data; - oop _class_loader; // oop used to uniquely identify a class loader - // class loader or a canonical class path - oop _dependencies; // oop to hold dependencies from this class loader - // data to others. + oop _class_loader; // oop used to uniquely identify a class loader + // class loader or a canonical class path + Dependencies _dependencies; // holds dependencies from this class loader + // data to others. + Metaspace * _metaspace; // Meta-space where meta-data defined by the // classes in the class loader are allocated. Mutex* _metaspace_lock; // Locks the metaspace for allocations and setup. @@ -134,9 +147,6 @@ static Metaspace* _ro_metaspace; static Metaspace* _rw_metaspace; - void add_dependency(Handle dependency, TRAPS); - void locked_add_dependency(objArrayHandle last, objArrayHandle new_dependency); - void set_next(ClassLoaderData* next) { _next = next; } ClassLoaderData* next() const { return _next; } diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/classfile/systemDictionary.cpp --- a/src/share/vm/classfile/systemDictionary.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/classfile/systemDictionary.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -1592,9 +1592,10 @@ // Used for assertions and verification only Klass* SystemDictionary::find_class(Symbol* class_name, ClassLoaderData* loader_data) { #ifndef ASSERT - guarantee(VerifyBeforeGC || - VerifyDuringGC || - VerifyBeforeExit || + guarantee(VerifyBeforeGC || + VerifyDuringGC || + VerifyBeforeExit || + VerifyDuringStartup || VerifyAfterGC, "too expensive"); #endif assert_locked_or_safepoint(SystemDictionary_lock); diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/classfile/systemDictionary.hpp --- a/src/share/vm/classfile/systemDictionary.hpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/classfile/systemDictionary.hpp Sat Apr 13 00:33:37 2013 +0200 @@ -199,6 +199,7 @@ /* graal.api.code */ \ do_klass(Assumptions_klass, com_oracle_graal_api_code_Assumptions, Opt) \ do_klass(Assumptions_ConcreteMethod_klass, com_oracle_graal_api_code_Assumptions_ConcreteMethod, Opt) \ + do_klass(Assumptions_NoFinalizableSubclass_klass, com_oracle_graal_api_code_Assumptions_NoFinalizableSubclass, Opt) \ do_klass(Assumptions_ConcreteSubtype_klass, com_oracle_graal_api_code_Assumptions_ConcreteSubtype, Opt) \ do_klass(Assumptions_MethodContents_klass, com_oracle_graal_api_code_Assumptions_MethodContents, Opt) \ do_klass(Assumptions_CallSiteTargetValue_klass, com_oracle_graal_api_code_Assumptions_CallSiteTargetValue, Opt) \ @@ -210,8 +211,9 @@ do_klass(CompilationResult_DataPatch_klass, com_oracle_graal_api_code_CompilationResult_DataPatch, Opt) \ do_klass(CompilationResult_ExceptionHandler_klass, com_oracle_graal_api_code_CompilationResult_ExceptionHandler, Opt) \ do_klass(CompilationResult_Mark_klass, com_oracle_graal_api_code_CompilationResult_Mark, Opt) \ - do_klass(CompilationResult_Safepoint_klass, com_oracle_graal_api_code_CompilationResult_Safepoint, Opt) \ + do_klass(CompilationResult_Infopoint_klass, com_oracle_graal_api_code_CompilationResult_Infopoint, Opt) \ do_klass(CompilationResult_Site_klass, com_oracle_graal_api_code_CompilationResult_Site, Opt) \ + do_klass(InfopointReason_klass, com_oracle_graal_api_code_InfopointReason, Opt) \ do_klass(code_Register_klass, com_oracle_graal_api_code_Register, Opt) \ do_klass(RegisterValue_klass, com_oracle_graal_api_code_RegisterValue, Opt) \ do_klass(StackSlot_klass, com_oracle_graal_api_code_StackSlot, Opt) \ diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/classfile/verifier.cpp --- a/src/share/vm/classfile/verifier.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/classfile/verifier.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -63,6 +63,7 @@ #define NOFAILOVER_MAJOR_VERSION 51 #define NONZERO_PADDING_BYTES_IN_SWITCH_MAJOR_VERSION 51 +#define STATIC_METHOD_IN_INTERFACE_MAJOR_VERSION 52 // Access to external entry for VerifyClassCodes - old byte code verifier @@ -2320,6 +2321,11 @@ types = (1 << JVM_CONSTANT_InterfaceMethodref) | (1 << JVM_CONSTANT_Methodref); break; + case Bytecodes::_invokestatic: + types = (_klass->major_version() < STATIC_METHOD_IN_INTERFACE_MAJOR_VERSION) ? + (1 << JVM_CONSTANT_Methodref) : + ((1 << JVM_CONSTANT_InterfaceMethodref) | (1 << JVM_CONSTANT_Methodref)); + break; default: types = 1 << JVM_CONSTANT_Methodref; } diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/classfile/vmSymbols.hpp Sat Apr 13 00:33:37 2013 +0200 @@ -299,6 +299,7 @@ template(com_oracle_graal_hotspot_HotSpotCompilationResult, "com/oracle/graal/hotspot/HotSpotCompilationResult") \ template(com_oracle_graal_hotspot_HotSpotRuntimeCallTarget, "com/oracle/graal/hotspot/HotSpotRuntimeCallTarget") \ template(com_oracle_graal_hotspot_bridge_VMToCompiler, "com/oracle/graal/hotspot/bridge/VMToCompiler") \ + template(com_oracle_graal_hotspot_bridge_CompilerToVMImpl, "com/oracle/graal/hotspot/bridge/CompilerToVMImpl") \ template(com_oracle_graal_hotspot_meta_HotSpotCodeInfo, "com/oracle/graal/hotspot/meta/HotSpotCodeInfo") \ template(com_oracle_graal_hotspot_meta_HotSpotInstalledCode, "com/oracle/graal/hotspot/meta/HotSpotInstalledCode") \ template(com_oracle_graal_hotspot_meta_HotSpotJavaType, "com/oracle/graal/hotspot/meta/HotSpotJavaType") \ @@ -322,6 +323,7 @@ template(com_oracle_graal_api_code_Assumptions, "com/oracle/graal/api/code/Assumptions") \ template(com_oracle_graal_api_code_Assumptions_MethodContents, "com/oracle/graal/api/code/Assumptions$MethodContents") \ template(com_oracle_graal_api_code_Assumptions_ConcreteSubtype, "com/oracle/graal/api/code/Assumptions$ConcreteSubtype") \ + template(com_oracle_graal_api_code_Assumptions_NoFinalizableSubclass, "com/oracle/graal/api/code/Assumptions$NoFinalizableSubclass") \ template(com_oracle_graal_api_code_Assumptions_ConcreteMethod, "com/oracle/graal/api/code/Assumptions$ConcreteMethod") \ template(com_oracle_graal_api_code_Assumptions_CallSiteTargetValue,"com/oracle/graal/api/code/Assumptions$CallSiteTargetValue") \ template(com_oracle_graal_api_code_CompilationResult, "com/oracle/graal/api/code/CompilationResult") \ @@ -329,8 +331,9 @@ template(com_oracle_graal_api_code_CompilationResult_DataPatch, "com/oracle/graal/api/code/CompilationResult$DataPatch") \ template(com_oracle_graal_api_code_CompilationResult_ExceptionHandler, "com/oracle/graal/api/code/CompilationResult$ExceptionHandler") \ template(com_oracle_graal_api_code_CompilationResult_Mark, "com/oracle/graal/api/code/CompilationResult$Mark") \ - template(com_oracle_graal_api_code_CompilationResult_Safepoint, "com/oracle/graal/api/code/CompilationResult$Safepoint") \ + template(com_oracle_graal_api_code_CompilationResult_Infopoint, "com/oracle/graal/api/code/CompilationResult$Infopoint") \ template(com_oracle_graal_api_code_CompilationResult_Site, "com/oracle/graal/api/code/CompilationResult$Site") \ + template(com_oracle_graal_api_code_InfopointReason, "com/oracle/graal/api/code/InfopointReason") \ template(com_oracle_graal_api_code_BytecodeFrame, "com/oracle/graal/api/code/BytecodeFrame") \ template(com_oracle_graal_api_code_BytecodePosition, "com/oracle/graal/api/code/BytecodePosition") \ template(com_oracle_graal_api_code_DebugInfo, "com/oracle/graal/api/code/DebugInfo") \ @@ -338,6 +341,7 @@ template(com_oracle_graal_api_code_RegisterValue, "com/oracle/graal/api/code/RegisterValue") \ template(com_oracle_graal_api_code_StackSlot, "com/oracle/graal/api/code/StackSlot") \ template(com_oracle_graal_api_code_VirtualObject, "com/oracle/graal/api/code/VirtualObject") \ + template(com_oracle_graal_api_code_InvalidInstalledCodeException, "com/oracle/graal/api/code/InvalidInstalledCodeException") \ template(startCompiler_name, "startCompiler") \ template(bootstrap_name, "bootstrap") \ template(shutdownCompiler_name, "shutdownCompiler") \ @@ -378,7 +382,6 @@ template(forObject_name, "forObject") \ template(callbackInternal_name, "callbackInternal") \ template(callback_signature, "(Ljava/lang/Object;)Ljava/lang/Object;") \ - template(MethodInvalidatedException, "com/oracle/graal/api/code/InstalledCode$MethodInvalidatedException") \ /* graal.api.interpreter */ \ template(com_oracle_graal_api_interpreter_Interpreter, "com/oracle/graal/api/interpreter/Interpreter") \ template(interpreter_execute_name, "execute") \ @@ -1127,6 +1130,9 @@ do_intrinsic(_Double_valueOf, java_lang_Double, valueOf_name, Double_valueOf_signature, F_S) \ do_name( Double_valueOf_signature, "(D)Ljava/lang/Double;") \ \ + do_intrinsic(_CompilerToVMImpl_executeCompiledMethod, com_oracle_graal_hotspot_bridge_CompilerToVMImpl, executeCompiledMethod_name, CompilerToVMImpl_executeCompiledMethod_signature, F_SN)\ + do_name( CompilerToVMImpl_executeCompiledMethod_signature, "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;J)Ljava/lang/Object;") \ + do_name( executeCompiledMethod_name, "executeCompiledMethodIntrinsic") \ /*end*/ diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/code/dependencies.cpp --- a/src/share/vm/code/dependencies.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/code/dependencies.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -144,6 +144,11 @@ assert_common_1(evol_method, DepValue(_oop_recorder, m)); } +void Dependencies::assert_has_no_finalizable_subclasses(Klass* ctxk) { + check_ctxk(ctxk); + assert_common_1(no_finalizable_subclasses, DepValue(_oop_recorder, ctxk)); +} + void Dependencies::assert_leaf_type(Klass* ctxk) { if (ctxk->oop_is_array()) { // As a special case, support this assertion on an array type, diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/code/dependencies.hpp --- a/src/share/vm/code/dependencies.hpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/code/dependencies.hpp Sat Apr 13 00:33:37 2013 +0200 @@ -360,6 +360,7 @@ public: void assert_evol_method(Method* m); + void assert_has_no_finalizable_subclasses(Klass* ctxk); void assert_leaf_type(Klass* ctxk); void assert_unique_concrete_method(Klass* ctxk, Method* uniqm); void assert_abstract_with_unique_concrete_subtype(Klass* ctxk, Klass* conck); diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/code/nmethod.cpp --- a/src/share/vm/code/nmethod.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/code/nmethod.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -1307,10 +1307,12 @@ } #ifdef GRAAL - if (_graal_installed_code != NULL) { - HotSpotInstalledCode::set_nmethod(_graal_installed_code, 0); - _graal_installed_code = NULL; - } + // The method can only be unloaded after the pointer to the installed code + // Java wrapper is no longer alive. Here we need to clear out this weak + // reference to the dead object. + if (_graal_installed_code != NULL) { + _graal_installed_code = NULL; + } #endif // Make the class unloaded - i.e., change state and notify sweeper @@ -1394,18 +1396,17 @@ return false; } -#ifdef GRAAL - if (_graal_installed_code != NULL) { - HotSpotInstalledCode::set_nmethod(_graal_installed_code, 0); - _graal_installed_code = NULL; - } -#endif - // The caller can be calling the method statically or through an inline // cache call. if (!is_osr_method() && !is_not_entrant()) { - NativeJump::patch_verified_entry(entry_point(), verified_entry_point(), - SharedRuntime::get_handle_wrong_method_stub()); + address stub = SharedRuntime::get_handle_wrong_method_stub(); +#ifdef GRAAL + if (_graal_installed_code != NULL && !HotSpotInstalledCode::isDefault(_graal_installed_code)) { + // This was manually installed machine code. Patch entry with stub that throws an exception. + stub = SharedRuntime::get_deoptimized_installed_code_stub(); + } +#endif + NativeJump::patch_verified_entry(entry_point(), verified_entry_point(), stub); } if (is_in_use()) { diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/compiler/compileBroker.cpp --- a/src/share/vm/compiler/compileBroker.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/compiler/compileBroker.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -1225,12 +1225,9 @@ assert(method->method_holder()->oop_is_instance(), "not an instance method"); assert(osr_bci == InvocationEntryBci || (0 <= osr_bci && osr_bci < method->code_size()), "bci out of range"); assert(!method->is_abstract() && (osr_bci == InvocationEntryBci || !method->is_native()), "cannot compile abstract/native methods"); - assert(!method->method_holder()->is_not_initialized(), "method holder must be initialized"); - - if (!TieredCompilation) { - comp_level = CompLevel_highest_tier; - } - + assert(!method->method_holder()->is_not_initialized() || method->intrinsic_id() == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod, "method holder must be initialized"); + // allow any levels for WhiteBox + assert(WhiteBoxAPI || TieredCompilation || comp_level == CompLevel_highest_tier, "only CompLevel_highest_tier must be used in non-tiered"); // return quickly if possible // lock, make sure that the compilation diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/compiler/compileLog.cpp --- a/src/share/vm/compiler/compileLog.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/compiler/compileLog.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -60,28 +60,6 @@ } -// Advance kind up to a null or space, return this tail. -// Make sure kind is null-terminated, not space-terminated. -// Use the buffer if necessary. -static const char* split_attrs(const char* &kind, char* buffer) { - const char* attrs = strchr(kind, ' '); - // Tease apart the first word from the rest: - if (attrs == NULL) { - return ""; // no attrs, no split - } else if (kind == buffer) { - ((char*) attrs)[-1] = 0; - return attrs; - } else { - // park it in the buffer, so we can put a null on the end - assert(!(kind >= buffer && kind < buffer+100), "not obviously in buffer"); - int klen = attrs - kind; - strncpy(buffer, kind, klen); - buffer[klen] = 0; - kind = buffer; // return by reference - return attrs; - } -} - // see_tag, pop_tag: Override the default do-nothing methods on xmlStream. // These methods provide a hook for managing the the extra context markup. void CompileLog::see_tag(const char* tag, bool push) { diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/compiler/compilerOracle.cpp --- a/src/share/vm/compiler/compilerOracle.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/compiler/compilerOracle.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -237,13 +237,6 @@ "help" }; -static const char * command_name(OracleCommand command) { - if (command < OracleFirstCommand || command >= OracleCommandCount) { - return "unknown command"; - } - return command_names[command]; -} - class MethodMatcher; static MethodMatcher* lists[OracleCommandCount] = { 0, }; diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -48,6 +48,7 @@ #include "memory/iterator.hpp" #include "memory/referencePolicy.hpp" #include "memory/resourceArea.hpp" +#include "memory/tenuredGeneration.hpp" #include "oops/oop.inline.hpp" #include "prims/jvmtiExport.hpp" #include "runtime/globals_extension.hpp" @@ -916,7 +917,31 @@ return; } - size_t expand_bytes = 0; + // Compute some numbers about the state of the heap. + const size_t used_after_gc = used(); + const size_t capacity_after_gc = capacity(); + + CardGeneration::compute_new_size(); + + // Reset again after a possible resizing + cmsSpace()->reset_after_compaction(); + + assert(used() == used_after_gc && used_after_gc <= capacity(), + err_msg("used: " SIZE_FORMAT " used_after_gc: " SIZE_FORMAT + " capacity: " SIZE_FORMAT, used(), used_after_gc, capacity())); +} + +void ConcurrentMarkSweepGeneration::compute_new_size_free_list() { + assert_locked_or_safepoint(Heap_lock); + + // If incremental collection failed, we just want to expand + // to the limit. + if (incremental_collection_failed()) { + clear_incremental_collection_failed(); + grow_to_reserved(); + return; + } + double free_percentage = ((double) free()) / capacity(); double desired_free_percentage = (double) MinHeapFreeRatio / 100; double maximum_free_percentage = (double) MaxHeapFreeRatio / 100; @@ -925,9 +950,7 @@ if (free_percentage < desired_free_percentage) { size_t desired_capacity = (size_t)(used() / ((double) 1 - desired_free_percentage)); assert(desired_capacity >= capacity(), "invalid expansion size"); - expand_bytes = MAX2(desired_capacity - capacity(), MinHeapDeltaBytes); - } - if (expand_bytes > 0) { + size_t expand_bytes = MAX2(desired_capacity - capacity(), MinHeapDeltaBytes); if (PrintGCDetails && Verbose) { size_t desired_capacity = (size_t)(used() / ((double) 1 - desired_free_percentage)); gclog_or_tty->print_cr("\nFrom compute_new_size: "); @@ -961,6 +984,14 @@ gclog_or_tty->print_cr(" Expanded free fraction %f", ((double) free()) / capacity()); } + } else { + size_t desired_capacity = (size_t)(used() / ((double) 1 - desired_free_percentage)); + assert(desired_capacity <= capacity(), "invalid expansion size"); + size_t shrink_bytes = capacity() - desired_capacity; + // Don't shrink unless the delta is greater than the minimum shrink we want + if (shrink_bytes >= MinHeapDeltaBytes) { + shrink_free_list_by(shrink_bytes); + } } } @@ -1872,7 +1903,7 @@ assert_locked_or_safepoint(Heap_lock); FreelistLocker z(this); MetaspaceGC::compute_new_size(); - _cmsGen->compute_new_size(); + _cmsGen->compute_new_size_free_list(); } // A work method used by foreground collection to determine @@ -2601,6 +2632,10 @@ } void ConcurrentMarkSweepGeneration::gc_prologue(bool full) { + + _capacity_at_prologue = capacity(); + _used_at_prologue = used(); + // Delegate to CMScollector which knows how to coordinate between // this and any other CMS generations that it is responsible for // collecting. @@ -2774,6 +2809,23 @@ } } + +void +CMSCollector::print_on_error(outputStream* st) { + CMSCollector* collector = ConcurrentMarkSweepGeneration::_collector; + if (collector != NULL) { + CMSBitMap* bitmap = &collector->_markBitMap; + st->print_cr("Marking Bits: (CMSBitMap*) " PTR_FORMAT, bitmap); + bitmap->print_on_error(st, " Bits: "); + + st->cr(); + + CMSBitMap* mut_bitmap = &collector->_modUnionTable; + st->print_cr("Mod Union Table: (CMSBitMap*) " PTR_FORMAT, mut_bitmap); + mut_bitmap->print_on_error(st, " Bits: "); + } +} + //////////////////////////////////////////////////////// // CMS Verification Support //////////////////////////////////////////////////////// @@ -3300,6 +3352,26 @@ } +void ConcurrentMarkSweepGeneration::shrink_by(size_t bytes) { + assert_locked_or_safepoint(ExpandHeap_lock); + // Shrink committed space + _virtual_space.shrink_by(bytes); + // Shrink space; this also shrinks the space's BOT + _cmsSpace->set_end((HeapWord*) _virtual_space.high()); + size_t new_word_size = heap_word_size(_cmsSpace->capacity()); + // Shrink the shared block offset array + _bts->resize(new_word_size); + MemRegion mr(_cmsSpace->bottom(), new_word_size); + // Shrink the card table + Universe::heap()->barrier_set()->resize_covered_region(mr); + + if (Verbose && PrintGC) { + size_t new_mem_size = _virtual_space.committed_size(); + size_t old_mem_size = new_mem_size + bytes; + gclog_or_tty->print_cr("Shrinking %s from " SIZE_FORMAT "K to " SIZE_FORMAT "K", + name(), old_mem_size/K, new_mem_size/K); + } +} void ConcurrentMarkSweepGeneration::shrink(size_t bytes) { assert_locked_or_safepoint(Heap_lock); @@ -3351,7 +3423,7 @@ return success; } -void ConcurrentMarkSweepGeneration::shrink_by(size_t bytes) { +void ConcurrentMarkSweepGeneration::shrink_free_list_by(size_t bytes) { assert_locked_or_safepoint(Heap_lock); assert_lock_strong(freelistLock()); // XXX Fix when compaction is implemented. @@ -6476,6 +6548,10 @@ } } +void CMSBitMap::print_on_error(outputStream* st, const char* prefix) const { + _bm.print_on_error(st, prefix); +} + #ifndef PRODUCT void CMSBitMap::assert_locked() const { CMSLockVerifier::assert_locked(lock()); @@ -9074,51 +9150,6 @@ } } -// The desired expansion delta is computed so that: -// . desired free percentage or greater is used -void ASConcurrentMarkSweepGeneration::compute_new_size() { - assert_locked_or_safepoint(Heap_lock); - - GenCollectedHeap* gch = (GenCollectedHeap*) GenCollectedHeap::heap(); - - // If incremental collection failed, we just want to expand - // to the limit. - if (incremental_collection_failed()) { - clear_incremental_collection_failed(); - grow_to_reserved(); - return; - } - - assert(UseAdaptiveSizePolicy, "Should be using adaptive sizing"); - - assert(gch->kind() == CollectedHeap::GenCollectedHeap, - "Wrong type of heap"); - int prev_level = level() - 1; - assert(prev_level >= 0, "The cms generation is the lowest generation"); - Generation* prev_gen = gch->get_gen(prev_level); - assert(prev_gen->kind() == Generation::ASParNew, - "Wrong type of young generation"); - ParNewGeneration* younger_gen = (ParNewGeneration*) prev_gen; - size_t cur_eden = younger_gen->eden()->capacity(); - CMSAdaptiveSizePolicy* size_policy = cms_size_policy(); - size_t cur_promo = free(); - size_policy->compute_tenured_generation_free_space(cur_promo, - max_available(), - cur_eden); - resize(cur_promo, size_policy->promo_size()); - - // Record the new size of the space in the cms generation - // that is available for promotions. This is temporary. - // It should be the desired promo size. - size_policy->avg_cms_promo()->sample(free()); - size_policy->avg_old_live()->sample(used()); - - if (UsePerfData) { - CMSGCAdaptivePolicyCounters* counters = gc_adaptive_policy_counters(); - counters->update_cms_capacity_counter(capacity()); - } -} - void ASConcurrentMarkSweepGeneration::shrink_by(size_t desired_bytes) { assert_locked_or_safepoint(Heap_lock); assert_lock_strong(freelistLock()); diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Sat Apr 13 00:33:37 2013 +0200 @@ -60,6 +60,7 @@ class FreeChunk; class PromotionInfo; class ScanMarkedObjectsAgainCarefullyClosure; +class TenuredGeneration; // A generic CMS bit map. It's the basis for both the CMS marking bit map // as well as for the mod union table (in each case only a subset of the @@ -150,6 +151,8 @@ size_t heapWordToOffset(HeapWord* addr) const; size_t heapWordDiffToOffsetDiff(size_t diff) const; + void print_on_error(outputStream* st, const char* prefix) const; + // debugging // is this address range covered by the bit-map? NOT_PRODUCT( @@ -810,9 +813,6 @@ // used regions of each generation to limit the extent of sweep void save_sweep_limits(); - // Resize the generations included in the collector. - void compute_new_size(); - // A work method used by foreground collection to determine // what type of collection (compacting or not, continuing or fresh) // it should do. @@ -909,6 +909,9 @@ void releaseFreelistLocks() const; bool haveFreelistLocks() const; + // Adjust size of underlying generation + void compute_new_size(); + // GC prologue and epilogue void gc_prologue(bool full); void gc_epilogue(bool full); @@ -983,6 +986,8 @@ CMSAdaptiveSizePolicy* size_policy(); CMSGCAdaptivePolicyCounters* gc_adaptive_policy_counters(); + static void print_on_error(outputStream* st); + // debugging void verify(); bool verify_after_remark(); @@ -1082,7 +1087,7 @@ protected: // Shrink generation by specified size (returns false if unable to shrink) - virtual void shrink_by(size_t bytes); + void shrink_free_list_by(size_t bytes); // Update statistics for GC virtual void update_gc_stats(int level, bool full); @@ -1233,6 +1238,7 @@ CMSExpansionCause::Cause cause); virtual bool expand(size_t bytes, size_t expand_bytes); void shrink(size_t bytes); + void shrink_by(size_t bytes); HeapWord* expand_and_par_lab_allocate(CMSParGCThreadState* ps, size_t word_sz); bool expand_and_ensure_spooling_space(PromotionInfo* promo); @@ -1293,7 +1299,13 @@ bool must_be_youngest() const { return false; } bool must_be_oldest() const { return true; } - void compute_new_size(); + // Resize the generation after a compacting GC. The + // generation can be treated as a contiguous space + // after the compaction. + virtual void compute_new_size(); + // Resize the generation after a non-compacting + // collection. + void compute_new_size_free_list(); CollectionTypes debug_collection_type() { return _debug_collection_type; } void rotate_debug_collection_type(); @@ -1315,7 +1327,6 @@ virtual void shrink_by(size_t bytes); public: - virtual void compute_new_size(); ASConcurrentMarkSweepGeneration(ReservedSpace rs, size_t initial_byte_size, int level, CardTableRS* ct, bool use_adaptive_freelists, diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/gc_implementation/g1/concurrentMark.cpp --- a/src/share/vm/gc_implementation/g1/concurrentMark.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -101,6 +101,10 @@ } #endif +void CMBitMapRO::print_on_error(outputStream* st, const char* prefix) const { + _bm.print_on_error(st, prefix); +} + bool CMBitMap::allocate(ReservedSpace heap_rs) { _bmStartWord = (HeapWord*)(heap_rs.base()); _bmWordSize = heap_rs.size()/HeapWordSize; // heap_rs.size() is in bytes @@ -3277,6 +3281,13 @@ } } +void ConcurrentMark::print_on_error(outputStream* st) const { + st->print_cr("Marking Bits (Prev, Next): (CMBitMap*) " PTR_FORMAT ", (CMBitMap*) " PTR_FORMAT, + _prevMarkBitMap, _nextMarkBitMap); + _prevMarkBitMap->print_on_error(st, " Prev Bits: "); + _nextMarkBitMap->print_on_error(st, " Next Bits: "); +} + // We take a break if someone is trying to stop the world. bool ConcurrentMark::do_yield_check(uint worker_id) { if (should_yield()) { diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/gc_implementation/g1/concurrentMark.hpp --- a/src/share/vm/gc_implementation/g1/concurrentMark.hpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.hpp Sat Apr 13 00:33:37 2013 +0200 @@ -113,6 +113,8 @@ return res; } + void print_on_error(outputStream* st, const char* prefix) const; + // debugging NOT_PRODUCT(bool covers(ReservedSpace rs) const;) }; @@ -829,6 +831,8 @@ void print_worker_threads_on(outputStream* st) const; + void print_on_error(outputStream* st) const; + // The following indicate whether a given verbose level has been // set. Notice that anything above stats is conditional to // _MARKING_VERBOSE_ having been set to 1 diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -3437,6 +3437,15 @@ heap_region_iterate(&blk); } +void G1CollectedHeap::print_on_error(outputStream* st) const { + this->CollectedHeap::print_on_error(st); + + if (_cm != NULL) { + st->cr(); + _cm->print_on_error(st); + } +} + void G1CollectedHeap::print_gc_threads_on(outputStream* st) const { if (G1CollectedHeap::use_parallel_gc_threads()) { workers()->print_worker_threads_on(st); diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Sat Apr 13 00:33:37 2013 +0200 @@ -1581,6 +1581,7 @@ virtual void verify(bool silent); virtual void print_on(outputStream* st) const; virtual void print_extended_on(outputStream* st) const; + virtual void print_on_error(outputStream* st) const; virtual void print_gc_threads_on(outputStream* st) const; virtual void gc_threads_do(ThreadClosure* tc) const; diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -1359,18 +1359,6 @@ #endif // PRODUCT } -#ifndef PRODUCT -// for debugging, bit of a hack... -static char* -region_num_to_mbs(int length) { - static char buffer[64]; - double bytes = (double) (length * HeapRegion::GrainBytes); - double mbs = bytes / (double) (1024 * 1024); - sprintf(buffer, "%7.2lfMB", mbs); - return buffer; -} -#endif // PRODUCT - uint G1CollectorPolicy::max_regions(int purpose) { switch (purpose) { case GCAllocForSurvived: diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/gc_implementation/g1/ptrQueue.cpp --- a/src/share/vm/gc_implementation/g1/ptrQueue.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/gc_implementation/g1/ptrQueue.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -53,15 +53,6 @@ } -static int byte_index_to_index(int ind) { - assert((ind % oopSize) == 0, "Invariant."); - return ind / oopSize; -} - -static int index_to_byte_index(int byte_ind) { - return byte_ind * oopSize; -} - void PtrQueue::enqueue_known_active(void* ptr) { assert(0 <= _index && _index <= _sz, "Invariant."); assert(_index == 0 || _buf != NULL, "invariant"); diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.hpp --- a/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.hpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.hpp Sat Apr 13 00:33:37 2013 +0200 @@ -173,6 +173,12 @@ void reset_counters(); #endif // #ifndef PRODUCT + void print_on_error(outputStream* st) const { + st->print_cr("Marking Bits: (ParMarkBitMap*) " PTR_FORMAT, this); + _beg_bits.print_on_error(st, " Begin Bits: "); + _end_bits.print_on_error(st, " End Bits: "); + } + #ifdef ASSERT void verify_clear() const; inline void verify_bit(idx_t bit) const; diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -648,6 +648,15 @@ MetaspaceAux::print_on(st); } +void ParallelScavengeHeap::print_on_error(outputStream* st) const { + this->CollectedHeap::print_on_error(st); + + if (UseParallelOldGC) { + st->cr(); + PSParallelCompact::print_on_error(st); + } +} + void ParallelScavengeHeap::gc_threads_do(ThreadClosure* tc) const { PSScavenge::gc_task_manager()->threads_do(tc); } diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp --- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp Sat Apr 13 00:33:37 2013 +0200 @@ -220,6 +220,7 @@ void prepare_for_verify(); virtual void print_on(outputStream* st) const; + virtual void print_on_error(outputStream* st) const; virtual void print_gc_threads_on(outputStream* st) const; virtual void gc_threads_do(ThreadClosure* tc) const; virtual void print_tracing_info() const; diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -165,6 +165,10 @@ #endif // #ifdef ASSERT +void PSParallelCompact::print_on_error(outputStream* st) { + _mark_bitmap.print_on_error(st); +} + #ifndef PRODUCT const char* PSParallelCompact::space_names[] = { "old ", "eden", "from", "to " diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp --- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp Sat Apr 13 00:33:37 2013 +0200 @@ -1163,6 +1163,8 @@ // Time since last full gc (in milliseconds). static jlong millis_since_last_gc(); + static void print_on_error(outputStream* st); + #ifndef PRODUCT // Debugging support. static const char* space_names[last_space_id]; diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/gc_interface/collectedHeap.hpp --- a/src/share/vm/gc_interface/collectedHeap.hpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/gc_interface/collectedHeap.hpp Sat Apr 13 00:33:37 2013 +0200 @@ -567,6 +567,14 @@ print_on(st); } + virtual void print_on_error(outputStream* st) const { + st->print_cr("Heap:"); + print_extended_on(st); + st->cr(); + + _barrier_set->print_on(st); + } + // Print all GC threads (other than the VM thread) // used by this heap. virtual void print_gc_threads_on(outputStream* st) const = 0; diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/graal/graalCodeInstaller.cpp --- a/src/share/vm/graal/graalCodeInstaller.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -294,6 +294,8 @@ if (!assumption.is_null()) { if (assumption->klass() == Assumptions_MethodContents::klass()) { assumption_MethodContents(assumption); + } else if (assumption->klass() == Assumptions_NoFinalizableSubclass::klass()) { + assumption_NoFinalizableSubclass(assumption); } else if (assumption->klass() == Assumptions_ConcreteSubtype::klass()) { assumption_ConcreteSubtype(assumption); } else if (assumption->klass() == Assumptions_ConcreteMethod::klass()) { @@ -418,9 +420,17 @@ if (site->is_a(CompilationResult_Call::klass())) { TRACE_graal_4("call at %i", pc_offset); site_Call(buffer, pc_offset, site); - } else if (site->is_a(CompilationResult_Safepoint::klass())) { - TRACE_graal_4("safepoint at %i", pc_offset); - site_Safepoint(buffer, pc_offset, site); + } else if (site->is_a(CompilationResult_Infopoint::klass())) { + // three reasons for infopoints denote actual safepoints + oop reason = CompilationResult_Infopoint::reason(site); + if (InfopointReason::SAFEPOINT() == reason || InfopointReason::CALL() == reason || InfopointReason::IMPLICIT_EXCEPTION() == reason) { + TRACE_graal_4("safepoint at %i", pc_offset); + site_Safepoint(buffer, pc_offset, site); + } else { + // if the infopoint is not an actual safepoint, it must have one of the other reasons + // (safeguard against new safepoint types that require handling above) + assert(InfopointReason::METHOD_START() == reason || InfopointReason::METHOD_END() == reason || InfopointReason::LINE_NUMBER() == reason, ""); + } } else if (site->is_a(CompilationResult_DataPatch::klass())) { TRACE_graal_4("datapatch at %i", pc_offset); site_DataPatch(buffer, pc_offset, site); @@ -439,6 +449,12 @@ _dependencies->assert_evol_method(method()); } +void CodeInstaller::assumption_NoFinalizableSubclass(Handle assumption) { + Handle receiverType_handle = Assumptions_NoFinalizableSubclass::receiverType(assumption()); + Klass* receiverType = asKlass(HotSpotResolvedObjectType::metaspaceKlass(receiverType_handle)); + _dependencies->assert_has_no_finalizable_subclasses(receiverType); +} + void CodeInstaller::assumption_ConcreteSubtype(Handle assumption) { Handle context_handle = Assumptions_ConcreteSubtype::context(assumption()); Handle subtype_handle = Assumptions_ConcreteSubtype::subtype(assumption()); @@ -587,7 +603,7 @@ } void CodeInstaller::site_Safepoint(CodeBuffer& buffer, jint pc_offset, oop site) { - oop debug_info = CompilationResult_Safepoint::debugInfo(site); + oop debug_info = CompilationResult_Infopoint::debugInfo(site); assert(debug_info != NULL, "debug info expected"); // address instruction = _instructions->start() + pc_offset; diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/graal/graalCodeInstaller.hpp --- a/src/share/vm/graal/graalCodeInstaller.hpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/graal/graalCodeInstaller.hpp Sat Apr 13 00:33:37 2013 +0200 @@ -93,6 +93,7 @@ void initialize_buffer(CodeBuffer& buffer); void assumption_MethodContents(Handle assumption); + void assumption_NoFinalizableSubclass(Handle assumption); void assumption_ConcreteSubtype(Handle assumption); void assumption_ConcreteMethod(Handle assumption); void assumption_CallSiteTargetValue(Handle assumption); diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/graal/graalCompiler.hpp --- a/src/share/vm/graal/graalCompiler.hpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/graal/graalCompiler.hpp Sat Apr 13 00:33:37 2013 +0200 @@ -98,6 +98,21 @@ return ((index & 0xFF) << 24) | ((index & 0xFF00) << 8) | ((index & 0xFF0000) >> 8) | ((index & 0xFF000000) >> 24); } + static int to_cp_index(int raw_index, Bytecodes::Code bc) { + int cp_index; + if (bc == Bytecodes::_invokedynamic) { + cp_index = to_index_u4(raw_index); + assert(ConstantPool::is_invokedynamic_index(cp_index), "not an invokedynamic constant pool index"); + } else { + assert(bc == Bytecodes::_getfield || bc == Bytecodes::_putfield || + bc == Bytecodes::_getstatic || bc == Bytecodes::_putstatic || + bc == Bytecodes::_invokeinterface || bc == Bytecodes::_invokevirtual || + bc == Bytecodes::_invokespecial || bc == Bytecodes::_invokestatic, err_msg("unexpected invoke opcode: %d %s", bc, Bytecodes::name(bc))); + cp_index = to_cp_index_u2(raw_index); + } + return cp_index; + } + static void initialize_buffer_blob(); }; diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -416,10 +416,11 @@ return JNIHandles::make_local(THREAD, result); C2V_END -C2V_VMENTRY(jobject, lookupAppendixInPool, (JNIEnv *env, jobject, jobject type, jint index)) - assert(GraalCompiler::to_index_u4(index) < 0, "not an invokedynamic constant pool index"); +C2V_VMENTRY(jobject, lookupAppendixInPool, (JNIEnv *env, jobject, jobject type, jint index, jbyte opcode)) + Bytecodes::Code bc = (Bytecodes::Code) (((int) opcode) & 0xFF); + index = GraalCompiler::to_cp_index(index, bc); constantPoolHandle cpool(InstanceKlass::cast(java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(type)))->constants()); - oop appendix_oop = ConstantPool::appendix_at_if_loaded(cpool, GraalCompiler::to_index_u4(index)); + oop appendix_oop = ConstantPool::appendix_at_if_loaded(cpool, index); return JNIHandles::make_local(THREAD, appendix_oop); C2V_END @@ -429,7 +430,7 @@ instanceKlassHandle pool_holder(cp->pool_holder()); Bytecodes::Code bc = (Bytecodes::Code) (((int) opcode) & 0xFF); - index = (bc == Bytecodes::_invokedynamic) ? GraalCompiler::to_index_u4(index) : GraalCompiler::to_cp_index_u2(index); + index = GraalCompiler::to_cp_index(index, bc); methodHandle method = GraalEnv::get_method_by_index(cp, index, bc, pool_holder); if (!method.is_null()) { @@ -459,11 +460,11 @@ C2V_VMENTRY(void, lookupReferencedTypeInPool, (JNIEnv *env, jobject, jobject type, jint index, jbyte op)) ConstantPool* cp = InstanceKlass::cast(java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(type)))->constants(); - int opcode = (op & 0xFF); - if (opcode != Bytecodes::_checkcast && opcode != Bytecodes::_instanceof && opcode != Bytecodes::_new && opcode != Bytecodes::_anewarray - && opcode != Bytecodes::_multianewarray && opcode != Bytecodes::_ldc && opcode != Bytecodes::_ldc_w && opcode != Bytecodes::_ldc2_w) + Bytecodes::Code bc = (Bytecodes::Code) (((int) op) & 0xFF); + if (bc != Bytecodes::_checkcast && bc != Bytecodes::_instanceof && bc != Bytecodes::_new && bc != Bytecodes::_anewarray + && bc != Bytecodes::_multianewarray && bc != Bytecodes::_ldc && bc != Bytecodes::_ldc_w && bc != Bytecodes::_ldc2_w) { - index = cp->remap_instruction_operand_from_cache((opcode == Bytecodes::_invokedynamic) ? GraalCompiler::to_index_u4(index) : GraalCompiler::to_cp_index_u2(index)); + index = cp->remap_instruction_operand_from_cache(GraalCompiler::to_cp_index(index, bc)); } constantTag tag = cp->tag_at(index); if (tag.is_field_or_method()) { @@ -620,6 +621,8 @@ #endif set_boolean("verifyOops", VerifyOops); set_boolean("ciTime", CITime); + set_boolean("printCompilation", PrintCompilation); + set_boolean("printInlining", PrintInlining); set_boolean("useFastLocking", GraalUseFastLocking); set_boolean("useBiasedLocking", UseBiasedLocking); set_boolean("usePopCountInstruction", UsePopCountInstruction); @@ -654,6 +657,7 @@ set_int("constMethodMaxStackOffset", in_bytes(ConstMethod::max_stack_offset())); set_int("extraStackEntries", Method::extra_stack_entries()); set_int("methodAccessFlagsOffset", in_bytes(Method::access_flags_offset())); + set_int("methodIntrinsicIdOffset", Method::intrinsic_id_offset_in_bytes()); set_int("klassHasFinalizerFlag", JVM_ACC_HAS_FINALIZER); set_int("threadExceptionOopOffset", in_bytes(JavaThread::exception_oop_offset())); set_int("threadExceptionPcOffset", in_bytes(JavaThread::exception_pc_offset())); @@ -777,6 +781,13 @@ set_int("deoptActionReinterpret", Deoptimization::Action_reinterpret); set_int("deoptActionMakeNotEntrant", Deoptimization::Action_make_not_entrant); set_int("deoptActionMakeNotCompilable", Deoptimization::Action_make_not_compilable); + + set_int("vmIntrinsicInvokeBasic", vmIntrinsics::_invokeBasic); + set_int("vmIntrinsicLinkToVirtual", vmIntrinsics::_linkToVirtual); + set_int("vmIntrinsicLinkToStatic", vmIntrinsics::_linkToStatic); + set_int("vmIntrinsicLinkToSpecial", vmIntrinsics::_linkToSpecial); + set_int("vmIntrinsicLinkToInterface", vmIntrinsics::_linkToInterface); + set_int("g1CardQueueIndexOffset", in_bytes(JavaThread::dirty_card_queue_offset() + PtrQueue::byte_offset_of_index())); set_int("g1CardQueueBufferOffset", in_bytes(JavaThread::dirty_card_queue_offset() + PtrQueue::byte_offset_of_buf())); set_int("logOfHRGrainBytes", HeapRegion::LogOfHRGrainBytes); @@ -896,23 +907,17 @@ return JNIHandles::make_local(element); C2V_END -C2V_VMENTRY(jobject, executeCompiledMethodVarargs, (JNIEnv *env, jobject, jlong metaspace_method, jlong metaspace_nmethod, jobject args)) +C2V_VMENTRY(jobject, executeCompiledMethodVarargs, (JNIEnv *env, jobject, jobject args, jlong nativeMethod)) ResourceMark rm; HandleMark hm; - assert(metaspace_method != 0, "just checking"); - methodHandle mh = asMethod(metaspace_method); + nmethod* nm = (nmethod*) (address) nativeMethod; + methodHandle mh = nm->method(); Symbol* signature = mh->signature(); JavaCallArguments jca(mh->size_of_parameters()); JavaArgumentUnboxer jap(signature, &jca, (arrayOop) JNIHandles::resolve(args), mh->is_static()); JavaValue result(jap.get_ret_type()); - - nmethod* nm = (nmethod*) (address) metaspace_nmethod; - if (nm == NULL || !nm->is_alive()) { - THROW_0(vmSymbols::MethodInvalidatedException()); - } - jca.set_alternative_target(nm); JavaCalls::call(&result, mh, &jca, CHECK_NULL); @@ -926,29 +931,6 @@ } C2V_END -C2V_VMENTRY(jobject, executeCompiledMethod, (JNIEnv *env, jobject, jlong metaspace_method, jlong metaspace_nmethod, jobject arg1, jobject arg2, jobject arg3)) - ResourceMark rm; - HandleMark hm; - - methodHandle method = asMethod(metaspace_method); - assert(!method.is_null(), "just checking"); - JavaValue result(T_OBJECT); - JavaCallArguments args; - args.push_oop(JNIHandles::resolve(arg1)); - args.push_oop(JNIHandles::resolve(arg2)); - args.push_oop(JNIHandles::resolve(arg3)); - - nmethod* nm = (nmethod*) (address) metaspace_nmethod; - if (nm == NULL || !nm->is_alive()) { - THROW_0(vmSymbols::MethodInvalidatedException()); - } - - args.set_alternative_target(nm); - JavaCalls::call(&result, method, &args, CHECK_NULL); - - return JNIHandles::make_local((oop) result.get_jobject()); -C2V_END - C2V_VMENTRY(jint, getVtableEntryOffset, (JNIEnv *, jobject, jlong metaspace_method)) Method* method = asMethod(metaspace_method); @@ -1019,10 +1001,10 @@ u2 typeCPIdx = table[i].descriptor_cp_index; u2 slot = table[i].slot; - char* name = method->constants()->string_at_noresolve(nameCPIdx); + char* name = method->constants()->symbol_at(nameCPIdx)->as_C_string(); Handle nameHandle = java_lang_String::create_from_str(name, CHECK_NULL); - char* typeInfo = method->constants()->string_at_noresolve(typeCPIdx); + char* typeInfo = method->constants()->symbol_at(typeCPIdx)->as_C_string(); Handle typeHandle = java_lang_String::create_from_str(typeInfo, CHECK_NULL); Handle holderHandle = GraalCompiler::createHotSpotResolvedObjectType(method, CHECK_0); @@ -1067,6 +1049,20 @@ C2V_END +C2V_VMENTRY(void, invalidateInstalledCode, (JNIEnv *env, jobject, jlong nativeMethod)) + nmethod* m = (nmethod*)nativeMethod; + if (!m->is_not_entrant()) { + m->mark_for_deoptimization(); + VM_Deoptimize op; + VMThread::execute(&op); + } +C2V_END + + +C2V_VMENTRY(jboolean, isInstalledCodeValid, (JNIEnv *env, jobject, jlong nativeMethod)) + nmethod* m = (nmethod*)nativeMethod; + return m->is_alive() && !m->is_not_entrant(); +C2V_END #define CC (char*) /*cast a literal from (const char*)*/ #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(c2v_ ## f)) @@ -1118,7 +1114,7 @@ {CC"getVtableEntryOffset", CC"("METASPACE_METHOD")I", FN_PTR(getVtableEntryOffset)}, {CC"lookupType", CC"("STRING HS_RESOLVED_TYPE"Z)"TYPE, FN_PTR(lookupType)}, {CC"lookupConstantInPool", CC"("HS_RESOLVED_TYPE"I)"OBJECT, FN_PTR(lookupConstantInPool)}, - {CC"lookupAppendixInPool", CC"("HS_RESOLVED_TYPE"I)"OBJECT, FN_PTR(lookupAppendixInPool)}, + {CC"lookupAppendixInPool", CC"("HS_RESOLVED_TYPE"IB)"OBJECT, FN_PTR(lookupAppendixInPool)}, {CC"lookupMethodInPool", CC"("HS_RESOLVED_TYPE"IB)"METHOD, FN_PTR(lookupMethodInPool)}, {CC"lookupTypeInPool", CC"("HS_RESOLVED_TYPE"I)"TYPE, FN_PTR(lookupTypeInPool)}, {CC"lookupReferencedTypeInPool", CC"("HS_RESOLVED_TYPE"IB)V", FN_PTR(lookupReferencedTypeInPool)}, @@ -1136,14 +1132,15 @@ {CC"installCode0", CC"("HS_COMP_RESULT HS_INSTALLED_CODE"[Z)I", FN_PTR(installCode0)}, {CC"getCode", CC"(J)[B", FN_PTR(getCode)}, {CC"disassembleNMethod", CC"(J)"STRING, FN_PTR(disassembleNMethod)}, - {CC"executeCompiledMethod", CC"("METASPACE_METHOD NMETHOD OBJECT OBJECT OBJECT")"OBJECT, FN_PTR(executeCompiledMethod)}, - {CC"executeCompiledMethodVarargs", CC"("METASPACE_METHOD NMETHOD "["OBJECT")"OBJECT, FN_PTR(executeCompiledMethodVarargs)}, + {CC"executeCompiledMethodVarargs", CC"(["OBJECT NMETHOD")"OBJECT, FN_PTR(executeCompiledMethodVarargs)}, {CC"getDeoptedLeafGraphIds", CC"()[J", FN_PTR(getDeoptedLeafGraphIds)}, {CC"getLineNumberTable", CC"("HS_RESOLVED_METHOD")[J", FN_PTR(getLineNumberTable)}, {CC"getLocalVariableTable", CC"("HS_RESOLVED_METHOD")["LOCAL, FN_PTR(getLocalVariableTable)}, {CC"getFileName", CC"("HS_RESOLVED_JAVA_TYPE")"STRING, FN_PTR(getFileName)}, {CC"clearQueuedForCompilation", CC"("HS_RESOLVED_METHOD")V", FN_PTR(clearQueuedForCompilation)}, {CC"reprofile", CC"("METASPACE_METHOD")V", FN_PTR(reprofile)}, + {CC"invalidateInstalledCode", CC"(J)V", FN_PTR(invalidateInstalledCode)}, + {CC"isInstalledCodeValid", CC"(J)Z", FN_PTR(isInstalledCodeValid)}, }; int CompilerToVM_methods_count() { diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/graal/graalEnv.cpp --- a/src/share/vm/graal/graalEnv.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/graal/graalEnv.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -340,6 +340,27 @@ Symbol* name_sym = cpool->name_ref_at(index); Symbol* sig_sym = cpool->signature_ref_at(index); + if (cpool->has_preresolution() + || (holder() == SystemDictionary::MethodHandle_klass() && + MethodHandles::is_signature_polymorphic_name(holder(), name_sym))) { + // Short-circuit lookups for JSR 292-related call sites. + // That is, do not rely only on name-based lookups, because they may fail + // if the names are not resolvable in the boot class loader (7056328). + switch (bc) { + case Bytecodes::_invokevirtual: + case Bytecodes::_invokeinterface: + case Bytecodes::_invokespecial: + case Bytecodes::_invokestatic: + { + Method* m = ConstantPool::method_at_if_loaded(cpool, index); + if (m != NULL) { + return m; + } + } + break; + } + } + if (holder_is_accessible) { // Our declared holder is loaded. instanceKlassHandle lookup = get_instance_klass_for_declared_method_holder(holder); methodHandle m = lookup_method(accessor, lookup, name_sym, sig_sym, bc); diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/graal/graalJavaAccess.hpp --- a/src/share/vm/graal/graalJavaAccess.hpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/graal/graalJavaAccess.hpp Sat Apr 13 00:33:37 2013 +0200 @@ -110,6 +110,9 @@ start_class(Assumptions_MethodContents) \ oop_field(Assumptions_MethodContents, method, "Lcom/oracle/graal/api/meta/ResolvedJavaMethod;") \ end_class \ + start_class(Assumptions_NoFinalizableSubclass) \ + oop_field(Assumptions_NoFinalizableSubclass, receiverType, "Lcom/oracle/graal/api/meta/ResolvedJavaType;") \ + end_class \ start_class(Assumptions_ConcreteSubtype) \ oop_field(Assumptions_ConcreteSubtype, context, "Lcom/oracle/graal/api/meta/ResolvedJavaType;") \ oop_field(Assumptions_ConcreteSubtype, subtype, "Lcom/oracle/graal/api/meta/ResolvedJavaType;") \ @@ -135,8 +138,18 @@ int_field(CompilationResult_DataPatch, alignment) \ boolean_field(CompilationResult_DataPatch, inlined) \ end_class \ - start_class(CompilationResult_Safepoint) \ - oop_field(CompilationResult_Safepoint, debugInfo, "Lcom/oracle/graal/api/code/DebugInfo;") \ + start_class(InfopointReason) \ + static_oop_field(InfopointReason, UNKNOWN, "Lcom/oracle/graal/api/code/InfopointReason;") \ + static_oop_field(InfopointReason, SAFEPOINT, "Lcom/oracle/graal/api/code/InfopointReason;") \ + static_oop_field(InfopointReason, CALL, "Lcom/oracle/graal/api/code/InfopointReason;") \ + static_oop_field(InfopointReason, IMPLICIT_EXCEPTION, "Lcom/oracle/graal/api/code/InfopointReason;") \ + static_oop_field(InfopointReason, METHOD_START, "Lcom/oracle/graal/api/code/InfopointReason;") \ + static_oop_field(InfopointReason, METHOD_END, "Lcom/oracle/graal/api/code/InfopointReason;") \ + static_oop_field(InfopointReason, LINE_NUMBER, "Lcom/oracle/graal/api/code/InfopointReason;") \ + end_class \ + start_class(CompilationResult_Infopoint) \ + oop_field(CompilationResult_Infopoint, debugInfo, "Lcom/oracle/graal/api/code/DebugInfo;") \ + oop_field(CompilationResult_Infopoint, reason, "Lcom/oracle/graal/api/code/InfopointReason;") \ end_class \ start_class(CompilationResult_ExceptionHandler) \ int_field(CompilationResult_ExceptionHandler, handlerPos) \ diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/interpreter/abstractInterpreter.hpp --- a/src/share/vm/interpreter/abstractInterpreter.hpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/interpreter/abstractInterpreter.hpp Sat Apr 13 00:33:37 2013 +0200 @@ -85,6 +85,9 @@ zerolocals_synchronized, // method needs locals initialization & is synchronized native, // native method native_synchronized, // native method & is synchronized +#ifdef GRAAL + execute_compiled_method, // direct call to compiled method address +#endif empty, // empty method (code: _return) accessor, // accessor method (code: _aload_0, _getfield, _(a|i)return) abstract, // abstract method (throws an AbstractMethodException) diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/interpreter/interpreter.cpp --- a/src/share/vm/interpreter/interpreter.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/interpreter/interpreter.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -188,6 +188,13 @@ // Method handle primitive? if (m->is_method_handle_intrinsic()) { vmIntrinsics::ID id = m->intrinsic_id(); +#ifdef GRAAL + if (id == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod) { + // Special method kind for directly executing the verified entry point + // of a given nmethod. + return AbstractInterpreter::execute_compiled_method; + } +#endif assert(MethodHandles::is_signature_polymorphic(id), "must match an intrinsic"); MethodKind kind = (MethodKind)( method_handle_invoke_FIRST + ((int)id - vmIntrinsics::FIRST_MH_SIG_POLY) ); @@ -287,6 +294,9 @@ case zerolocals_synchronized: tty->print("zerolocals_synchronized"); break; case native : tty->print("native" ); break; case native_synchronized : tty->print("native_synchronized" ); break; +#ifdef GRAAL + case execute_compiled_method: tty->print("execute_compiled_method"); break; +#endif case empty : tty->print("empty" ); break; case accessor : tty->print("accessor" ); break; case abstract : tty->print("abstract" ); break; diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/interpreter/interpreterRuntime.cpp --- a/src/share/vm/interpreter/interpreterRuntime.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/interpreter/interpreterRuntime.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -568,11 +568,6 @@ // be shared by method invocation and synchronized blocks. //%note synchronization_3 -static void trace_locking(Handle& h_locking_obj, bool is_locking) { - ObjectSynchronizer::trace_locking(h_locking_obj, false, true, is_locking); -} - - //%note monitor_1 IRT_ENTRY_NO_ASYNC(void, InterpreterRuntime::monitorenter(JavaThread* thread, BasicObjectLock* elem)) #ifdef ASSERT diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/interpreter/linkResolver.cpp --- a/src/share/vm/interpreter/linkResolver.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/interpreter/linkResolver.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -217,6 +217,7 @@ TRAPS) { vmIntrinsics::ID iid = MethodHandles::signature_polymorphic_name_id(name); if (TraceMethodHandles) { + ResourceMark rm(THREAD); tty->print_cr("lookup_polymorphic_method iid=%s %s.%s%s", vmIntrinsics::name_at(iid), klass->external_name(), name->as_C_string(), full_signature->as_C_string()); @@ -231,6 +232,7 @@ TempNewSymbol basic_signature = MethodHandles::lookup_basic_type_signature(full_signature, keep_last_arg, CHECK); if (TraceMethodHandles) { + ResourceMark rm(THREAD); tty->print_cr("lookup_polymorphic_method %s %s => basic %s", name->as_C_string(), full_signature->as_C_string(), @@ -283,6 +285,8 @@ } if (result.not_null()) { #ifdef ASSERT + ResourceMark rm(THREAD); + TempNewSymbol basic_signature = MethodHandles::lookup_basic_type_signature(full_signature, CHECK); int actual_size_of_params = result->size_of_parameters(); @@ -1222,8 +1226,10 @@ Symbol* method_signature = NULL; KlassHandle current_klass; resolve_pool(resolved_klass, method_name, method_signature, current_klass, pool, index, CHECK); - if (TraceMethodHandles) + if (TraceMethodHandles) { + ResourceMark rm(THREAD); tty->print_cr("resolve_invokehandle %s %s", method_name->as_C_string(), method_signature->as_C_string()); + } resolve_handle_call(result, resolved_klass, method_name, method_signature, current_klass, CHECK); } diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/interpreter/templateInterpreter.cpp --- a/src/share/vm/interpreter/templateInterpreter.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/interpreter/templateInterpreter.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -360,6 +360,9 @@ method_entry(zerolocals) method_entry(zerolocals_synchronized) method_entry(empty) +#ifdef GRAAL + method_entry(execute_compiled_method) +#endif method_entry(accessor) method_entry(abstract) method_entry(java_lang_math_sin ) diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/memory/allocation.hpp --- a/src/share/vm/memory/allocation.hpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/memory/allocation.hpp Sat Apr 13 00:33:37 2013 +0200 @@ -611,4 +611,23 @@ void check() PRODUCT_RETURN; }; +// Helper class to allocate arrays that may become large. +// Uses the OS malloc for allocations smaller than ArrayAllocatorMallocLimit +// and uses mapped memory for larger allocations. +// Most OS mallocs do something similar but Solaris malloc does not revert +// to mapped memory for large allocations. By default ArrayAllocatorMallocLimit +// is set so that we always use malloc except for Solaris where we set the +// limit to get mapped memory. +template +class ArrayAllocator : StackObj { + char* _addr; + bool _use_malloc; + size_t _size; + public: + ArrayAllocator() : _addr(NULL), _use_malloc(false), _size(0) { } + ~ArrayAllocator() { free(); } + E* allocate(size_t length); + void free(); +}; + #endif // SHARE_VM_MEMORY_ALLOCATION_HPP diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/memory/allocation.inline.hpp --- a/src/share/vm/memory/allocation.inline.hpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/memory/allocation.inline.hpp Sat Apr 13 00:33:37 2013 +0200 @@ -108,5 +108,49 @@ FreeHeap(p, F); } +template +E* ArrayAllocator::allocate(size_t length) { + assert(_addr == NULL, "Already in use"); + + _size = sizeof(E) * length; + _use_malloc = _size < ArrayAllocatorMallocLimit; + + if (_use_malloc) { + _addr = AllocateHeap(_size, F); + if (_addr == NULL && _size >= (size_t)os::vm_allocation_granularity()) { + // malloc failed let's try with mmap instead + _use_malloc = false; + } else { + return (E*)_addr; + } + } + + int alignment = os::vm_allocation_granularity(); + _size = align_size_up(_size, alignment); + + _addr = os::reserve_memory(_size, NULL, alignment); + if (_addr == NULL) { + vm_exit_out_of_memory(_size, "Allocator (reserve)"); + } + + bool success = os::commit_memory(_addr, _size, false /* executable */); + if (!success) { + vm_exit_out_of_memory(_size, "Allocator (commit)"); + } + + return (E*)_addr; +} + +template +void ArrayAllocator::free() { + if (_addr != NULL) { + if (_use_malloc) { + FreeHeap(_addr, F); + } else { + os::release_memory(_addr, _size); + } + _addr = NULL; + } +} #endif // SHARE_VM_MEMORY_ALLOCATION_INLINE_HPP diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/memory/genCollectedHeap.cpp --- a/src/share/vm/memory/genCollectedHeap.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/memory/genCollectedHeap.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -819,12 +819,13 @@ // Returns "TRUE" iff "p" points into the committed areas of the heap. bool GenCollectedHeap::is_in(const void* p) const { #ifndef ASSERT - guarantee(VerifyBeforeGC || - VerifyDuringGC || - VerifyBeforeExit || - PrintAssembly || - tty->count() != 0 || // already printing - VerifyAfterGC || + guarantee(VerifyBeforeGC || + VerifyDuringGC || + VerifyBeforeExit || + VerifyDuringStartup || + PrintAssembly || + tty->count() != 0 || // already printing + VerifyAfterGC || VMError::fatal_error_in_progress(), "too expensive"); #endif @@ -1132,6 +1133,17 @@ #endif // INCLUDE_ALL_GCS } +void GenCollectedHeap::print_on_error(outputStream* st) const { + this->CollectedHeap::print_on_error(st); + +#if INCLUDE_ALL_GCS + if (UseConcMarkSweepGC) { + st->cr(); + CMSCollector::print_on_error(st); + } +#endif // INCLUDE_ALL_GCS +} + void GenCollectedHeap::print_tracing_info() const { if (TraceGen0Time) { get_gen(0)->print_summary_info(); diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/memory/genCollectedHeap.hpp --- a/src/share/vm/memory/genCollectedHeap.hpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/memory/genCollectedHeap.hpp Sat Apr 13 00:33:37 2013 +0200 @@ -344,6 +344,7 @@ virtual void print_gc_threads_on(outputStream* st) const; virtual void gc_threads_do(ThreadClosure* tc) const; virtual void print_tracing_info() const; + virtual void print_on_error(outputStream* st) const; // PrintGC, PrintGCDetails support void print_heap_change(size_t prev_used) const; diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/memory/generation.cpp --- a/src/share/vm/memory/generation.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/memory/generation.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -382,7 +382,9 @@ CardGeneration::CardGeneration(ReservedSpace rs, size_t initial_byte_size, int level, GenRemSet* remset) : - Generation(rs, initial_byte_size, level), _rs(remset) + Generation(rs, initial_byte_size, level), _rs(remset), + _shrink_factor(0), _min_heap_delta_bytes(), _capacity_at_prologue(), + _used_at_prologue() { HeapWord* start = (HeapWord*)rs.base(); size_t reserved_byte_size = rs.size(); @@ -406,6 +408,9 @@ // the end if we try. guarantee(_rs->is_aligned(reserved_mr.end()), "generation must be card aligned"); } + _min_heap_delta_bytes = MinHeapDeltaBytes; + _capacity_at_prologue = initial_byte_size; + _used_at_prologue = 0; } bool CardGeneration::expand(size_t bytes, size_t expand_bytes) { @@ -457,6 +462,160 @@ } +void CardGeneration::compute_new_size() { + assert(_shrink_factor <= 100, "invalid shrink factor"); + size_t current_shrink_factor = _shrink_factor; + _shrink_factor = 0; + + // We don't have floating point command-line arguments + // Note: argument processing ensures that MinHeapFreeRatio < 100. + const double minimum_free_percentage = MinHeapFreeRatio / 100.0; + const double maximum_used_percentage = 1.0 - minimum_free_percentage; + + // Compute some numbers about the state of the heap. + const size_t used_after_gc = used(); + const size_t capacity_after_gc = capacity(); + + const double min_tmp = used_after_gc / maximum_used_percentage; + size_t minimum_desired_capacity = (size_t)MIN2(min_tmp, double(max_uintx)); + // Don't shrink less than the initial generation size + minimum_desired_capacity = MAX2(minimum_desired_capacity, + spec()->init_size()); + assert(used_after_gc <= minimum_desired_capacity, "sanity check"); + + if (PrintGC && Verbose) { + const size_t free_after_gc = free(); + const double free_percentage = ((double)free_after_gc) / capacity_after_gc; + gclog_or_tty->print_cr("TenuredGeneration::compute_new_size: "); + gclog_or_tty->print_cr(" " + " minimum_free_percentage: %6.2f" + " maximum_used_percentage: %6.2f", + minimum_free_percentage, + maximum_used_percentage); + gclog_or_tty->print_cr(" " + " free_after_gc : %6.1fK" + " used_after_gc : %6.1fK" + " capacity_after_gc : %6.1fK", + free_after_gc / (double) K, + used_after_gc / (double) K, + capacity_after_gc / (double) K); + gclog_or_tty->print_cr(" " + " free_percentage: %6.2f", + free_percentage); + } + + if (capacity_after_gc < minimum_desired_capacity) { + // If we have less free space than we want then expand + size_t expand_bytes = minimum_desired_capacity - capacity_after_gc; + // Don't expand unless it's significant + if (expand_bytes >= _min_heap_delta_bytes) { + expand(expand_bytes, 0); // safe if expansion fails + } + if (PrintGC && Verbose) { + gclog_or_tty->print_cr(" expanding:" + " minimum_desired_capacity: %6.1fK" + " expand_bytes: %6.1fK" + " _min_heap_delta_bytes: %6.1fK", + minimum_desired_capacity / (double) K, + expand_bytes / (double) K, + _min_heap_delta_bytes / (double) K); + } + return; + } + + // No expansion, now see if we want to shrink + size_t shrink_bytes = 0; + // We would never want to shrink more than this + size_t max_shrink_bytes = capacity_after_gc - minimum_desired_capacity; + + if (MaxHeapFreeRatio < 100) { + const double maximum_free_percentage = MaxHeapFreeRatio / 100.0; + const double minimum_used_percentage = 1.0 - maximum_free_percentage; + const double max_tmp = used_after_gc / minimum_used_percentage; + size_t maximum_desired_capacity = (size_t)MIN2(max_tmp, double(max_uintx)); + maximum_desired_capacity = MAX2(maximum_desired_capacity, + spec()->init_size()); + if (PrintGC && Verbose) { + gclog_or_tty->print_cr(" " + " maximum_free_percentage: %6.2f" + " minimum_used_percentage: %6.2f", + maximum_free_percentage, + minimum_used_percentage); + gclog_or_tty->print_cr(" " + " _capacity_at_prologue: %6.1fK" + " minimum_desired_capacity: %6.1fK" + " maximum_desired_capacity: %6.1fK", + _capacity_at_prologue / (double) K, + minimum_desired_capacity / (double) K, + maximum_desired_capacity / (double) K); + } + assert(minimum_desired_capacity <= maximum_desired_capacity, + "sanity check"); + + if (capacity_after_gc > maximum_desired_capacity) { + // Capacity too large, compute shrinking size + shrink_bytes = capacity_after_gc - maximum_desired_capacity; + // We don't want shrink all the way back to initSize if people call + // System.gc(), because some programs do that between "phases" and then + // we'd just have to grow the heap up again for the next phase. So we + // damp the shrinking: 0% on the first call, 10% on the second call, 40% + // on the third call, and 100% by the fourth call. But if we recompute + // size without shrinking, it goes back to 0%. + shrink_bytes = shrink_bytes / 100 * current_shrink_factor; + assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size"); + if (current_shrink_factor == 0) { + _shrink_factor = 10; + } else { + _shrink_factor = MIN2(current_shrink_factor * 4, (size_t) 100); + } + if (PrintGC && Verbose) { + gclog_or_tty->print_cr(" " + " shrinking:" + " initSize: %.1fK" + " maximum_desired_capacity: %.1fK", + spec()->init_size() / (double) K, + maximum_desired_capacity / (double) K); + gclog_or_tty->print_cr(" " + " shrink_bytes: %.1fK" + " current_shrink_factor: %d" + " new shrink factor: %d" + " _min_heap_delta_bytes: %.1fK", + shrink_bytes / (double) K, + current_shrink_factor, + _shrink_factor, + _min_heap_delta_bytes / (double) K); + } + } + } + + if (capacity_after_gc > _capacity_at_prologue) { + // We might have expanded for promotions, in which case we might want to + // take back that expansion if there's room after GC. That keeps us from + // stretching the heap with promotions when there's plenty of room. + size_t expansion_for_promotion = capacity_after_gc - _capacity_at_prologue; + expansion_for_promotion = MIN2(expansion_for_promotion, max_shrink_bytes); + // We have two shrinking computations, take the largest + shrink_bytes = MAX2(shrink_bytes, expansion_for_promotion); + assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size"); + if (PrintGC && Verbose) { + gclog_or_tty->print_cr(" " + " aggressive shrinking:" + " _capacity_at_prologue: %.1fK" + " capacity_after_gc: %.1fK" + " expansion_for_promotion: %.1fK" + " shrink_bytes: %.1fK", + capacity_after_gc / (double) K, + _capacity_at_prologue / (double) K, + expansion_for_promotion / (double) K, + shrink_bytes / (double) K); + } + } + // Don't shrink unless it's significant + if (shrink_bytes >= _min_heap_delta_bytes) { + shrink(shrink_bytes); + } +} + // Currently nothing to do. void CardGeneration::prepare_for_verify() {} diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/memory/generation.hpp --- a/src/share/vm/memory/generation.hpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/memory/generation.hpp Sat Apr 13 00:33:37 2013 +0200 @@ -634,6 +634,17 @@ // This is local to this generation. BlockOffsetSharedArray* _bts; + // current shrinking effect: this damps shrinking when the heap gets empty. + size_t _shrink_factor; + + size_t _min_heap_delta_bytes; // Minimum amount to expand. + + // Some statistics from before gc started. + // These are gathered in the gc_prologue (and should_collect) + // to control growing/shrinking policy in spite of promotions. + size_t _capacity_at_prologue; + size_t _used_at_prologue; + CardGeneration(ReservedSpace rs, size_t initial_byte_size, int level, GenRemSet* remset); @@ -644,6 +655,11 @@ // necessarily the full "bytes") was done. virtual bool expand(size_t bytes, size_t expand_bytes); + // Shrink generation with specified size (returns false if unable to shrink) + virtual void shrink(size_t bytes) = 0; + + virtual void compute_new_size(); + virtual void clear_remembered_set(); virtual void invalidate_remembered_set(); @@ -667,7 +683,6 @@ friend class VM_PopulateDumpSharedSpace; protected: - size_t _min_heap_delta_bytes; // Minimum amount to expand. ContiguousSpace* _the_space; // actual space holding objects WaterMark _last_gc; // watermark between objects allocated before // and after last GC. @@ -688,11 +703,10 @@ public: OneContigSpaceCardGeneration(ReservedSpace rs, size_t initial_byte_size, - size_t min_heap_delta_bytes, int level, GenRemSet* remset, ContiguousSpace* space) : CardGeneration(rs, initial_byte_size, level, remset), - _the_space(space), _min_heap_delta_bytes(min_heap_delta_bytes) + _the_space(space) {} inline bool is_in(const void* p) const; diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/memory/heap.cpp --- a/src/share/vm/memory/heap.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/memory/heap.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -79,13 +79,6 @@ } -static size_t align_to_allocation_size(size_t size) { - const size_t alignment = (size_t)os::vm_allocation_granularity(); - assert(is_power_of_2(alignment), "no kidding ???"); - return (size + alignment - 1) & ~(alignment - 1); -} - - void CodeHeap::on_code_mapping(char* base, size_t size) { #ifdef LINUX extern void linux_wrap_code(char* base, size_t size); diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/memory/tenuredGeneration.cpp --- a/src/share/vm/memory/tenuredGeneration.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/memory/tenuredGeneration.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -39,7 +39,7 @@ size_t initial_byte_size, int level, GenRemSet* remset) : OneContigSpaceCardGeneration(rs, initial_byte_size, - MinHeapDeltaBytes, level, remset, NULL) + level, remset, NULL) { HeapWord* bottom = (HeapWord*) _virtual_space.low(); HeapWord* end = (HeapWord*) _virtual_space.high(); @@ -86,162 +86,6 @@ return "tenured generation"; } -void TenuredGeneration::compute_new_size() { - assert(_shrink_factor <= 100, "invalid shrink factor"); - size_t current_shrink_factor = _shrink_factor; - _shrink_factor = 0; - - // We don't have floating point command-line arguments - // Note: argument processing ensures that MinHeapFreeRatio < 100. - const double minimum_free_percentage = MinHeapFreeRatio / 100.0; - const double maximum_used_percentage = 1.0 - minimum_free_percentage; - - // Compute some numbers about the state of the heap. - const size_t used_after_gc = used(); - const size_t capacity_after_gc = capacity(); - - const double min_tmp = used_after_gc / maximum_used_percentage; - size_t minimum_desired_capacity = (size_t)MIN2(min_tmp, double(max_uintx)); - // Don't shrink less than the initial generation size - minimum_desired_capacity = MAX2(minimum_desired_capacity, - spec()->init_size()); - assert(used_after_gc <= minimum_desired_capacity, "sanity check"); - - if (PrintGC && Verbose) { - const size_t free_after_gc = free(); - const double free_percentage = ((double)free_after_gc) / capacity_after_gc; - gclog_or_tty->print_cr("TenuredGeneration::compute_new_size: "); - gclog_or_tty->print_cr(" " - " minimum_free_percentage: %6.2f" - " maximum_used_percentage: %6.2f", - minimum_free_percentage, - maximum_used_percentage); - gclog_or_tty->print_cr(" " - " free_after_gc : %6.1fK" - " used_after_gc : %6.1fK" - " capacity_after_gc : %6.1fK", - free_after_gc / (double) K, - used_after_gc / (double) K, - capacity_after_gc / (double) K); - gclog_or_tty->print_cr(" " - " free_percentage: %6.2f", - free_percentage); - } - - if (capacity_after_gc < minimum_desired_capacity) { - // If we have less free space than we want then expand - size_t expand_bytes = minimum_desired_capacity - capacity_after_gc; - // Don't expand unless it's significant - if (expand_bytes >= _min_heap_delta_bytes) { - expand(expand_bytes, 0); // safe if expansion fails - } - if (PrintGC && Verbose) { - gclog_or_tty->print_cr(" expanding:" - " minimum_desired_capacity: %6.1fK" - " expand_bytes: %6.1fK" - " _min_heap_delta_bytes: %6.1fK", - minimum_desired_capacity / (double) K, - expand_bytes / (double) K, - _min_heap_delta_bytes / (double) K); - } - return; - } - - // No expansion, now see if we want to shrink - size_t shrink_bytes = 0; - // We would never want to shrink more than this - size_t max_shrink_bytes = capacity_after_gc - minimum_desired_capacity; - - if (MaxHeapFreeRatio < 100) { - const double maximum_free_percentage = MaxHeapFreeRatio / 100.0; - const double minimum_used_percentage = 1.0 - maximum_free_percentage; - const double max_tmp = used_after_gc / minimum_used_percentage; - size_t maximum_desired_capacity = (size_t)MIN2(max_tmp, double(max_uintx)); - maximum_desired_capacity = MAX2(maximum_desired_capacity, - spec()->init_size()); - if (PrintGC && Verbose) { - gclog_or_tty->print_cr(" " - " maximum_free_percentage: %6.2f" - " minimum_used_percentage: %6.2f", - maximum_free_percentage, - minimum_used_percentage); - gclog_or_tty->print_cr(" " - " _capacity_at_prologue: %6.1fK" - " minimum_desired_capacity: %6.1fK" - " maximum_desired_capacity: %6.1fK", - _capacity_at_prologue / (double) K, - minimum_desired_capacity / (double) K, - maximum_desired_capacity / (double) K); - } - assert(minimum_desired_capacity <= maximum_desired_capacity, - "sanity check"); - - if (capacity_after_gc > maximum_desired_capacity) { - // Capacity too large, compute shrinking size - shrink_bytes = capacity_after_gc - maximum_desired_capacity; - // We don't want shrink all the way back to initSize if people call - // System.gc(), because some programs do that between "phases" and then - // we'd just have to grow the heap up again for the next phase. So we - // damp the shrinking: 0% on the first call, 10% on the second call, 40% - // on the third call, and 100% by the fourth call. But if we recompute - // size without shrinking, it goes back to 0%. - shrink_bytes = shrink_bytes / 100 * current_shrink_factor; - assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size"); - if (current_shrink_factor == 0) { - _shrink_factor = 10; - } else { - _shrink_factor = MIN2(current_shrink_factor * 4, (size_t) 100); - } - if (PrintGC && Verbose) { - gclog_or_tty->print_cr(" " - " shrinking:" - " initSize: %.1fK" - " maximum_desired_capacity: %.1fK", - spec()->init_size() / (double) K, - maximum_desired_capacity / (double) K); - gclog_or_tty->print_cr(" " - " shrink_bytes: %.1fK" - " current_shrink_factor: %d" - " new shrink factor: %d" - " _min_heap_delta_bytes: %.1fK", - shrink_bytes / (double) K, - current_shrink_factor, - _shrink_factor, - _min_heap_delta_bytes / (double) K); - } - } - } - - if (capacity_after_gc > _capacity_at_prologue) { - // We might have expanded for promotions, in which case we might want to - // take back that expansion if there's room after GC. That keeps us from - // stretching the heap with promotions when there's plenty of room. - size_t expansion_for_promotion = capacity_after_gc - _capacity_at_prologue; - expansion_for_promotion = MIN2(expansion_for_promotion, max_shrink_bytes); - // We have two shrinking computations, take the largest - shrink_bytes = MAX2(shrink_bytes, expansion_for_promotion); - assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size"); - if (PrintGC && Verbose) { - gclog_or_tty->print_cr(" " - " aggressive shrinking:" - " _capacity_at_prologue: %.1fK" - " capacity_after_gc: %.1fK" - " expansion_for_promotion: %.1fK" - " shrink_bytes: %.1fK", - capacity_after_gc / (double) K, - _capacity_at_prologue / (double) K, - expansion_for_promotion / (double) K, - shrink_bytes / (double) K); - } - } - // Don't shrink unless it's significant - if (shrink_bytes >= _min_heap_delta_bytes) { - shrink(shrink_bytes); - } - assert(used() == used_after_gc && used_after_gc <= capacity(), - "sanity check"); -} - void TenuredGeneration::gc_prologue(bool full) { _capacity_at_prologue = capacity(); _used_at_prologue = used(); @@ -312,6 +156,19 @@ size, is_tlab); } +void TenuredGeneration::compute_new_size() { + assert_locked_or_safepoint(Heap_lock); + + // Compute some numbers about the state of the heap. + const size_t used_after_gc = used(); + const size_t capacity_after_gc = capacity(); + + CardGeneration::compute_new_size(); + + assert(used() == used_after_gc && used_after_gc <= capacity(), + err_msg("used: " SIZE_FORMAT " used_after_gc: " SIZE_FORMAT + " capacity: " SIZE_FORMAT, used(), used_after_gc, capacity())); +} void TenuredGeneration::update_gc_stats(int current_level, bool full) { // If the next lower level(s) has been collected, gather any statistics diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/memory/tenuredGeneration.hpp --- a/src/share/vm/memory/tenuredGeneration.hpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/memory/tenuredGeneration.hpp Sat Apr 13 00:33:37 2013 +0200 @@ -38,13 +38,6 @@ class TenuredGeneration: public OneContigSpaceCardGeneration { friend class VMStructs; protected: - // current shrinking effect: this damps shrinking when the heap gets empty. - size_t _shrink_factor; - // Some statistics from before gc started. - // These are gathered in the gc_prologue (and should_collect) - // to control growing/shrinking policy in spite of promotions. - size_t _capacity_at_prologue; - size_t _used_at_prologue; #if INCLUDE_ALL_GCS // To support parallel promotion: an array of parallel allocation @@ -80,9 +73,6 @@ return !CollectGen0First; } - // Mark sweep support - void compute_new_size(); - virtual void gc_prologue(bool full); virtual void gc_epilogue(bool full); bool should_collect(bool full, @@ -93,6 +83,7 @@ bool clear_all_soft_refs, size_t size, bool is_tlab); + virtual void compute_new_size(); #if INCLUDE_ALL_GCS // Overrides. diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/memory/universe.cpp --- a/src/share/vm/memory/universe.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/memory/universe.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -1326,6 +1326,8 @@ static uintptr_t _verify_klass_data[2] = {0, (uintptr_t)-1}; +#ifndef PRODUCT + static void calculate_verify_data(uintptr_t verify_data[2], HeapWord* low_boundary, HeapWord* high_boundary) { @@ -1360,9 +1362,7 @@ verify_data[1] = bits; } - // Oop verification (see MacroAssembler::verify_oop) -#ifndef PRODUCT uintptr_t Universe::verify_oop_mask() { MemRegion m = heap()->reserved_region(); diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/oops/constantPool.cpp --- a/src/share/vm/oops/constantPool.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/oops/constantPool.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -1378,12 +1378,13 @@ // JVMTI GetConstantPool support -// For temporary use until code is stable. -#define DBG(code) +// For debugging of constant pool +const bool debug_cpool = false; -static const char* WARN_MSG = "Must not be such entry!"; +#define DBG(code) do { if (debug_cpool) { (code); } } while(0) static void print_cpool_bytes(jint cnt, u1 *bytes) { + const char* WARN_MSG = "Must not be such entry!"; jint size = 0; u2 idx1, idx2; @@ -1669,8 +1670,7 @@ idx1 = tbl->symbol_to_value(sym); assert(idx1 != 0, "Have not found a hashtable entry"); Bytes::put_Java_u2((address) (bytes+1), idx1); - DBG(char *str = sym->as_utf8()); - DBG(printf("JVM_CONSTANT_String: idx=#%03hd, %s", idx1, str)); + DBG(printf("JVM_CONSTANT_String: idx=#%03hd, %s", idx1, sym->as_utf8())); break; } case JVM_CONSTANT_Fieldref: @@ -1745,6 +1745,8 @@ return (int)(bytes - start_bytes); } /* end copy_cpool_bytes */ +#undef DBG + void ConstantPool::set_on_stack(const bool value) { if (value) { diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/oops/instanceKlass.cpp --- a/src/share/vm/oops/instanceKlass.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/oops/instanceKlass.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -3157,7 +3157,7 @@ Array* method_ordering = this->method_ordering(); int length = method_ordering->length(); if (JvmtiExport::can_maintain_original_method_order() || - (UseSharedSpaces && length != 0)) { + ((UseSharedSpaces || DumpSharedSpaces) && length != 0)) { guarantee(length == methods()->length(), "invalid method ordering length"); jlong sum = 0; for (int j = 0; j < length; j++) { diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/oops/method.cpp --- a/src/share/vm/oops/method.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/oops/method.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -722,7 +722,7 @@ if (number_of_breakpoints() > 0) return true; if (is_method_handle_intrinsic()) - return !is_synthetic(); // the generated adapters must be compiled + return !is_synthetic() && intrinsic_id() != vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod; // the generated adapters must be compiled if (comp_level == CompLevel_any) return is_not_c1_compilable() || is_not_c2_compilable(); if (is_c1_compile(comp_level)) @@ -851,6 +851,14 @@ // ONLY USE the h_method now as make_adapter may have blocked +#ifdef GRAAL + // Check for special intrinsic that executes a compiled method. + if (h_method->intrinsic_id() == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod) { + // Actively install the stub for calling the intrinsic from compiled code. + CompileBroker::compile_method(h_method, InvocationEntryBci, CompLevel_highest_tier, + methodHandle(), CompileThreshold, "executeCompiledMethod", CHECK); + } +#endif } address Method::make_adapters(methodHandle mh, TRAPS) { @@ -1014,8 +1022,8 @@ // Test if this method is an internal MH primitive method. bool Method::is_method_handle_intrinsic() const { vmIntrinsics::ID iid = intrinsic_id(); - return (MethodHandles::is_signature_polymorphic(iid) && - MethodHandles::is_signature_polymorphic_intrinsic(iid)); + return ((MethodHandles::is_signature_polymorphic(iid) && + MethodHandles::is_signature_polymorphic_intrinsic(iid))) || iid == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod; } bool Method::has_member_arg() const { diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/oops/method.hpp --- a/src/share/vm/oops/method.hpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/oops/method.hpp Sat Apr 13 00:33:37 2013 +0200 @@ -776,15 +776,19 @@ void print_made_not_compilable(int comp_level, bool is_osr, bool report, const char* reason); public: - bool is_not_c1_compilable() const { return access_flags().is_not_c1_compilable(); } - void set_not_c1_compilable() { _access_flags.set_not_c1_compilable(); } - bool is_not_c2_compilable() const { return access_flags().is_not_c2_compilable(); } - void set_not_c2_compilable() { _access_flags.set_not_c2_compilable(); } + bool is_not_c1_compilable() const { return access_flags().is_not_c1_compilable(); } + void set_not_c1_compilable() { _access_flags.set_not_c1_compilable(); } + void clear_not_c1_compilable() { _access_flags.clear_not_c1_compilable(); } + bool is_not_c2_compilable() const { return access_flags().is_not_c2_compilable(); } + void set_not_c2_compilable() { _access_flags.set_not_c2_compilable(); } + void clear_not_c2_compilable() { _access_flags.clear_not_c2_compilable(); } - bool is_not_c1_osr_compilable() const { return is_not_c1_compilable(); } // don't waste an accessFlags bit - void set_not_c1_osr_compilable() { set_not_c1_compilable(); } // don't waste an accessFlags bit - bool is_not_c2_osr_compilable() const { return access_flags().is_not_c2_osr_compilable(); } - void set_not_c2_osr_compilable() { _access_flags.set_not_c2_osr_compilable(); } + bool is_not_c1_osr_compilable() const { return is_not_c1_compilable(); } // don't waste an accessFlags bit + void set_not_c1_osr_compilable() { set_not_c1_compilable(); } // don't waste an accessFlags bit + void clear_not_c1_osr_compilable() { clear_not_c1_compilable(); } // don't waste an accessFlags bit + bool is_not_c2_osr_compilable() const { return access_flags().is_not_c2_osr_compilable(); } + void set_not_c2_osr_compilable() { _access_flags.set_not_c2_osr_compilable(); } + void clear_not_c2_osr_compilable() { _access_flags.clear_not_c2_osr_compilable(); } // Background compilation support bool queued_for_compilation() const { return access_flags().queued_for_compilation(); } diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/oops/methodData.cpp --- a/src/share/vm/oops/methodData.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/oops/methodData.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -676,29 +676,9 @@ No_Safepoint_Verifier no_safepoint; // init function atomic wrt GC ResourceMark rm; - _invocation_counter.init(); - _backedge_counter.init(); - _invocation_counter_start = 0; - _backedge_counter_start = 0; - _num_loops = 0; - _num_blocks = 0; - _highest_comp_level = 0; - _highest_osr_comp_level = 0; - _would_profile = true; + init(); set_creation_mileage(mileage_of(method())); - // Initialize flags and trap history. - _nof_decompiles = 0; - _nof_overflow_recompiles = 0; - _nof_overflow_traps = 0; - _eflags = 0; - _arg_local = 0; - _arg_stack = 0; - _arg_returned = 0; - assert(sizeof(_trap_hist) % sizeof(HeapWord) == 0, "align"); - Copy::zero_to_words((HeapWord*) &_trap_hist, - sizeof(_trap_hist) / sizeof(HeapWord)); - // Go through the bytecodes and allocate and initialize the // corresponding data cells. int data_size = 0; @@ -743,7 +723,27 @@ post_initialize(&stream); set_size(object_size); +} +void MethodData::init() { + _invocation_counter.init(); + _backedge_counter.init(); + _invocation_counter_start = 0; + _backedge_counter_start = 0; + _num_loops = 0; + _num_blocks = 0; + _highest_comp_level = 0; + _highest_osr_comp_level = 0; + _would_profile = true; + + // Initialize flags and trap history. + _nof_decompiles = 0; + _nof_overflow_recompiles = 0; + _nof_overflow_traps = 0; + clear_escape_info(); + assert(sizeof(_trap_hist) % sizeof(HeapWord) == 0, "align"); + Copy::zero_to_words((HeapWord*) &_trap_hist, + sizeof(_trap_hist) / sizeof(HeapWord)); } bool MethodData::is_empty_data(int size_in_bytes, Bytecodes::Code code) { diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/oops/methodData.hpp --- a/src/share/vm/oops/methodData.hpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/oops/methodData.hpp Sat Apr 13 00:33:37 2013 +0200 @@ -1304,7 +1304,10 @@ static bool bytecode_has_profile(Bytecodes::Code code) { return bytecode_cell_count(code) != no_profile_data; } - + + // reset into original state + void init(); + // My size int size_in_bytes() const { return _size; } int size() const { return align_object_size(align_size_up(_size, BytesPerWord)/BytesPerWord); } @@ -1384,6 +1387,7 @@ intx arg_stack() { return _arg_stack; } intx arg_returned() { return _arg_returned; } uint arg_modified(int a) { ArgInfoData *aid = arg_info(); + assert(aid != NULL, "arg_info must be not null"); assert(a >= 0 && a < aid->number_of_args(), "valid argument number"); return aid->arg_modified(a); } @@ -1392,8 +1396,8 @@ void set_arg_stack(intx v) { _arg_stack = v; } void set_arg_returned(intx v) { _arg_returned = v; } void set_arg_modified(int a, uint v) { ArgInfoData *aid = arg_info(); + assert(aid != NULL, "arg_info must be not null"); assert(a >= 0 && a < aid->number_of_args(), "valid argument number"); - aid->set_arg_modified(a, v); } void clear_escape_info() { _eflags = _arg_local = _arg_stack = _arg_returned = 0; } diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/opto/block.cpp --- a/src/share/vm/opto/block.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/opto/block.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -1028,26 +1028,6 @@ } #ifndef PRODUCT -static void edge_dump(GrowableArray *edges) { - tty->print_cr("---- Edges ----"); - for (int i = 0; i < edges->length(); i++) { - CFGEdge *e = edges->at(i); - if (e != NULL) { - edges->at(i)->dump(); - } - } -} - -static void trace_dump(Trace *traces[], int count) { - tty->print_cr("---- Traces ----"); - for (int i = 0; i < count; i++) { - Trace *tr = traces[i]; - if (tr != NULL) { - tr->dump(); - } - } -} - void Trace::dump( ) const { tty->print_cr("Trace (freq %f)", first_block()->_freq); for (Block *b = first_block(); b != NULL; b = next(b)) { diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/opto/compile.cpp --- a/src/share/vm/opto/compile.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/opto/compile.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -2326,12 +2326,14 @@ int get_inner_loop_count() const { return _inner_loop_count; } }; +#ifdef ASSERT static bool oop_offset_is_sane(const TypeInstPtr* tp) { ciInstanceKlass *k = tp->klass()->as_instance_klass(); // Make sure the offset goes inside the instance layout. return k->contains_field_offset(tp->offset()); // Note that OffsetBot and OffsetTop are very negative. } +#endif // Eliminate trivially redundant StoreCMs and accumulate their // precedence edges. diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/opto/connode.cpp --- a/src/share/vm/opto/connode.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/opto/connode.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -465,29 +465,6 @@ return (phase->type(in(1)) == phase->type(this)) ? in(1) : this; } -// Determine whether "n" is a node which can cause an alias of one of its inputs. Node types -// which can create aliases are: CheckCastPP, Phi, and any store (if there is also a load from -// the location.) -// Note: this checks for aliases created in this compilation, not ones which may -// be potentially created at call sites. -static bool can_cause_alias(Node *n, PhaseTransform *phase) { - bool possible_alias = false; - - if (n->is_Store()) { - possible_alias = !n->as_Store()->value_never_loaded(phase); - } else { - int opc = n->Opcode(); - possible_alias = n->is_Phi() || - opc == Op_CheckCastPP || - opc == Op_StorePConditional || - opc == Op_CompareAndSwapP || - opc == Op_CompareAndSwapN || - opc == Op_GetAndSetP || - opc == Op_GetAndSetN; - } - return possible_alias; -} - //------------------------------Value------------------------------------------ // Take 'join' of input and cast-up type, unless working with an Interface const Type *CheckCastPPNode::Value( PhaseTransform *phase ) const { diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/opto/subnode.cpp --- a/src/share/vm/opto/subnode.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/opto/subnode.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -1078,16 +1078,6 @@ return (_test._test == b->_test._test); } -//------------------------------clone_cmp-------------------------------------- -// Clone a compare/bool tree -static Node *clone_cmp( Node *cmp, Node *cmp1, Node *cmp2, PhaseGVN *gvn, BoolTest::mask test ) { - Node *ncmp = cmp->clone(); - ncmp->set_req(1,cmp1); - ncmp->set_req(2,cmp2); - ncmp = gvn->transform( ncmp ); - return new (gvn->C) BoolNode( ncmp, test ); -} - //-------------------------------make_predicate-------------------------------- Node* BoolNode::make_predicate(Node* test_value, PhaseGVN* phase) { if (test_value->is_Con()) return test_value; diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/prims/jni.cpp --- a/src/share/vm/prims/jni.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/prims/jni.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -1292,32 +1292,6 @@ JNI_NONVIRTUAL }; -static methodHandle jni_resolve_interface_call(Handle recv, methodHandle method, TRAPS) { - assert(!method.is_null() , "method should not be null"); - - KlassHandle recv_klass; // Default to NULL (use of ?: can confuse gcc) - if (recv.not_null()) recv_klass = KlassHandle(THREAD, recv->klass()); - KlassHandle spec_klass (THREAD, method->method_holder()); - Symbol* name = method->name(); - Symbol* signature = method->signature(); - CallInfo info; - LinkResolver::resolve_interface_call(info, recv, recv_klass, spec_klass, name, signature, KlassHandle(), false, true, CHECK_(methodHandle())); - return info.selected_method(); -} - -static methodHandle jni_resolve_virtual_call(Handle recv, methodHandle method, TRAPS) { - assert(!method.is_null() , "method should not be null"); - - KlassHandle recv_klass; // Default to NULL (use of ?: can confuse gcc) - if (recv.not_null()) recv_klass = KlassHandle(THREAD, recv->klass()); - KlassHandle spec_klass (THREAD, method->method_holder()); - Symbol* name = method->name(); - Symbol* signature = method->signature(); - CallInfo info; - LinkResolver::resolve_virtual_call(info, recv, recv_klass, spec_klass, name, signature, KlassHandle(), false, true, CHECK_(methodHandle())); - return info.selected_method(); -} - static void jni_invoke_static(JNIEnv *env, JavaValue* result, jobject receiver, JNICallType call_type, jmethodID method_id, JNI_ArgumentPusher *args, TRAPS) { @@ -5056,6 +5030,7 @@ void execute_internal_vm_tests() { if (ExecuteInternalVMTests) { tty->print_cr("Running internal VM tests"); + run_unit_test(GlobalDefinitions::test_globals()); run_unit_test(arrayOopDesc::test_max_array_length()); run_unit_test(CollectedHeap::test_is_in()); run_unit_test(QuickSort::test_quick_sort()); diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/prims/jniCheck.hpp --- a/src/share/vm/prims/jniCheck.hpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/prims/jniCheck.hpp Sat Apr 13 00:33:37 2013 +0200 @@ -33,7 +33,7 @@ // within IN_VM macro), one to be called when in NATIVE state. // When in VM state: - static void ReportJNIFatalError(JavaThread* thr, const char *msg) { + static inline void ReportJNIFatalError(JavaThread* thr, const char *msg) { tty->print_cr("FATAL ERROR in native method: %s", msg); thr->print_stack(); os::abort(true); diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/prims/unsafe.cpp --- a/src/share/vm/prims/unsafe.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/prims/unsafe.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -116,7 +116,11 @@ inline void* index_oop_from_field_offset_long(oop p, jlong field_offset) { jlong byte_offset = field_offset_to_byte_offset(field_offset); // Don't allow unsafe to be used to read or write the header word of oops + // unless running GRAAL which wants to read the misc word for example when + // interpreting computeHashCode(). +#ifndef GRAAL assert(p == NULL || field_offset >= oopDesc::header_size(), "offset must be outside of header"); +#endif #ifdef ASSERT if (p != NULL) { assert(byte_offset >= 0 && byte_offset <= (jlong)MAX_OBJECT_SIZE, "sane offset"); diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/prims/whitebox.cpp --- a/src/share/vm/prims/whitebox.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/prims/whitebox.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -49,6 +49,7 @@ #endif // INCLUDE_NMT #include "compiler/compileBroker.hpp" +#include "runtime/compilationPolicy.hpp" bool WhiteBox::_used = false; @@ -118,45 +119,46 @@ #endif // INCLUDE_ALL_GCS #ifdef INCLUDE_NMT -// Keep track of the 3 allocations in NMTAllocTest so we can free them later -// on and verify that they're not visible anymore -static void* nmtMtTest1 = NULL, *nmtMtTest2 = NULL, *nmtMtTest3 = NULL; - // Alloc memory using the test memory type so that we can use that to see if // NMT picks it up correctly -WB_ENTRY(jboolean, WB_NMTAllocTest(JNIEnv* env)) - void *mem; +WB_ENTRY(jlong, WB_NMTMalloc(JNIEnv* env, jobject o, jlong size)) + jlong addr = 0; - if (!MemTracker::is_on() || MemTracker::shutdown_in_progress()) { - return false; + if (MemTracker::is_on() && !MemTracker::shutdown_in_progress()) { + addr = (jlong)(uintptr_t)os::malloc(size, mtTest); } - // Allocate 2 * 128k + 256k + 1024k and free the 1024k one to make sure we track - // everything correctly. Total should be 512k held alive. - nmtMtTest1 = os::malloc(128 * 1024, mtTest); - mem = os::malloc(1024 * 1024, mtTest); - nmtMtTest2 = os::malloc(256 * 1024, mtTest); - os::free(mem, mtTest); - nmtMtTest3 = os::malloc(128 * 1024, mtTest); - - return true; + return addr; WB_END // Free the memory allocated by NMTAllocTest -WB_ENTRY(jboolean, WB_NMTFreeTestMemory(JNIEnv* env)) +WB_ENTRY(void, WB_NMTFree(JNIEnv* env, jobject o, jlong mem)) + os::free((void*)(uintptr_t)mem, mtTest); +WB_END - if (nmtMtTest1 == NULL || nmtMtTest2 == NULL || nmtMtTest3 == NULL) { - return false; +WB_ENTRY(jlong, WB_NMTReserveMemory(JNIEnv* env, jobject o, jlong size)) + jlong addr = 0; + + if (MemTracker::is_on() && !MemTracker::shutdown_in_progress()) { + addr = (jlong)(uintptr_t)os::reserve_memory(size); + MemTracker::record_virtual_memory_type((address)addr, mtTest); } - os::free(nmtMtTest1, mtTest); - nmtMtTest1 = NULL; - os::free(nmtMtTest2, mtTest); - nmtMtTest2 = NULL; - os::free(nmtMtTest3, mtTest); - nmtMtTest3 = NULL; + return addr; +WB_END + - return true; +WB_ENTRY(void, WB_NMTCommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size)) + os::commit_memory((char *)(uintptr_t)addr, size); + MemTracker::record_virtual_memory_type((address)(uintptr_t)addr, mtTest); +WB_END + +WB_ENTRY(void, WB_NMTUncommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size)) + os::uncommit_memory((char *)(uintptr_t)addr, size); +WB_END + +WB_ENTRY(void, WB_NMTReleaseMemory(JNIEnv* env, jobject o, jlong addr, jlong size)) + os::release_memory((char *)(uintptr_t)addr, size); WB_END // Block until the current generation of NMT data to be merged, used to reliably test the NMT feature @@ -213,11 +215,11 @@ return (code->is_alive() && !code->is_marked_for_deoptimization()); WB_END -WB_ENTRY(jboolean, WB_IsMethodCompilable(JNIEnv* env, jobject o, jobject method)) +WB_ENTRY(jboolean, WB_IsMethodCompilable(JNIEnv* env, jobject o, jobject method, jint comp_level)) jmethodID jmid = reflected_method_to_jmid(thread, env, method); MutexLockerEx mu(Compile_lock); methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); - return !mh->is_not_compilable(); + return CompilationPolicy::can_be_compiled(mh, comp_level); WB_END WB_ENTRY(jboolean, WB_IsMethodQueuedForCompilation(JNIEnv* env, jobject o, jobject method)) @@ -241,7 +243,7 @@ mh->set_not_compilable(); WB_END -WB_ENTRY(jboolean, WB_SetDontInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value)) +WB_ENTRY(jboolean, WB_TestSetDontInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value)) jmethodID jmid = reflected_method_to_jmid(thread, env, method); methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); bool result = mh->dont_inline(); @@ -254,6 +256,54 @@ CompileBroker::queue_size(CompLevel_full_profile) /* C1 */; WB_END + +WB_ENTRY(jboolean, WB_TestSetForceInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value)) + jmethodID jmid = reflected_method_to_jmid(thread, env, method); + methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); + bool result = mh->force_inline(); + mh->set_force_inline(value == JNI_TRUE); + return result; +WB_END + +WB_ENTRY(jboolean, WB_EnqueueMethodForCompilation(JNIEnv* env, jobject o, jobject method, jint comp_level)) + jmethodID jmid = reflected_method_to_jmid(thread, env, method); + methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); + nmethod* nm = CompileBroker::compile_method(mh, InvocationEntryBci, comp_level, mh, mh->invocation_count(), "WhiteBox", THREAD); + MutexLockerEx mu(Compile_lock); + return (mh->queued_for_compilation() || nm != NULL); +WB_END + +WB_ENTRY(void, WB_ClearMethodState(JNIEnv* env, jobject o, jobject method)) + jmethodID jmid = reflected_method_to_jmid(thread, env, method); + methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); + MutexLockerEx mu(Compile_lock); + MethodData* mdo = mh->method_data(); + + if (mdo != NULL) { + mdo->init(); + ResourceMark rm; + int arg_count = mdo->method()->size_of_parameters(); + for (int i = 0; i < arg_count; i++) { + mdo->set_arg_modified(i, 0); + } + } + + mh->backedge_counter()->init(); + mh->invocation_counter()->init(); + mh->set_interpreter_invocation_count(0); + mh->set_interpreter_throwout_count(0); + mh->clear_not_c1_compilable(); + mh->clear_not_c2_compilable(); + mh->clear_not_c2_osr_compilable(); + NOT_PRODUCT(mh->set_compiled_invocation_count(0)); + +#ifdef TIERED + mh->set_rate(0.0F); + mh->set_prev_event_count(0); + mh->set_prev_time(0); +#endif +WB_END + WB_ENTRY(jboolean, WB_IsInStringTable(JNIEnv* env, jobject o, jstring javaString)) ResourceMark rm(THREAD); int len; @@ -271,7 +321,6 @@ Universe::heap()->collect(GCCause::_last_ditch_collection); WB_END - //Some convenience methods to deal with objects from java int WhiteBox::offset_for_field(const char* field_name, oop object, Symbol* signature_symbol) { @@ -340,27 +389,37 @@ {CC"g1RegionSize", CC"()I", (void*)&WB_G1RegionSize }, #endif // INCLUDE_ALL_GCS #ifdef INCLUDE_NMT - {CC"NMTAllocTest", CC"()Z", (void*)&WB_NMTAllocTest }, - {CC"NMTFreeTestMemory", CC"()Z", (void*)&WB_NMTFreeTestMemory }, - {CC"NMTWaitForDataMerge",CC"()Z", (void*)&WB_NMTWaitForDataMerge}, + {CC"NMTMalloc", CC"(J)J", (void*)&WB_NMTMalloc }, + {CC"NMTFree", CC"(J)V", (void*)&WB_NMTFree }, + {CC"NMTReserveMemory", CC"(J)J", (void*)&WB_NMTReserveMemory }, + {CC"NMTCommitMemory", CC"(JJ)V", (void*)&WB_NMTCommitMemory }, + {CC"NMTUncommitMemory", CC"(JJ)V", (void*)&WB_NMTUncommitMemory }, + {CC"NMTReleaseMemory", CC"(JJ)V", (void*)&WB_NMTReleaseMemory }, + {CC"NMTWaitForDataMerge", CC"()Z", (void*)&WB_NMTWaitForDataMerge}, #endif // INCLUDE_NMT {CC"deoptimizeAll", CC"()V", (void*)&WB_DeoptimizeAll }, {CC"deoptimizeMethod", CC"(Ljava/lang/reflect/Method;)I", (void*)&WB_DeoptimizeMethod }, {CC"isMethodCompiled", CC"(Ljava/lang/reflect/Method;)Z", (void*)&WB_IsMethodCompiled }, - {CC"isMethodCompilable", CC"(Ljava/lang/reflect/Method;)Z", + {CC"isMethodCompilable", CC"(Ljava/lang/reflect/Method;I)Z", (void*)&WB_IsMethodCompilable}, {CC"isMethodQueuedForCompilation", CC"(Ljava/lang/reflect/Method;)Z", (void*)&WB_IsMethodQueuedForCompilation}, {CC"makeMethodNotCompilable", CC"(Ljava/lang/reflect/Method;)V", (void*)&WB_MakeMethodNotCompilable}, - {CC"setDontInlineMethod", - CC"(Ljava/lang/reflect/Method;Z)Z", (void*)&WB_SetDontInlineMethod}, + {CC"testSetDontInlineMethod", + CC"(Ljava/lang/reflect/Method;Z)Z", (void*)&WB_TestSetDontInlineMethod}, {CC"getMethodCompilationLevel", CC"(Ljava/lang/reflect/Method;)I", (void*)&WB_GetMethodCompilationLevel}, {CC"getCompileQueuesSize", CC"()I", (void*)&WB_GetCompileQueuesSize}, + {CC"testSetForceInlineMethod", + CC"(Ljava/lang/reflect/Method;Z)Z", (void*)&WB_TestSetForceInlineMethod}, + {CC"enqueueMethodForCompilation", + CC"(Ljava/lang/reflect/Method;I)Z", (void*)&WB_EnqueueMethodForCompilation}, + {CC"clearMethodState", + CC"(Ljava/lang/reflect/Method;)V", (void*)&WB_ClearMethodState}, {CC"isInStringTable", CC"(Ljava/lang/String;)Z", (void*)&WB_IsInStringTable }, {CC"fullGC", CC"()V", (void*)&WB_FullGC }, }; diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/runtime/arguments.cpp --- a/src/share/vm/runtime/arguments.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/runtime/arguments.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -1763,11 +1763,15 @@ return false; } +#if !INCLUDE_ALL_GCS +#ifdef ASSERT static bool verify_serial_gc_flags() { return (UseSerialGC && !(UseParNewGC || (UseConcMarkSweepGC || CMSIncrementalMode) || UseG1GC || UseParallelGC || UseParallelOldGC)); } +#endif // ASSERT +#endif // INCLUDE_ALL_GCS // check if do gclog rotation // +UseGCLogFileRotation is a must, @@ -2015,11 +2019,12 @@ // than just disable the lock verification. This will be fixed under // bug 4788986. if (UseConcMarkSweepGC && FLSVerifyAllHeapReferences) { - if (VerifyGCStartAt == 0) { + if (VerifyDuringStartup) { warning("Heap verification at start-up disabled " "(due to current incompatibility with FLSVerifyAllHeapReferences)"); - VerifyGCStartAt = 1; // Disable verification at start-up + VerifyDuringStartup = false; // Disable verification at start-up } + if (VerifyBeforeExit) { warning("Heap verification at shutdown disabled " "(due to current incompatibility with FLSVerifyAllHeapReferences)"); @@ -3158,6 +3163,7 @@ } \ } while(0) +#if !INCLUDE_ALL_GCS static void force_serial_gc() { FLAG_SET_DEFAULT(UseSerialGC, true); FLAG_SET_DEFAULT(CMSIncrementalMode, false); // special CMS suboption @@ -3167,6 +3173,7 @@ UNSUPPORTED_GC_OPTION(UseConcMarkSweepGC); UNSUPPORTED_GC_OPTION(UseParNewGC); } +#endif // INCLUDE_ALL_GCS // Parse entry point called from JNI_CreateJavaVM diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/runtime/compilationPolicy.cpp --- a/src/share/vm/runtime/compilationPolicy.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/runtime/compilationPolicy.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -130,9 +130,10 @@ } if (comp_level == CompLevel_all) { return !m->is_not_compilable(CompLevel_simple) && !m->is_not_compilable(CompLevel_full_optimization); - } else { + } else if (is_compile(comp_level)) { return !m->is_not_compilable(comp_level); } + return false; } bool CompilationPolicy::is_compilation_enabled() { diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/runtime/compilationPolicy.hpp --- a/src/share/vm/runtime/compilationPolicy.hpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/runtime/compilationPolicy.hpp Sat Apr 13 00:33:37 2013 +0200 @@ -96,7 +96,7 @@ void reset_counter_for_back_branch_event(methodHandle method); public: NonTieredCompPolicy() : _compiler_count(0) { } - virtual CompLevel initial_compile_level() { return CompLevel_initial_compile; } + virtual CompLevel initial_compile_level() { return CompLevel_highest_tier; } virtual int compiler_count(CompLevel comp_level); virtual void do_safepoint_work(); virtual void reprofile(ScopeDesc* trap_scope, bool is_osr); diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/runtime/globals.hpp --- a/src/share/vm/runtime/globals.hpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/runtime/globals.hpp Sat Apr 13 00:33:37 2013 +0200 @@ -2140,6 +2140,10 @@ product(intx, PrefetchFieldsAhead, -1, \ "How many fields ahead to prefetch in oop scan (<= 0 means off)") \ \ + diagnostic(bool, VerifyDuringStartup, false, \ + "Verify memory system before executing any Java code " \ + "during VM initialization") \ + \ diagnostic(bool, VerifyBeforeExit, trueInDebug, \ "Verify system before exiting") \ \ @@ -3684,8 +3688,13 @@ product(bool, PrintGCCause, true, \ "Include GC cause in GC logging") \ \ - product(bool, AllowNonVirtualCalls, false, \ - "Obey the ACC_SUPER flag and allow invokenonvirtual calls") + product(bool , AllowNonVirtualCalls, false, \ + "Obey the ACC_SUPER flag and allow invokenonvirtual calls") \ + \ + experimental(uintx, ArrayAllocatorMallocLimit, \ + SOLARIS_ONLY(64*K) NOT_SOLARIS(max_uintx), \ + "Allocation less than this value will be allocated " \ + "using malloc. Larger allocations will use mmap.") /* * Macros for factoring of globals diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/runtime/javaCalls.cpp --- a/src/share/vm/runtime/javaCalls.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/runtime/javaCalls.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -412,7 +412,7 @@ ((JavaThread*) THREAD)->set_graal_alternate_call_target(nm->verified_entry_point()); entry_point = method->adapter()->get_i2c_entry(); } else { - THROW(vmSymbols::MethodInvalidatedException()); + THROW(vmSymbols::com_oracle_graal_api_code_InvalidInstalledCodeException()); } } #endif diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/runtime/safepoint.cpp --- a/src/share/vm/runtime/safepoint.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/runtime/safepoint.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -735,6 +735,9 @@ // Exception handlers #ifndef PRODUCT + +#ifdef SPARC + #ifdef _LP64 #define PTR_PAD "" #else @@ -755,7 +758,6 @@ newptr, is_oop?"oop":" ", (wasoop && !is_oop) ? "STALE" : ((wasoop==false&&is_oop==false&&oldptr !=newptr)?"STOMP":" ")); } -#ifdef SPARC static void print_me(intptr_t *new_sp, intptr_t *old_sp, bool *was_oops) { #ifdef _LP64 tty->print_cr("--------+------address-----+------before-----------+-------after----------+"); diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/runtime/sharedRuntime.cpp --- a/src/share/vm/runtime/sharedRuntime.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/runtime/sharedRuntime.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -83,6 +83,7 @@ #endif // Shared stub locations +RuntimeStub* SharedRuntime::_deoptimized_installed_code_blob; RuntimeStub* SharedRuntime::_wrong_method_blob; RuntimeStub* SharedRuntime::_ic_miss_blob; RuntimeStub* SharedRuntime::_resolve_opt_virtual_call_blob; @@ -101,6 +102,7 @@ //----------------------------generate_stubs----------------------------------- void SharedRuntime::generate_stubs() { + _deoptimized_installed_code_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::handle_deoptimized_installed_code), "deoptimized_installed_code"); _wrong_method_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::handle_wrong_method), "wrong_method_stub"); _ic_miss_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::handle_wrong_method_ic_miss), "ic_miss_stub"); _resolve_opt_virtual_call_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::resolve_opt_virtual_call_C), "resolve_opt_virtual_call"); @@ -1350,6 +1352,12 @@ return callee_method->verified_code_entry(); JRT_END +// Installed code has been deoptimized +JRT_BLOCK_ENTRY(address, SharedRuntime::handle_deoptimized_installed_code(JavaThread* thread)) + JavaThread* THREAD = thread; + ThreadInVMfromJava tiv(THREAD); + THROW_(vmSymbols::com_oracle_graal_api_code_InvalidInstalledCodeException(), NULL); +JRT_END // Handle call site that has been made non-entrant JRT_BLOCK_ENTRY(address, SharedRuntime::handle_wrong_method(JavaThread* thread)) diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/runtime/sharedRuntime.hpp --- a/src/share/vm/runtime/sharedRuntime.hpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/runtime/sharedRuntime.hpp Sat Apr 13 00:33:37 2013 +0200 @@ -55,6 +55,7 @@ // Shared stub locations + static RuntimeStub* _deoptimized_installed_code_blob; static RuntimeStub* _wrong_method_blob; static RuntimeStub* _ic_miss_blob; static RuntimeStub* _resolve_opt_virtual_call_blob; @@ -209,6 +210,11 @@ return _wrong_method_blob->entry_point(); } + static address get_deoptimized_installed_code_stub() { + assert(_deoptimized_installed_code_blob!= NULL, "oops"); + return _deoptimized_installed_code_blob->entry_point(); + } + #ifdef COMPILER2 static void generate_uncommon_trap_blob(void); static UncommonTrapBlob* uncommon_trap_blob() { return _uncommon_trap_blob; } @@ -486,6 +492,9 @@ static address handle_wrong_method(JavaThread* thread); static address handle_wrong_method_ic_miss(JavaThread* thread); + // handle deoptimized installed code + static address handle_deoptimized_installed_code(JavaThread* thread); + #ifndef PRODUCT // Collect and print inline cache miss statistics diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/runtime/synchronizer.cpp --- a/src/share/vm/runtime/synchronizer.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/runtime/synchronizer.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -449,8 +449,6 @@ // and explicit fences (barriers) to control for architectural reordering performed // by the CPU(s) or platform. -static int MBFence (int x) { OrderAccess::fence(); return x; } - struct SharedGlobals { // These are highly shared mostly-read variables. // To avoid false-sharing they need to be the sole occupants of a $ line. @@ -1639,11 +1637,6 @@ #ifndef PRODUCT -void ObjectSynchronizer::trace_locking(Handle locking_obj, bool is_compiled, - bool is_method, bool is_locking) { - // Don't know what to do here -} - // Verify all monitors in the monitor cache, the verification is weak. void ObjectSynchronizer::verify() { ObjectMonitor* block = gBlockList; diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/runtime/synchronizer.hpp --- a/src/share/vm/runtime/synchronizer.hpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/runtime/synchronizer.hpp Sat Apr 13 00:33:37 2013 +0200 @@ -121,7 +121,6 @@ static void oops_do(OopClosure* f); // debugging - static void trace_locking(Handle obj, bool is_compiled, bool is_method, bool is_locking) PRODUCT_RETURN; static void verify() PRODUCT_RETURN; static int verify_objmon_isinpool(ObjectMonitor *addr) PRODUCT_RETURN0; diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/runtime/thread.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -3449,9 +3449,9 @@ } assert (Universe::is_fully_initialized(), "not initialized"); - if (VerifyBeforeGC && VerifyGCStartAt == 0) { - Universe::heap()->prepare_for_verify(); - Universe::verify(); // make sure we're starting with a clean slate + if (VerifyDuringStartup) { + VM_Verify verify_op(false /* silent */); // make sure we're starting with a clean slate + VMThread::execute(&verify_op); } EXCEPTION_MARK; diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/runtime/vmStructs.cpp --- a/src/share/vm/runtime/vmStructs.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/runtime/vmStructs.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -478,6 +478,9 @@ \ nonstatic_field(CardGeneration, _rs, GenRemSet*) \ nonstatic_field(CardGeneration, _bts, BlockOffsetSharedArray*) \ + nonstatic_field(CardGeneration, _shrink_factor, size_t) \ + nonstatic_field(CardGeneration, _capacity_at_prologue, size_t) \ + nonstatic_field(CardGeneration, _used_at_prologue, size_t) \ \ nonstatic_field(CardTableModRefBS, _whole_heap, const MemRegion) \ nonstatic_field(CardTableModRefBS, _guard_index, const size_t) \ @@ -548,8 +551,6 @@ nonstatic_field(Space, _bottom, HeapWord*) \ nonstatic_field(Space, _end, HeapWord*) \ \ - nonstatic_field(TenuredGeneration, _shrink_factor, size_t) \ - nonstatic_field(TenuredGeneration, _capacity_at_prologue, size_t) \ nonstatic_field(ThreadLocalAllocBuffer, _start, HeapWord*) \ nonstatic_field(ThreadLocalAllocBuffer, _top, HeapWord*) \ nonstatic_field(ThreadLocalAllocBuffer, _end, HeapWord*) \ diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/runtime/vm_operations.cpp --- a/src/share/vm/runtime/vm_operations.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/runtime/vm_operations.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -177,7 +177,8 @@ } void VM_Verify::doit() { - Universe::verify(); + Universe::heap()->prepare_for_verify(); + Universe::verify(_silent); } bool VM_PrintThreads::doit_prologue() { diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/runtime/vm_operations.hpp --- a/src/share/vm/runtime/vm_operations.hpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/runtime/vm_operations.hpp Sat Apr 13 00:33:37 2013 +0200 @@ -301,9 +301,9 @@ class VM_Verify: public VM_Operation { private: - KlassHandle _dependee; + bool _silent; public: - VM_Verify() {} + VM_Verify(bool silent) : _silent(silent) {} VMOp_Type type() const { return VMOp_Verify; } void doit(); }; diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/services/memTracker.cpp --- a/src/share/vm/services/memTracker.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/services/memTracker.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -127,12 +127,15 @@ assert(_state == NMT_bootstrapping_multi_thread, "wrong state"); _snapshot = new (std::nothrow)MemSnapshot(); - if (_snapshot != NULL && !_snapshot->out_of_memory()) { - if (start_worker()) { + if (_snapshot != NULL) { + if (!_snapshot->out_of_memory() && start_worker()) { _state = NMT_started; NMT_track_callsite = (_tracking_level == NMT_detail && can_walk_stack()); return; } + + delete _snapshot; + _snapshot = NULL; } // fail to start native memory tracking, shut it down @@ -544,7 +547,10 @@ assert(_worker_thread == NULL, "Just Check"); _worker_thread = new (std::nothrow) MemTrackWorker(); if (_worker_thread == NULL || _worker_thread->has_error()) { - shutdown(NMT_initialization); + if (_worker_thread != NULL) { + delete _worker_thread; + _worker_thread = NULL; + } return false; } _worker_thread->start(); diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/utilities/accessFlags.hpp --- a/src/share/vm/utilities/accessFlags.hpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/utilities/accessFlags.hpp Sat Apr 13 00:33:37 2013 +0200 @@ -194,6 +194,9 @@ void set_is_obsolete() { atomic_set_bits(JVM_ACC_IS_OBSOLETE); } void set_is_prefixed_native() { atomic_set_bits(JVM_ACC_IS_PREFIXED_NATIVE); } + void clear_not_c1_compilable() { atomic_clear_bits(JVM_ACC_NOT_C1_COMPILABLE); } + void clear_not_c2_compilable() { atomic_clear_bits(JVM_ACC_NOT_C2_COMPILABLE); } + void clear_not_c2_osr_compilable() { atomic_clear_bits(JVM_ACC_NOT_C2_OSR_COMPILABLE); } // Klass* flags void set_has_vanilla_constructor() { atomic_set_bits(JVM_ACC_HAS_VANILLA_CONSTRUCTOR); } void set_has_finalizer() { atomic_set_bits(JVM_ACC_HAS_FINALIZER); } diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/utilities/bitMap.cpp --- a/src/share/vm/utilities/bitMap.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/utilities/bitMap.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -516,6 +516,10 @@ return sum; } +void BitMap::print_on_error(outputStream* st, const char* prefix) const { + st->print_cr("%s[" PTR_FORMAT ", " PTR_FORMAT ")", + prefix, map(), (char*)map() + (size() >> LogBitsPerByte)); +} #ifndef PRODUCT diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/utilities/bitMap.hpp --- a/src/share/vm/utilities/bitMap.hpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/utilities/bitMap.hpp Sat Apr 13 00:33:37 2013 +0200 @@ -262,6 +262,7 @@ bool is_full() const; bool is_empty() const; + void print_on_error(outputStream* st, const char* prefix) const; #ifndef PRODUCT public: diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/utilities/debug.cpp --- a/src/share/vm/utilities/debug.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/utilities/debug.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -608,18 +608,6 @@ return CodeCache::find_nmethod((address)addr); } -static address same_page(address x, address y) { - intptr_t page_bits = -os::vm_page_size(); - if ((intptr_t(x) & page_bits) == (intptr_t(y) & page_bits)) { - return x; - } else if (x > y) { - return (address)(intptr_t(y) | ~page_bits) + 1; - } else { - return (address)(intptr_t(y) & page_bits); - } -} - - // Another interface that isn't ambiguous in dbx. // Can we someday rename the other find to hsfind? extern "C" void hsfind(intptr_t x) { diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/utilities/globalDefinitions.cpp --- a/src/share/vm/utilities/globalDefinitions.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/utilities/globalDefinitions.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -355,3 +355,33 @@ return size_t(result); } + +#ifndef PRODUCT + +void GlobalDefinitions::test_globals() { + intptr_t page_sizes[] = { os::vm_page_size(), 4096, 8192, 65536, 2*1024*1024 }; + const int num_page_sizes = sizeof(page_sizes) / sizeof(page_sizes[0]); + + for (int i = 0; i < num_page_sizes; i++) { + intptr_t page_size = page_sizes[i]; + + address a_page = (address)(10*page_size); + + // Check that address within page is returned as is + assert(clamp_address_in_page(a_page, a_page, page_size) == a_page, "incorrect"); + assert(clamp_address_in_page(a_page + 128, a_page, page_size) == a_page + 128, "incorrect"); + assert(clamp_address_in_page(a_page + page_size - 1, a_page, page_size) == a_page + page_size - 1, "incorrect"); + + // Check that address above page returns start of next page + assert(clamp_address_in_page(a_page + page_size, a_page, page_size) == a_page + page_size, "incorrect"); + assert(clamp_address_in_page(a_page + page_size + 1, a_page, page_size) == a_page + page_size, "incorrect"); + assert(clamp_address_in_page(a_page + page_size*5 + 1, a_page, page_size) == a_page + page_size, "incorrect"); + + // Check that address below page returns start of page + assert(clamp_address_in_page(a_page - 1, a_page, page_size) == a_page, "incorrect"); + assert(clamp_address_in_page(a_page - 2*page_size - 1, a_page, page_size) == a_page, "incorrect"); + assert(clamp_address_in_page(a_page - 5*page_size - 1, a_page, page_size) == a_page, "incorrect"); + } +} + +#endif // PRODUCT diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/utilities/globalDefinitions.hpp --- a/src/share/vm/utilities/globalDefinitions.hpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/utilities/globalDefinitions.hpp Sat Apr 13 00:33:37 2013 +0200 @@ -419,6 +419,24 @@ return align_size_up(offset, HeapWordsPerLong); } +// Clamp an address to be within a specific page +// 1. If addr is on the page it is returned as is +// 2. If addr is above the page_address the start of the *next* page will be returned +// 3. Otherwise, if addr is below the page_address the start of the page will be returned +inline address clamp_address_in_page(address addr, address page_address, intptr_t page_size) { + if (align_size_down(intptr_t(addr), page_size) == align_size_down(intptr_t(page_address), page_size)) { + // address is in the specified page, just return it as is + return addr; + } else if (addr > page_address) { + // address is above specified page, return start of next page + return (address)align_size_down(intptr_t(page_address), page_size) + page_size; + } else { + // address is below specified page, return start of page + return (address)align_size_down(intptr_t(page_address), page_size); + } +} + + // The expected size in bytes of a cache line, used to pad data structures. #define DEFAULT_CACHE_LINE_SIZE 64 @@ -827,6 +845,10 @@ return comp_level == CompLevel_highest_tier; } +inline bool is_compile(int comp_level) { + return is_c1_compile(comp_level) || is_c2_compile(comp_level); +} + //---------------------------------------------------------------------------------------------------- // 'Forward' declarations of frequently used classes // (in order to reduce interface dependencies & reduce @@ -1296,4 +1318,15 @@ return *(void**)addr; } + +#ifndef PRODUCT + +// For unit testing only +class GlobalDefinitions { +public: + static void test_globals(); +}; + +#endif // PRODUCT + #endif // SHARE_VM_UTILITIES_GLOBALDEFINITIONS_HPP diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/utilities/taskqueue.hpp --- a/src/share/vm/utilities/taskqueue.hpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/utilities/taskqueue.hpp Sat Apr 13 00:33:37 2013 +0200 @@ -253,6 +253,7 @@ template class GenericTaskQueue: public TaskQueueSuper { + ArrayAllocator _array_allocator; protected: typedef typename TaskQueueSuper::Age Age; typedef typename TaskQueueSuper::idx_t idx_t; @@ -314,7 +315,7 @@ template void GenericTaskQueue::initialize() { - _elems = NEW_C_HEAP_ARRAY(E, N, F); + _elems = _array_allocator.allocate(N); } template diff -r 2cae919cd3af -r 0c8ec85fa013 src/share/vm/utilities/vmError.cpp --- a/src/share/vm/utilities/vmError.cpp Fri Apr 12 23:29:45 2013 +0200 +++ b/src/share/vm/utilities/vmError.cpp Sat Apr 13 00:33:37 2013 +0200 @@ -685,13 +685,7 @@ STEP(190, "(printing heap information)" ) if (_verbose && Universe::is_fully_initialized()) { - // Print heap information before vm abort. As we'd like as much - // information as possible in the report we ask for the - // extended (i.e., more detailed) version. - Universe::print_on(st, true /* extended */); - st->cr(); - - Universe::heap()->barrier_set()->print_on(st); + Universe::heap()->print_on_error(st); st->cr(); st->print_cr("Polling page: " INTPTR_FORMAT, os::get_polling_page()); diff -r 2cae919cd3af -r 0c8ec85fa013 test/compiler/6863420/Test.java --- a/test/compiler/6863420/Test.java Fri Apr 12 23:29:45 2013 +0200 +++ b/test/compiler/6863420/Test.java Sat Apr 13 00:33:37 2013 +0200 @@ -27,17 +27,35 @@ * @bug 6863420 * @summary os::javaTimeNanos() go backward on Solaris x86 * - * @run main/othervm Test + * Notice the internal timeout in timeout thread Test.TOT. + * @run main/othervm/timeout=300 Test */ public class Test { + + static final int INTERNAL_TIMEOUT=240; + static class TOT extends Thread { + public void run() { + try { + Thread.sleep(INTERNAL_TIMEOUT*1000); + } catch (InterruptedException ex) { + } + done = true; + } + } + static long value = 0; static boolean got_backward_time = false; + static volatile boolean done = false; public static void main(String args[]) { final int count = 100000; - for (int numThreads = 1; numThreads <= 32; numThreads++) { + TOT tot = new TOT(); + tot.setDaemon(true); + tot.start(); + + for (int numThreads = 1; !done && numThreads <= 32; numThreads++) { final int numRuns = 1; for (int t=1; t <= numRuns; t++) { final int curRun = t; @@ -48,7 +66,7 @@ Runnable thread = new Runnable() { public void run() { - for (long l = 0; l < 100000; l++) { + for (long l = 0; !done && l < 100000; l++) { final long start = System.nanoTime(); if (value == 12345678) { System.out.println("Wow!"); diff -r 2cae919cd3af -r 0c8ec85fa013 test/compiler/8011706/Test8011706.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/8011706/Test8011706.java Sat Apr 13 00:33:37 2013 +0200 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2013, 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. + */ + +/* + * @test + * @bug 8011706 + * @summary loop invariant code motion may move load before store to the same field + * @run main/othervm -XX:-UseOnStackReplacement -XX:-BackgroundCompilation Test8011706 + * + */ + +public class Test8011706 { + int[] array; + + void m(boolean test, int[] array1, int[] array2) { + int i = 0; + if (test) { + array = array1; + } else { + array = array2; + } + + while(true) { + int v = array[i]; + i++; + if (i >= 10) return; + } + } + + static public void main(String[] args) { + int[] new_array = new int[10]; + Test8011706 ti = new Test8011706(); + boolean failed = false; + try { + for (int i = 0; i < 10000; i++) { + ti.array = null; + ti.m(true, new_array, new_array); + } + } catch(NullPointerException ex) { + throw new RuntimeException("TEST FAILED", ex); + } + System.out.println("TEST PASSED"); + } + +} diff -r 2cae919cd3af -r 0c8ec85fa013 test/compiler/whitebox/ClearMethodStateTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/whitebox/ClearMethodStateTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2013, 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. + */ + +/* + * @test ClearMethodStateTest + * @library /testlibrary /testlibrary/whitebox + * @build ClearMethodStateTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ClearMethodStateTest + * @author igor.ignatyev@oracle.com + */ +public class ClearMethodStateTest extends CompilerWhiteBoxTest { + public static void main(String[] args) throws Exception { + // to prevent inlining #method into #compile() and #test() + WHITE_BOX.testSetDontInlineMethod(METHOD, true); + new ClearMethodStateTest().runTest(); + } + + protected void test() throws Exception { + checkNotCompiled(METHOD); + compile(); + checkCompiled(METHOD); + WHITE_BOX.clearMethodState(METHOD); + WHITE_BOX.deoptimizeMethod(METHOD); + checkNotCompiled(METHOD); + + + if (!TIERED_COMPILATION) { + WHITE_BOX.clearMethodState(METHOD); + compile(COMPILE_THRESHOLD); + checkCompiled(METHOD); + + WHITE_BOX.deoptimizeMethod(METHOD); + checkNotCompiled(METHOD); + WHITE_BOX.clearMethodState(METHOD); + + if (COMPILE_THRESHOLD > 1) { + compile(COMPILE_THRESHOLD - 1); + checkNotCompiled(METHOD); + } else { + System.err.println("Warning: 'CompileThreshold' <= 1"); + } + + method(); + checkCompiled(METHOD); + } else { + System.err.println( + "Warning: part of test is not applicable in Tiered"); + } + } +} diff -r 2cae919cd3af -r 0c8ec85fa013 test/compiler/whitebox/CompilerWhiteBoxTest.java --- a/test/compiler/whitebox/CompilerWhiteBoxTest.java Fri Apr 12 23:29:45 2013 +0200 +++ b/test/compiler/whitebox/CompilerWhiteBoxTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -37,6 +37,8 @@ = Integer.parseInt(getVMOption("CompileThreshold", "10000")); protected static final boolean BACKGROUND_COMPILATION = Boolean.valueOf(getVMOption("BackgroundCompilation", "true")); + protected static final boolean TIERED_COMPILATION + = Boolean.valueOf(getVMOption("TieredCompilation", "false")); protected static Method getMethod(String name) { try { @@ -81,6 +83,9 @@ } protected static void checkNotCompiled(Method method) { + if (WHITE_BOX.isMethodQueuedForCompilation(method)) { + throw new RuntimeException(method + " must not be in queue"); + } if (WHITE_BOX.isMethodCompiled(method)) { throw new RuntimeException(method + " must be not compiled"); } @@ -139,8 +144,11 @@ protected abstract void test() throws Exception; protected final int compile() { + return compile(Math.max(COMPILE_THRESHOLD, 150000)); + } + + protected final int compile(int count) { int result = 0; - int count = Math.max(COMPILE_THRESHOLD, 150000); for (int i = 0; i < count; ++i) { result += method(); } diff -r 2cae919cd3af -r 0c8ec85fa013 test/compiler/whitebox/DeoptimizeAllTest.java --- a/test/compiler/whitebox/DeoptimizeAllTest.java Fri Apr 12 23:29:45 2013 +0200 +++ b/test/compiler/whitebox/DeoptimizeAllTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -33,7 +33,7 @@ public static void main(String[] args) throws Exception { // to prevent inlining #method into #compile() - WHITE_BOX.setDontInlineMethod(METHOD, true); + WHITE_BOX.testSetDontInlineMethod(METHOD, true); new DeoptimizeAllTest().runTest(); } diff -r 2cae919cd3af -r 0c8ec85fa013 test/compiler/whitebox/DeoptimizeMethodTest.java --- a/test/compiler/whitebox/DeoptimizeMethodTest.java Fri Apr 12 23:29:45 2013 +0200 +++ b/test/compiler/whitebox/DeoptimizeMethodTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -33,7 +33,7 @@ public static void main(String[] args) throws Exception { // to prevent inlining #method into #compile() - WHITE_BOX.setDontInlineMethod(METHOD, true); + WHITE_BOX.testSetDontInlineMethod(METHOD, true); new DeoptimizeMethodTest().runTest(); } diff -r 2cae919cd3af -r 0c8ec85fa013 test/compiler/whitebox/EnqueueMethodForCompilationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/whitebox/EnqueueMethodForCompilationTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2013, 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. + */ + +/* + * @test EnqueueMethodForCompilationTest + * @library /testlibrary /testlibrary/whitebox + * @build EnqueueMethodForCompilationTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI EnqueueMethodForCompilationTest + * @author igor.ignatyev@oracle.com + */ +public class EnqueueMethodForCompilationTest extends CompilerWhiteBoxTest { + public static void main(String[] args) throws Exception { + // to prevent inlining #method into #compile() + WHITE_BOX.testSetDontInlineMethod(METHOD, true); + new EnqueueMethodForCompilationTest().runTest(); + } + + protected void test() throws Exception { + checkNotCompiled(METHOD); + + WHITE_BOX.enqueueMethodForCompilation(METHOD, 0); + if (WHITE_BOX.isMethodCompilable(METHOD, 0)) { + throw new RuntimeException(METHOD + " is compilable at level 0"); + } + checkNotCompiled(METHOD); + + WHITE_BOX.enqueueMethodForCompilation(METHOD, -1); + checkNotCompiled(METHOD); + + WHITE_BOX.enqueueMethodForCompilation(METHOD, 5); + if (!WHITE_BOX.isMethodCompilable(METHOD, 5)) { + checkNotCompiled(METHOD); + compile(); + checkCompiled(METHOD); + } else { + checkCompiled(METHOD); + } + + int compLevel = WHITE_BOX.getMethodCompilationLevel(METHOD); + WHITE_BOX.deoptimizeMethod(METHOD); + checkNotCompiled(METHOD); + + WHITE_BOX.enqueueMethodForCompilation(METHOD, compLevel); + checkCompiled(METHOD); + WHITE_BOX.deoptimizeMethod(METHOD); + checkNotCompiled(METHOD); + + compile(); + checkCompiled(METHOD); + WHITE_BOX.deoptimizeMethod(METHOD); + checkNotCompiled(METHOD); + } +} diff -r 2cae919cd3af -r 0c8ec85fa013 test/compiler/whitebox/IsMethodCompilableTest.java --- a/test/compiler/whitebox/IsMethodCompilableTest.java Fri Apr 12 23:29:45 2013 +0200 +++ b/test/compiler/whitebox/IsMethodCompilableTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -45,7 +45,7 @@ public static void main(String[] args) throws Exception { // to prevent inlining #method into #compile() - WHITE_BOX.setDontInlineMethod(METHOD, true); + WHITE_BOX.testSetDontInlineMethod(METHOD, true); new IsMethodCompilableTest().runTest(); } @@ -60,26 +60,47 @@ "Warning: test is not applicable if PerMethodRecompilationCutoff == Inf"); return; } - boolean madeNotCompilable = false; + + // deoptimze 'PerMethodRecompilationCutoff' times and clear state + for (long i = 0L, n = PER_METHOD_RECOMPILATION_CUTOFF - 1; i < n; ++i) { + compileAndDeoptimaze(); + } + if (!WHITE_BOX.isMethodCompilable(METHOD)) { + throw new RuntimeException(METHOD + " is not compilable after " + + (PER_METHOD_RECOMPILATION_CUTOFF - 1) + " iterations"); + } + WHITE_BOX.clearMethodState(METHOD); - for (long i = 0; i < PER_METHOD_RECOMPILATION_CUTOFF; ++i) { - compile(); - waitBackgroundCompilation(METHOD); - WHITE_BOX.deoptimizeMethod(METHOD); - if (!WHITE_BOX.isMethodCompilable(METHOD)) { - madeNotCompilable = true; - break; - } + // deoptimze 'PerMethodRecompilationCutoff' + 1 times + long i; + for (i = 0L; i < PER_METHOD_RECOMPILATION_CUTOFF + && WHITE_BOX.isMethodCompilable(METHOD); ++i) { + compileAndDeoptimaze(); } - if (!madeNotCompilable) { + if (i != PER_METHOD_RECOMPILATION_CUTOFF) { + throw new RuntimeException(METHOD + " is not compilable after " + + i + " iterations, but must only after " + + PER_METHOD_RECOMPILATION_CUTOFF); + } + if (WHITE_BOX.isMethodCompilable(METHOD)) { throw new RuntimeException(METHOD + " is still compilable after " + PER_METHOD_RECOMPILATION_CUTOFF + " iterations"); } compile(); - if (WHITE_BOX.isMethodCompiled(METHOD)) { - printInfo(METHOD); - throw new RuntimeException( - METHOD + " is not compilable but compiled"); + checkNotCompiled(METHOD); + + WHITE_BOX.clearMethodState(METHOD); + if (!WHITE_BOX.isMethodCompilable(METHOD)) { + throw new RuntimeException(METHOD + + " is compilable after clearMethodState()"); } + compile(); + checkCompiled(METHOD); + } + + private void compileAndDeoptimaze() throws Exception { + compile(); + waitBackgroundCompilation(METHOD); + WHITE_BOX.deoptimizeMethod(METHOD); } } diff -r 2cae919cd3af -r 0c8ec85fa013 test/compiler/whitebox/MakeMethodNotCompilableTest.java --- a/test/compiler/whitebox/MakeMethodNotCompilableTest.java Fri Apr 12 23:29:45 2013 +0200 +++ b/test/compiler/whitebox/MakeMethodNotCompilableTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -33,7 +33,7 @@ public static void main(String[] args) throws Exception { // to prevent inlining #method into #compile() - WHITE_BOX.setDontInlineMethod(METHOD, true); + WHITE_BOX.testSetDontInlineMethod(METHOD, true); new MakeMethodNotCompilableTest().runTest(); } @@ -46,9 +46,6 @@ throw new RuntimeException(METHOD + " must be not compilable"); } compile(); - if (WHITE_BOX.isMethodQueuedForCompilation(METHOD)) { - throw new RuntimeException(METHOD + " must not be in queue"); - } checkNotCompiled(METHOD); if (WHITE_BOX.isMethodCompilable(METHOD)) { throw new RuntimeException(METHOD + " must be not compilable"); diff -r 2cae919cd3af -r 0c8ec85fa013 test/compiler/whitebox/SetDontInlineMethodTest.java --- a/test/compiler/whitebox/SetDontInlineMethodTest.java Fri Apr 12 23:29:45 2013 +0200 +++ b/test/compiler/whitebox/SetDontInlineMethodTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -36,23 +36,23 @@ } protected void test() throws Exception { - if (WHITE_BOX.setDontInlineMethod(METHOD, true)) { + if (WHITE_BOX.testSetDontInlineMethod(METHOD, true)) { throw new RuntimeException("on start " + METHOD + " must be inlineable"); } - if (!WHITE_BOX.setDontInlineMethod(METHOD, true)) { + if (!WHITE_BOX.testSetDontInlineMethod(METHOD, true)) { throw new RuntimeException("after first change to true " + METHOD + " must be not inlineable"); } - if (!WHITE_BOX.setDontInlineMethod(METHOD, false)) { + if (!WHITE_BOX.testSetDontInlineMethod(METHOD, false)) { throw new RuntimeException("after second change to true " + METHOD + " must be still not inlineable"); } - if (WHITE_BOX.setDontInlineMethod(METHOD, false)) { + if (WHITE_BOX.testSetDontInlineMethod(METHOD, false)) { throw new RuntimeException("after first change to false" + METHOD + " must be inlineable"); } - if (WHITE_BOX.setDontInlineMethod(METHOD, false)) { + if (WHITE_BOX.testSetDontInlineMethod(METHOD, false)) { throw new RuntimeException("after second change to false " + METHOD + " must be inlineable"); } diff -r 2cae919cd3af -r 0c8ec85fa013 test/compiler/whitebox/SetForceInlineMethodTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/whitebox/SetForceInlineMethodTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2013, 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. + */ + +/* + * @test SetForceInlineMethodTest + * @library /testlibrary /testlibrary/whitebox + * @build SetForceInlineMethodTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI SetForceInlineMethodTest + * @author igor.ignatyev@oracle.com + */ +public class SetForceInlineMethodTest extends CompilerWhiteBoxTest { + + public static void main(String[] args) throws Exception { + new SetForceInlineMethodTest().runTest(); + } + + protected void test() throws Exception { + if (WHITE_BOX.testSetForceInlineMethod(METHOD, true)) { + throw new RuntimeException("on start " + METHOD + + " must be not force inlineable"); + } + if (!WHITE_BOX.testSetForceInlineMethod(METHOD, true)) { + throw new RuntimeException("after first change to true " + METHOD + + " must be force inlineable"); + } + if (!WHITE_BOX.testSetForceInlineMethod(METHOD, false)) { + throw new RuntimeException("after second change to true " + METHOD + + " must be still force inlineable"); + } + if (WHITE_BOX.testSetForceInlineMethod(METHOD, false)) { + throw new RuntimeException("after first change to false" + METHOD + + " must be not force inlineable"); + } + if (WHITE_BOX.testSetForceInlineMethod(METHOD, false)) { + throw new RuntimeException("after second change to false " + METHOD + + " must be not force inlineable"); + } + } +} diff -r 2cae919cd3af -r 0c8ec85fa013 test/gc/6941923/Test6941923.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/6941923/Test6941923.java Sat Apr 13 00:33:37 2013 +0200 @@ -0,0 +1,121 @@ +/* + * 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. + */ + +/* + * @test Test6941923.java + * @bug 6941923 + * @summary test flags for gc log rotation + * @library /testlibrary + * @run main/othervm/timeout=600 Test6941923 + * + */ +import com.oracle.java.testlibrary.*; +import java.io.File; +import java.io.FilenameFilter; +import java.util.ArrayList; +import java.util.Arrays; + +class GCLoggingGenerator { + + public static void main(String[] args) throws Exception { + + long sizeOfLog = Long.parseLong(args[0]); + long lines = sizeOfLog / 80; + // full.GC generates ad least 1-line which is not shorter then 80 chars + // for some GC 2 shorter lines are generated + for (long i = 0; i < lines; i++) { + System.gc(); + } + } +} + +public class Test6941923 { + + static final File currentDirectory = new File("."); + static final String logFileName = "test.log"; + static final int logFileSizeK = 16; + static FilenameFilter logFilter = new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + return name.startsWith(logFileName); + } + }; + + public static void cleanLogs() { + for (File log : currentDirectory.listFiles(logFilter)) { + if (!log.delete()) { + throw new Error("Unable to delete " + log.getAbsolutePath()); + } + } + } + + public static void runTest(int numberOfFiles) throws Exception { + + ArrayList args = new ArrayList(); + String[] logOpts = new String[]{ + "-cp", System.getProperty("java.class.path"), + "-Xloggc:" + logFileName, + "-XX:-DisableExplicitGC", // to sure that System.gc() works + "-XX:+PrintGC", "-XX:+PrintGCDetails", "-XX:+UseGCLogFileRotation", + "-XX:NumberOfGCLogFiles=" + numberOfFiles, + "-XX:GCLogFileSize=" + logFileSizeK + "K", "-Xmx128M"}; + // System.getProperty("test.java.opts") is '' if no options is set + // need to skip such empty + String[] externalVMopts = System.getProperty("test.java.opts").length() == 0 + ? new String[0] + : System.getProperty("test.java.opts").split(" "); + args.addAll(Arrays.asList(externalVMopts)); + args.addAll(Arrays.asList(logOpts)); + args.add(GCLoggingGenerator.class.getName()); + args.add(String.valueOf(numberOfFiles * logFileSizeK * 1024)); + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args.toArray(new String[0])); + pb.redirectErrorStream(true); + pb.redirectOutput(new File(GCLoggingGenerator.class.getName() + ".log")); + Process process = pb.start(); + int result = process.waitFor(); + if (result != 0) { + throw new Error("Unexpected exit code = " + result); + } + File[] logs = currentDirectory.listFiles(logFilter); + int smallFilesNumber = 0; + for (File log : logs) { + if (log.length() < logFileSizeK * 1024) { + smallFilesNumber++; + } + } + if (logs.length != numberOfFiles) { + throw new Error("There are only " + logs.length + " logs instead " + numberOfFiles); + } + if (smallFilesNumber > 1) { + throw new Error("There should maximum one log with size < " + logFileSizeK + "K"); + } + } + + public static void main(String[] args) throws Exception { + cleanLogs(); + runTest(1); + cleanLogs(); + runTest(3); + cleanLogs(); + } +} diff -r 2cae919cd3af -r 0c8ec85fa013 test/gc/6941923/test6941923.sh --- a/test/gc/6941923/test6941923.sh Fri Apr 12 23:29:45 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,166 +0,0 @@ -## -## @test @(#)test6941923.sh -## @bug 6941923 -## @summary test new added flags for gc log rotation -## @author yqi -## @run shell test6941923.sh -## -## some tests require path to find test source dir -if [ "${TESTSRC}" = "" ] -then - TESTSRC=${PWD} - echo "TESTSRC not set. Using "${TESTSRC}" as default" -fi -echo "TESTSRC=${TESTSRC}" -## Adding common setup Variables for running shell tests. -. ${TESTSRC}/../../test_env.sh - -## skip on windows -OS=`uname -s` -case "$OS" in - Windows_* | CYGWIN_* ) - echo "Test skipped for Windows" - exit 0 - ;; -esac - -# create a small test case -testname="Test" -if [ -e ${testname}.java ]; then - rm -rf ${testname}.* -fi - -cat >> ${testname}.java << __EOF__ -import java.util.Vector; - -public class Test implements Runnable -{ - private boolean _should_stop = false; - - public static void main(String[] args) throws Exception { - - long limit = Long.parseLong(args[0]) * 60L * 1000L; // minutes - Test t = new Test(); - t.set_stop(false); - Thread thr = new Thread(t); - thr.start(); - - long time1 = System.currentTimeMillis(); - long time2 = System.currentTimeMillis(); - while (time2 - time1 < limit) { - try { - Thread.sleep(2000); // 2 seconds - } - catch(Exception e) {} - time2 = System.currentTimeMillis(); - System.out.print("\r... " + (time2 - time1)/1000 + " seconds"); - } - System.out.println(); - t.set_stop(true); - } - public void set_stop(boolean value) { _should_stop = value; } - public void run() { - int cap = 20000; - int fix_size = 2048; - int loop = 0; - Vector< byte[] > v = new Vector< byte[] >(cap); - while(!_should_stop) { - byte[] g = new byte[fix_size]; - v.add(g); - loop++; - if (loop > cap) { - v = null; - cap *= 2; - if (cap > 80000) cap = 80000; - v = new Vector< byte[] >(cap); - } - } - } -} -__EOF__ - -msgsuccess="succeeded" -msgfail="failed" -gclogsize="16K" -filesize=$((16*1024)) -${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} ${testname}.java > $NULL 2>&1 - -if [ $? != 0 ]; then - echo "${COMPILEJAVA}/bin/javac ${testname}.java $fail" - exit -1 -fi - -# test for 2 minutes, it will complete circulation of gc log rotation -tts=2 -logfile="test.log" -hotspotlog="hotspot.log" - -if [ -e $logfile ]; then - rm -rf $logfile -fi - -#also delete $hotspotlog if it exists -if [ -f $hotspotlog ]; then - rm -rf $hotspotlog -fi - -options="-Xloggc:$logfile -XX:+UseConcMarkSweepGC -XX:+PrintGC -XX:+PrintGCDetails -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=1 -XX:GCLogFileSize=$gclogsize" -echo "Test gc log rotation in same file, wait for $tts minutes ...." -${TESTJAVA}/bin/java $options $testname $tts -if [ $? != 0 ]; then - echo "$msgfail" - exit -1 -fi - -# rotation file will be $logfile.0 -if [ -f $logfile.0 ]; then - outfilesize=`ls -l $logfile.0 | awk '{print $5 }'` - if [ $((outfilesize)) -ge $((filesize)) ]; then - echo $msgsuccess - else - echo $msgfail - fi -else - echo $msgfail - exit -1 -fi - -# delete log file -rm -rf $logfile.0 -if [ -f $hotspotlog ]; then - rm -rf $hotspotlog -fi - -#multiple log files -numoffiles=3 -options="-Xloggc:$logfile -XX:+UseConcMarkSweepGC -XX:+PrintGC -XX:+PrintGCDetails -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=$numoffiles -XX:GCLogFileSize=$gclogsize" -echo "Test gc log rotation in $numoffiles files, wait for $tts minutes ...." -${TESTJAVA}/bin/java $options $testname $tts -if [ $? != 0 ]; then - echo "$msgfail" - exit -1 -fi - -atleast=0 # at least size of numoffile-1 files >= $gclogsize -tk=0 -while [ $(($tk)) -lt $(($numoffiles)) ] -do - if [ -f $logfile.$tk ]; then - outfilesize=`ls -l $logfile.$tk | awk '{ print $5 }'` - if [ $(($outfilesize)) -ge $(($filesize)) ]; then - atleast=$((atleast+1)) - fi - fi - tk=$((tk+1)) -done - -rm -rf $logfile.* -rm -rf $testname.* -rm -rf $hotspotlog - -if [ $(($atleast)) -ge $(($numoffiles-1)) ]; then - echo $msgsuccess -else - echo $msgfail - exit -1 -fi diff -r 2cae919cd3af -r 0c8ec85fa013 test/gc/TestVerifyBeforeGCDuringStartup.java --- a/test/gc/TestVerifyBeforeGCDuringStartup.java Fri Apr 12 23:29:45 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2013, 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. - */ - -/* @test TestVerifyBeforeGCDuringStartup.java - * @key gc - * @bug 8010463 - * @summary Simple test run with -XX:+VerifyBeforeGC -XX:-UseTLAB to verify 8010463 - * @library /testlibrary - */ - -import com.oracle.java.testlibrary.OutputAnalyzer; -import com.oracle.java.testlibrary.ProcessTools; - -public class TestVerifyBeforeGCDuringStartup { - public static void main(String args[]) throws Exception { - ProcessBuilder pb = - ProcessTools.createJavaProcessBuilder(System.getProperty("test.vm.opts"), - "-XX:-UseTLAB", - "-XX:+UnlockDiagnosticVMOptions", - "-XX:+VerifyBeforeGC", "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); - output.shouldContain("[Verifying"); - output.shouldHaveExitValue(0); - } -} diff -r 2cae919cd3af -r 0c8ec85fa013 test/gc/TestVerifyDuringStartup.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/TestVerifyDuringStartup.java Sat Apr 13 00:33:37 2013 +0200 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2013, 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. + */ + +/* @test TestVerifyDuringStartup.java + * @key gc + * @bug 8010463 + * @summary Simple test run with -XX:+VerifyDuringStartup -XX:-UseTLAB to verify 8010463 + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.ProcessTools; + +public class TestVerifyDuringStartup { + public static void main(String args[]) throws Exception { + ProcessBuilder pb = + ProcessTools.createJavaProcessBuilder(System.getProperty("test.vm.opts"), + "-XX:-UseTLAB", + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+VerifyDuringStartup", "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("[Verifying"); + output.shouldHaveExitValue(0); + } +} diff -r 2cae919cd3af -r 0c8ec85fa013 test/gc/metaspace/G1AddMetaspaceDependency.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/metaspace/G1AddMetaspaceDependency.java Sat Apr 13 00:33:37 2013 +0200 @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2013, 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. + */ + +/* + * @test G1AddMetaspaceDependency + * @bug 8010196 + * @summary Checks that we don't get locking problems when adding metaspace dependencies with the G1 update buffer monitor + * @run main/othervm -XX:+UseG1GC -XX:G1UpdateBufferSize=1 G1AddMetaspaceDependency + */ + +import java.io.InputStream; + +public class G1AddMetaspaceDependency { + + static byte[] getClassBytes(String name) { + byte[] b = null; + try (InputStream is = ClassLoader.getSystemResourceAsStream(name)) { + byte[] tmp = new byte[is.available()]; + is.read(tmp); + b = tmp; + } finally { + if (b == null) { + throw new RuntimeException("Unable to load class file"); + } + return b; + } + } + + static final String a_name = G1AddMetaspaceDependency.class.getName() + "$A"; + static final String b_name = G1AddMetaspaceDependency.class.getName() + "$B"; + + public static void main(String... args) throws Exception { + final byte[] a_bytes = getClassBytes(a_name + ".class"); + final byte[] b_bytes = getClassBytes(b_name + ".class"); + + for (int i = 0; i < 1000; i += 1) { + runTest(a_bytes, b_bytes); + } + } + + static class Loader extends ClassLoader { + private final String myClass; + private final byte[] myBytes; + private final String friendClass; + private final ClassLoader friendLoader; + + Loader(String myClass, byte[] myBytes, + String friendClass, ClassLoader friendLoader) { + this.myClass = myClass; + this.myBytes = myBytes; + this.friendClass = friendClass; + this.friendLoader = friendLoader; + } + + Loader(String myClass, byte[] myBytes) { + this(myClass, myBytes, null, null); + } + + @Override + public Class loadClass(String name) throws ClassNotFoundException { + Class c = findLoadedClass(name); + if (c != null) { + return c; + } + + if (name.equals(friendClass)) { + return friendLoader.loadClass(name); + } + + if (name.equals(myClass)) { + c = defineClass(name, myBytes, 0, myBytes.length); + resolveClass(c); + return c; + } + + return findSystemClass(name); + } + + } + + private static void runTest(final byte[] a_bytes, final byte[] b_bytes) throws Exception { + Loader a_loader = new Loader(a_name, a_bytes); + Loader b_loader = new Loader(b_name, b_bytes, a_name, a_loader); + Loader c_loader = new Loader(b_name, b_bytes, a_name, a_loader); + Loader d_loader = new Loader(b_name, b_bytes, a_name, a_loader); + Loader e_loader = new Loader(b_name, b_bytes, a_name, a_loader); + Loader f_loader = new Loader(b_name, b_bytes, a_name, a_loader); + Loader g_loader = new Loader(b_name, b_bytes, a_name, a_loader); + + byte[] b = new byte[20 * 2 << 20]; + Class c; + c = b_loader.loadClass(b_name); + c = c_loader.loadClass(b_name); + c = d_loader.loadClass(b_name); + c = e_loader.loadClass(b_name); + c = f_loader.loadClass(b_name); + c = g_loader.loadClass(b_name); + } + public class A { + } + class B extends A { + } +} diff -r 2cae919cd3af -r 0c8ec85fa013 test/runtime/NMT/AllocTestType.java --- a/test/runtime/NMT/AllocTestType.java Fri Apr 12 23:29:45 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2013, 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. - */ - -/* - * @test - * @summary Test consistency of NMT by leaking a few select allocations of the Test type and then verify visibility with jcmd - * @key nmt jcmd - * @library /testlibrary /testlibrary/whitebox - * @build AllocTestType - * @run main ClassFileInstaller sun.hotspot.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail AllocTestType - */ - -import com.oracle.java.testlibrary.*; -import sun.hotspot.WhiteBox; - -public class AllocTestType { - - public static void main(String args[]) throws Exception { - OutputAnalyzer output; - - // Grab my own PID - String pid = Integer.toString(ProcessTools.getProcessId()); - ProcessBuilder pb = new ProcessBuilder(); - - // Use WB API to alloc with the mtTest type - if (!WhiteBox.getWhiteBox().NMTAllocTest()) { - throw new Exception("Call to WB API NMTAllocTest() failed"); - } - - // Use WB API to ensure that all data has been merged before we continue - if (!WhiteBox.getWhiteBox().NMTWaitForDataMerge()) { - throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); - } - - // Run 'jcmd VM.native_memory summary' - pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary"}); - output = new OutputAnalyzer(pb.start()); - output.shouldContain("Test (reserved=512KB, committed=512KB)"); - - // Free the memory allocated by NMTAllocTest - if (!WhiteBox.getWhiteBox().NMTFreeTestMemory()) { - throw new Exception("Call to WB API NMTFreeTestMemory() failed"); - } - - // Use WB API to ensure that all data has been merged before we continue - if (!WhiteBox.getWhiteBox().NMTWaitForDataMerge()) { - throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); - } - output = new OutputAnalyzer(pb.start()); - output.shouldNotContain("Test (reserved="); - } -} diff -r 2cae919cd3af -r 0c8ec85fa013 test/runtime/NMT/MallocTestType.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/NMT/MallocTestType.java Sat Apr 13 00:33:37 2013 +0200 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2013, 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. + */ + +/* + * @test + * @summary Test consistency of NMT by leaking a few select allocations of the Test type and then verify visibility with jcmd + * @key nmt jcmd + * @library /testlibrary /testlibrary/whitebox + * @build MallocTestType + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail MallocTestType + */ + +import com.oracle.java.testlibrary.*; +import sun.hotspot.WhiteBox; + +public class MallocTestType { + + public static void main(String args[]) throws Exception { + OutputAnalyzer output; + WhiteBox wb = WhiteBox.getWhiteBox(); + + // Grab my own PID + String pid = Integer.toString(ProcessTools.getProcessId()); + ProcessBuilder pb = new ProcessBuilder(); + + // Use WB API to alloc and free with the mtTest type + long memAlloc3 = wb.NMTMalloc(128 * 1024); + long memAlloc2 = wb.NMTMalloc(256 * 1024); + wb.NMTFree(memAlloc3); + long memAlloc1 = wb.NMTMalloc(512 * 1024); + wb.NMTFree(memAlloc2); + + // Use WB API to ensure that all data has been merged before we continue + if (!wb.NMTWaitForDataMerge()) { + throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); + } + + // Run 'jcmd VM.native_memory summary' + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=512KB, committed=512KB)"); + + // Free the memory allocated by NMTAllocTest + wb.NMTFree(memAlloc1); + + // Use WB API to ensure that all data has been merged before we continue + if (!wb.NMTWaitForDataMerge()) { + throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); + } + output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("Test (reserved="); + } +} diff -r 2cae919cd3af -r 0c8ec85fa013 test/runtime/NMT/ThreadedMallocTestType.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/NMT/ThreadedMallocTestType.java Sat Apr 13 00:33:37 2013 +0200 @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2013, 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. + */ + +/* + * @test + * @key nmt jcmd + * @library /testlibrary /testlibrary/whitebox + * @build ThreadedMallocTestType + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail ThreadedMallocTestType + */ + +import com.oracle.java.testlibrary.*; +import sun.hotspot.WhiteBox; + +public class ThreadedMallocTestType { + public static long memAlloc1; + public static long memAlloc2; + public static long memAlloc3; + + public static void main(String args[]) throws Exception { + OutputAnalyzer output; + final WhiteBox wb = WhiteBox.getWhiteBox(); + + // Grab my own PID + String pid = Integer.toString(ProcessTools.getProcessId()); + ProcessBuilder pb = new ProcessBuilder(); + + Thread allocThread = new Thread() { + public void run() { + // Alloc memory using the WB api + memAlloc1 = wb.NMTMalloc(128 * 1024); + memAlloc2 = wb.NMTMalloc(256 * 1024); + memAlloc3 = wb.NMTMalloc(512 * 1024); + } + }; + + allocThread.start(); + allocThread.join(); + + // Use WB API to ensure that all data has been merged before we continue + if (!wb.NMTWaitForDataMerge()) { + throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); + } + + // Run 'jcmd VM.native_memory summary' + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=896KB, committed=896KB)"); + + Thread freeThread = new Thread() { + public void run() { + // Free the memory allocated by NMTMalloc + wb.NMTFree(memAlloc1); + wb.NMTFree(memAlloc2); + wb.NMTFree(memAlloc3); + } + }; + + freeThread.start(); + freeThread.join(); + + // Use WB API to ensure that all data has been merged before we continue + if (!wb.NMTWaitForDataMerge()) { + throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); + } + + output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("Test (reserved="); + } +} diff -r 2cae919cd3af -r 0c8ec85fa013 test/runtime/NMT/ThreadedVirtualAllocTestType.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/NMT/ThreadedVirtualAllocTestType.java Sat Apr 13 00:33:37 2013 +0200 @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2013, 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. + */ + +/* + * @test + * @key nmt jcmd + * @library /testlibrary /testlibrary/whitebox + * @build ThreadedVirtualAllocTestType + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail ThreadedVirtualAllocTestType + */ + +import com.oracle.java.testlibrary.*; +import sun.hotspot.WhiteBox; + +public class ThreadedVirtualAllocTestType { + public static long addr; + public static final WhiteBox wb = WhiteBox.getWhiteBox(); + public static final long commitSize = 128 * 1024; + public static final long reserveSize = 512 * 1024; + + public static void main(String args[]) throws Exception { + OutputAnalyzer output; + + String pid = Integer.toString(ProcessTools.getProcessId()); + ProcessBuilder pb = new ProcessBuilder(); + + Thread reserveThread = new Thread() { + public void run() { + addr = wb.NMTReserveMemory(reserveSize); + } + }; + reserveThread.start(); + reserveThread.join(); + + mergeData(); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "detail"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=512KB, committed=0KB)"); + output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + reserveSize) + "\\] reserved 512KB for Test"); + + Thread commitThread = new Thread() { + public void run() { + wb.NMTCommitMemory(addr, commitSize); + } + }; + commitThread.start(); + commitThread.join(); + + mergeData(); + + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=512KB, committed=128KB)"); + output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + commitSize) + "\\] committed 128KB"); + + Thread uncommitThread = new Thread() { + public void run() { + wb.NMTUncommitMemory(addr, commitSize); + } + }; + uncommitThread.start(); + uncommitThread.join(); + + mergeData(); + + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=512KB, committed=0KB)"); + output.shouldNotMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + commitSize) + "\\] committed"); + + Thread releaseThread = new Thread() { + public void run() { + wb.NMTReleaseMemory(addr, reserveSize); + } + }; + releaseThread.start(); + releaseThread.join(); + + mergeData(); + + output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("Test (reserved="); + output.shouldNotContain("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + reserveSize) + "\\] reserved"); + } + + public static void mergeData() throws Exception { + // Use WB API to ensure that all data has been merged before we continue + if (!wb.NMTWaitForDataMerge()) { + throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); + } + } +} diff -r 2cae919cd3af -r 0c8ec85fa013 test/runtime/NMT/VirtualAllocTestType.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/NMT/VirtualAllocTestType.java Sat Apr 13 00:33:37 2013 +0200 @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2013, 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. + */ + +/* + * @test + * @summary Test Reserve/Commit/Uncommit/Release of virtual memory and that we track it correctly + * @key nmt jcmd + * @library /testlibrary /testlibrary/whitebox + * @build VirtualAllocTestType + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail VirtualAllocTestType + */ + +import com.oracle.java.testlibrary.*; +import sun.hotspot.WhiteBox; + +public class VirtualAllocTestType { + + public static WhiteBox wb = WhiteBox.getWhiteBox(); + public static void main(String args[]) throws Exception { + OutputAnalyzer output; + long commitSize = 128 * 1024; + long reserveSize = 256 * 1024; + long addr; + + String pid = Integer.toString(ProcessTools.getProcessId()); + ProcessBuilder pb = new ProcessBuilder(); + + addr = wb.NMTReserveMemory(reserveSize); + mergeData(); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "detail"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=256KB, committed=0KB)"); + output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + reserveSize) + "\\] reserved 256KB for Test"); + + wb.NMTCommitMemory(addr, commitSize); + + mergeData(); + + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=256KB, committed=128KB)"); + output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + commitSize) + "\\] committed 128KB"); + + wb.NMTUncommitMemory(addr, commitSize); + + mergeData(); + + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=256KB, committed=0KB)"); + output.shouldNotMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + commitSize) + "\\] committed"); + + wb.NMTReleaseMemory(addr, reserveSize); + + mergeData(); + + output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("Test (reserved="); + output.shouldNotMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + reserveSize) + "\\] reserved"); + } + + public static void mergeData() throws Exception { + // Use WB API to ensure that all data has been merged before we continue + if (!wb.NMTWaitForDataMerge()) { + throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); + } + } +} diff -r 2cae919cd3af -r 0c8ec85fa013 test/testlibrary/OutputAnalyzerTest.java --- a/test/testlibrary/OutputAnalyzerTest.java Fri Apr 12 23:29:45 2013 +0200 +++ b/test/testlibrary/OutputAnalyzerTest.java Sat Apr 13 00:33:37 2013 +0200 @@ -36,6 +36,11 @@ String stdout = "aaaaaa"; String stderr = "bbbbbb"; + // Regexps used for testing pattern matching of the test input + String stdoutPattern = "[a]"; + String stderrPattern = "[b]"; + String nonExistingPattern = "[c]"; + OutputAnalyzer output = new OutputAnalyzer(stdout, stderr); if (!stdout.equals(output.getStdout())) { @@ -99,10 +104,73 @@ } try { - output.stderrShouldNotContain(stderr); - throw new Exception("shouldContain() failed to throw exception"); + output.stderrShouldNotContain(stderr); + throw new Exception("shouldContain() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + // Should match + try { + output.shouldMatch(stdoutPattern); + output.stdoutShouldMatch(stdoutPattern); + output.shouldMatch(stderrPattern); + output.stderrShouldMatch(stderrPattern); + } catch (RuntimeException e) { + throw new Exception("shouldMatch() failed", e); + } + + try { + output.shouldMatch(nonExistingPattern); + throw new Exception("shouldMatch() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + try { + output.stdoutShouldMatch(stderrPattern); + throw new Exception( + "stdoutShouldMatch() failed to throw exception"); } catch (RuntimeException e) { - // expected + // expected + } + + try { + output.stderrShouldMatch(stdoutPattern); + throw new Exception( + "stderrShouldMatch() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + // Should not match + try { + output.shouldNotMatch(nonExistingPattern); + output.stdoutShouldNotMatch(nonExistingPattern); + output.stderrShouldNotMatch(nonExistingPattern); + } catch (RuntimeException e) { + throw new Exception("shouldNotMatch() failed", e); + } + + try { + output.shouldNotMatch(stdoutPattern); + throw new Exception("shouldNotMatch() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + try { + output.stdoutShouldNotMatch(stdoutPattern); + throw new Exception("shouldNotMatch() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + try { + output.stderrShouldNotMatch(stderrPattern); + throw new Exception("shouldNotMatch() failed to throw exception"); + } catch (RuntimeException e) { + // expected } } } diff -r 2cae919cd3af -r 0c8ec85fa013 test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java --- a/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java Fri Apr 12 23:29:45 2013 +0200 +++ b/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java Sat Apr 13 00:33:37 2013 +0200 @@ -24,6 +24,8 @@ package com.oracle.java.testlibrary; import java.io.IOException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public final class OutputAnalyzer { @@ -142,15 +144,112 @@ } /** + * Verify that the stdout and stderr contents of output buffer matches + * the pattern + * + * @param pattern + * @throws RuntimeException If the pattern was not found + */ + public void shouldMatch(String pattern) { + Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout); + Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr); + if (!stdoutMatcher.find() && !stderrMatcher.find()) { + throw new RuntimeException("'" + pattern + + "' missing from stdout/stderr: [" + stdout + stderr + + "]\n"); + } + } + + /** + * Verify that the stdout contents of output buffer matches the + * pattern + * + * @param pattern + * @throws RuntimeException If the pattern was not found + */ + public void stdoutShouldMatch(String pattern) { + Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout); + if (!matcher.find()) { + throw new RuntimeException("'" + pattern + + "' missing from stdout: [" + stdout + "]\n"); + } + } + + /** + * Verify that the stderr contents of output buffer matches the + * pattern + * + * @param pattern + * @throws RuntimeException If the pattern was not found + */ + public void stderrShouldMatch(String pattern) { + Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr); + if (!matcher.find()) { + throw new RuntimeException("'" + pattern + + "' missing from stderr: [" + stderr + "]\n"); + } + } + + /** + * Verify that the stdout and stderr contents of output buffer does not + * match the pattern + * + * @param pattern + * @throws RuntimeException If the pattern was found + */ + public void shouldNotMatch(String pattern) { + Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout); + if (matcher.find()) { + throw new RuntimeException("'" + pattern + + "' found in stdout: [" + stdout + "]\n"); + } + matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr); + if (matcher.find()) { + throw new RuntimeException("'" + pattern + + "' found in stderr: [" + stderr + "]\n"); + } + } + + /** + * Verify that the stdout contents of output buffer does not match the + * pattern + * + * @param pattern + * @throws RuntimeException If the pattern was found + */ + public void stdoutShouldNotMatch(String pattern) { + Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout); + if (matcher.find()) { + throw new RuntimeException("'" + pattern + + "' found in stdout: [" + stdout + "]\n"); + } + } + + /** + * Verify that the stderr contents of output buffer does not match the + * pattern + * + * @param pattern + * @throws RuntimeException If the pattern was found + */ + public void stderrShouldNotMatch(String pattern) { + Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr); + if (matcher.find()) { + throw new RuntimeException("'" + pattern + + "' found in stderr: [" + stderr + "]\n"); + } + } + + /** * Verifiy the exit value of the process * * @param expectedExitValue Expected exit value from process * @throws RuntimeException If the exit value from the process did not match the expected value */ public void shouldHaveExitValue(int expectedExitValue) { - if (getExitValue() != expectedExitValue) { - throw new RuntimeException("Exit value " + getExitValue() + " , expected to get " + expectedExitValue); - } + if (getExitValue() != expectedExitValue) { + throw new RuntimeException("Exit value " + getExitValue() + " , expected to get " + expectedExitValue); + } } /** diff -r 2cae919cd3af -r 0c8ec85fa013 test/testlibrary/whitebox/sun/hotspot/WhiteBox.java --- a/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Fri Apr 12 23:29:45 2013 +0200 +++ b/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Sat Apr 13 00:33:37 2013 +0200 @@ -80,20 +80,30 @@ public native Object[] parseCommandLine(String commandline, DiagnosticCommand[] args); // NMT - public native boolean NMTAllocTest(); - public native boolean NMTFreeTestMemory(); + public native long NMTMalloc(long size); + public native void NMTFree(long mem); + public native long NMTReserveMemory(long size); + public native void NMTCommitMemory(long addr, long size); + public native void NMTUncommitMemory(long addr, long size); + public native void NMTReleaseMemory(long addr, long size); public native boolean NMTWaitForDataMerge(); // Compiler public native void deoptimizeAll(); public native boolean isMethodCompiled(Method method); - public native boolean isMethodCompilable(Method method); + public boolean isMethodCompilable(Method method) { + return isMethodCompilable(method, -1 /*any*/); + } + public native boolean isMethodCompilable(Method method, int compLevel); public native boolean isMethodQueuedForCompilation(Method method); public native int deoptimizeMethod(Method method); public native void makeMethodNotCompilable(Method method); public native int getMethodCompilationLevel(Method method); - public native boolean setDontInlineMethod(Method method, boolean value); + public native boolean testSetDontInlineMethod(Method method, boolean value); public native int getCompileQueuesSize(); + public native boolean testSetForceInlineMethod(Method method, boolean value); + public native boolean enqueueMethodForCompilation(Method method, int compLevel); + public native void clearMethodState(Method method); //Intered strings public native boolean isInStringTable(String str);