# HG changeset patch # User Thomas Wuerthinger # Date 1427472173 -3600 # Node ID eea134855f85bcab99f22d3be79b0097ad5a91d2 # Parent d22307a9a0256652a8dbb3c5eb229a3d3e66053a# Parent b7477f2df5531b315aef1d2c0ca37139e51e7985 Merge. diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DebugInfo.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DebugInfo.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DebugInfo.java Fri Mar 27 17:02:53 2015 +0100 @@ -24,6 +24,8 @@ import java.util.*; +import com.oracle.graal.api.meta.*; + /** * Represents the debugging information for a particular point of execution. This information * includes: @@ -40,6 +42,7 @@ private final BytecodePosition bytecodePosition; private final ReferenceMap referenceMap; + @SuppressWarnings("unused") private final Value[] virtualObjectMapping; private RegisterSaveLayout calleeSaveInfo; /** @@ -48,10 +51,16 @@ * @param codePos the {@linkplain BytecodePosition code position} or {@linkplain BytecodeFrame * frame} info * @param referenceMap the reference map + * @param virtualObjectMapping the mapping of {@link VirtualObject}s to their real values */ - public DebugInfo(BytecodePosition codePos, ReferenceMap referenceMap) { + public DebugInfo(BytecodePosition codePos, ReferenceMap referenceMap, Value[] virtualObjectMapping) { this.bytecodePosition = codePos; this.referenceMap = referenceMap; + this.virtualObjectMapping = virtualObjectMapping; + } + + public DebugInfo(BytecodePosition codePos) { + this(codePos, null, null); } /** diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Assumptions.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Assumptions.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Assumptions.java Fri Mar 27 17:02:53 2015 +0100 @@ -57,7 +57,7 @@ public AssumptionResult(T result, Assumption... assumptions) { this.result = result; - this.assumptions = assumptions.clone(); + this.assumptions = assumptions; } public AssumptionResult(T result) { diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java Fri Mar 27 17:02:53 2015 +0100 @@ -51,7 +51,7 @@ */ public static long getMemorySizeRecursive(MetaAccessProvider access, ConstantReflectionProvider constantReflection, JavaConstant constant, PrintStream out, int printTopN) { Set marked = new HashSet<>(); - Stack stack = new Stack<>(); + Deque stack = new ArrayDeque<>(); if (constant.getKind() == Kind.Object && constant.isNonNull()) { marked.add(constant); } @@ -120,7 +120,7 @@ return sum; } - private static void pushConstant(Set marked, Stack stack, JavaConstant value) { + private static void pushConstant(Set marked, Deque stack, JavaConstant value) { if (value.isNonNull()) { if (!marked.contains(value)) { marked.add(value); diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java --- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Fri Mar 27 17:02:53 2015 +0100 @@ -728,6 +728,7 @@ public static final AMD64MOp IMUL = new AMD64MOp("IMUL", 0xF7, 5); public static final AMD64MOp DIV = new AMD64MOp("DIV", 0xF7, 6); public static final AMD64MOp IDIV = new AMD64MOp("IDIV", 0xF7, 7); + public static final AMD64MOp INC = new AMD64MOp("INC", 0xFF, 0); // @formatter:on private final int ext; @@ -2412,4 +2413,12 @@ emitOperandHelper(1, src); } + /** + * Emits an instruction which is considered to be illegal. This is used if we deliberately want + * to crash the program (debugging etc.). + */ + public void illegal() { + emitByte(0x0f); + emitByte(0x0b); + } } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java --- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java Fri Mar 27 17:02:53 2015 +0100 @@ -1741,4 +1741,20 @@ public void casxa(Register rs1, Register rs2, Register rd, Asi asi) { ld(Casxa, new SPARCAddress(rs1, rs2), rd, asi); } + + @Override + public InstructionCounter getInstructionCounter() { + return new SPARCInstructionCounter(this); + } + + public void patchAddImmediate(int position, int simm13) { + int inst = getInt(position); + assert SPARCAssembler.isSimm13(simm13) : simm13; + assert (inst >>> 30) == 0b10 : String.format("0x%x", inst); + assert ((inst >>> 18) & 0b11_1111) == 0 : String.format("0x%x", inst); + assert (inst & (1 << 13)) != 0 : String.format("0x%x", inst); + inst = inst & (~((1 << 13) - 1)); + inst |= simm13 & ((1 << 12) - 1); + emitInt(inst, position); + } } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCInstructionCounter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCInstructionCounter.java Fri Mar 27 17:02:53 2015 +0100 @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2009, 2015, 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.asm.sparc; + +import java.util.*; + +import com.oracle.graal.asm.Assembler.InstructionCounter; + +public class SPARCInstructionCounter implements InstructionCounter { + // Use a treemap to keep the order in the output + private static final TreeMap INSTRUCTION_MATCHER = new TreeMap<>(); + static { + // @formatter:off + INSTRUCTION_MATCHER.put("nop", new SPARCInstructionMatch(0xFFFF_FFFF, 0x0100_0000)); + INSTRUCTION_MATCHER.put("st", new OP3LowBitsMatcher(0b11, 0x4, 0x5, 0x6, 0x7, 0xe, 0xf)); + INSTRUCTION_MATCHER.put("ld", new OP3LowBitsMatcher(0b11, 0x0, 0x1, 0x2, 0x3, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd)); + INSTRUCTION_MATCHER.put("all", new SPARCInstructionMatch(0x0, 0x0)); + // @formatter:on + } + private final SPARCAssembler asm; + + public SPARCInstructionCounter(SPARCAssembler asm) { + super(); + this.asm = asm; + } + + @Override + public int[] countInstructions(String[] instructionTypes, int beginPc, int endPc) { + SPARCInstructionMatch[] matchers = new SPARCInstructionMatch[instructionTypes.length]; + for (int i = 0; i < instructionTypes.length; i++) { + String typeName = instructionTypes[i]; + matchers[i] = INSTRUCTION_MATCHER.get(typeName); + if (matchers[i] == null) { + throw new IllegalArgumentException(String.format("Unknown instruction class %s, supported types are: %s", typeName, INSTRUCTION_MATCHER.keySet())); + } + } + return countBetween(matchers, beginPc, endPc); + } + + private int[] countBetween(SPARCInstructionMatch[] matchers, int startPc, int endPc) { + int[] counts = new int[matchers.length]; + for (int p = startPc; p < endPc; p += 4) { + int instr = asm.getInt(p); + for (int i = 0; i < matchers.length; i++) { + SPARCInstructionMatch matcher = matchers[i]; + if (matcher.matches(instr)) { + counts[i]++; + } + } + } + return counts; + } + + @Override + public String[] getSupportedInstructionTypes() { + return INSTRUCTION_MATCHER.keySet().toArray(new String[0]); + } + + /** + * Tests the lower 3 bits of the op3 field. + */ + private static class OP3LowBitsMatcher extends SPARCInstructionMatch { + private final int[] op3b03; + private final int op; + + public OP3LowBitsMatcher(int op, int... op3b03) { + super(0, 0); + this.op = op; + this.op3b03 = op3b03; + } + + @Override + public boolean matches(int instruction) { + if (instruction >>> 30 != op) { + return false; + } + int op3lo = (instruction >> 19) & ((1 << 4) - 1); + for (int op3Part : op3b03) { + if (op3Part == op3lo) { + return true; + } + } + return false; + } + } + + private static class SPARCInstructionMatch { + private final int mask; + private final int[] patterns; + + public SPARCInstructionMatch(int mask, int... patterns) { + super(); + this.mask = mask; + this.patterns = patterns; + } + + public boolean matches(int instruction) { + for (int pattern : patterns) { + if ((instruction & mask) == pattern) { + return true; + } + } + return false; + } + } +} diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.asm/src/com/oracle/graal/asm/Assembler.java --- a/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/Assembler.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/Assembler.java Fri Mar 27 17:02:53 2015 +0100 @@ -213,6 +213,10 @@ return hint; } + public InstructionCounter getInstructionCounter() { + throw new UnsupportedOperationException("Instruction counter is not implemented for " + this); + } + public static class LabelHint { private Label label; private int forPosition; @@ -242,4 +246,14 @@ return capturedTarget >= 0; } } + + /** + * Instruction counter class which gives the user of the assembler to count different kinds of + * instructions in the generated assembler code. + */ + public interface InstructionCounter { + String[] getSupportedInstructionTypes(); + + int[] countInstructions(String[] instructionTypes, int beginPc, int endPc); + } } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/UnsafeAccess.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/UnsafeAccess.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/UnsafeAccess.java Fri Mar 27 17:02:53 2015 +0100 @@ -65,7 +65,7 @@ if (address == 0) { return null; } - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); for (int i = 0;; i++) { char c = (char) unsafe.getByte(address + i); if (c == 0) { diff -r d22307a9a025 -r eea134855f85 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 Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Fri Mar 27 17:02:53 2015 +0100 @@ -320,7 +320,14 @@ throw Debug.handle(e); } FrameMapBuilder frameMapBuilder = backend.newFrameMapBuilder(registerConfig); - LIRGenerationResult lirGenRes = backend.newLIRGenerationResult(lir, frameMapBuilder, graph.method(), stub); + String compilationUnitName; + ResolvedJavaMethod method = graph.method(); + if (method == null) { + compilationUnitName = ""; + } else { + compilationUnitName = method.format("%H.%n(%p)"); + } + LIRGenerationResult lirGenRes = backend.newLIRGenerationResult(compilationUnitName, lir, frameMapBuilder, graph.method(), stub); LIRGeneratorTool lirGen = backend.newLIRGenerator(cc, lirGenRes); NodeLIRBuilderTool nodeLirGen = backend.newNodeLIRBuilder(graph, lirGen); diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java Fri Mar 27 17:02:53 2015 +0100 @@ -40,13 +40,16 @@ // @formatter:off @Option(help = "Pattern for scope(s) in which dumping is enabled (see DebugFilter and Debug.dump)", type = OptionType.Debug) public static final OptionValue Dump = new OptionValue<>(null); - @Option(help = "Pattern for scope(s) in which metering is enabled (see DebugFilter and Debug.metric)", type = OptionType.Debug) + @Option(help = "Pattern for scope(s) in which metering is enabled (see DebugFilter and Debug.metric). " + + "An empty value enables all metrics unconditionally.", type = OptionType.Debug) public static final OptionValue Meter = new OptionValue<>(null); - @Option(help = "Pattern for scope(s) in which verification is enabled (see DebugFilter and Debug.verify)", type = OptionType.Debug) + @Option(help = "Pattern for scope(s) in which verification is enabled (see DebugFilter and Debug.verify).", type = OptionType.Debug) public static final OptionValue Verify = new OptionValue<>(null); - @Option(help = "Pattern for scope(s) in which memory use tracking is enabled (see DebugFilter and Debug.metric)", type = OptionType.Debug) + @Option(help = "Pattern for scope(s) in which memory use tracking is enabled (see DebugFilter and Debug.metric). " + + "An empty value enables all memory use trackers unconditionally.", type = OptionType.Debug) public static final OptionValue TrackMemUse = new OptionValue<>(null); - @Option(help = "Pattern for scope(s) in which timing is enabled (see DebugFilter and Debug.timer)", type = OptionType.Debug) + @Option(help = "Pattern for scope(s) in which timing is enabled (see DebugFilter and Debug.timer). " + + "An empty value enables all timers unconditionally.", type = OptionType.Debug) public static final OptionValue Time = new OptionValue<>(null); @Option(help = "Pattern for scope(s) in which logging is enabled (see DebugFilter and Debug.log)", type = OptionType.Debug) public static final OptionValue Log = new OptionValue<>(null); @@ -63,6 +66,8 @@ public static final OptionValue DebugValueSummary = new OptionValue<>("Name"); @Option(help = "Omit reporting 0-value metrics", type = OptionType.Debug) public static final OptionValue SuppressZeroDebugValues = new OptionValue<>(true); + @Option(help = "Only report debug values for maps which match the regular expression.", type = OptionType.Debug) + public static final OptionValue DebugValueThreadFilter = new OptionValue<>(null); @Option(help = "Send Graal IR to dump handlers on error", type = OptionType.Debug) public static final OptionValue DumpOnError = new OptionValue<>(false); @Option(help = "Intercept also bailout exceptions", type = OptionType.Debug) @@ -71,12 +76,20 @@ public static final OptionValue LogVerbose = new OptionValue<>(false); // @formatter:on - public static boolean areDebugScopePatternsEnabled() { - return DumpOnError.getValue() || Dump.getValue() != null || Log.getValue() != null || areMetricsOrTimersEnabled(); + public static boolean isNotEmpty(OptionValue option) { + return option.getValue() != null && !option.getValue().isEmpty(); } - public static boolean areMetricsOrTimersEnabled() { - return Meter.getValue() != null || Time.getValue() != null || TrackMemUse.getValue() != null; + public static boolean areDebugScopePatternsEnabled() { + return DumpOnError.getValue() || Dump.getValue() != null || Log.getValue() != null || areScopedMetricsOrTimersEnabled(); + } + + /** + * Determines if any of {@link #Meter}, {@link #Time} or {@link #TrackMemUse} has a non-null, + * non-empty value. + */ + public static boolean areScopedMetricsOrTimersEnabled() { + return isNotEmpty(Meter) || isNotEmpty(Time) || isNotEmpty(TrackMemUse); } private final DebugFilter logFilter; diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/MethodFilter.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/MethodFilter.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/MethodFilter.java Fri Mar 27 17:02:53 2015 +0100 @@ -121,6 +121,18 @@ return false; } + /** + * Determines if a given class name is matched by a given array of filters. + */ + public static boolean matchesClassName(MethodFilter[] filters, String className) { + for (MethodFilter filter : filters) { + if (filter.matchesClassName(className)) { + return true; + } + } + return false; + } + public MethodFilter(String sourcePattern) { String pattern = sourcePattern.trim(); @@ -162,7 +174,7 @@ } else if (pattern.contains(".")) { return Pattern.compile(createGlobString(pattern)); } else { - return Pattern.compile("([^\\.]*\\.)*" + createGlobString(pattern)); + return Pattern.compile("([^\\.\\$]*[\\.\\$])*" + createGlobString(pattern)); } } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java Fri Mar 27 17:02:53 2015 +0100 @@ -78,7 +78,7 @@ public abstract LIRGeneratorTool newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes); - public abstract LIRGenerationResult newLIRGenerationResult(LIR lir, FrameMapBuilder frameMapBuilder, ResolvedJavaMethod method, Object stub); + public abstract LIRGenerationResult newLIRGenerationResult(String compilationUnitName, LIR lir, FrameMapBuilder frameMapBuilder, ResolvedJavaMethod method, Object stub); public abstract NodeLIRBuilderTool newNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen); diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java Fri Mar 27 17:02:53 2015 +0100 @@ -853,7 +853,7 @@ * A disabled tracker has virtually no overhead. */ public static DebugMemUseTracker memUseTracker(CharSequence name) { - if (!ENABLED) { + if (!isUnconditionalMemUseTrackingEnabled && !ENABLED) { return VOID_MEM_USE_TRACKER; } return createMemUseTracker("%s", name, null); @@ -871,7 +871,7 @@ * @see #metric(String, Object, Object) */ public static DebugMemUseTracker memUseTracker(String format, Object arg) { - if (!ENABLED) { + if (!isUnconditionalMemUseTrackingEnabled && !ENABLED) { return VOID_MEM_USE_TRACKER; } return createMemUseTracker(format, arg, null); @@ -898,7 +898,7 @@ * @see #memUseTracker(CharSequence) */ public static DebugMemUseTracker memUseTracker(String format, Object arg1, Object arg2) { - if (!ENABLED) { + if (!isUnconditionalMemUseTrackingEnabled && !ENABLED) { return VOID_MEM_USE_TRACKER; } return createMemUseTracker(format, arg1, arg2); @@ -906,7 +906,7 @@ private static DebugMemUseTracker createMemUseTracker(String format, Object arg1, Object arg2) { String name = formatDebugName(format, arg1, arg2); - return new MemUseTrackerImpl(name); + return new MemUseTrackerImpl(name, !isUnconditionalMemUseTrackingEnabled); } /** @@ -920,7 +920,7 @@ * A disabled metric has virtually no overhead. */ public static DebugMetric metric(CharSequence name) { - if (enabledMetrics == null && !ENABLED) { + if (!areUnconditionalMetricsEnabled() && !ENABLED) { return VOID_METRIC; } return createMetric("%s", name, null); @@ -963,7 +963,7 @@ * @see #metric(String, Object, Object) */ public static DebugMetric metric(String format, Object arg) { - if (enabledMetrics == null && !ENABLED) { + if (!areUnconditionalMetricsEnabled() && !ENABLED) { return VOID_METRIC; } return createMetric(format, arg, null); @@ -990,7 +990,7 @@ * @see #metric(CharSequence) */ public static DebugMetric metric(String format, Object arg1, Object arg2) { - if (enabledMetrics == null && !ENABLED) { + if (!areUnconditionalMetricsEnabled() && !ENABLED) { return VOID_METRIC; } return createMetric(format, arg1, arg2); @@ -1140,6 +1140,10 @@ } }; + public static final String ENABLE_UNSCOPED_TIMERS_PROPERTY_NAME = "graal.debug.unscopedTimers"; + public static final String ENABLE_UNSCOPED_METRICS_PROPERTY_NAME = "graal.debug.unscopedMetrics"; + public static final String ENABLE_UNSCOPED_MEM_USE_TRACKERS_PROPERTY_NAME = "graal.debug.unscopedMemUseTrackers"; + /** * @see #timer(CharSequence) */ @@ -1150,20 +1154,53 @@ */ public static final String ENABLE_METRIC_PROPERTY_NAME_PREFIX = "graal.debug.metric."; + /** + * Set of unconditionally enabled metrics. Possible values and their meanings: + *
    + *
  • {@code null}: no unconditionally enabled metrics
  • + *
  • {@code isEmpty()}: all metrics are unconditionally enabled
  • + *
  • {@code !isEmpty()}: use {@link #findMatch(Set, Set, String)} on this set and + * {@link #enabledMetricsSubstrings} to determine which metrics are unconditionally enabled
  • + *
+ */ private static final Set enabledMetrics; + + /** + * Set of unconditionally enabled timers. Same interpretation of values as for + * {@link #enabledMetrics}. + */ private static final Set enabledTimers; + private static final Set enabledMetricsSubstrings = new HashSet<>(); private static final Set enabledTimersSubstrings = new HashSet<>(); + /** + * Specifies if all mem use trackers are unconditionally enabled. + */ + private static final boolean isUnconditionalMemUseTrackingEnabled; + static { Set metrics = new HashSet<>(); Set timers = new HashSet<>(); parseMetricAndTimerSystemProperties(metrics, timers, enabledMetricsSubstrings, enabledTimersSubstrings); - enabledMetrics = metrics.isEmpty() && enabledMetricsSubstrings.isEmpty() ? null : metrics; - enabledTimers = timers.isEmpty() && enabledTimersSubstrings.isEmpty() ? null : timers; + metrics = metrics.isEmpty() && enabledMetricsSubstrings.isEmpty() ? null : metrics; + timers = timers.isEmpty() && enabledTimersSubstrings.isEmpty() ? null : timers; + if (metrics == null && Boolean.getBoolean(ENABLE_UNSCOPED_METRICS_PROPERTY_NAME)) { + metrics = Collections.emptySet(); + } + if (timers == null && Boolean.getBoolean(ENABLE_UNSCOPED_TIMERS_PROPERTY_NAME)) { + timers = Collections.emptySet(); + } + enabledMetrics = metrics; + enabledTimers = timers; + isUnconditionalMemUseTrackingEnabled = Boolean.getBoolean(ENABLE_UNSCOPED_MEM_USE_TRACKERS_PROPERTY_NAME); } private static boolean findMatch(Set haystack, Set haystackSubstrings, String needle) { + if (haystack.isEmpty()) { + // Empty haystack means match all + return true; + } if (haystack.contains(needle)) { return true; } @@ -1224,7 +1261,7 @@ * A disabled timer has virtually no overhead. */ public static DebugTimer timer(CharSequence name) { - if (enabledTimers == null && !ENABLED) { + if (!areUnconditionalTimersEnabled() && !ENABLED) { return VOID_TIMER; } return createTimer("%s", name, null); @@ -1242,7 +1279,7 @@ * @see #timer(String, Object, Object) */ public static DebugTimer timer(String format, Object arg) { - if (enabledTimers == null && !ENABLED) { + if (!areUnconditionalTimersEnabled() && !ENABLED) { return VOID_TIMER; } return createTimer(format, arg, null); @@ -1269,7 +1306,7 @@ * @see #timer(CharSequence) */ public static DebugTimer timer(String format, Object arg1, Object arg2) { - if (enabledTimers == null && !ENABLED) { + if (!areUnconditionalTimersEnabled() && !ENABLED) { return VOID_TIMER; } return createTimer(format, arg1, arg2); diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/MemUseTrackerImpl.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/MemUseTrackerImpl.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/MemUseTrackerImpl.java Fri Mar 27 17:02:53 2015 +0100 @@ -48,8 +48,8 @@ */ private static final ThreadLocal currentTracker = new ThreadLocal<>(); - public MemUseTrackerImpl(String name) { - super(name, true, new DebugValue(name + "_Flat", true) { + public MemUseTrackerImpl(String name, boolean conditional) { + super(name, conditional, new DebugValue(name + "_Flat", conditional) { @Override public String toString(long value) { diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/matchers/NodeIterableContains.java --- a/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/matchers/NodeIterableContains.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/matchers/NodeIterableContains.java Fri Mar 27 17:02:53 2015 +0100 @@ -35,19 +35,16 @@ } public void describeTo(Description description) { - description.appendText("is a NodeIterable containing").appendValue(node); + description.appendText("is a NodeIterable containing ").appendValue(node); } public static NodeIterableContains contains(T node) { return new NodeIterableContains<>(node); } - public static NodeIterableContains d(T node) { - return new NodeIterableContains<>(node); - } - @Override - protected boolean matchesSafely(NodeIterable iterable, Description description) { + protected boolean matchesSafely(NodeIterable iterable, Description mismatchDescription) { + mismatchDescription.appendText("is a NodeIterable that does not contain ").appendValue(node); return iterable.contains(node); } } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/matchers/NodeIterableCount.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/matchers/NodeIterableCount.java Fri Mar 27 17:02:53 2015 +0100 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.graph.test.matchers; + +import org.hamcrest.*; + +import com.oracle.graal.graph.iterators.*; + +public class NodeIterableCount extends TypeSafeDiagnosingMatcher> { + private int count; + + public NodeIterableCount(int count) { + this.count = count; + } + + @Override + public void describeTo(Description description) { + description.appendText("is a NodeIterable containing ").appendValue(count).appendText(" elements"); + } + + public static NodeIterableCount hasCount(int count) { + return new NodeIterableCount(count); + } + + @Override + protected boolean matchesSafely(NodeIterable iterable, Description mismatchDescription) { + mismatchDescription.appendText("is a NodeIterable containing ").appendValue(iterable.count()).appendText(" elements"); + return iterable.count() == count; + } +} diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/matchers/NodeIterableIsEmpty.java --- a/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/matchers/NodeIterableIsEmpty.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/matchers/NodeIterableIsEmpty.java Fri Mar 27 17:02:53 2015 +0100 @@ -27,12 +27,14 @@ import com.oracle.graal.graph.iterators.*; -public class NodeIterableIsEmpty extends BaseMatcher> { +public class NodeIterableIsEmpty extends TypeSafeDiagnosingMatcher> { private static final NodeIterableIsEmpty INSTANCE = new NodeIterableIsEmpty(); - public boolean matches(Object iterable) { - return iterable instanceof NodeIterable && ((NodeIterable) iterable).isEmpty(); + @Override + public boolean matchesSafely(NodeIterable iterable, Description mismatchDescription) { + mismatchDescription.appendText("is a non-empty NodeIterable"); + return iterable.isEmpty(); } public void describeTo(Description description) { diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.graph/.checkstyle_checks.xml --- a/graal/com.oracle.graal.graph/.checkstyle_checks.xml Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.graph/.checkstyle_checks.xml Fri Mar 27 17:02:53 2015 +0100 @@ -122,9 +122,13 @@ + - + + + + diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/GraphBuilderContext.java --- a/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/GraphBuilderContext.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/GraphBuilderContext.java Fri Mar 27 17:02:53 2015 +0100 @@ -25,6 +25,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -59,16 +60,101 @@ boolean isIntrinsic(); } + /** + * Raw operation for adding a node to the graph when neither {@link #add}, + * {@link #addPush(ValueNode)} nor {@link #addPush(Kind, ValueNode)} can be used. + * + * @return either the node added or an equivalent node + */ T append(T value); /** - * Adds the given floating node to the graph and also adds recursively all referenced inputs. + * Adds the given node to the graph and also adds recursively all referenced inputs. * - * @param value the floating node to be added to the graph + * @param value the node to be added to the graph * @return either the node added or an equivalent node */ T recursiveAppend(T value); + /** + * Pushes a given value to the frame state stack using an explicit kind. This should be used + * when {@code value.getKind()} is different from the kind that the bytecode instruction + * currently being parsed pushes to the stack. + * + * @param kind the kind to use when type checking this operation + * @param value the value to push to the stack. The value must already have been + * {@linkplain #append(ValueNode) appended}. + */ + void push(Kind kind, ValueNode value); + + /** + * Adds a node to the graph. If the returned node is a {@link StateSplit} with a null + * {@linkplain StateSplit#stateAfter() frame state}, the frame state is initialized. + * + * @param value the value to add to the graph and push to the stack. The {@code value.getKind()} + * kind is used when type checking this operation. + * @return a node equivalent to {@code value} in the graph + */ + default T add(T value) { + if (value.graph() != null) { + assert !(value instanceof StateSplit) || ((StateSplit) value).stateAfter() != null; + return value; + } + T equivalentValue = append(value); + if (equivalentValue instanceof StateSplit) { + StateSplit stateSplit = (StateSplit) equivalentValue; + if (stateSplit.stateAfter() == null) { + stateSplit.setStateAfter(createStateAfter()); + } + } + return equivalentValue; + } + + /** + * Adds a node with a non-void kind to the graph, pushes it to the stack. If the returned node + * is a {@link StateSplit} with a null {@linkplain StateSplit#stateAfter() frame state}, the + * frame state is initialized. + * + * @param value the value to add to the graph and push to the stack. The {@code value.getKind()} + * kind is used when type checking this operation. + * @return a node equivalent to {@code value} in the graph + */ + default T addPush(T value) { + return addPush(value.getKind().getStackKind(), value); + } + + /** + * Adds a node with a non-void kind to the graph, pushes it to the stack. If the returned node + * is a {@link StateSplit} with a null {@linkplain StateSplit#stateAfter() frame state}, the + * frame state is initialized. + * + * @param kind the kind to use when type checking this operation + * @param value the value to add to the graph and push to the stack + * @return a node equivalent to {@code value} in the graph + */ + default T addPush(Kind kind, T value) { + T equivalentValue = value.graph() != null ? value : append(value); + push(kind.getStackKind(), equivalentValue); + if (equivalentValue instanceof StateSplit) { + StateSplit stateSplit = (StateSplit) equivalentValue; + if (stateSplit.stateAfter() == null) { + stateSplit.setStateAfter(createStateAfter()); + } + } + return equivalentValue; + } + + /** + * Handles an invocation that a plugin determines can replace the original invocation (i.e., the + * one for which the plugin was applied). This applies all standard graph builder processing to + * the replaced invocation including applying any relevant plugins to it. + * + * @param invokeKind the kind of the replacement invocation + * @param targetMethod the target of the replacement invocation + * @param args the arguments to the replacement invocation + */ + void handleReplacedInvoke(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args); + StampProvider getStampProvider(); MetaAccessProvider getMetaAccess(); @@ -79,10 +165,12 @@ SnippetReflectionProvider getSnippetReflection(); - void push(Kind kind, ValueNode value); - StructuredGraph getGraph(); + /** + * Creates a snap shot of the current frame state with the BCI of the instruction after the one + * currently being parsed. + */ FrameState createStateAfter(); /** @@ -106,6 +194,16 @@ int bci(); /** + * Gets the kind of invocation currently being parsed. + */ + InvokeKind getInvokeKind(); + + /** + * Gets the return type of the invocation currently being parsed. + */ + JavaType getInvokeReturnType(); + + /** * Gets the inline depth of this context. 0 implies this is the context for the * {@linkplain #getRootMethod() root method}. */ diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugin.java --- a/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugin.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugin.java Fri Mar 27 17:02:53 2015 +0100 @@ -22,6 +22,7 @@ */ package com.oracle.graal.graphbuilderconf; +import java.lang.invoke.*; import java.lang.reflect.*; import com.oracle.graal.api.meta.*; @@ -35,45 +36,65 @@ public interface InvocationPlugin extends GraphBuilderPlugin { /** + * Determines if this plugin is for a method with a polymorphic signature (e.g. + * {@link MethodHandle#invokeExact(Object...)}). + */ + default boolean isSignaturePolymorphic() { + return false; + } + + /** + * Handles invocation of a signature polymorphic method. + * + * @param receiver access to the receiver, {@code null} if {@code targetMethod} is static + * @param argsIncludingReceiver all arguments to the invocation include the raw receiver in + * position 0 if {@code targetMethod} is not static + * @see #execute + */ + default boolean applyPolymorphic(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode... argsIncludingReceiver) { + return defaultHandler(b, targetMethod, receiver, argsIncludingReceiver); + } + + /** * @see #execute */ default boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { - throw invalidHandler(b, targetMethod, receiver); + return defaultHandler(b, targetMethod, receiver); } /** * @see #execute */ default boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg) { - throw invalidHandler(b, targetMethod, receiver, arg); + return defaultHandler(b, targetMethod, receiver, arg); } /** * @see #execute */ default boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg1, ValueNode arg2) { - throw invalidHandler(b, targetMethod, receiver, arg1, arg2); + return defaultHandler(b, targetMethod, receiver, arg1, arg2); } /** * @see #execute */ default boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg1, ValueNode arg2, ValueNode arg3) { - throw invalidHandler(b, targetMethod, receiver, arg1, arg2, arg3); + return defaultHandler(b, targetMethod, receiver, arg1, arg2, arg3); } /** * @see #execute */ default boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg1, ValueNode arg2, ValueNode arg3, ValueNode arg4) { - throw invalidHandler(b, targetMethod, receiver, arg1, arg2, arg3, arg4); + return defaultHandler(b, targetMethod, receiver, arg1, arg2, arg3, arg4); } /** * @see #execute */ default boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg1, ValueNode arg2, ValueNode arg3, ValueNode arg4, ValueNode arg5) { - throw invalidHandler(b, targetMethod, receiver, arg1, arg2, arg3, arg4, arg5); + return defaultHandler(b, targetMethod, receiver, arg1, arg2, arg3, arg4, arg5); } default ResolvedJavaMethod getSubstitute() { @@ -82,56 +103,64 @@ /** * Executes a given plugin against a set of invocation arguments by dispatching to the - * {@code apply(...)} method that matches the number of arguments. + * {@code apply(...)} method that matches the number of arguments or to + * {@link #applyPolymorphic} if {@code plugin} is {@linkplain #isSignaturePolymorphic() + * signature polymorphic}. * * @param targetMethod the method for which plugin is being applied * @param receiver access to the receiver, {@code null} if {@code targetMethod} is static - * @param args the remaining arguments + * @param argsIncludingReceiver all arguments to the invocation include the receiver in position + * 0 if {@code targetMethod} is not static * @return {@code true} if the plugin handled the invocation of {@code targetMethod} * {@code false} if the graph builder should process the invoke further (e.g., by * inlining it or creating an {@link Invoke} node). A plugin that does not handle an * invocation must not modify the graph being constructed. */ - static boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin plugin, Receiver receiver, ValueNode[] args) { - if (receiver != null) { + static boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin plugin, Receiver receiver, ValueNode[] argsIncludingReceiver) { + if (plugin.isSignaturePolymorphic()) { + return plugin.applyPolymorphic(b, targetMethod, receiver, argsIncludingReceiver); + } else if (receiver != null) { assert !targetMethod.isStatic(); - assert args.length > 0; - if (args.length == 1) { + assert argsIncludingReceiver.length > 0; + if (argsIncludingReceiver.length == 1) { return plugin.apply(b, targetMethod, receiver); - } else if (args.length == 2) { - return plugin.apply(b, targetMethod, receiver, args[1]); - } else if (args.length == 3) { - return plugin.apply(b, targetMethod, receiver, args[1], args[2]); - } else if (args.length == 4) { - return plugin.apply(b, targetMethod, receiver, args[1], args[2], args[3]); - } else if (args.length == 5) { - return plugin.apply(b, targetMethod, receiver, args[1], args[2], args[3], args[4]); + } else if (argsIncludingReceiver.length == 2) { + return plugin.apply(b, targetMethod, receiver, argsIncludingReceiver[1]); + } else if (argsIncludingReceiver.length == 3) { + return plugin.apply(b, targetMethod, receiver, argsIncludingReceiver[1], argsIncludingReceiver[2]); + } else if (argsIncludingReceiver.length == 4) { + return plugin.apply(b, targetMethod, receiver, argsIncludingReceiver[1], argsIncludingReceiver[2], argsIncludingReceiver[3]); + } else if (argsIncludingReceiver.length == 5) { + return plugin.apply(b, targetMethod, receiver, argsIncludingReceiver[1], argsIncludingReceiver[2], argsIncludingReceiver[3], argsIncludingReceiver[4]); } else { - throw plugin.invalidHandler(b, targetMethod, receiver, args); + return plugin.defaultHandler(b, targetMethod, receiver, argsIncludingReceiver); } } else { assert targetMethod.isStatic(); - if (args.length == 0) { + if (argsIncludingReceiver.length == 0) { return plugin.apply(b, targetMethod, null); - } else if (args.length == 1) { - return plugin.apply(b, targetMethod, null, args[0]); - } else if (args.length == 2) { - return plugin.apply(b, targetMethod, null, args[0], args[1]); - } else if (args.length == 3) { - return plugin.apply(b, targetMethod, null, args[0], args[1], args[2]); - } else if (args.length == 4) { - return plugin.apply(b, targetMethod, null, args[0], args[1], args[2], args[3]); - } else if (args.length == 5) { - return plugin.apply(b, targetMethod, null, args[0], args[1], args[2], args[3], args[4]); + } else if (argsIncludingReceiver.length == 1) { + return plugin.apply(b, targetMethod, null, argsIncludingReceiver[0]); + } else if (argsIncludingReceiver.length == 2) { + return plugin.apply(b, targetMethod, null, argsIncludingReceiver[0], argsIncludingReceiver[1]); + } else if (argsIncludingReceiver.length == 3) { + return plugin.apply(b, targetMethod, null, argsIncludingReceiver[0], argsIncludingReceiver[1], argsIncludingReceiver[2]); + } else if (argsIncludingReceiver.length == 4) { + return plugin.apply(b, targetMethod, null, argsIncludingReceiver[0], argsIncludingReceiver[1], argsIncludingReceiver[2], argsIncludingReceiver[3]); + } else if (argsIncludingReceiver.length == 5) { + return plugin.apply(b, targetMethod, null, argsIncludingReceiver[0], argsIncludingReceiver[1], argsIncludingReceiver[2], argsIncludingReceiver[3], argsIncludingReceiver[4]); } else { - throw plugin.invalidHandler(b, targetMethod, receiver, args); + return plugin.defaultHandler(b, targetMethod, receiver, argsIncludingReceiver); } } } - default Error invalidHandler(@SuppressWarnings("unused") GraphBuilderContext b, ResolvedJavaMethod targetMethod, @SuppressWarnings("unused") Receiver receiver, ValueNode... args) { - return new GraalInternalError("Invocation plugin for %s does not handle invocations with %d arguments", targetMethod.format("%H.%n(%p)"), args.length); + /** + * Handles an invocation when a specific {@code apply} method is not available. + */ + default boolean defaultHandler(@SuppressWarnings("unused") GraphBuilderContext b, ResolvedJavaMethod targetMethod, @SuppressWarnings("unused") Receiver receiver, ValueNode... args) { + throw new GraalInternalError("Invocation plugin for %s does not handle invocations with %d arguments", targetMethod.format("%H.%n(%p)"), args.length); } default StackTraceElement getApplySourceLocation(MetaAccessProvider metaAccess) { @@ -139,8 +168,10 @@ for (Method m : c.getDeclaredMethods()) { if (m.getName().equals("apply")) { return metaAccess.lookupJavaMethod(m).asStackTraceElement(0); + } else if (m.getName().equals("defaultHandler")) { + return metaAccess.lookupJavaMethod(m).asStackTraceElement(0); } } - throw new GraalInternalError("could not find method named \"apply\" in " + c.getName()); + throw new GraalInternalError("could not find method named \"apply\" or \"defaultHandler\" in " + c.getName()); } } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/LoadFieldPlugin.java --- a/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/LoadFieldPlugin.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/LoadFieldPlugin.java Fri Mar 27 17:02:53 2015 +0100 @@ -39,8 +39,8 @@ default boolean tryConstantFold(GraphBuilderContext b, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ResolvedJavaField field, JavaConstant receiver) { JavaConstant result = constantReflection.readConstantFieldValue(field, receiver); if (result != null) { - ConstantNode constantNode = b.append(ConstantNode.forConstant(result, metaAccess)); - b.push(constantNode.getKind().getStackKind(), constantNode); + ConstantNode constantNode = ConstantNode.forConstant(result, metaAccess); + b.addPush(constantNode.getKind().getStackKind(), constantNode); return true; } return false; diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Fri Mar 27 17:02:53 2015 +0100 @@ -78,8 +78,8 @@ } @Override - public LIRGenerationResult newLIRGenerationResult(LIR lir, FrameMapBuilder frameMapBuilder, ResolvedJavaMethod method, Object stub) { - return new AMD64HotSpotLIRGenerationResult(lir, frameMapBuilder, stub); + public LIRGenerationResult newLIRGenerationResult(String compilationUnitName, LIR lir, FrameMapBuilder frameMapBuilder, ResolvedJavaMethod method, Object stub) { + return new AMD64HotSpotLIRGenerationResult(compilationUnitName, lir, frameMapBuilder, stub); } @Override @@ -254,6 +254,9 @@ // Emit the suffix emitCodeSuffix(installedCodeOwner, crb, asm, frameMap); + + // Profile assembler instructions + profileInstructions(lir, crb); } /** diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCounterOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCounterOp.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCounterOp.java Fri Mar 27 17:02:53 2015 +0100 @@ -24,6 +24,11 @@ import static com.oracle.graal.amd64.AMD64.*; import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.asm.NumUtil.*; +import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.*; +import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64MOp.*; +import static com.oracle.graal.asm.amd64.AMD64Assembler.OperandSize.*; +import static com.oracle.graal.compiler.common.GraalInternalError.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; @@ -54,7 +59,19 @@ AMD64MacroAssembler masm = (AMD64MacroAssembler) crb.asm; TargetDescription target = crb.target; - Register scratch = rax; + Register scratch; + // It can happen that the rax register is the increment register, in this case we do not + // want to spill it to the stack. + if (!contains(increments, rax)) { + scratch = rax; + } else if (!contains(increments, rbx)) { + scratch = rbx; + } else { + // In this case rax and rbx are used as increment. Either we implement a third register + // or we implement a spillover the value from rax to rbx or vice versa during + // emitIncrement(). + throw unimplemented("RAX and RBX are increment registers a the same time, spilling over the scratch register is not supported right now"); + } // address for counters array AMD64Address countersArrayAddr = new AMD64Address(thread, config.graalCountersThreadOffset); @@ -65,21 +82,39 @@ // load counters array masm.movptr(countersArrayReg, countersArrayAddr); - - forEachCounter((name, group, increment) -> emitIncrement(masm, target, countersArrayReg, name, group, increment)); + CounterProcedure emitProcedure = (counterIndex, increment, displacement) -> emitIncrement(masm, countersArrayReg, increment, displacement); + forEachCounter(emitProcedure, target); // restore scratch register masm.movq(scratch, (AMD64Address) crb.asAddress(backupSlot)); } - private void emitIncrement(AMD64MacroAssembler masm, TargetDescription target, Register countersArrayReg, String name, String group, Value increment) { + /** + * Tests if the array contains the register. + */ + private static boolean contains(Value[] increments, Register register) { + for (Value increment : increments) { + if (isRegister(increment) && asRegister(increment).equals(register)) { + return true; + } + } + return false; + } + + private static void emitIncrement(AMD64MacroAssembler masm, Register countersArrayReg, Value incrementValue, int displacement) { // address for counter value - AMD64Address counterAddr = new AMD64Address(countersArrayReg, getDisplacementForLongIndex(target, getIndex(name, group, increment))); + AMD64Address counterAddr = new AMD64Address(countersArrayReg, displacement); // increment counter (in memory) - if (isConstant(increment)) { - masm.incrementl(counterAddr, asInt(asConstant(increment))); + if (isConstant(incrementValue)) { + int increment = asInt(asConstant(incrementValue)); + if (increment == 1) { + INC.emit(masm, QWORD, counterAddr); + } else { + ADD.getMIOpcode(QWORD, isByte(increment)).emit(masm, QWORD, counterAddr, increment); + } } else { - masm.addq(counterAddr, asRegister(increment)); + masm.addq(counterAddr, asRegister(incrementValue)); } + } } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerationResult.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerationResult.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerationResult.java Fri Mar 27 17:02:53 2015 +0100 @@ -48,8 +48,8 @@ */ private Map calleeSaveInfo = CollectionsFactory.newMap(); - public AMD64HotSpotLIRGenerationResult(LIR lir, FrameMapBuilder frameMapBuilder, Object stub) { - super(lir, frameMapBuilder); + public AMD64HotSpotLIRGenerationResult(String compilationUnitName, LIR lir, FrameMapBuilder frameMapBuilder, Object stub) { + super(compilationUnitName, lir, frameMapBuilder); this.stub = stub; } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java Fri Mar 27 17:02:53 2015 +0100 @@ -80,8 +80,8 @@ } @Override - public LIRGenerationResult newLIRGenerationResult(LIR lir, FrameMapBuilder frameMapBuilder, ResolvedJavaMethod method, Object stub) { - return new SPARCHotSpotLIRGenerationResult(lir, frameMapBuilder, stub); + public LIRGenerationResult newLIRGenerationResult(String compilationUnitName, LIR lir, FrameMapBuilder frameMapBuilder, ResolvedJavaMethod method, Object stub) { + return new SPARCHotSpotLIRGenerationResult(compilationUnitName, lir, frameMapBuilder, stub); } @Override @@ -247,6 +247,8 @@ crb.emit(lir); } while (i++ < 1); + profileInstructions(lir, crb); + HotSpotFrameContext frameContext = (HotSpotFrameContext) crb.frameContext; HotSpotForeignCallsProvider foreignCalls = getProviders().getForeignCalls(); if (!frameContext.isStub) { diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCounterOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCounterOp.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCounterOp.java Fri Mar 27 17:02:53 2015 +0100 @@ -23,11 +23,14 @@ package com.oracle.graal.hotspot.sparc; import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.asm.sparc.SPARCAssembler.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.*; import com.oracle.graal.asm.sparc.*; -import com.oracle.graal.asm.sparc.SPARCMacroAssembler.*; +import com.oracle.graal.asm.sparc.SPARCMacroAssembler.ScratchRegister; +import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setx; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.lir.*; @@ -37,12 +40,16 @@ public class SPARCHotSpotCounterOp extends HotSpotCounterOp { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCHotSpotCounterOp.class); + private int[] counterPatchOffsets; + public SPARCHotSpotCounterOp(String name, String group, Value increment, HotSpotRegistersProvider registers, HotSpotVMConfig config) { super(TYPE, name, group, increment, registers, config); + this.counterPatchOffsets = new int[1]; } public SPARCHotSpotCounterOp(String[] names, String[] groups, Value[] increments, HotSpotRegistersProvider registers, HotSpotVMConfig config) { super(TYPE, names, groups, increments, registers, config); + this.counterPatchOffsets = new int[names.length]; } @Override @@ -57,19 +64,17 @@ // load counters array masm.ldx(countersArrayAddr, countersArrayReg); - - forEachCounter((name, group, increment) -> emitIncrement(masm, target, countersArrayReg, name, group, increment)); + IncrementEmitter emitter = new IncrementEmitter(countersArrayReg, masm); + forEachCounter(emitter, target); } } - private void emitIncrement(SPARCMacroAssembler masm, TargetDescription target, Register countersArrayReg, String name, String group, Value increment) { - // address for counter - SPARCAddress counterAddr = new SPARCAddress(countersArrayReg, getDisplacementForLongIndex(target, getIndex(name, group, increment))); - + private void emitIncrement(int counterIndex, SPARCMacroAssembler masm, SPARCAddress counterAddr, Value increment) { try (ScratchRegister scratch = masm.getScratchRegister()) { Register counterReg = scratch.getRegister(); // load counter value masm.ldx(counterAddr, counterReg); + counterPatchOffsets[counterIndex] = masm.position(); // increment counter if (isConstant(increment)) { masm.add(counterReg, asInt(asConstant(increment)), counterReg); @@ -80,4 +85,53 @@ masm.stx(counterReg, counterAddr); } } + + /** + * Patches the increment value in the instruction emitted by the + * {@link #emitIncrement(int, SPARCMacroAssembler, SPARCAddress, Value)} method. This method is + * used if patching is needed after assembly. + * + * @param asm + * @param increment + */ + @Override + public void patchCounterIncrement(Assembler asm, int[] increment) { + for (int i = 0; i < increment.length; i++) { + int inst = counterPatchOffsets[i]; + ((SPARCAssembler) asm).patchAddImmediate(inst, increment[i]); + } + } + + public int[] getCounterPatchOffsets() { + return counterPatchOffsets; + } + + private class IncrementEmitter implements CounterProcedure { + private int lastDisplacement = 0; + private final Register countersArrayReg; + private final SPARCMacroAssembler masm; + + public IncrementEmitter(Register countersArrayReg, SPARCMacroAssembler masm) { + super(); + this.countersArrayReg = countersArrayReg; + this.masm = masm; + } + + public void apply(int counterIndex, Value increment, int displacement) { + SPARCAddress counterAddr; + int relativeDisplacement = displacement - lastDisplacement; + if (isSimm13(relativeDisplacement)) { // Displacement fits into ld instruction + counterAddr = new SPARCAddress(countersArrayReg, relativeDisplacement); + } else { + try (ScratchRegister scratch = masm.getScratchRegister()) { + Register tempOffsetRegister = scratch.getRegister(); + new Setx(relativeDisplacement, tempOffsetRegister, false).emit(masm); + masm.add(countersArrayReg, tempOffsetRegister, countersArrayReg); + } + lastDisplacement = displacement; + counterAddr = new SPARCAddress(countersArrayReg, 0); + } + emitIncrement(counterIndex, masm, counterAddr, increment); + } + } } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerationResult.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerationResult.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerationResult.java Fri Mar 27 17:02:53 2015 +0100 @@ -47,8 +47,8 @@ */ private Map calleeSaveInfo = new HashMap<>(); - public SPARCHotSpotLIRGenerationResult(LIR lir, FrameMapBuilder frameMapBuilder, Object stub) { - super(lir, frameMapBuilder); + public SPARCHotSpotLIRGenerationResult(String compilationUnitName, LIR lir, FrameMapBuilder frameMapBuilder, Object stub) { + super(compilationUnitName, lir, frameMapBuilder); this.stub = stub; } @@ -67,5 +67,4 @@ Map getCalleeSaveInfo() { return calleeSaveInfo; } - } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompileTheWorldTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompileTheWorldTest.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompileTheWorldTest.java Fri Mar 27 17:02:53 2015 +0100 @@ -40,7 +40,7 @@ boolean originalSetting = ExitVMOnException.getValue(); // Compile a couple classes in rt.jar String file = System.getProperty("java.home") + "/lib/rt.jar"; - new CompileTheWorld(file, new Config(null), 1, 5, false).compile(); + new CompileTheWorld(file, new Config(null), 1, 5, null, false).compile(); ExitVMOnException.setValue(originalSetting); } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompressedOopTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompressedOopTest.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompressedOopTest.java Fri Mar 27 17:02:53 2015 +0100 @@ -299,8 +299,8 @@ @Test public void test14() throws Exception { - HotSpotInstalledCode installedBenchmarkCode = getInstalledCode("stringBufferTest", Object.class, Object.class); - StringBuffer buffer = new StringBuffer("TestTestTestTestTestTestTest"); + HotSpotInstalledCode installedBenchmarkCode = getInstalledCode("stringBuilderTest", Object.class, Object.class); + StringBuilder buffer = new StringBuilder("TestTestTestTestTestTestTest"); Assert.assertTrue(buffer.length() == 28); String a = new String("TestTestTestTestTestTestTest"); installedBenchmarkCode.executeVarargs(buffer, a.toCharArray()); @@ -308,8 +308,8 @@ Assert.assertTrue(buffer.toString().equals("TestTestTestTestTestTestTestTestTestTestTestTestTestTest")); } - public static void stringBufferTest(Object c1, Object c2) { - StringBuffer source = (StringBuffer) c1; + public static void stringBuilderTest(Object c1, Object c2) { + StringBuilder source = (StringBuilder) c1; char[] add = (char[]) c2; for (int i = 0; i < add.length; i++) { source.append(add[i]); @@ -318,12 +318,12 @@ @Test public void test15() throws Exception { - HotSpotInstalledCode installedBenchmarkCode = getInstalledCode("stringBufferTestIn"); + HotSpotInstalledCode installedBenchmarkCode = getInstalledCode("stringBuilderTestIn"); installedBenchmarkCode.executeVarargs(); } - public static void stringBufferTestIn() { - StringBuffer buffer = new StringBuffer("TestTestTestTestTestTestTest"); + public static void stringBuilderTestIn() { + StringBuilder buffer = new StringBuilder("TestTestTestTestTestTestTest"); Assert.assertTrue(buffer.length() == 28); String a = new String("TestTestTestTestTestTestTest"); char[] add = a.toCharArray(); @@ -336,12 +336,12 @@ @Test public void test16() throws Exception { - HotSpotInstalledCode installedBenchmarkCode = getInstalledCode("stringBufferArrayCopy"); + HotSpotInstalledCode installedBenchmarkCode = getInstalledCode("stringBuilderArrayCopy"); installedBenchmarkCode.executeVarargs(); } - public static void stringBufferArrayCopy() { - StringBuffer buffer = new StringBuffer("TestTestTestTestTestTestTest"); + public static void stringBuilderArrayCopy() { + StringBuilder buffer = new StringBuilder("TestTestTestTestTestTestTest"); Assert.assertTrue(buffer.length() == 28); String a = new String("TestTestTestTestTestTestTest"); char[] dst = new char[buffer.length() * 2]; diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/MemoryUsageBenchmark.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/MemoryUsageBenchmark.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/MemoryUsageBenchmark.java Fri Mar 27 17:02:53 2015 +0100 @@ -63,7 +63,7 @@ return cs.hashCode(); } - if (cs instanceof StringBuffer) { + if (cs instanceof StringBuilder) { int[] hash = {0}; cs.chars().forEach(c -> hash[0] += c); return hash[0]; @@ -180,7 +180,7 @@ compileAndTime("complex"); if (CompileTheWorldClasspath.getValue() != SUN_BOOT_CLASS_PATH) { CompileTheWorld ctw = new CompileTheWorld(CompileTheWorldClasspath.getValue(), new Config(CompileTheWorldConfig.getValue()), CompileTheWorldStartAt.getValue(), - CompileTheWorldStopAt.getValue(), CompileTheWorldVerbose.getValue()); + CompileTheWorldStopAt.getValue(), CompileTheWorldMethodFilter.getValue(), CompileTheWorldVerbose.getValue()); try { ctw.compile(); } catch (Throwable e) { diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java Fri Mar 27 17:02:53 2015 +0100 @@ -34,6 +34,7 @@ import java.util.concurrent.*; import java.util.concurrent.atomic.*; import java.util.jar.*; +import java.util.stream.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.bytecode.*; @@ -41,6 +42,7 @@ import com.oracle.graal.compiler.CompilerThreadFactory.DebugConfigAccess; import com.oracle.graal.compiler.common.*; import com.oracle.graal.debug.*; +import com.oracle.graal.debug.internal.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.options.*; import com.oracle.graal.options.OptionUtils.OptionConsumer; @@ -66,6 +68,8 @@ public static final OptionValue CompileTheWorldVerbose = new OptionValue<>(true); @Option(help = "The number of CompileTheWorld iterations to perform", type = OptionType.Debug) public static final OptionValue CompileTheWorldIterations = new OptionValue<>(1); + @Option(help = "Only compile methods matching this filter", type = OptionType.Debug) + public static final OptionValue CompileTheWorldMethodFilter = new OptionValue<>(null); @Option(help = "First class to consider when using -XX:+CompileTheWorld", type = OptionType.Debug) public static final OptionValue CompileTheWorldStartAt = new OptionValue<>(1); @Option(help = "Last class to consider when using -XX:+CompileTheWorld", type = OptionType.Debug) @@ -75,8 +79,10 @@ "The format for each option is the same as on the command line just without the '-G:' prefix.", type = OptionType.Debug) public static final OptionValue CompileTheWorldConfig = new OptionValue<>(null); - @Option(help = "Last class to consider when using -XX:+CompileTheWorld", type = OptionType.Debug) + @Option(help = "Run CTW using as many threads as there are processors on the system", type = OptionType.Debug) public static final OptionValue CompileTheWorldMultiThreaded = new OptionValue<>(false); + @Option(help = "Number of threads to use for multithreaded CTW. Defaults to Runtime.getRuntime().availableProcessors()", type = OptionType.Debug) + public static final OptionValue CompileTheWorldThreads = new OptionValue<>(0); // @formatter:on /** @@ -149,6 +155,9 @@ /** Class index to stop compilation at (see {@link Options#CompileTheWorldStopAt}). */ private final int stopAt; + /** Only compile methods matching one of the filters in this array if the array is non-null. */ + private final MethodFilter[] methodFilters; + // Counters private int classFileCounter = 0; private AtomicLong compiledMethodsCounter = new AtomicLong(); @@ -158,6 +167,11 @@ private boolean verbose; private final Config config; + /** + * Signal that the threads should start compiling in multithreaded mode. + */ + private boolean running; + private ThreadPoolExecutor threadPool; /** @@ -167,10 +181,11 @@ * @param startAt index of the class file to start compilation at * @param stopAt index of the class file to stop compilation at */ - public CompileTheWorld(String files, Config config, int startAt, int stopAt, boolean verbose) { + public CompileTheWorld(String files, Config config, int startAt, int stopAt, String methodFilters, boolean verbose) { this.files = files; this.startAt = startAt; this.stopAt = stopAt; + this.methodFilters = methodFilters == null || methodFilters.isEmpty() ? null : MethodFilter.parse(methodFilters); this.verbose = verbose; this.config = config; @@ -189,6 +204,11 @@ * files from the boot class path. */ public void compile() throws Throwable { + // By default only report statistics for the CTW threads themselves + if (GraalDebugConfig.DebugValueThreadFilter.hasInitialValue()) { + GraalDebugConfig.DebugValueThreadFilter.setValue("^CompileTheWorld"); + } + if (SUN_BOOT_CLASS_PATH.equals(files)) { final String[] entries = System.getProperty(SUN_BOOT_CLASS_PATH).split(File.pathSeparator); String bcpFiles = ""; @@ -234,15 +254,29 @@ final String[] entries = fileList.split(File.pathSeparator); long start = System.currentTimeMillis(); - if (Options.CompileTheWorldMultiThreaded.getValue()) { - CompilerThreadFactory factory = new CompilerThreadFactory("CompileTheWorld", new DebugConfigAccess() { - public GraalDebugConfig getDebugConfig() { + CompilerThreadFactory factory = new CompilerThreadFactory("CompileTheWorld", new DebugConfigAccess() { + public GraalDebugConfig getDebugConfig() { + if (Debug.isEnabled() && DebugScope.getConfig() == null) { return DebugEnvironment.initialize(System.out); } - }); - int availableProcessors = Runtime.getRuntime().availableProcessors(); - threadPool = new ThreadPoolExecutor(availableProcessors, availableProcessors, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), factory); + return null; + } + }); + + /* + * Always use a thread pool, even for single threaded mode since it simplifies the use of + * DebugValueThreadFilter to filter on the thread names. + */ + int threadCount = 1; + if (Options.CompileTheWorldMultiThreaded.getValue()) { + threadCount = Options.CompileTheWorldThreads.getValue(); + if (threadCount == 0) { + threadCount = Runtime.getRuntime().availableProcessors(); + } + } else { + running = true; } + threadPool = new ThreadPoolExecutor(threadCount, threadCount, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), factory); try (OverrideScope s = config.apply()) { for (int i = 0; i < entries.length; i++) { @@ -255,7 +289,12 @@ continue; } - println("CompileTheWorld : Compiling all classes in " + entry); + if (methodFilters == null || methodFilters.length == 0) { + println("CompileTheWorld : Compiling all classes in " + entry); + } else { + println("CompileTheWorld : Compiling all methods in " + entry + " matching one of the following filters: " + + Arrays.asList(methodFilters).stream().map(MethodFilter::toString).collect(Collectors.joining(", "))); + } println(); URL url = new URL("jar", "", "file:" + entry + "!/"); @@ -276,11 +315,16 @@ } String className = je.getName().substring(0, je.getName().length() - ".class".length()); + String dottedClassName = className.replace('/', '.'); classFileCounter++; + if (methodFilters != null && !MethodFilter.matchesClassName(methodFilters, dottedClassName)) { + continue; + } + try { // Load and initialize class - Class javaClass = Class.forName(className.replace('/', '.'), true, loader); + Class javaClass = Class.forName(dottedClassName, true, loader); // Pre-load all classes in the constant pool. try { @@ -321,22 +365,42 @@ } } - if (threadPool != null) { - while (threadPool.getCompletedTaskCount() != threadPool.getTaskCount()) { - System.out.println("CompileTheWorld : Waiting for " + (threadPool.getTaskCount() - threadPool.getCompletedTaskCount()) + " compiles"); - try { - threadPool.awaitTermination(15, TimeUnit.SECONDS); - } catch (InterruptedException e) { - } + if (!running) { + startThreads(); + } + while (threadPool.getCompletedTaskCount() != threadPool.getTaskCount()) { + TTY.println("CompileTheWorld : Waiting for " + (threadPool.getTaskCount() - threadPool.getCompletedTaskCount()) + " compiles"); + try { + threadPool.awaitTermination(15, TimeUnit.SECONDS); + } catch (InterruptedException e) { } - threadPool = null; } + threadPool = null; long elapsedTime = System.currentTimeMillis() - start; println(); - println("CompileTheWorld : Done (%d classes, %d methods, %d ms elapsed, %d ms compile time, %d bytes of memory used)", classFileCounter, compiledMethodsCounter.get(), elapsedTime, - compileTime.get(), memoryUsed.get()); + if (Options.CompileTheWorldMultiThreaded.getValue()) { + TTY.println("CompileTheWorld : Done (%d classes, %d methods, %d ms elapsed, %d ms compile time, %d bytes of memory used)", classFileCounter, compiledMethodsCounter.get(), elapsedTime, + compileTime.get(), memoryUsed.get()); + } else { + TTY.println("CompileTheWorld : Done (%d classes, %d methods, %d ms, %d bytes of memory used)", classFileCounter, compiledMethodsCounter.get(), compileTime.get(), memoryUsed.get()); + } + } + + private synchronized void startThreads() { + running = true; + // Wake up any waiting threads + notifyAll(); + } + + private synchronized void waitToRun() { + while (!running) { + try { + wait(); + } catch (InterruptedException e) { + } + } } class CTWCompilationTask extends CompilationTask { @@ -355,17 +419,20 @@ } } - private void compileMethod(HotSpotResolvedJavaMethod method) { - if (threadPool != null) { - threadPool.submit(new Runnable() { - public void run() { - try (OverrideScope s = config.apply()) { - compileMethod(method, classFileCounter); - } + private void compileMethod(HotSpotResolvedJavaMethod method) throws InterruptedException, ExecutionException { + if (methodFilters != null && !MethodFilter.matches(methodFilters, method)) { + return; + } + Future task = threadPool.submit(new Runnable() { + public void run() { + waitToRun(); + try (OverrideScope s = config.apply()) { + compileMethod(method, classFileCounter); } - }); - } else { - compileMethod(method, classFileCounter); + } + }); + if (threadPool.getCorePoolSize() == 1) { + task.get(); } } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/DebugValuesPrinter.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/DebugValuesPrinter.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/DebugValuesPrinter.java Fri Mar 27 17:02:53 2015 +0100 @@ -26,6 +26,8 @@ import java.io.*; import java.util.*; +import java.util.regex.*; +import java.util.stream.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.debug.*; @@ -51,6 +53,12 @@ if (summary == null) { summary = "Complete"; } + if (DebugValueThreadFilter.getValue() != null && topLevelMaps.size() != 0) { + topLevelMaps = topLevelMaps.stream().filter(map -> Pattern.compile(DebugValueThreadFilter.getValue()).matcher(map.getName()).find()).collect(Collectors.toList()); + if (topLevelMaps.size() == 0) { + TTY.println("Warning: DebugValueThreadFilter=%s eliminated all maps so nothing will be printed", DebugValueThreadFilter.getValue()); + } + } switch (summary) { case "Name": printSummary(topLevelMaps, sortedValues); diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java Fri Mar 27 17:02:53 2015 +0100 @@ -40,6 +40,7 @@ import com.oracle.graal.lir.LIRInstruction.OperandMode; import com.oracle.graal.lir.StandardOp.LabelOp; import com.oracle.graal.lir.StandardOp.SaveRegistersOp; +import com.oracle.graal.lir.asm.*; import com.oracle.graal.lir.framemap.*; import com.oracle.graal.nodes.*; import com.oracle.graal.options.*; @@ -55,6 +56,9 @@ // @formatter:off @Option(help = "Use Graal stubs instead of HotSpot stubs where possible") public static final OptionValue PreferGraalStubs = new OptionValue<>(false); + @Option(help = "Enables instruction profiling on assembler level. Valid values are a comma separated list of supported instructions." + + " Compare with subclasses of Assembler.InstructionCounter.", type = OptionType.Debug) + public static final OptionValue ASMInstructionProfiling = new OptionValue<>(null); // @formatter:on } @@ -235,4 +239,10 @@ public DisassemblerProvider getDisassembler() { return getProviders().getDisassembler(); } + + protected void profileInstructions(LIR lir, CompilationResultBuilder crb) { + if (HotSpotBackend.Options.ASMInstructionProfiling.getValue() != null) { + HotSpotInstructionProfiling.countInstructions(lir, crb.asm); + } + } } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCounterOp.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCounterOp.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCounterOp.java Fri Mar 27 17:02:53 2015 +0100 @@ -24,6 +24,8 @@ import static com.oracle.graal.api.code.ValueUtil.*; +import java.util.*; + import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; @@ -67,12 +69,42 @@ } protected interface CounterProcedure { - void apply(String name, String group, Value increment); + /** + * Lambda interface for iterating over counters declared in this op. + * + * @param counterIndex Index in this CounterOp object. + * @param increment Value for increment + * @param displacement Displacement in bytes in the counter array + */ + void apply(int counterIndex, Value increment, int displacement); } - protected void forEachCounter(CounterProcedure proc) { - for (int i = 0; i < names.length; i++) { - proc.apply(names[i], groups[i], increments[i]); + /** + * Calls the {@link CounterProcedure} for each counter in ascending order of their displacement + * in the counter array. + * + * @param proc The procedure to be called + * @param target Target architecture (used to calculate the array displacements) + */ + protected void forEachCounter(CounterProcedure proc, TargetDescription target) { + if (names.length == 1) { // fast path + int arrayIndex = getIndex(names[0], groups[0], increments[0]); + int displacement = getDisplacementForLongIndex(target, arrayIndex); + proc.apply(0, increments[0], displacement); + } else { // Slow path with sort by displacements ascending + int[] displacements = new int[names.length]; + HashMap offsetMap = new HashMap<>(names.length); + for (int i = 0; i < names.length; i++) { + int arrayIndex = getIndex(names[i], groups[i], increments[i]); + displacements[i] = getDisplacementForLongIndex(target, arrayIndex); + offsetMap.put(displacements[i], i); + } + Arrays.sort(displacements); + // Now apply in order + for (int offset : displacements) { + int idx = offsetMap.get(offset); + proc.apply(idx, increments[idx], displacements[idx]); + } } } @@ -86,6 +118,17 @@ return BenchmarkCounters.getIndex(name, group, config); } + /** + * Patches the increment value in the instruction emitted by this instruction. Use only, if + * patching is needed after assembly. + * + * @param asm + * @param increment + */ + public void patchCounterIncrement(Assembler asm, int[] increment) { + throw GraalInternalError.unimplemented(); + } + private static long asLong(JavaConstant value) { Kind kind = value.getKind(); switch (kind) { @@ -109,4 +152,11 @@ return (int) l; } + public String[] getNames() { + return names; + } + + public String[] getGroups() { + return groups; + } } diff -r d22307a9a025 -r eea134855f85 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 Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Fri Mar 27 17:02:53 2015 +0100 @@ -110,9 +110,9 @@ this.compilerToVm = toVM; - if (Log.getValue() == null && Meter.getValue() == null && Time.getValue() == null && Dump.getValue() == null && Verify.getValue() == null) { + if (Log.getValue() == null && !areScopedMetricsOrTimersEnabled() && Dump.getValue() == null && Verify.getValue() == null) { if (MethodFilter.getValue() != null) { - TTY.println("WARNING: Ignoring MethodFilter option since Log, Meter, Time, Dump and Verify options are all null"); + TTY.println("WARNING: Ignoring MethodFilter option since Log, Meter, Time, TrackMemUse, Dump and Verify options are all null"); } } @@ -133,7 +133,7 @@ } } - if (Debug.areUnconditionalMetricsEnabled() || Debug.areUnconditionalTimersEnabled() || (Debug.isEnabled() && areMetricsOrTimersEnabled())) { + if (Debug.areUnconditionalMetricsEnabled() || Debug.areUnconditionalTimersEnabled() || (Debug.isEnabled() && areScopedMetricsOrTimersEnabled())) { // This must be created here to avoid loading the DebugValuesPrinter class // during shutdown() which in turn can cause a deadlock debugValuesPrinter = new DebugValuesPrinter(); @@ -552,7 +552,7 @@ getCompilerToVM().resetCompilationStatistics(); TTY.println("CompileTheWorld : iteration " + i); CompileTheWorld ctw = new CompileTheWorld(CompileTheWorldClasspath.getValue(), new Config(CompileTheWorldConfig.getValue()), CompileTheWorldStartAt.getValue(), - CompileTheWorldStopAt.getValue(), CompileTheWorldVerbose.getValue()); + CompileTheWorldStopAt.getValue(), CompileTheWorldMethodFilter.getValue(), CompileTheWorldVerbose.getValue()); ctw.compile(); } System.exit(0); diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java Fri Mar 27 17:02:53 2015 +0100 @@ -88,7 +88,6 @@ } if (BootstrapReplacements.getValue()) { for (ResolvedJavaMethod method : replacements.getAllReplacements()) { - replacements.getMacroSubstitution(method); replacements.getMethodSubstitution(method); } } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotInstructionProfiling.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotInstructionProfiling.java Fri Mar 27 17:02:53 2015 +0100 @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2015, 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; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.*; +import com.oracle.graal.asm.Assembler.*; +import com.oracle.graal.compiler.common.cfg.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.StandardOp.BlockEndOp; +import com.oracle.graal.lir.StandardOp.LabelOp; +import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.gen.*; +import com.oracle.graal.lir.phases.*; + +public class HotSpotInstructionProfiling extends PostAllocationOptimizationPhase { + public static final String COUNTER_GROUP = "INSTRUCTION_COUNTER"; + private final String[] instructionsToProfile; + + public HotSpotInstructionProfiling(String instructionsToProfile) { + this.instructionsToProfile = instructionsToProfile.split(","); + } + + @Override + protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, + BenchmarkCounterFactory counterFactory) { + new Analyzer(lirGenRes.getCompilationUnitName(), lirGenRes.getLIR(), counterFactory).run(); + } + + private class Analyzer { + private final LIR lir; + private final BenchmarkCounterFactory counterFactory; + private final LIRInsertionBuffer buffer; + private final String compilationUnitName; + + public Analyzer(String compilationUnitName, LIR lir, BenchmarkCounterFactory counterFactory) { + this.lir = lir; + this.compilationUnitName = compilationUnitName; + this.counterFactory = counterFactory; + this.buffer = new LIRInsertionBuffer(); + } + + public void run() { + for (AbstractBlockBase block : lir.getControlFlowGraph().getBlocks()) { + doBlock(block); + } + } + + public void doBlock(AbstractBlockBase block) { + List instructions = lir.getLIRforBlock(block); + assert instructions.size() >= 2 : "Malformed block: " + block + ", " + instructions; + assert instructions.get(instructions.size() - 1) instanceof BlockEndOp : "Not a BlockEndOp: " + instructions.get(instructions.size() - 1); + assert !(instructions.get(instructions.size() - 2) instanceof BlockEndOp) : "Is a BlockEndOp: " + instructions.get(instructions.size() - 2); + assert instructions.get(0) instanceof LabelOp : "Not a LabelOp: " + instructions.get(0); + assert !(instructions.get(1) instanceof LabelOp) : "Is a LabelOp: " + instructions.get(1); + String[] names = new String[instructionsToProfile.length]; + String[] groups = new String[instructionsToProfile.length]; + Value[] increments = new Value[instructionsToProfile.length]; + for (int i = 0; i < instructionsToProfile.length; i++) { + names[i] = compilationUnitName; + groups[i] = COUNTER_GROUP + " " + instructionsToProfile[i]; + increments[i] = JavaConstant.INT_0; + } + HotSpotCounterOp op = (HotSpotCounterOp) counterFactory.createMultiBenchmarkCounter(names, groups, increments); + LIRInstruction inst = new InstructionCounterOp(op, instructionsToProfile); + assert inst != null; + buffer.init(instructions); + buffer.append(1, inst); + buffer.finish(); + } + } + + /** + * After assembly the {@link HotSpotBackend#profileInstructions(LIR, CompilationResultBuilder)} + * calls this method for patching the instruction counts into the coutner increment code. + */ + public static void countInstructions(LIR lir, Assembler asm) { + InstructionCounterOp lastOp = null; + InstructionCounter counter = asm.getInstructionCounter(); + for (AbstractBlockBase block : lir.codeEmittingOrder()) { + for (LIRInstruction inst : lir.getLIRforBlock(block)) { + if (inst instanceof InstructionCounterOp) { + InstructionCounterOp currentOp = (InstructionCounterOp) inst; + + if (lastOp != null) { + int beginPc = lastOp.countOffsetEnd; + int endPc = currentOp.countOffsetBegin; + int[] instructionCounts = counter.countInstructions(lastOp.instructionsToProfile, beginPc, endPc); + lastOp.delegate.patchCounterIncrement(asm, instructionCounts); + } + lastOp = ((InstructionCounterOp) inst); + } + } + } + if (lastOp != null) { + assert lastOp.countOffsetBegin < asm.position(); + int beginPc = lastOp.countOffsetBegin; + int endPc = asm.position(); + int[] instructionCounts = counter.countInstructions(lastOp.instructionsToProfile, beginPc, endPc); + lastOp.delegate.patchCounterIncrement(asm, instructionCounts); + } + } + + public static class InstructionCounterOp extends LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(InstructionCounterOp.class); + private final HotSpotCounterOp delegate; + private final String[] instructionsToProfile; + private int countOffsetBegin; + private int countOffsetEnd; + + public InstructionCounterOp(HotSpotCounterOp delegate, String[] instructionsToProfile) { + super(TYPE); + this.delegate = delegate; + this.instructionsToProfile = instructionsToProfile; + } + + @Override + public void emitCode(CompilationResultBuilder crb) { + countOffsetBegin = crb.asm.position(); + this.delegate.emitCode(crb); + countOffsetEnd = crb.asm.position(); + } + + public String[] getInstructionsToProfile() { + return instructionsToProfile; + } + } +} diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java Fri Mar 27 17:02:53 2015 +0100 @@ -63,6 +63,15 @@ if (areDebugScopePatternsEnabled()) { System.setProperty(Debug.Initialization.INITIALIZER_PROPERTY_NAME, "true"); } + if ("".equals(Meter.getValue())) { + System.setProperty(Debug.ENABLE_UNSCOPED_METRICS_PROPERTY_NAME, "true"); + } + if ("".equals(Time.getValue())) { + System.setProperty(Debug.ENABLE_UNSCOPED_TIMERS_PROPERTY_NAME, "true"); + } + if ("".equals(TrackMemUse.getValue())) { + System.setProperty(Debug.ENABLE_UNSCOPED_MEM_USE_TRACKERS_PROPERTY_NAME, "true"); + } } /** diff -r d22307a9a025 -r eea134855f85 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 Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java Fri Mar 27 17:02:53 2015 +0100 @@ -28,9 +28,8 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; import com.oracle.graal.compiler.common.*; -import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.replacements.*; -import com.oracle.graal.nodes.*; +import com.oracle.graal.hotspot.word.*; import com.oracle.graal.phases.util.*; import com.oracle.graal.replacements.*; @@ -48,6 +47,11 @@ } @Override + protected boolean hasGenericInvocationPluginAnnotation(ResolvedJavaMethod method) { + return method.getAnnotation(HotSpotOperation.class) != null || super.hasGenericInvocationPluginAnnotation(method); + } + + @Override protected ResolvedJavaMethod registerMethodSubstitution(ClassReplacements cr, Executable originalMethod, Method substituteMethod) { final Class substituteClass = substituteMethod.getDeclaringClass(); if (substituteClass == IntegerSubstitutions.class || substituteClass == LongSubstitutions.class) { @@ -75,21 +79,4 @@ } return super.registerMethodSubstitution(cr, originalMethod, substituteMethod); } - - @Override - public Class getMacroSubstitution(ResolvedJavaMethod method) { - HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) method; - int intrinsicId = hsMethod.intrinsicId(); - if (intrinsicId != 0) { - /* - * The methods of MethodHandle that need substitution are signature-polymorphic, i.e., - * the VM replicates them for every signature that they are actually used for. - * Therefore, we cannot use the usual annotation-driven mechanism to define the - */ - if (MethodHandleNode.lookupMethodHandleIntrinsic(method, providers.getConstantReflection().getMethodHandleAccess()) != null) { - return MethodHandleNode.class; - } - } - return super.getMacroSubstitution(method); - } } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java Fri Mar 27 17:02:53 2015 +0100 @@ -24,6 +24,10 @@ import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; +import java.lang.invoke.*; + +import sun.reflect.*; + import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; @@ -35,7 +39,9 @@ import com.oracle.graal.graphbuilderconf.InvocationPlugins.Registration; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.hotspot.nodes.ClassQueryNode.Query; import com.oracle.graal.hotspot.replacements.*; +import com.oracle.graal.hotspot.replacements.arraycopy.*; import com.oracle.graal.hotspot.word.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.HeapAccess.BarrierType; @@ -60,7 +66,7 @@ */ public static Plugins create(HotSpotVMConfig config, HotSpotWordTypes wordTypes, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, SnippetReflectionProvider snippetReflection, ForeignCallsProvider foreignCalls, StampProvider stampProvider, ReplacementsImpl replacements, Architecture arch) { - InvocationPlugins invocationPlugins = new HotSpotInvocationPlugins(config, metaAccess); + InvocationPlugins invocationPlugins = new HotSpotInvocationPlugins(config, metaAccess, constantReflection.getMethodHandleAccess()); Plugins plugins = new Plugins(invocationPlugins); NodeIntrinsificationPhase nodeIntrinsification = new NodeIntrinsificationPhase(metaAccess, constantReflection, snippetReflection, foreignCalls, stampProvider); @@ -69,12 +75,15 @@ plugins.setParameterPlugin(new HotSpotParameterPlugin(wordTypes)); plugins.setLoadFieldPlugin(new HotSpotLoadFieldPlugin(metaAccess, constantReflection)); plugins.setLoadIndexedPlugin(new HotSpotLoadIndexedPlugin(wordTypes)); - plugins.setInlineInvokePlugin(new HotSpotInlineInvokePlugin(nodeIntrinsification, replacements)); - plugins.setGenericInvocationPlugin(new DefaultGenericInvocationPlugin(nodeIntrinsification, wordOperationPlugin)); + plugins.setInlineInvokePlugin(new DefaultInlineInvokePlugin(replacements)); + plugins.setGenericInvocationPlugin(new DefaultGenericInvocationPlugin(metaAccess, nodeIntrinsification, wordOperationPlugin)); registerObjectPlugins(invocationPlugins); + registerClassPlugins(invocationPlugins); registerSystemPlugins(invocationPlugins, foreignCalls); registerThreadPlugins(invocationPlugins, metaAccess, wordTypes, config); + registerCallSitePlugins(invocationPlugins); + registerReflectionPlugins(invocationPlugins); registerStableOptionPlugins(invocationPlugins); StandardGraphBuilderPlugins.registerInvocationPlugins(metaAccess, arch, invocationPlugins, !config.useHeapProfiler); @@ -89,13 +98,79 @@ ObjectStamp objectStamp = (ObjectStamp) rcvr.stamp(); ValueNode mirror; if (objectStamp.isExactType() && objectStamp.nonNull() && !GraalOptions.ImmutableCode.getValue()) { - mirror = b.append(ConstantNode.forConstant(objectStamp.type().getJavaClass(), b.getMetaAccess())); + mirror = ConstantNode.forConstant(objectStamp.type().getJavaClass(), b.getMetaAccess()); } else { StampProvider stampProvider = b.getStampProvider(); - LoadHubNode hub = b.append(new LoadHubNode(stampProvider, rcvr)); - mirror = b.append(new HubGetClassNode(b.getMetaAccess(), hub)); + LoadHubNode hub = b.add(new LoadHubNode(stampProvider, rcvr)); + mirror = new HubGetClassNode(b.getMetaAccess(), hub); + } + b.addPush(Kind.Object, mirror); + return true; + } + }); + r.register1("clone", Receiver.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { + ValueNode object = receiver.get(); + b.addPush(Kind.Object, new ObjectCloneNode(b.getInvokeKind(), targetMethod, b.bci(), b.getInvokeReturnType(), object)); + return true; + } + }); + } + + private static void registerClassPlugins(InvocationPlugins plugins) { + Registration r = new Registration(plugins, Class.class); + + for (Query query : Query.values()) { + r.register1(query.name(), Receiver.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { + ValueNode javaClass = receiver.get(); + ValueNode folded = ClassQueryNode.tryFold(javaClass, query, b.getMetaAccess(), b.getConstantReflection()); + if (folded != null) { + b.addPush(query.returnKind, folded); + } else { + b.addPush(query.returnKind, new ClassQueryNode(b.getInvokeKind(), targetMethod, query, b.bci(), b.getInvokeReturnType(), javaClass)); + } + return true; } - b.push(Kind.Object, mirror); + }); + } + r.register2("cast", Receiver.class, Object.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode object) { + ValueNode javaClass = receiver.get(); + ValueNode folded = ClassCastNode.tryFold(javaClass, object, b.getConstantReflection(), b.getAssumptions()); + if (folded != null) { + b.addPush(Kind.Object, folded); + } else { + b.addPush(Kind.Object, new ClassCastNode(b.getInvokeKind(), targetMethod, b.bci(), b.getInvokeReturnType(), javaClass, object)); + } + return true; + } + }); + } + + private static void registerCallSitePlugins(InvocationPlugins plugins) { + InvocationPlugin plugin = new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { + ValueNode callSite = receiver.get(); + ValueNode folded = CallSiteTargetNode.tryFold(callSite, b.getMetaAccess(), b.getAssumptions()); + if (folded != null) { + b.addPush(Kind.Object, folded); + } else { + b.addPush(Kind.Object, new CallSiteTargetNode(b.getInvokeKind(), targetMethod, b.bci(), b.getInvokeReturnType(), callSite)); + } + return true; + } + }; + plugins.register(plugin, ConstantCallSite.class, "getTarget", Receiver.class); + plugins.register(plugin, MutableCallSite.class, "getTarget", Receiver.class); + plugins.register(plugin, VolatileCallSite.class, "getTarget", Receiver.class); + } + + private static void registerReflectionPlugins(InvocationPlugins plugins) { + Registration r = new Registration(plugins, Reflection.class); + r.register0("getCallerClass", new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { + b.addPush(new ReflectionGetCallerClassNode(b.getInvokeKind(), targetMethod, b.bci(), b.getInvokeReturnType())); return true; } }); @@ -105,17 +180,25 @@ Registration r = new Registration(plugins, System.class); r.register0("currentTimeMillis", new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { - ForeignCallNode foreignCall = new ForeignCallNode(foreignCalls, SystemSubstitutions.JAVA_TIME_MILLIS, StampFactory.forKind(Kind.Long)); - b.push(Kind.Long, b.append(foreignCall)); - foreignCall.setStateAfter(b.createStateAfter()); + b.addPush(Kind.Long, new ForeignCallNode(foreignCalls, SystemSubstitutions.JAVA_TIME_MILLIS, StampFactory.forKind(Kind.Long))); return true; } }); r.register0("nanoTime", new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { - ForeignCallNode foreignCall = new ForeignCallNode(foreignCalls, SystemSubstitutions.JAVA_TIME_NANOS, StampFactory.forKind(Kind.Long)); - b.push(Kind.Long, b.append(foreignCall)); - foreignCall.setStateAfter(b.createStateAfter()); + b.addPush(Kind.Long, new ForeignCallNode(foreignCalls, SystemSubstitutions.JAVA_TIME_NANOS, StampFactory.forKind(Kind.Long))); + return true; + } + }); + r.register1("identityHashCode", Object.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode object) { + b.addPush(new SystemIdentityHashCodeNode(b.getInvokeKind(), targetMethod, b.bci(), b.getInvokeReturnType(), object)); + return true; + } + }); + r.register5("arraycopy", Object.class, int.class, Object.class, int.class, int.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode src, ValueNode srcPos, ValueNode dst, ValueNode dstPos, ValueNode length) { + b.add(new ArrayCopyNode(b.getInvokeKind(), targetMethod, b.bci(), b.getInvokeReturnType(), src, srcPos, dst, dstPos, length)); return true; } }); @@ -125,13 +208,13 @@ Registration r = new Registration(plugins, Thread.class); r.register0("currentThread", new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { - CurrentJavaThreadNode thread = b.append(new CurrentJavaThreadNode(wordTypes.getWordKind())); - ConstantLocationNode location = b.append(new ConstantLocationNode(JAVA_THREAD_THREAD_OBJECT_LOCATION, config.threadObjectOffset)); + CurrentJavaThreadNode thread = b.add(new CurrentJavaThreadNode(wordTypes.getWordKind())); + ConstantLocationNode location = b.add(new ConstantLocationNode(JAVA_THREAD_THREAD_OBJECT_LOCATION, config.threadObjectOffset)); boolean compressible = false; ValueNode javaThread = WordOperationPlugin.readOp(b, Kind.Object, thread, location, BarrierType.NONE, compressible); boolean exactType = compressible; boolean nonNull = true; - b.push(Kind.Object, b.append(new PiNode(javaThread, metaAccess.lookupJavaType(Thread.class), exactType, nonNull))); + b.addPush(Kind.Object, new PiNode(javaThread, metaAccess.lookupJavaType(Thread.class), exactType, nonNull)); return true; } }); @@ -144,8 +227,7 @@ if (receiver.isConstant()) { Object object = ((HotSpotObjectConstantImpl) receiver.get().asConstant()).object(); StableOptionValue option = (StableOptionValue) object; - ConstantNode value = b.append(ConstantNode.forConstant(HotSpotObjectConstantImpl.forObject(option.getValue()), b.getMetaAccess())); - b.push(Kind.Object, value); + b.addPush(Kind.Object, ConstantNode.forConstant(HotSpotObjectConstantImpl.forObject(option.getValue()), b.getMetaAccess())); return true; } return false; diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInlineInvokePlugin.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInlineInvokePlugin.java Fri Mar 27 15:43:31 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,89 +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. - */ -package com.oracle.graal.hotspot.meta; - -import static com.oracle.graal.compiler.common.GraalOptions.*; -import static com.oracle.graal.java.AbstractBytecodeParser.Options.*; -import static java.lang.String.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.*; -import com.oracle.graal.graph.Node.NodeIntrinsic; -import com.oracle.graal.graphbuilderconf.*; -import com.oracle.graal.graphbuilderconf.GraphBuilderContext.Replacement; -import com.oracle.graal.hotspot.word.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.replacements.*; -import com.oracle.graal.word.*; - -public final class HotSpotInlineInvokePlugin implements InlineInvokePlugin { - private final ReplacementsImpl replacements; - private final NodeIntrinsificationPhase nodeIntrinsification; - - public HotSpotInlineInvokePlugin(NodeIntrinsificationPhase nodeIntrinsification, ReplacementsImpl replacements) { - this.nodeIntrinsification = nodeIntrinsification; - this.replacements = replacements; - } - - private static final int MAX_GRAPH_INLINING_DEPTH = 100; // more than enough - - public InlineInfo getInlineInfo(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args, JavaType returnType) { - ResolvedJavaMethod subst = replacements.getMethodSubstitutionMethod(method); - if (subst != null) { - if (b.parsingReplacement() || InlineDuringParsing.getValue()) { - // Forced inlining of intrinsics - return new InlineInfo(subst, true, true); - } - } - if (b.parsingReplacement()) { - assert nodeIntrinsification.getIntrinsic(method) == null && method.getAnnotation(Word.Operation.class) == null && method.getAnnotation(HotSpotOperation.class) == null && - !nodeIntrinsification.isFoldable(method) : format("%s should have been handled by %s", method.format("%H.%n(%p)"), DefaultGenericInvocationPlugin.class.getName()); - - assert b.getDepth() < MAX_GRAPH_INLINING_DEPTH : "inlining limit exceeded"; - - if (method.getName().startsWith("$jacoco")) { - throw new GraalInternalError("Found call to JaCoCo instrumentation method " + method.format("%H.%n(%p)") + ". Placing \"//JaCoCo Exclude\" anywhere in " + - b.getMethod().getDeclaringClass().getSourceFileName() + " should fix this."); - } - - // Force inlining when parsing replacements - return new InlineInfo(method, true, true); - } else { - assert nodeIntrinsification.getIntrinsic(method) == null : String.format("@%s method %s must only be called from within a replacement%n%s", NodeIntrinsic.class.getSimpleName(), - method.format("%h.%n"), b); - if (InlineDuringParsing.getValue() && method.hasBytecodes() && method.getCode().length <= TrivialInliningSize.getValue() && b.getDepth() < InlineDuringParsingMaxDepth.getValue()) { - return new InlineInfo(method, false, false); - } - } - return null; - } - - public void notifyOfNoninlinedInvoke(GraphBuilderContext b, ResolvedJavaMethod method, Invoke invoke) { - if (b.parsingReplacement()) { - boolean compilingSnippet = b.getRootMethod().getAnnotation(Snippet.class) != null; - Replacement replacement = b.getReplacement(); - assert compilingSnippet : format("All calls in the replacement %s must be inlined or intrinsified: found call to %s", replacement.getReplacementMethod().format("%H.%n(%p)"), - method.format("%h.%n(%p)")); - } - } -} diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInvocationPlugins.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInvocationPlugins.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInvocationPlugins.java Fri Mar 27 17:02:53 2015 +0100 @@ -22,14 +22,22 @@ */ package com.oracle.graal.hotspot.meta; +import static com.oracle.graal.hotspot.meta.HotSpotMethodHandleAccessProvider.*; + +import java.lang.invoke.*; +import java.util.*; + import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.meta.MethodHandleAccessProvider.IntrinsicMethod; import com.oracle.graal.compiler.common.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.iterators.*; import com.oracle.graal.graphbuilderconf.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.phases.*; +import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.replacements.StandardGraphBuilderPlugins.BoxPlugin; /** @@ -37,10 +45,12 @@ */ final class HotSpotInvocationPlugins extends InvocationPlugins { final HotSpotVMConfig config; + final MethodHandleAccessProvider methodHandleAccess; - public HotSpotInvocationPlugins(HotSpotVMConfig config, MetaAccessProvider metaAccess) { + public HotSpotInvocationPlugins(HotSpotVMConfig config, MetaAccessProvider metaAccess, MethodHandleAccessProvider methodHandleAccess) { super(metaAccess); this.config = config; + this.methodHandleAccess = methodHandleAccess; } @Override @@ -74,6 +84,68 @@ super.register(plugin, declaringClass, name, argumentTypes); } + private ResolvedJavaType methodHandleClass; + private final Map methodHandlePlugins = new EnumMap<>(IntrinsicMethod.class); + + @Override + public InvocationPlugin lookupInvocation(ResolvedJavaMethod method) { + if (methodHandleClass == null) { + methodHandleClass = metaAccess.lookupJavaType(MethodHandle.class); + } + if (method.getDeclaringClass().equals(methodHandleClass)) { + HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) method; + int intrinsicId = hsMethod.intrinsicId(); + if (intrinsicId != 0) { + /* + * The methods of MethodHandle that need substitution are signature-polymorphic, + * i.e., the VM replicates them for every signature that they are actually used for. + */ + IntrinsicMethod intrinsicMethod = getMethodHandleIntrinsic(intrinsicId); + if (intrinsicMethod != null) { + InvocationPlugin plugin = methodHandlePlugins.get(intrinsicMethod); + if (plugin == null) { + plugin = new InvocationPlugin() { + public boolean applyPolymorphic(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode... argsIncludingReceiver) { + InvokeKind invokeKind = b.getInvokeKind(); + if (invokeKind != InvokeKind.Static) { + receiver.get(); + } + JavaType invokeReturnType = b.getInvokeReturnType(); + InvokeNode invoke = MethodHandleNode.tryResolveTargetInvoke(b.getAssumptions(), b.getConstantReflection().getMethodHandleAccess(), intrinsicMethod, targetMethod, + b.bci(), invokeReturnType, argsIncludingReceiver); + if (invoke == null) { + MethodHandleNode methodHandleNode = new MethodHandleNode(intrinsicMethod, invokeKind, targetMethod, b.bci(), invokeReturnType, argsIncludingReceiver); + if (invokeReturnType.getKind() == Kind.Void) { + b.add(methodHandleNode); + } else { + b.addPush(methodHandleNode); + } + } else { + CallTargetNode callTarget = invoke.callTarget(); + NodeInputList argumentsList = callTarget.arguments(); + ValueNode[] args = argumentsList.toArray(new ValueNode[argumentsList.size()]); + for (ValueNode arg : args) { + b.recursiveAppend(arg); + } + b.handleReplacedInvoke(invoke.getInvokeKind(), callTarget.targetMethod(), args); + } + return true; + } + + public boolean isSignaturePolymorphic() { + return true; + } + }; + methodHandlePlugins.put(intrinsicMethod, plugin); + } + return plugin; + } + } + + } + return super.lookupInvocation(method); + } + @Override public void checkNewNodes(GraphBuilderContext b, InvocationPlugin plugin, NodeIterable newNodes) { if (GraalOptions.ImmutableCode.getValue()) { diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoadFieldPlugin.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoadFieldPlugin.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoadFieldPlugin.java Fri Mar 27 17:02:53 2015 +0100 @@ -75,8 +75,7 @@ // HotSpotInlineInvokePlugin.notifyOfNoninlinedInvoke). Direct use of // assertions in intrinsics is forbidden. assert b.getMethod().getAnnotation(MethodSubstitution.class) == null : "cannot use assertions in " + b.getMethod().format("%H.%n(%p)"); - ConstantNode trueNode = b.append(ConstantNode.forBoolean(true)); - b.push(trueNode.getKind().getStackKind(), trueNode); + b.addPush(ConstantNode.forBoolean(true)); return true; } return tryReadField(b, staticField, null); diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoadIndexedPlugin.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoadIndexedPlugin.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoadIndexedPlugin.java Fri Mar 27 17:02:53 2015 +0100 @@ -54,9 +54,9 @@ */ Stamp componentStamp = wordTypes.getWordStamp(arrayType.getComponentType()); if (componentStamp instanceof MetaspacePointerStamp) { - b.push(elementKind, b.append(new LoadIndexedPointerNode(componentStamp, array, index))); + b.addPush(elementKind, new LoadIndexedPointerNode(componentStamp, array, index)); } else { - b.push(elementKind, b.append(new LoadIndexedNode(array, index, wordTypes.getWordKind()))); + b.addPush(elementKind, new LoadIndexedNode(array, index, wordTypes.getWordKind())); } return true; } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodHandleAccessProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodHandleAccessProvider.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodHandleAccessProvider.java Fri Mar 27 17:02:53 2015 +0100 @@ -98,18 +98,23 @@ public IntrinsicMethod lookupMethodHandleIntrinsic(ResolvedJavaMethod method) { int intrinsicId = ((HotSpotResolvedJavaMethodImpl) method).intrinsicId(); if (intrinsicId != 0) { - HotSpotVMConfig config = runtime().getConfig(); - if (intrinsicId == config.vmIntrinsicInvokeBasic) { - return IntrinsicMethod.INVOKE_BASIC; - } else if (intrinsicId == config.vmIntrinsicLinkToInterface) { - return IntrinsicMethod.LINK_TO_INTERFACE; - } else if (intrinsicId == config.vmIntrinsicLinkToSpecial) { - return IntrinsicMethod.LINK_TO_SPECIAL; - } else if (intrinsicId == config.vmIntrinsicLinkToStatic) { - return IntrinsicMethod.LINK_TO_STATIC; - } else if (intrinsicId == config.vmIntrinsicLinkToVirtual) { - return IntrinsicMethod.LINK_TO_VIRTUAL; - } + return getMethodHandleIntrinsic(intrinsicId); + } + return null; + } + + public static IntrinsicMethod getMethodHandleIntrinsic(int intrinsicId) { + HotSpotVMConfig config = runtime().getConfig(); + if (intrinsicId == config.vmIntrinsicInvokeBasic) { + return IntrinsicMethod.INVOKE_BASIC; + } else if (intrinsicId == config.vmIntrinsicLinkToInterface) { + return IntrinsicMethod.LINK_TO_INTERFACE; + } else if (intrinsicId == config.vmIntrinsicLinkToSpecial) { + return IntrinsicMethod.LINK_TO_SPECIAL; + } else if (intrinsicId == config.vmIntrinsicLinkToStatic) { + return IntrinsicMethod.LINK_TO_STATIC; + } else if (intrinsicId == config.vmIntrinsicLinkToVirtual) { + return IntrinsicMethod.LINK_TO_VIRTUAL; } return null; } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectTypeImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectTypeImpl.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectTypeImpl.java Fri Mar 27 17:02:53 2015 +0100 @@ -160,8 +160,9 @@ if (leafConcreteSubtype != null) { assert !leafConcreteSubtype.getResult().equals(implementor); AssumptionResult newResult = new AssumptionResult<>(leafConcreteSubtype.getResult(), new ConcreteSubtype(this, implementor)); + // Accumulate leaf assumptions and return the combined result. newResult.add(leafConcreteSubtype); - return leafConcreteSubtype; + return newResult; } return null; } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java Fri Mar 27 17:02:53 2015 +0100 @@ -132,7 +132,11 @@ } public LIRSuites createLIRSuites() { - return Suites.createDefaultLIRSuites(); + LIRSuites suites = Suites.createDefaultLIRSuites(); + String profileInstructions = HotSpotBackend.Options.ASMInstructionProfiling.getValue(); + if (profileInstructions != null) { + suites.getPostAllocationOptimizationStage().appendPhase(new HotSpotInstructionProfiling(profileInstructions)); + } + return suites; } - } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotWordOperationPlugin.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotWordOperationPlugin.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotWordOperationPlugin.java Fri Mar 27 17:02:53 2015 +0100 @@ -79,10 +79,10 @@ assert right.stamp() instanceof MetaspacePointerStamp : right + " " + right.stamp(); assert opcode == POINTER_EQ || opcode == POINTER_NE; - PointerEqualsNode comparison = b.append(new PointerEqualsNode(left, right)); - ValueNode eqValue = b.append(forBoolean(opcode == POINTER_EQ)); - ValueNode neValue = b.append(forBoolean(opcode == POINTER_NE)); - b.push(returnStackKind, b.append(new ConditionalNode(comparison, eqValue, neValue))); + PointerEqualsNode comparison = b.add(new PointerEqualsNode(left, right)); + ValueNode eqValue = b.add(forBoolean(opcode == POINTER_EQ)); + ValueNode neValue = b.add(forBoolean(opcode == POINTER_NE)); + b.addPush(returnStackKind, new ConditionalNode(comparison, eqValue, neValue)); break; case IS_NULL: @@ -90,23 +90,23 @@ ValueNode pointer = args[0]; assert pointer.stamp() instanceof MetaspacePointerStamp; - IsNullNode isNull = b.append(new IsNullNode(pointer)); - b.push(returnStackKind, b.append(new ConditionalNode(isNull, b.append(forBoolean(true)), b.append(forBoolean(false))))); + IsNullNode isNull = b.add(new IsNullNode(pointer)); + b.addPush(returnStackKind, new ConditionalNode(isNull, b.add(forBoolean(true)), b.add(forBoolean(false)))); break; case FROM_POINTER: assert args.length == 1; - b.push(returnStackKind, b.append(new PointerCastNode(StampFactory.forKind(wordKind), args[0]))); + b.addPush(returnStackKind, new PointerCastNode(StampFactory.forKind(wordKind), args[0])); break; case TO_KLASS_POINTER: assert args.length == 1; - b.push(returnStackKind, b.append(new PointerCastNode(KlassPointerStamp.klass(), args[0]))); + b.addPush(returnStackKind, new PointerCastNode(KlassPointerStamp.klass(), args[0])); break; case TO_METHOD_POINTER: assert args.length == 1; - b.push(returnStackKind, b.append(new PointerCastNode(MethodPointerStamp.method(), args[0]))); + b.addPush(returnStackKind, new PointerCastNode(MethodPointerStamp.method(), args[0])); break; case READ_KLASS_POINTER: @@ -118,7 +118,7 @@ } else { location = makeLocation(b, args[1], args[2]); } - ReadNode read = b.append(new ReadNode(args[0], location, readStamp, BarrierType.NONE)); + ReadNode read = b.add(new ReadNode(args[0], location, readStamp, BarrierType.NONE)); /* * The read must not float outside its block otherwise it may float above an * explicit zero check on its base address. diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassCastNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassCastNode.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassCastNode.java Fri Mar 27 17:02:53 2015 +0100 @@ -25,24 +25,23 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; -import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.util.*; import com.oracle.graal.replacements.nodes.*; /** * {@link MacroNode Macro node} for {@link Class#cast(Object)}. - * - * @see HotSpotClassSubstitutions#cast(Class, Object) */ @NodeInfo public final class ClassCastNode extends MacroStateSplitNode implements Canonicalizable.Binary { public static final NodeClass TYPE = NodeClass.create(ClassCastNode.class); - public ClassCastNode(Invoke invoke) { - super(TYPE, invoke); + public ClassCastNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, int bci, JavaType returnType, ValueNode receiver, ValueNode object) { + super(TYPE, invokeKind, targetMethod, bci, returnType, receiver, object); } private ValueNode getJavaClass() { @@ -63,12 +62,18 @@ @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forJavaClass, ValueNode forObject) { - if (forJavaClass.isConstant()) { - ResolvedJavaType type = tool.getConstantReflection().asJavaType(forJavaClass.asConstant()); + ValueNode folded = tryFold(forJavaClass, forObject, tool.getConstantReflection(), null); + return folded != null ? folded : this; + } + + public static ValueNode tryFold(ValueNode javaClass, ValueNode object, ConstantReflectionProvider constantReflection, Assumptions assumptions) { + ValueNode value = GraphUtil.originalValue(javaClass); + if (value.isConstant()) { + ResolvedJavaType type = constantReflection.asJavaType(value.asConstant()); if (type != null && !type.isPrimitive()) { - return new CheckCastNode(type, forObject, null, false); + return CheckCastNode.create(type, object, null, false, assumptions); } } - return this; + return null; } } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetClassLoader0Node.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetClassLoader0Node.java Fri Mar 27 15:43:31 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.hotspot.nodes; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.spi.*; -import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.hotspot.replacements.*; -import com.oracle.graal.nodeinfo.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.replacements.nodes.*; - -/** - * {@link MacroNode Macro node} for {@link Class#getClassLoader0()}. - * - * @see HotSpotClassSubstitutions#getClassLoader0(Class) - */ -@SuppressWarnings("javadoc") -@NodeInfo -public final class ClassGetClassLoader0Node extends MacroStateSplitNode implements Canonicalizable { - - public static final NodeClass TYPE = NodeClass.create(ClassGetClassLoader0Node.class); - - public ClassGetClassLoader0Node(Invoke invoke) { - super(TYPE, invoke); - } - - private ValueNode getJavaClass() { - return arguments.get(0); - } - - @Override - public Node canonical(CanonicalizerTool tool) { - ValueNode javaClass = getJavaClass(); - if (javaClass.isConstant() && !GraalOptions.ImmutableCode.getValue()) { - HotSpotObjectConstant c = (HotSpotObjectConstant) javaClass.asConstant(); - JavaConstant classLoader = c.getClassLoader(); - if (classLoader != null) { - return ConstantNode.forConstant(classLoader, tool.getMetaAccess()); - } - } - return this; - } -} diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetComponentTypeNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetComponentTypeNode.java Fri Mar 27 15:43:31 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.hotspot.nodes; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.spi.*; -import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.hotspot.replacements.*; -import com.oracle.graal.nodeinfo.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.replacements.nodes.*; - -/** - * {@link MacroNode Macro node} for {@link Class#getComponentType()}. - * - * @see HotSpotClassSubstitutions#getComponentType(Class) - */ -@NodeInfo -public final class ClassGetComponentTypeNode extends MacroNode implements Canonicalizable { - - public static final NodeClass TYPE = NodeClass.create(ClassGetComponentTypeNode.class); - - public ClassGetComponentTypeNode(Invoke invoke) { - super(TYPE, invoke); - } - - private ValueNode getJavaClass() { - return arguments.get(0); - } - - @Override - public Node canonical(CanonicalizerTool tool) { - ValueNode javaClass = getJavaClass(); - if (javaClass.isConstant()) { - HotSpotObjectConstant c = (HotSpotObjectConstant) javaClass.asConstant(); - JavaConstant componentType = c.getComponentType(); - if (componentType != null) { - return ConstantNode.forConstant(componentType, tool.getMetaAccess()); - } - } - return this; - } -} diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetModifiersNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetModifiersNode.java Fri Mar 27 15:43:31 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.hotspot.nodes; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.spi.*; -import com.oracle.graal.hotspot.replacements.*; -import com.oracle.graal.nodeinfo.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.replacements.nodes.*; - -/** - * {@link MacroNode Macro node} for {@link Class#getModifiers()}. - * - * @see HotSpotClassSubstitutions#getModifiers(Class) - */ -@NodeInfo -public final class ClassGetModifiersNode extends MacroNode implements Canonicalizable { - public static final NodeClass TYPE = NodeClass.create(ClassGetModifiersNode.class); - - public ClassGetModifiersNode(Invoke invoke) { - super(TYPE, invoke); - } - - private ValueNode getJavaClass() { - return arguments.get(0); - } - - @Override - public Node canonical(CanonicalizerTool tool) { - ValueNode javaClass = getJavaClass(); - if (javaClass.isConstant()) { - ConstantReflectionProvider constantReflection = tool.getConstantReflection(); - ResolvedJavaType type = constantReflection.asJavaType(javaClass.asConstant()); - if (type != null) { - return ConstantNode.forInt(type.getModifiers()); - } - } - return this; - } -} diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetSuperclassNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetSuperclassNode.java Fri Mar 27 15:43:31 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.hotspot.nodes; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.spi.*; -import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.hotspot.replacements.*; -import com.oracle.graal.nodeinfo.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.replacements.nodes.*; - -/** - * {@link MacroNode Macro node} for {@link Class#getSuperclass()}. - * - * @see HotSpotClassSubstitutions#getSuperclass(Class) - */ -@NodeInfo -public final class ClassGetSuperclassNode extends MacroNode implements Canonicalizable { - - public static final NodeClass TYPE = NodeClass.create(ClassGetSuperclassNode.class); - - public ClassGetSuperclassNode(Invoke invoke) { - super(TYPE, invoke); - } - - private ValueNode getJavaClass() { - return arguments.get(0); - } - - @Override - public Node canonical(CanonicalizerTool tool) { - ValueNode javaClass = getJavaClass(); - if (javaClass.isConstant()) { - HotSpotObjectConstant c = (HotSpotObjectConstant) javaClass.asConstant(); - JavaConstant superclass = c.getSuperclass(); - if (superclass != null) { - return ConstantNode.forConstant(superclass, tool.getMetaAccess()); - } - } - return this; - } -} diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsArrayNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsArrayNode.java Fri Mar 27 15:43:31 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.hotspot.nodes; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.spi.*; -import com.oracle.graal.hotspot.replacements.*; -import com.oracle.graal.nodeinfo.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.replacements.nodes.*; - -/** - * {@link MacroNode Macro node} for {@link Class#isArray()}. - * - * @see HotSpotClassSubstitutions#isArray(Class) - */ -@NodeInfo -public final class ClassIsArrayNode extends MacroNode implements Canonicalizable { - - public static final NodeClass TYPE = NodeClass.create(ClassIsArrayNode.class); - - public ClassIsArrayNode(Invoke invoke) { - super(TYPE, invoke); - } - - private ValueNode getJavaClass() { - return arguments.get(0); - } - - @Override - public Node canonical(CanonicalizerTool tool) { - ValueNode javaClass = getJavaClass(); - if (javaClass.isConstant()) { - ConstantReflectionProvider constantReflection = tool.getConstantReflection(); - ResolvedJavaType type = constantReflection.asJavaType(javaClass.asConstant()); - if (type != null) { - return ConstantNode.forBoolean(type.isArray()); - } - } - return this; - } -} diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsInterfaceNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsInterfaceNode.java Fri Mar 27 15:43:31 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.hotspot.nodes; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.spi.*; -import com.oracle.graal.hotspot.replacements.*; -import com.oracle.graal.nodeinfo.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.replacements.nodes.*; - -/** - * {@link MacroNode Macro node} for {@link Class#isInterface()}. - * - * @see HotSpotClassSubstitutions#isInterface(Class) - */ -@NodeInfo -public final class ClassIsInterfaceNode extends MacroNode implements Canonicalizable { - - public static final NodeClass TYPE = NodeClass.create(ClassIsInterfaceNode.class); - - public ClassIsInterfaceNode(Invoke invoke) { - super(TYPE, invoke); - } - - private ValueNode getJavaClass() { - return arguments.get(0); - } - - @Override - public Node canonical(CanonicalizerTool tool) { - ValueNode javaClass = getJavaClass(); - if (javaClass.isConstant()) { - ConstantReflectionProvider constantReflection = tool.getConstantReflection(); - ResolvedJavaType type = constantReflection.asJavaType(javaClass.asConstant()); - if (type != null) { - return ConstantNode.forBoolean(type.isInterface()); - } - } - return this; - } -} diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsPrimitiveNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsPrimitiveNode.java Fri Mar 27 15:43:31 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.hotspot.nodes; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.spi.*; -import com.oracle.graal.hotspot.replacements.*; -import com.oracle.graal.nodeinfo.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.replacements.nodes.*; - -/** - * {@link MacroNode Macro node} for {@link Class#isPrimitive()}. - * - * @see HotSpotClassSubstitutions#isPrimitive(Class) - */ -@NodeInfo -public final class ClassIsPrimitiveNode extends MacroNode implements Canonicalizable { - - public static final NodeClass TYPE = NodeClass.create(ClassIsPrimitiveNode.class); - - public ClassIsPrimitiveNode(Invoke invoke) { - super(TYPE, invoke); - } - - private ValueNode getJavaClass() { - return arguments.get(0); - } - - @Override - public Node canonical(CanonicalizerTool tool) { - ValueNode javaClass = getJavaClass(); - if (javaClass.isConstant()) { - ConstantReflectionProvider constantReflection = tool.getConstantReflection(); - ResolvedJavaType type = constantReflection.asJavaType(javaClass.asConstant()); - if (type != null) { - return ConstantNode.forBoolean(type.isPrimitive()); - } - } - return this; - } -} diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassQueryNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassQueryNode.java Fri Mar 27 17:02:53 2015 +0100 @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.nodes; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.spi.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.util.*; +import com.oracle.graal.replacements.nodes.*; + +/** + * {@link MacroNode Macro node} for some basic query methods in {@link Class}. + */ +@NodeInfo +public final class ClassQueryNode extends MacroStateSplitNode implements Canonicalizable { + + /** + * The query methods in {@link Class} supported by {@link ClassQueryNode}. + */ + public enum Query { + getClassLoader0(Kind.Object), + getComponentType(Kind.Object), + getSuperclass(Kind.Object), + getModifiers(Kind.Int), + isArray(Kind.Boolean), + isInterface(Kind.Boolean), + isPrimitive(Kind.Boolean); + + private Query(Kind returnKind) { + this.returnKind = returnKind; + } + + public final Kind returnKind; + } + + public static final NodeClass TYPE = NodeClass.create(ClassQueryNode.class); + + protected final Query query; + + public ClassQueryNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, Query query, int bci, JavaType returnType, ValueNode receiver) { + super(TYPE, invokeKind, targetMethod, bci, returnType, receiver); + this.query = query; + assert query.returnKind == targetMethod.getSignature().getReturnKind(); + } + + private ValueNode getJavaClass() { + return arguments.get(0); + } + + @Override + public Node canonical(CanonicalizerTool tool) { + ValueNode value = tryFold(getJavaClass(), query, tool.getMetaAccess(), tool.getConstantReflection()); + return value == null ? this : value; + } + + public static ValueNode tryFold(ValueNode javaClass, Query query, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection) { + ValueNode value = GraphUtil.originalValue(javaClass); + if (value != null && value.isConstant()) { + if (query.returnKind == Kind.Object) { + if (GraalOptions.ImmutableCode.getValue()) { + return null; + } + HotSpotObjectConstant c = (HotSpotObjectConstant) value.asConstant(); + JavaConstant answer; + switch (query) { + case getClassLoader0: + answer = c.getClassLoader(); + break; + case getComponentType: + answer = c.getComponentType(); + break; + case getSuperclass: + answer = c.getSuperclass(); + break; + default: + GraalInternalError.shouldNotReachHere(); + answer = null; + } + if (answer != null) { + return ConstantNode.forConstant(answer, metaAccess); + } + } else { + ResolvedJavaType type = constantReflection.asJavaType(value.asConstant()); + if (type != null) { + switch (query) { + case isArray: + return ConstantNode.forBoolean(type.isArray()); + case isPrimitive: + return ConstantNode.forBoolean(type.isPrimitive()); + case isInterface: + return ConstantNode.forBoolean(type.isInterface()); + case getModifiers: + return ConstantNode.forInt(type.getModifiers()); + default: + GraalInternalError.shouldNotReachHere(); + } + } + } + } + return null; + } +} diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ResolvedMethodHandleCallTargetNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ResolvedMethodHandleCallTargetNode.java Fri Mar 27 17:02:53 2015 +0100 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.nodes; + +import java.lang.invoke.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.replacements.*; +import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.spi.*; + +/** + * A call target that replaces itself in the graph when being lowered by restoring the original + * {@link MethodHandle} invocation target. This is required for when a {@link MethodHandle} call was + * resolved to a constant target but the target was not inlined. In that case, the original + * invocation must be restored with all of its original arguments. Why? HotSpot linkage for + * {@link MethodHandle} intrinsics (see {@code MethodHandles::generate_method_handle_dispatch}) + * expects certain implicit arguments to be on the stack such as the MemberName suffix argument for + * a call to one of the MethodHandle.linkTo* methods. An + * {@linkplain MethodHandleNode#tryResolveTargetInvoke resolved} {@link MethodHandle} invocation + * drops these arguments which means the interpreter won't find them. + */ +@NodeInfo +public final class ResolvedMethodHandleCallTargetNode extends MethodCallTargetNode implements Lowerable { + + public static final NodeClass TYPE = NodeClass.create(ResolvedMethodHandleCallTargetNode.class); + protected final ResolvedJavaMethod originalTargetMethod; + protected final JavaType originalReturnType; + @Input NodeInputList originalArguments; + + public ResolvedMethodHandleCallTargetNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] arguments, JavaType returnType, ResolvedJavaMethod originalTargetMethod, + ValueNode[] originalArguments, JavaType originalReturnType) { + super(TYPE, invokeKind, targetMethod, arguments, returnType); + this.originalTargetMethod = originalTargetMethod; + this.originalReturnType = originalReturnType; + this.originalArguments = new NodeInputList<>(this, originalArguments); + } + + @Override + public void lower(LoweringTool tool) { + InvokeKind replacementInvokeKind = originalTargetMethod.isStatic() ? InvokeKind.Static : InvokeKind.Special; + MethodCallTargetNode replacement = graph().add( + new MethodCallTargetNode(replacementInvokeKind, originalTargetMethod, originalArguments.toArray(new ValueNode[originalArguments.size()]), originalReturnType)); + + // Replace myself... + this.replaceAndDelete(replacement); + } + + @Override + public void generate(NodeLIRBuilderTool gen) { + throw GraalInternalError.shouldNotReachHere("should have replaced itself"); + } +} diff -r d22307a9a025 -r eea134855f85 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 Mar 27 15:43:31 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +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. - */ -package com.oracle.graal.hotspot.replacements; - -import java.lang.invoke.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.replacements.*; -import com.oracle.graal.api.runtime.*; -import com.oracle.graal.nodes.spi.*; - -@ServiceProvider(ReplacementsProvider.class) -public class CallSiteSubstitutions implements ReplacementsProvider { - - @Override - public void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider loweringProvider, SnippetReflectionProvider snippetReflection, Replacements replacements, TargetDescription target) { - replacements.registerSubstitutions(ConstantCallSite.class, ConstantCallSiteSubstitutions.class); - replacements.registerSubstitutions(MutableCallSite.class, MutableCallSiteSubstitutions.class); - replacements.registerSubstitutions(VolatileCallSite.class, VolatileCallSiteSubstitutions.class); - } - - @ClassSubstitution(ConstantCallSite.class) - private static class ConstantCallSiteSubstitutions { - - @MacroSubstitution(isStatic = false, macro = CallSiteTargetNode.class) - public static native MethodHandle getTarget(ConstantCallSite callSite); - } - - @ClassSubstitution(MutableCallSite.class) - private static class MutableCallSiteSubstitutions { - - @MacroSubstitution(isStatic = false, macro = CallSiteTargetNode.class) - public static native MethodHandle getTarget(MutableCallSite callSite); - } - - @ClassSubstitution(VolatileCallSite.class) - private static class VolatileCallSiteSubstitutions { - - @MacroSubstitution(isStatic = false, macro = CallSiteTargetNode.class) - public static native MethodHandle getTarget(VolatileCallSite callSite); - } -} diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteTargetNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteTargetNode.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteTargetNode.java Fri Mar 27 17:02:53 2015 +0100 @@ -27,8 +27,10 @@ import com.oracle.graal.graph.spi.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.util.*; import com.oracle.graal.replacements.nodes.*; @NodeInfo @@ -36,18 +38,19 @@ public static final NodeClass TYPE = NodeClass.create(CallSiteTargetNode.class); - public CallSiteTargetNode(Invoke invoke) { - super(TYPE, invoke); + public CallSiteTargetNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, int bci, JavaType returnType, ValueNode receiver) { + super(TYPE, invokeKind, targetMethod, bci, returnType, receiver); } private ValueNode getCallSite() { return arguments.get(0); } - private ConstantNode getConstantCallTarget(MetaAccessProvider metaAccess) { - if (getCallSite().isConstant() && !getCallSite().isNullConstant()) { - HotSpotObjectConstant c = (HotSpotObjectConstant) getCallSite().asConstant(); - JavaConstant target = c.getCallSiteTarget(graph().getAssumptions()); + public static ConstantNode tryFold(ValueNode initialCallSite, MetaAccessProvider metaAccess, Assumptions assumptions) { + ValueNode callSite = GraphUtil.originalValue(initialCallSite); + if (callSite.isConstant() && !callSite.isNullConstant()) { + HotSpotObjectConstant c = (HotSpotObjectConstant) callSite.asConstant(); + JavaConstant target = c.getCallSiteTarget(assumptions); if (target != null) { return ConstantNode.forConstant(target, metaAccess); } @@ -57,7 +60,7 @@ @Override public Node canonical(CanonicalizerTool tool) { - ConstantNode target = getConstantCallTarget(tool.getMetaAccess()); + ConstantNode target = tryFold(getCallSite(), tool.getMetaAccess(), graph().getAssumptions()); if (target != null) { return target; } @@ -67,7 +70,7 @@ @Override public void lower(LoweringTool tool) { - ConstantNode target = getConstantCallTarget(tool.getMetaAccess()); + ConstantNode target = tryFold(getCallSite(), tool.getMetaAccess(), graph().getAssumptions()); if (target != null) { graph().replaceFixedWithFloating(this, target); diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotClassSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotClassSubstitutions.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotClassSubstitutions.java Fri Mar 27 17:02:53 2015 +0100 @@ -27,10 +27,8 @@ import java.lang.reflect.*; import com.oracle.graal.api.replacements.*; -import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.hotspot.word.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; import com.oracle.graal.word.*; /** @@ -39,7 +37,6 @@ @ClassSubstitution(java.lang.Class.class) public class HotSpotClassSubstitutions { - @MacroSubstitution(macro = ClassGetModifiersNode.class, isStatic = false) @MethodSubstitution(isStatic = false, forced = true) public static int getModifiers(final Class thisObj) { KlassPointer klass = ClassGetHubNode.readClass(thisObj); @@ -51,8 +48,6 @@ } } - // This MacroSubstitution should be removed once non-null klass pointers can be optimized - @MacroSubstitution(macro = ClassIsInterfaceNode.class, isStatic = false) @MethodSubstitution(isStatic = false, forced = true) public static boolean isInterface(final Class thisObj) { KlassPointer klass = ClassGetHubNode.readClass(thisObj); @@ -64,8 +59,6 @@ } } - // This MacroSubstitution should be removed once non-null klass pointers can be optimized - @MacroSubstitution(macro = ClassIsArrayNode.class, isStatic = false) @MethodSubstitution(isStatic = false, forced = true) public static boolean isArray(final Class thisObj) { KlassPointer klass = ClassGetHubNode.readClass(thisObj); @@ -76,18 +69,14 @@ } } - // This MacroSubstitution should be removed once non-null klass pointers can be optimized - @MacroSubstitution(macro = ClassIsPrimitiveNode.class, isStatic = false) @MethodSubstitution(isStatic = false, forced = true) public static boolean isPrimitive(final Class thisObj) { KlassPointer klass = ClassGetHubNode.readClass(thisObj); return klass.isNull(); } - @MacroSubstitution(macro = ClassGetClassLoader0Node.class, isStatic = false) public static native ClassLoader getClassLoader0(Class thisObj); - @MacroSubstitution(macro = ClassGetSuperclassNode.class, isStatic = false) @MethodSubstitution(isStatic = false) public static Class getSuperclass(final Class thisObj) { KlassPointer klass = ClassGetHubNode.readClass(thisObj); @@ -113,7 +102,6 @@ return PiNode.asNonNullClass(klass.readObject(classMirrorOffset(), CLASS_MIRROR_LOCATION)); } - @MacroSubstitution(macro = ClassGetComponentTypeNode.class, isStatic = false) @MethodSubstitution(isStatic = false) public static Class getComponentType(final Class thisObj) { KlassPointer klass = ClassGetHubNode.readClass(thisObj); @@ -124,7 +112,4 @@ } return null; } - - @MacroSubstitution(macro = ClassCastNode.class, isStatic = false) - public static native Object cast(final Class thisObj, Object obj); } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleNode.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleNode.java Fri Mar 27 17:02:53 2015 +0100 @@ -32,6 +32,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.CallTargetNode.InvokeKind; @@ -47,52 +48,50 @@ public final class MethodHandleNode extends MacroStateSplitNode implements Simplifiable { public static final NodeClass TYPE = NodeClass.create(MethodHandleNode.class); - // Replacement method data - protected ResolvedJavaMethod replacementTargetMethod; - protected JavaType replacementReturnType; - @Input NodeInputList replacementArguments; + protected final IntrinsicMethod intrinsicMethod; - public MethodHandleNode(Invoke invoke) { - super(TYPE, invoke); - MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget(); - // See if we need to save some replacement method data. - if (callTarget instanceof SelfReplacingMethodCallTargetNode) { - SelfReplacingMethodCallTargetNode selfReplacingMethodCallTargetNode = (SelfReplacingMethodCallTargetNode) callTarget; - replacementTargetMethod = selfReplacingMethodCallTargetNode.replacementTargetMethod(); - replacementReturnType = selfReplacingMethodCallTargetNode.replacementReturnType(); - replacementArguments = selfReplacingMethodCallTargetNode.replacementArguments(); - } else { - // NodeInputList can't be null. - replacementArguments = new NodeInputList<>(this); - } + public MethodHandleNode(IntrinsicMethod intrinsicMethod, InvokeKind invokeKind, ResolvedJavaMethod targetMethod, int bci, JavaType returnType, ValueNode... arguments) { + super(TYPE, invokeKind, targetMethod, bci, returnType, arguments); + this.intrinsicMethod = intrinsicMethod; } /** - * Returns the method handle method intrinsic identifier for the provided method, or - * {@code null} if the method is not a method that can be handled by this class. + * Attempts to transform application of an intrinsifiable {@link MethodHandle} method into an + * invocation on another method with possibly transformed arguments. + * + * @param assumptions object for recording any speculations made during the transformation + * @param methodHandleAccess objects for accessing the implementation internals of a + * {@link MethodHandle} + * @param intrinsicMethod denotes the intrinsifiable {@link MethodHandle} method being processed + * @param bci the BCI of the original {@link MethodHandle} call + * @param returnType return type of the original {@link MethodHandle} call + * @param arguments arguments to the original {@link MethodHandle} call + * @return a more direct invocation derived from the {@link MethodHandle} call or null */ - public static IntrinsicMethod lookupMethodHandleIntrinsic(ResolvedJavaMethod method, MethodHandleAccessProvider methodHandleAccess) { - return methodHandleAccess.lookupMethodHandleIntrinsic(method); + public static InvokeNode tryResolveTargetInvoke(Assumptions assumptions, MethodHandleAccessProvider methodHandleAccess, IntrinsicMethod intrinsicMethod, ResolvedJavaMethod original, int bci, + JavaType returnType, ValueNode... arguments) { + switch (intrinsicMethod) { + case INVOKE_BASIC: + return getInvokeBasicTarget(assumptions, intrinsicMethod, methodHandleAccess, original, bci, returnType, arguments); + case LINK_TO_STATIC: + case LINK_TO_SPECIAL: + case LINK_TO_VIRTUAL: + case LINK_TO_INTERFACE: + return getLinkToTarget(assumptions, intrinsicMethod, methodHandleAccess, original, bci, returnType, arguments); + default: + throw GraalInternalError.shouldNotReachHere(); + } } @Override public void simplify(SimplifierTool tool) { - InvokeNode invoke; - IntrinsicMethod intrinsicMethod = lookupMethodHandleIntrinsic(targetMethod, tool.getConstantReflection().getMethodHandleAccess()); - switch (intrinsicMethod) { - case INVOKE_BASIC: - invoke = getInvokeBasicTarget(tool, intrinsicMethod); - break; - case LINK_TO_STATIC: - case LINK_TO_SPECIAL: - case LINK_TO_VIRTUAL: - case LINK_TO_INTERFACE: - invoke = getLinkToTarget(tool, intrinsicMethod); - break; - default: - throw GraalInternalError.shouldNotReachHere(); - } + MethodHandleAccessProvider methodHandleAccess = tool.getConstantReflection().getMethodHandleAccess(); + ValueNode[] argumentsArray = arguments.toArray(new ValueNode[arguments.size()]); + InvokeNode invoke = tryResolveTargetInvoke(graph().getAssumptions(), methodHandleAccess, intrinsicMethod, targetMethod, bci, returnType, argumentsArray); if (invoke != null) { + assert invoke.graph() == null; + invoke = graph().addOrUniqueWithInputs(invoke); + invoke.setStateAfter(stateAfter()); FixedNode currentNext = next(); replaceAtUsages(invoke); GraphUtil.removeFixedWithUnusedInputs(this); @@ -105,8 +104,8 @@ * * @return the receiver argument node */ - private ValueNode getReceiver() { - return arguments.first(); + private static ValueNode getReceiver(ValueNode[] arguments) { + return arguments[0]; } /** @@ -114,8 +113,8 @@ * * @return the MemberName argument node (which is the last argument) */ - private ValueNode getMemberName() { - return arguments.last(); + private static ValueNode getMemberName(ValueNode[] arguments) { + return arguments[arguments.length - 1]; } /** @@ -124,10 +123,11 @@ * * @return invoke node for the {@link java.lang.invoke.MethodHandle} target */ - protected InvokeNode getInvokeBasicTarget(SimplifierTool tool, IntrinsicMethod intrinsicMethod) { - ValueNode methodHandleNode = getReceiver(); + private static InvokeNode getInvokeBasicTarget(Assumptions assumptions, IntrinsicMethod intrinsicMethod, MethodHandleAccessProvider methodHandleAccess, ResolvedJavaMethod original, int bci, + JavaType returnType, ValueNode[] arguments) { + ValueNode methodHandleNode = getReceiver(arguments); if (methodHandleNode.isConstant()) { - return getTargetInvokeNode(tool.getConstantReflection().getMethodHandleAccess().resolveInvokeBasicTarget(methodHandleNode.asJavaConstant(), false), intrinsicMethod); + return getTargetInvokeNode(assumptions, intrinsicMethod, bci, returnType, arguments, methodHandleAccess.resolveInvokeBasicTarget(methodHandleNode.asJavaConstant(), true), original); } return null; } @@ -140,10 +140,11 @@ * * @return invoke node for the member name target */ - protected InvokeNode getLinkToTarget(SimplifierTool tool, IntrinsicMethod intrinsicMethod) { - ValueNode memberNameNode = getMemberName(); + private static InvokeNode getLinkToTarget(Assumptions assumptions, IntrinsicMethod intrinsicMethod, MethodHandleAccessProvider methodHandleAccess, ResolvedJavaMethod original, int bci, + JavaType returnType, ValueNode[] arguments) { + ValueNode memberNameNode = getMemberName(arguments); if (memberNameNode.isConstant()) { - return getTargetInvokeNode(tool.getConstantReflection().getMethodHandleAccess().resolveLinkToTarget(memberNameNode.asJavaConstant()), intrinsicMethod); + return getTargetInvokeNode(assumptions, intrinsicMethod, bci, returnType, arguments, methodHandleAccess.resolveLinkToTarget(memberNameNode.asJavaConstant()), original); } return null; } @@ -155,7 +156,8 @@ * @param target the target, already loaded from the member name node * @return invoke node for the member name target */ - private InvokeNode getTargetInvokeNode(ResolvedJavaMethod target, IntrinsicMethod intrinsicMethod) { + private static InvokeNode getTargetInvokeNode(Assumptions assumptions, IntrinsicMethod intrinsicMethod, int bci, JavaType returnType, ValueNode[] arguments, ResolvedJavaMethod target, + ResolvedJavaMethod original) { if (target == null) { return null; } @@ -171,34 +173,35 @@ // Cast receiver to its type. if (!isStatic) { JavaType receiverType = target.getDeclaringClass(); - maybeCastArgument(0, receiverType); + maybeCastArgument(arguments, 0, receiverType); } // Cast reference arguments to its type. for (int index = 0; index < signature.getParameterCount(false); index++) { JavaType parameterType = signature.getParameterType(index, target.getDeclaringClass()); - maybeCastArgument(receiverSkip + index, parameterType); + maybeCastArgument(arguments, receiverSkip + index, parameterType); } if (target.canBeStaticallyBound()) { - return createTargetInvokeNode(target, intrinsicMethod); + return createTargetInvokeNode(intrinsicMethod, target, original, bci, returnType, arguments); } // Try to get the most accurate receiver type if (intrinsicMethod == IntrinsicMethod.LINK_TO_VIRTUAL || intrinsicMethod == IntrinsicMethod.LINK_TO_INTERFACE) { - ResolvedJavaType receiverType = StampTool.typeOrNull(getReceiver().stamp()); + ValueNode receiver = getReceiver(arguments); + ResolvedJavaType receiverType = StampTool.typeOrNull(receiver.stamp()); if (receiverType != null) { AssumptionResult concreteMethod = receiverType.findUniqueConcreteMethod(target); if (concreteMethod != null) { - graph().getAssumptions().record(concreteMethod); - return createTargetInvokeNode(concreteMethod.getResult(), intrinsicMethod); + assumptions.record(concreteMethod); + return createTargetInvokeNode(intrinsicMethod, concreteMethod.getResult(), original, bci, returnType, arguments); } } } else { AssumptionResult concreteMethod = target.getDeclaringClass().findUniqueConcreteMethod(target); if (concreteMethod != null) { - graph().getAssumptions().record(concreteMethod); - return createTargetInvokeNode(concreteMethod.getResult(), intrinsicMethod); + assumptions.record(concreteMethod); + return createTargetInvokeNode(intrinsicMethod, concreteMethod.getResult(), original, bci, returnType, arguments); } } @@ -212,15 +215,15 @@ * @param index of the argument to be cast * @param type the type the argument should be cast to */ - private void maybeCastArgument(int index, JavaType type) { + private static void maybeCastArgument(ValueNode[] arguments, int index, JavaType type) { if (type instanceof ResolvedJavaType) { ResolvedJavaType targetType = (ResolvedJavaType) type; if (!targetType.isPrimitive()) { - ValueNode argument = arguments.get(index); + ValueNode argument = arguments[index]; ResolvedJavaType argumentType = StampTool.typeOrNull(argument.stamp()); if (argumentType == null || (argumentType.isAssignableFrom(targetType) && !argumentType.equals(targetType))) { - PiNode piNode = graph().unique(new PiNode(argument, StampFactory.declared(targetType))); - arguments.set(index, piNode); + PiNode piNode = new PiNode(argument, StampFactory.declared(targetType)); + arguments[index] = piNode; } } } @@ -228,57 +231,42 @@ /** * Creates an {@link InvokeNode} for the given target method. The {@link CallTargetNode} passed - * to the InvokeNode is in fact a {@link SelfReplacingMethodCallTargetNode}. + * to the InvokeNode is in fact a {@link ResolvedMethodHandleCallTargetNode}. * - * @param target the method to be called * @return invoke node for the member name target */ - private InvokeNode createTargetInvokeNode(ResolvedJavaMethod target, IntrinsicMethod intrinsicMethod) { + private static InvokeNode createTargetInvokeNode(IntrinsicMethod intrinsicMethod, ResolvedJavaMethod target, ResolvedJavaMethod original, int bci, JavaType returnType, ValueNode[] arguments) { InvokeKind targetInvokeKind = target.isStatic() ? InvokeKind.Static : InvokeKind.Special; JavaType targetReturnType = target.getSignature().getReturnType(null); // MethodHandleLinkTo* nodes have a trailing MemberName argument which // needs to be popped. - ValueNode[] originalArguments = arguments.toArray(new ValueNode[arguments.size()]); ValueNode[] targetArguments; switch (intrinsicMethod) { case INVOKE_BASIC: - targetArguments = originalArguments; + targetArguments = arguments; break; case LINK_TO_STATIC: case LINK_TO_SPECIAL: case LINK_TO_VIRTUAL: case LINK_TO_INTERFACE: - targetArguments = Arrays.copyOfRange(originalArguments, 0, arguments.size() - 1); + targetArguments = Arrays.copyOfRange(arguments, 0, arguments.length - 1); break; default: throw GraalInternalError.shouldNotReachHere(); } - // If there is already replacement information, use that instead. - MethodCallTargetNode callTarget; - if (replacementTargetMethod == null) { - callTarget = new SelfReplacingMethodCallTargetNode(targetInvokeKind, target, targetArguments, targetReturnType, getTargetMethod(), originalArguments, getReturnType()); - } else { - ValueNode[] args = replacementArguments.toArray(new ValueNode[replacementArguments.size()]); - callTarget = new SelfReplacingMethodCallTargetNode(targetInvokeKind, target, targetArguments, targetReturnType, replacementTargetMethod, args, replacementReturnType); - } - graph().add(callTarget); + MethodCallTargetNode callTarget = new ResolvedMethodHandleCallTargetNode(targetInvokeKind, target, targetArguments, targetReturnType, original, arguments, returnType); // The call target can have a different return type than the invoker, // e.g. the target returns an Object but the invoker void. In this case // we need to use the stamp of the invoker. Note: always using the // invoker's stamp would be wrong because it's a less concrete type // (usually java.lang.Object). - InvokeNode invoke; - if (stamp() == StampFactory.forVoid()) { - invoke = new InvokeNode(callTarget, getBci(), stamp()); + if (returnType.getKind() == Kind.Void) { + return new InvokeNode(callTarget, bci, StampFactory.forVoid()); } else { - invoke = new InvokeNode(callTarget, getBci()); + return new InvokeNode(callTarget, bci); } - graph().add(invoke); - invoke.setStateAfter(stateAfter()); - return invoke; } - } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java Fri Mar 27 17:02:53 2015 +0100 @@ -31,6 +31,7 @@ import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.java.*; @@ -43,8 +44,8 @@ public static final NodeClass TYPE = NodeClass.create(ObjectCloneNode.class); - public ObjectCloneNode(Invoke invoke) { - super(TYPE, invoke); + public ObjectCloneNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, int bci, JavaType returnType, ValueNode receiver) { + super(TYPE, invokeKind, targetMethod, bci, returnType, receiver); } @Override diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectSubstitutions.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectSubstitutions.java Fri Mar 27 17:02:53 2015 +0100 @@ -28,7 +28,6 @@ import com.oracle.graal.hotspot.word.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.spi.*; /** * Substitutions for {@link java.lang.Object} methods. @@ -51,7 +50,4 @@ public static void init(Object thisObj) { RegisterFinalizerNode.register(thisObj); } - - @MacroSubstitution(macro = ObjectCloneNode.class, isStatic = false, forced = true) - public static native Object clone(Object obj); } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionGetCallerClassNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionGetCallerClassNode.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionGetCallerClassNode.java Fri Mar 27 17:02:53 2015 +0100 @@ -31,6 +31,7 @@ import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.nodes.*; @@ -39,8 +40,8 @@ public static final NodeClass TYPE = NodeClass.create(ReflectionGetCallerClassNode.class); - public ReflectionGetCallerClassNode(Invoke invoke) { - super(TYPE, invoke); + public ReflectionGetCallerClassNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, int bci, JavaType returnType, ValueNode... arguments) { + super(TYPE, invokeKind, targetMethod, bci, returnType, arguments); } @Override diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionSubstitutions.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionSubstitutions.java Fri Mar 27 17:02:53 2015 +0100 @@ -29,7 +29,6 @@ import com.oracle.graal.api.replacements.*; import com.oracle.graal.hotspot.word.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; /** * Substitutions for {@link sun.reflect.Reflection} methods. @@ -37,9 +36,6 @@ @ClassSubstitution(sun.reflect.Reflection.class) public class ReflectionSubstitutions { - @MacroSubstitution(macro = ReflectionGetCallerClassNode.class, optional = true) - public static native Class getCallerClass(); - @MethodSubstitution public static int getClassAccessFlags(Class aClass) { KlassPointer klass = ClassGetHubNode.readClass(GuardingPiNode.asNonNullClass(aClass)); diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemIdentityHashCodeNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemIdentityHashCodeNode.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemIdentityHashCodeNode.java Fri Mar 27 17:02:53 2015 +0100 @@ -29,6 +29,7 @@ import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.replacements.nodes.*; @NodeInfo @@ -36,8 +37,8 @@ public static final NodeClass TYPE = NodeClass.create(SystemIdentityHashCodeNode.class); - public SystemIdentityHashCodeNode(Invoke invoke) { - super(TYPE, invoke); + public SystemIdentityHashCodeNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, int bci, JavaType returnType, ValueNode object) { + super(TYPE, invokeKind, targetMethod, bci, returnType, object); } @Override diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemSubstitutions.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemSubstitutions.java Fri Mar 27 17:02:53 2015 +0100 @@ -27,8 +27,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; -import com.oracle.graal.hotspot.replacements.arraycopy.*; -import com.oracle.graal.nodes.spi.*; /** * Substitutions for {@link java.lang.System} methods. @@ -39,10 +37,6 @@ public static final ForeignCallDescriptor JAVA_TIME_MILLIS = new ForeignCallDescriptor("javaTimeMillis", long.class); public static final ForeignCallDescriptor JAVA_TIME_NANOS = new ForeignCallDescriptor("javaTimeNanos", long.class); - @MacroSubstitution(macro = ArrayCopyNode.class) - public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length); - - @MacroSubstitution(macro = SystemIdentityHashCodeNode.class) @MethodSubstitution public static int identityHashCode(Object x) { if (probability(NOT_FREQUENT_PROBABILITY, x == null)) { diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopyNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopyNode.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopyNode.java Fri Mar 27 17:02:53 2015 +0100 @@ -32,6 +32,7 @@ import com.oracle.graal.loop.phases.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.common.*; @@ -43,8 +44,8 @@ public static final NodeClass TYPE = NodeClass.create(ArrayCopyNode.class); - public ArrayCopyNode(Invoke invoke) { - super(TYPE, invoke); + public ArrayCopyNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, int bci, JavaType returnType, ValueNode src, ValueNode srcPos, ValueNode dst, ValueNode dstPos, ValueNode length) { + super(TYPE, invokeKind, targetMethod, bci, returnType, src, srcPos, dst, dstPos, length); } private StructuredGraph selectSnippet(LoweringTool tool, final Replacements replacements) { diff -r d22307a9a025 -r eea134855f85 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 Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Fri Mar 27 17:02:53 2015 +0100 @@ -296,7 +296,7 @@ private final boolean explodeLoops; private final boolean mergeExplosions; private final Map mergeExplosionsMap; - private Stack explodeLoopsContext; + private Deque explodeLoopsContext; private int nextPeelIteration = 1; private boolean controlFlowSplit; private final InvocationPluginReceiver invocationPluginReceiver = new InvocationPluginReceiver(this); @@ -452,7 +452,7 @@ private void detectLoops(FixedNode startInstruction) { NodeBitMap visited = currentGraph.createNodeBitMap(); NodeBitMap active = currentGraph.createNodeBitMap(); - Stack stack = new Stack<>(); + Deque stack = new ArrayDeque<>(); stack.add(startInstruction); visited.mark(startInstruction); while (!stack.isEmpty()) { @@ -498,7 +498,7 @@ private void insertLoopEnds(FixedNode startInstruction) { NodeBitMap visited = currentGraph.createNodeBitMap(); - Stack stack = new Stack<>(); + Deque stack = new ArrayDeque<>(); stack.add(startInstruction); visited.mark(startInstruction); List loopBegins = new ArrayList<>(); @@ -538,7 +538,7 @@ private void insertLoopExits(LoopBeginNode loopBegin, IdentityHashMap> innerLoopsMap) { NodeBitMap visited = currentGraph.createNodeBitMap(); - Stack stack = new Stack<>(); + Deque stack = new ArrayDeque<>(); for (LoopEndNode loopEnd : loopBegin.loopEnds()) { stack.push(loopEnd); visited.mark(loopEnd); @@ -622,7 +622,7 @@ private int iterateExplodedLoopHeader(BciBlock[] blocks, BciBlock header) { if (explodeLoopsContext == null) { - explodeLoopsContext = new Stack<>(); + explodeLoopsContext = new ArrayDeque<>(); } ExplodedLoopContext context = new ExplodedLoopContext(); @@ -823,9 +823,7 @@ @Override protected void genStoreIndexed(ValueNode array, ValueNode index, Kind kind, ValueNode value) { - StoreIndexedNode storeIndexed = new StoreIndexedNode(array, index, kind, value); - append(storeIndexed); - storeIndexed.setStateAfter(this.createStateAfter()); + add(new StoreIndexedNode(array, index, kind, value)); } @Override @@ -1145,6 +1143,21 @@ } } + private InvokeKind currentInvokeKind; + private JavaType currentInvokeReturnType; + + public InvokeKind getInvokeKind() { + return currentInvokeKind; + } + + public JavaType getInvokeReturnType() { + return currentInvokeReturnType; + } + + public void handleReplacedInvoke(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args) { + appendInvoke(invokeKind, targetMethod, args); + } + private void appendInvoke(InvokeKind initialInvokeKind, ResolvedJavaMethod initialTargetMethod, ValueNode[] args) { ResolvedJavaMethod targetMethod = initialTargetMethod; InvokeKind invokeKind = initialInvokeKind; @@ -1181,22 +1194,29 @@ } } - if (tryGenericInvocationPlugin(args, targetMethod)) { - if (TraceParserPlugins.getValue()) { - traceWithContext("used generic invocation plugin for %s", targetMethod.format("%h.%n(%p)")); + try { + currentInvokeReturnType = returnType; + currentInvokeKind = invokeKind; + if (tryGenericInvocationPlugin(args, targetMethod)) { + if (TraceParserPlugins.getValue()) { + traceWithContext("used generic invocation plugin for %s", targetMethod.format("%h.%n(%p)")); + } + return; } - return; - } - if (tryInvocationPlugin(args, targetMethod, resultType)) { - if (TraceParserPlugins.getValue()) { - traceWithContext("used invocation plugin for %s", targetMethod.format("%h.%n(%p)")); + if (tryInvocationPlugin(args, targetMethod, resultType)) { + if (TraceParserPlugins.getValue()) { + traceWithContext("used invocation plugin for %s", targetMethod.format("%h.%n(%p)")); + } + return; } - return; - } - if (tryInline(args, targetMethod, invokeKind, returnType)) { - return; + if (tryInline(args, targetMethod, invokeKind, returnType)) { + return; + } + } finally { + currentInvokeReturnType = null; + currentInvokeKind = null; } MethodCallTargetNode callTarget = currentGraph.add(createMethodCallTarget(invokeKind, targetMethod, args, returnType)); @@ -1254,7 +1274,8 @@ boolean check(boolean pluginResult) { if (pluginResult == true) { - assert beforeStackSize + resultType.getSlotCount() == frameState.stackSize : error("plugin manipulated the stack incorrectly"); + int expectedStackSize = beforeStackSize + resultType.getSlotCount(); + assert expectedStackSize == frameState.stackSize : error("plugin manipulated the stack incorrectly: expected=%d, actual=%d", expectedStackSize, frameState.stackSize); NodeIterable newNodes = currentGraph.getNewNodes(mark); assert !needsNullCheck || isPointerNonNull(args[0].stamp()) : error("plugin needs to null check the receiver of %s: receiver=%s", targetMethod.format("%H.%n(%p)"), args[0]); for (Node n : newNodes) { @@ -1280,6 +1301,15 @@ private boolean tryInvocationPlugin(ValueNode[] args, ResolvedJavaMethod targetMethod, Kind resultType) { InvocationPlugin plugin = graphBuilderConfig.getPlugins().getInvocationPlugins().lookupInvocation(targetMethod); if (plugin != null) { + + ReplacementContext context = this.replacementContext; + if (context != null && context.isCallToOriginal(targetMethod)) { + // Self recursive replacement means the original + // method should be called. + assert !targetMethod.hasBytecodes() : "TODO: when does this happen?"; + return false; + } + InvocationPluginAssertions assertions = assertionsEnabled() ? new InvocationPluginAssertions(plugin, args, targetMethod, resultType) : null; if (InvocationPlugin.execute(this, targetMethod, plugin, invocationPluginReceiver.init(targetMethod, args), args)) { assert assertions.check(true); @@ -1307,7 +1337,7 @@ return false; } - boolean inline(InlineInvokePlugin plugin, ResolvedJavaMethod targetMethod, InlineInfo inlineInfo, ValueNode[] args) { + public boolean inline(InlineInvokePlugin plugin, ResolvedJavaMethod targetMethod, InlineInfo inlineInfo, ValueNode[] args) { int bci = bci(); ResolvedJavaMethod inlinedMethod = inlineInfo.methodToInline; if (TraceInlineDuringParsing.getValue() || TraceParserPlugins.getValue()) { @@ -1872,9 +1902,7 @@ } private int findOperatingDimensionWithLoopExplosion(BciBlock block, HIRFrameStateBuilder state) { - int i; - for (i = explodeLoopsContext.size() - 1; i >= 0; --i) { - ExplodedLoopContext context = explodeLoopsContext.elementAt(i); + for (ExplodedLoopContext context : explodeLoopsContext) { if (context.header == block) { if (this.mergeExplosions) { @@ -2415,6 +2443,7 @@ } public void push(Kind kind, ValueNode value) { + assert value.isAlive(); assert kind == kind.getStackKind(); frameState.push(kind, value); } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/UntrustedInterfaces.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/UntrustedInterfaces.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/UntrustedInterfaces.java Fri Mar 27 17:02:53 2015 +0100 @@ -23,7 +23,7 @@ package com.oracle.graal.jtt.except; import org.junit.*; -import org.objectweb.asm.*; +import jdk.internal.org.objectweb.asm.*; import com.oracle.graal.jtt.*; diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/Switch02.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/Switch02.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/Switch02.java Fri Mar 27 17:02:53 2015 +0100 @@ -89,7 +89,7 @@ break; case (char) 0xFFFF - 21: result = 858112498 / val; - x = new Hashtable<>(); + x = new HashMap<>(); break; default: result = 34324341 / val; @@ -142,7 +142,7 @@ break; case (short) -0x7FFF + 21: result = 858112498 / val; - x = new Hashtable<>(); + x = new HashMap<>(); break; default: result = 34324341 / val; @@ -198,7 +198,7 @@ break; case (byte) -0x7F + 21: result = 858112498 / val; - x = new Hashtable<>(); + x = new HashMap<>(); break; default: result = 34324341 / val; diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java Fri Mar 27 17:02:53 2015 +0100 @@ -130,7 +130,7 @@ * @param canHaveRegisters True if there can be any register map entries. */ public void initDebugInfo(FrameMap frameMap, boolean canHaveRegisters) { - debugInfo = new DebugInfo(topFrame, frameMap.initReferenceMap(canHaveRegisters)); + debugInfo = new DebugInfo(topFrame, frameMap.initReferenceMap(canHaveRegisters), virtualObjects); } /** diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/SimpleInfopointOp.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/SimpleInfopointOp.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/SimpleInfopointOp.java Fri Mar 27 17:02:53 2015 +0100 @@ -39,6 +39,6 @@ @Override public void emitCode(CompilationResultBuilder crb) { - crb.recordInfopoint(crb.asm.position(), new DebugInfo(position, null), reason); + crb.recordInfopoint(crb.asm.position(), new DebugInfo(position), reason); } } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerationResult.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerationResult.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerationResult.java Fri Mar 27 17:02:53 2015 +0100 @@ -56,4 +56,6 @@ boolean hasForeignCall(); void setForeignCall(boolean b); + + String getCompilationUnitName(); } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerationResultBase.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerationResultBase.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerationResultBase.java Fri Mar 27 17:02:53 2015 +0100 @@ -34,10 +34,15 @@ * Records whether the code being generated makes at least one foreign call. */ private boolean hasForeignCall; + /** + * Human readable name of this compilation unit. + */ + private final String compilationUnitName; - public LIRGenerationResultBase(LIR lir, FrameMapBuilder frameMapBuilder) { + public LIRGenerationResultBase(String compilationUnitName, LIR lir, FrameMapBuilder frameMapBuilder) { this.lir = lir; this.frameMapBuilder = frameMapBuilder; + this.compilationUnitName = compilationUnitName; } public LIR getLIR() { @@ -69,4 +74,8 @@ assert frameMap != null : "getFrameMap() can only be used after calling buildFrameMap()!"; return frameMap; } + + public String getCompilationUnitName() { + return compilationUnitName; + } } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/profiling/MoveProfiling.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/profiling/MoveProfiling.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/profiling/MoveProfiling.java Fri Mar 27 17:02:53 2015 +0100 @@ -136,12 +136,13 @@ } String[] groups = new String[names.size()]; Arrays.fill(groups, "Move Operations"); - - LIRInstruction inst = counterFactory.createMultiBenchmarkCounter(names.toArray(new String[0]), groups, increments.toArray(new Value[0])); - assert inst != null; - buffer.init(instructions); - buffer.append(1, inst); - buffer.finish(); + if (names.size() > 0) { // Don't pollute LIR when nothing has to be done + LIRInstruction inst = counterFactory.createMultiBenchmarkCounter(names.toArray(new String[0]), groups, increments.toArray(new Value[0])); + assert inst != null; + buffer.init(instructions); + buffer.append(1, inst); + buffer.finish(); + } } } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.nodeinfo/src/com/oracle/graal/nodeinfo/StructuralInput.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodeinfo/src/com/oracle/graal/nodeinfo/StructuralInput.java Fri Mar 27 17:02:53 2015 +0100 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2015, 2015, 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.nodeinfo; + +import java.lang.annotation.*; + +/** + * Marker type for describing node inputs in snippets that are not of type {@link InputType#Value}. + */ +public abstract class StructuralInput { + + private StructuralInput() { + throw new Error("Illegal instance of StructuralInput. This class should be used in snippets only."); + } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE) + public @interface MarkerType { + InputType value(); + } + + /** + * Marker type for {@link InputType#Memory} edges in snippets. + */ + @MarkerType(InputType.Memory) + public abstract static class Memory extends StructuralInput { + } + + /** + * Marker type for {@link InputType#Condition} edges in snippets. + */ + @MarkerType(InputType.Condition) + public abstract static class Condition extends StructuralInput { + } + + /** + * Marker type for {@link InputType#State} edges in snippets. + */ + @MarkerType(InputType.State) + public abstract static class State extends StructuralInput { + } + + /** + * Marker type for {@link InputType#Guard} edges in snippets. + */ + @MarkerType(InputType.Guard) + public abstract static class Guard extends StructuralInput { + } + + /** + * Marker type for {@link InputType#Anchor} edges in snippets. + */ + @MarkerType(InputType.Anchor) + public abstract static class Anchor extends StructuralInput { + } + + /** + * Marker type for {@link InputType#Association} edges in snippets. + */ + @MarkerType(InputType.Association) + public abstract static class Association extends StructuralInput { + } + + /** + * Marker type for {@link InputType#Extension} edges in snippets. + */ + @MarkerType(InputType.Extension) + public abstract static class Extension extends StructuralInput { + } +} diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Fri Mar 27 17:02:53 2015 +0100 @@ -781,6 +781,8 @@ } } } + transferProxies(trueSuccessor(), trueMerge); + transferProxies(falseSuccessor(), falseMerge); cleanupMerge(tool, merge); cleanupMerge(tool, trueMerge); @@ -789,6 +791,14 @@ return true; } + private static void transferProxies(AbstractBeginNode successor, MergeNode falseMerge) { + if (falseMerge != null) { + for (ProxyNode proxy : successor.proxies().snapshot()) { + proxy.replaceFirstInput(successor, falseMerge); + } + } + } + private void cleanupMerge(SimplifierTool tool, MergeNode merge) { if (merge != null && merge.isAlive()) { if (merge.forwardEndCount() == 0) { diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryAnchorNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryAnchorNode.java Fri Mar 27 17:02:53 2015 +0100 @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2014, 2015, 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.extended; + +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.nodeinfo.StructuralInput.Memory; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; + +@NodeInfo(allowedUsageTypes = {InputType.Memory}) +public final class MemoryAnchorNode extends FixedWithNextNode implements LIRLowerable, MemoryNode, Canonicalizable { + + public static final NodeClass TYPE = NodeClass.create(MemoryAnchorNode.class); + + public MemoryAnchorNode() { + super(TYPE, StampFactory.forVoid()); + } + + public void generate(NodeLIRBuilderTool generator) { + // Nothing to emit, since this node is used for structural purposes only. + } + + @Override + public Node canonical(CanonicalizerTool tool) { + return hasNoUsages() ? null : this; + } + + @NodeIntrinsic + public static native Memory anchor(); +} diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/SelfReplacingMethodCallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/SelfReplacingMethodCallTargetNode.java Fri Mar 27 15:43:31 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2013, 2015, 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.java; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodeinfo.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; - -/** - * A SelfReplacingMethodCallTargetNode replaces itself in the graph when being lowered with a - * {@link MethodCallTargetNode} that calls the stored replacement target method. - * - * This node is used for method handle call nodes which have a constant call target but are not - * inlined. - */ -@NodeInfo -public final class SelfReplacingMethodCallTargetNode extends MethodCallTargetNode implements Lowerable { - - public static final NodeClass TYPE = NodeClass.create(SelfReplacingMethodCallTargetNode.class); - // Replacement method data - protected final ResolvedJavaMethod replacementTargetMethod; - protected final JavaType replacementReturnType; - @Input NodeInputList replacementArguments; - - public SelfReplacingMethodCallTargetNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] arguments, JavaType returnType, ResolvedJavaMethod replacementTargetMethod, - ValueNode[] replacementArguments, JavaType replacementReturnType) { - super(TYPE, invokeKind, targetMethod, arguments, returnType); - this.replacementTargetMethod = replacementTargetMethod; - this.replacementReturnType = replacementReturnType; - this.replacementArguments = new NodeInputList<>(this, replacementArguments); - } - - public ResolvedJavaMethod replacementTargetMethod() { - return replacementTargetMethod; - } - - public JavaType replacementReturnType() { - return replacementReturnType; - } - - public NodeInputList replacementArguments() { - return replacementArguments; - } - - @Override - public void lower(LoweringTool tool) { - InvokeKind replacementInvokeKind = replacementTargetMethod.isStatic() ? InvokeKind.Static : InvokeKind.Special; - MethodCallTargetNode replacement = graph().add( - new MethodCallTargetNode(replacementInvokeKind, replacementTargetMethod, replacementArguments.toArray(new ValueNode[replacementArguments.size()]), replacementReturnType)); - - // Replace myself... - this.replaceAndDelete(replacement); - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - throw GraalInternalError.shouldNotReachHere("should have replaced itself"); - } -} diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/MacroSubstitution.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/MacroSubstitution.java Fri Mar 27 15:43:31 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,89 +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. - */ -package com.oracle.graal.nodes.spi; - -import java.lang.annotation.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.replacements.*; -import com.oracle.graal.nodes.*; - -/** - * Denotes a macro substitute method. This replaces a method invocation with an instance of the - * {@link #macro() specified} node class. - *

- * A macro substitution can be combined with a {@link MethodSubstitution method substitution}. In - * this case, if the macro is not removed during canonicalization, it is lowered via the method - * substitution. - *

- * If a macro is not combined with a method substitution, it is lowered to an invocation of the - * original method. - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.METHOD) -public @interface MacroSubstitution { - - /** - * Gets the name of the substituted method. - *

- * If the default value is specified for this element, then the name of the substituted method - * is same as the substitute method. - */ - String value() default ""; - - /** - * Determines if the substituted method is static. - */ - boolean isStatic() default true; - - /** - * Gets the {@linkplain Signature#toMethodDescriptor signature} of the substituted method. - *

- * If the default value is specified for this element, then the signature of the substituted - * method is the same as the substitute method. - */ - String signature() default ""; - - /** - * Determines if the substitution is for a method that may not be part of the runtime. For - * example, a method introduced in a later JDK version. Substitutions for such methods are - * omitted if the original method cannot be found. - */ - boolean optional() default false; - - /** - * The node class with which the method invocation should be replaced. It needs to be a subclass - * of {@link FixedWithNextNode}, and it is expected to provide a public constructor that takes - * an {@link InvokeNode} as a parameter. - */ - Class macro(); - - /** - * Determines if this method should be substituted in all cases, even if inlining thinks it is - * not important. - * - * Note that this is still depending on whether inlining sees the correct call target, so it's - * only a hard guarantee for static and special invocations. - */ - boolean forced() default false; -} diff -r d22307a9a025 -r eea134855f85 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 Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java Fri Mar 27 17:02:53 2015 +0100 @@ -47,7 +47,7 @@ * * @param recursiveEntry if the snippet contains a call to this method, it's considered as * recursive call and won't be processed for {@linkplain MethodSubstitution - * substitutions} or {@linkplain MacroSubstitution macro nodes}. + * substitutions}. * @param args arguments to the snippet if available, otherwise {@code null} * @return the snippet graph, if any, that is derived from {@code method} */ @@ -82,17 +82,8 @@ ResolvedJavaMethod getMethodSubstitutionMethod(ResolvedJavaMethod method); /** - * Gets the node class with which a method invocation should be replaced. - * - * @param method target of an invocation - * @return the {@linkplain MacroSubstitution#macro() macro node class} associated with - * {@code method} or null if there is no such association - */ - Class getMacroSubstitution(ResolvedJavaMethod method); - - /** - * Registers all the {@linkplain MethodSubstitution method} and {@linkplain MacroSubstitution - * macro} substitutions defined by a given class. + * Registers all the {@linkplain MethodSubstitution method} substitutions defined by a given + * class. * * @param original the original class for which substitutions are being registered. This must be * the same type denoted by the {@link ClassSubstitution} annotation on diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DominatorConditionalEliminationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DominatorConditionalEliminationPhase.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DominatorConditionalEliminationPhase.java Fri Mar 27 17:02:53 2015 +0100 @@ -130,13 +130,13 @@ private static class Instance { private final NodeMap map; - private final Stack loopExits; + private final Deque loopExits; private final Function> blockToNodes; private final Function nodeToBlock; public Instance(StructuredGraph graph, Function> blockToNodes, Function nodeToBlock) { map = graph.createNodeMap(); - loopExits = new Stack<>(); + loopExits = new ArrayDeque<>(); this.blockToNodes = blockToNodes; this.nodeToBlock = nodeToBlock; } @@ -282,8 +282,8 @@ } Block guardBlock = nodeToBlock.apply(proxiedGuard); assert guardBlock != null; - for (int i = 0; i < loopExits.size(); ++i) { - LoopExitNode loopExitNode = loopExits.get(i); + for (Iterator iter = loopExits.descendingIterator(); iter.hasNext();) { + LoopExitNode loopExitNode = iter.next(); Block loopExitBlock = nodeToBlock.apply(loopExitNode); if (guardBlock != loopExitBlock && AbstractControlFlowGraph.dominates(guardBlock, loopExitBlock)) { Block loopBeginBlock = nodeToBlock.apply(loopExitNode.loopBegin()); diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java Fri Mar 27 17:02:53 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, 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 @@ -255,6 +255,11 @@ @Override protected MemoryMapImpl processNode(FixedNode node, MemoryMapImpl state) { + if (node instanceof MemoryAnchorNode) { + processAnchor((MemoryAnchorNode) node, state); + return state; + } + if (node instanceof MemoryAccess) { processAccess((MemoryAccess) node, state); } @@ -274,6 +279,28 @@ return state; } + /** + * Improve the memory graph by re-wiring all usages of a {@link MemoryAnchorNode} to the + * real last access location. + */ + private static void processAnchor(MemoryAnchorNode anchor, MemoryMapImpl state) { + for (Node node : anchor.usages().snapshot()) { + if (node instanceof MemoryAccess) { + MemoryAccess access = (MemoryAccess) node; + if (access.getLastLocationAccess() == anchor) { + MemoryNode lastLocationAccess = state.getLastLocationAccess(access.getLocationIdentity()); + if (lastLocationAccess != null) { + access.setLastLocationAccess(lastLocationAccess); + } + } + } + } + + if (anchor.hasNoUsages()) { + anchor.graph().removeFixed(anchor); + } + } + private static void processAccess(MemoryAccess access, MemoryMapImpl state) { LocationIdentity locationIdentity = access.getLocationIdentity(); if (!locationIdentity.equals(LocationIdentity.any())) { diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java Fri Mar 27 17:02:53 2015 +0100 @@ -212,7 +212,7 @@ if (callTarget.targetMethod() == null) { return "target method is null"; } - assert invoke.stateAfter() != null; + assert invoke.stateAfter() != null : invoke; if (!invoke.useForInlining()) { return "the invoke is marked to be not used for inlining"; } @@ -574,17 +574,13 @@ } public static boolean canIntrinsify(Replacements replacements, ResolvedJavaMethod target) { - return replacements.getMethodSubstitutionMethod(target) != null || getMacroNodeClass(replacements, target) != null; + return replacements.getMethodSubstitutionMethod(target) != null; } public static StructuredGraph getIntrinsicGraph(Replacements replacements, ResolvedJavaMethod target) { return replacements.getMethodSubstitution(target); } - public static Class getMacroNodeClass(Replacements replacements, ResolvedJavaMethod target) { - return replacements.getMacroSubstitution(target); - } - public static FixedWithNextNode inlineMacroNode(Invoke invoke, ResolvedJavaMethod concrete, Class macroNodeClass) throws GraalInternalError { StructuredGraph graph = invoke.asNode().graph(); if (!concrete.equals(((MethodCallTargetNode) invoke.callTarget()).targetMethod())) { diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/AbstractInlineInfo.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/AbstractInlineInfo.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/AbstractInlineInfo.java Fri Mar 27 17:02:53 2015 +0100 @@ -52,17 +52,10 @@ protected static Collection inline(Invoke invoke, ResolvedJavaMethod concrete, Inlineable inlineable, boolean receiverNullCheck) { List canonicalizeNodes = new ArrayList<>(); - if (inlineable instanceof InlineableGraph) { - StructuredGraph calleeGraph = ((InlineableGraph) inlineable).getGraph(); - Map duplicateMap = InliningUtil.inline(invoke, calleeGraph, receiverNullCheck, canonicalizeNodes); - getInlinedParameterUsages(canonicalizeNodes, calleeGraph, duplicateMap); - } else { - assert inlineable instanceof InlineableMacroNode; - - Class macroNodeClass = ((InlineableMacroNode) inlineable).getMacroNodeClass(); - FixedWithNextNode macroNode = InliningUtil.inlineMacroNode(invoke, concrete, macroNodeClass); - canonicalizeNodes.add(macroNode); - } + assert inlineable instanceof InlineableGraph; + StructuredGraph calleeGraph = ((InlineableGraph) inlineable).getGraph(); + Map duplicateMap = InliningUtil.inline(invoke, calleeGraph, receiverNullCheck, canonicalizeNodes); + getInlinedParameterUsages(canonicalizeNodes, calleeGraph, duplicateMap); InliningUtil.InlinedBytecodes.add(concrete.getCodeSize()); StructuredGraph graph = invoke.asNode().graph(); diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/Inlineable.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/Inlineable.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/Inlineable.java Fri Mar 27 17:02:53 2015 +0100 @@ -22,24 +22,17 @@ */ package com.oracle.graal.phases.common.inlining.info.elem; -import com.oracle.graal.api.meta.ResolvedJavaMethod; -import com.oracle.graal.nodes.FixedWithNextNode; -import com.oracle.graal.nodes.Invoke; -import com.oracle.graal.phases.common.CanonicalizerPhase; -import com.oracle.graal.phases.common.inlining.InliningUtil; -import com.oracle.graal.phases.tiers.HighTierContext; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; public interface Inlineable { static Inlineable getInlineableElement(final ResolvedJavaMethod method, Invoke invoke, HighTierContext context, CanonicalizerPhase canonicalizer) { assert method != null; assert invoke != null; - Class macroNodeClass = InliningUtil.getMacroNodeClass(context.getReplacements(), method); - if (macroNodeClass != null) { - return new InlineableMacroNode(macroNodeClass); - } else { - return new InlineableGraph(method, invoke, context, canonicalizer); - } + return new InlineableGraph(method, invoke, context, canonicalizer); } int getNodeCount(); diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/InlineableMacroNode.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/InlineableMacroNode.java Fri Mar 27 15:43:31 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +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.phases.common.inlining.info.elem; - -import com.oracle.graal.compiler.common.*; -import com.oracle.graal.nodes.FixedWithNextNode; -import com.oracle.graal.nodes.Invoke; - -import java.util.Collections; - -public class InlineableMacroNode implements Inlineable { - - private final Class macroNodeClass; - - public InlineableMacroNode(Class macroNodeClass) { - this.macroNodeClass = macroNodeClass; - } - - @Override - public int getNodeCount() { - return 1; - } - - @Override - public Iterable getInvokes() { - return Collections.emptyList(); - } - - public Class getMacroNodeClass() { - return macroNodeClass; - } - - public double getProbability(Invoke invoke) { - throw GraalInternalError.shouldNotReachHere("No invokes in inlineable"); - } -} diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/CallsiteHolderDummy.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/CallsiteHolderDummy.java Fri Mar 27 15:43:31 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.phases.common.inlining.walker; - -import com.oracle.graal.api.meta.ResolvedJavaMethod; -import com.oracle.graal.nodes.StructuredGraph; - -import com.oracle.graal.phases.common.inlining.info.elem.InlineableMacroNode; - -/** - * A {@link CallsiteHolder} that stands for an {@link InlineableMacroNode} in the stack realized by - * {@link InliningData}. - */ -public final class CallsiteHolderDummy extends CallsiteHolder { - - public static final CallsiteHolderDummy DUMMY_CALLSITE_HOLDER = new CallsiteHolderDummy(); - - private CallsiteHolderDummy() { - // no instances other than the singleton - } - - @Override - public ResolvedJavaMethod method() { - return null; - } - - @Override - public boolean hasRemainingInvokes() { - return false; - } - - @Override - public StructuredGraph graph() { - return null; - } - - @Override - public String toString() { - return ""; - } -} diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java Fri Mar 27 17:02:53 2015 +0100 @@ -23,7 +23,6 @@ package com.oracle.graal.phases.common.inlining.walker; import static com.oracle.graal.compiler.common.GraalOptions.*; -import static com.oracle.graal.phases.common.inlining.walker.CallsiteHolderDummy.*; import java.util.*; @@ -560,7 +559,7 @@ assert graphQueue.size() <= maxGraphs; for (int i = 0; i < info.numberOfMethods(); i++) { CallsiteHolder ch = methodInvocation.buildCallsiteHolderForElement(i); - assert (ch == DUMMY_CALLSITE_HOLDER) || !contains(ch.graph()); + assert !contains(ch.graph()); graphQueue.push(ch); assert graphQueue.size() <= maxGraphs; } @@ -733,12 +732,8 @@ } CallsiteHolder queuedTargetCH = iter.next(); Inlineable targetIE = currentInvocation().callee().inlineableElementAt(i); - if (targetIE instanceof InlineableMacroNode) { - assert queuedTargetCH == DUMMY_CALLSITE_HOLDER; - } else { - InlineableGraph targetIG = (InlineableGraph) targetIE; - assert queuedTargetCH.method().equals(targetIG.getGraph().method()); - } + InlineableGraph targetIG = (InlineableGraph) targetIE; + assert queuedTargetCH.method().equals(targetIG.getGraph().method()); } return true; } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/MethodInvocation.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/MethodInvocation.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/MethodInvocation.java Fri Mar 27 17:02:53 2015 +0100 @@ -123,15 +123,11 @@ public CallsiteHolder buildCallsiteHolderForElement(int index) { Inlineable elem = callee.inlineableElementAt(index); - if (elem instanceof InlineableGraph) { - InlineableGraph ig = (InlineableGraph) elem; - final double invokeProbability = probability * callee.probabilityAt(index); - final double invokeRelevance = relevance * callee.relevanceAt(index); - return new CallsiteHolderExplorable(ig.getGraph(), invokeProbability, invokeRelevance, freshlyInstantiatedArguments); - } else { - assert elem instanceof InlineableMacroNode; - return CallsiteHolderDummy.DUMMY_CALLSITE_HOLDER; - } + assert elem instanceof InlineableGraph; + InlineableGraph ig = (InlineableGraph) elem; + final double invokeProbability = probability * callee.probabilityAt(index); + final double invokeRelevance = relevance * callee.relevanceAt(index); + return new CallsiteHolderExplorable(ig.getGraph(), invokeProbability, invokeRelevance, freshlyInstantiatedArguments); } @Override diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java Fri Mar 27 17:02:53 2015 +0100 @@ -141,8 +141,9 @@ } ControlFlowGraph cfg = schedule == null ? null : schedule.getCFG(); BlockMap> blockToNodes = schedule == null ? null : schedule.getBlockToNodesMap(); + NodeMap nodeToBlocks = schedule == null ? null : schedule.getNodeToBlockMap(); List blocks = cfg == null ? null : cfg.getBlocks(); - writeNodes(graph); + writeNodes(graph, nodeToBlocks); writeBlocks(blocks, blockToNodes); } @@ -399,7 +400,7 @@ return node.getId(); } - private void writeNodes(Graph graph) throws IOException { + private void writeNodes(Graph graph, NodeMap nodeToBlocks) throws IOException { ToDoubleFunction probabilities = null; if (PrintGraphProbabilities.getValue()) { try { @@ -421,6 +422,16 @@ props.put("probability", t); } } + if (nodeToBlocks != null) { + if (nodeToBlocks.isNew(node)) { + props.put("node-to-block", "NEW (not in schedule)"); + } else { + Block block = nodeToBlocks.get(node); + if (block != null) { + props.put("node-to-block", block.getId()); + } + } + } writeInt(getNodeId(node)); writePoolObject(nodeClass); writeByte(node.predecessor() == null ? 0 : 1); diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ReplacementsParseTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ReplacementsParseTest.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ReplacementsParseTest.java Fri Mar 27 17:02:53 2015 +0100 @@ -22,6 +22,8 @@ */ package com.oracle.graal.replacements.test; +import java.util.function.*; + import org.junit.*; import com.oracle.graal.api.meta.*; @@ -34,6 +36,9 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.runtime.*; +/** + * Tests for expected behavior when parsing snippets and intrinsics. + */ public class ReplacementsParseTest extends GraalCompilerTest { private static final Object THROW_EXCEPTION_MARKER = new Object() { @@ -64,6 +69,10 @@ } return res; } + + static String identity(String s) { + return s; + } } @ClassSubstitution(TestMethods.class) @@ -75,11 +84,17 @@ return Math.nextAfter(xx, d); } + /** + * Tests partial intrinsification. + */ @MethodSubstitution static String stringize(Object obj) { if (obj != null && obj.getClass() == String.class) { return asNonNullString(obj); } else { + // A recursive call denotes exiting/deoptimizing + // out of the partial intrinsification to the + // slow/uncommon case. return stringize(obj); } } @@ -91,6 +106,17 @@ @NodeIntrinsic(PiNode.class) private static native String asNonNullStringIntrinsic(Object object, @ConstantNodeParameter Class toType, @ConstantNodeParameter boolean exactType, @ConstantNodeParameter boolean nonNull); + /** + * Tests that non-capturing lambdas are folded away. + */ + @MethodSubstitution + static String identity(String value) { + return apply(s -> s, value); + } + + private static String apply(Function f, String value) { + return f.apply(value); + } } private static boolean substitutionsInstalled; @@ -156,7 +182,7 @@ test("callStringize", Boolean.TRUE); } - public Object callStringize(Object obj) { + public static Object callStringize(Object obj) { return TestMethods.stringize(obj); } @@ -167,4 +193,14 @@ test(method, null, Boolean.TRUE); test(method, null, THROW_EXCEPTION_MARKER); } + + @Test + public void testLambda() { + test("callLambda", (String) null); + test("callLambda", "a string"); + } + + public static String callLambda(String value) { + return TestMethods.identity(value); + } } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/SubstitutionsTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/SubstitutionsTest.java Fri Mar 27 17:02:53 2015 +0100 @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2015, 2015, 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.test; + +import static com.oracle.graal.nodeinfo.InputType.*; +import static org.hamcrest.CoreMatchers.*; + +import org.junit.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.iterators.*; +import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.nodeinfo.StructuralInput.Guard; +import com.oracle.graal.nodeinfo.StructuralInput.Memory; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.extended.*; + +public class SubstitutionsTest extends GraalCompilerTest { + + @NodeInfo(allowedUsageTypes = {Memory}) + private static class TestMemory extends FixedWithNextNode implements MemoryNode { + private static final NodeClass TYPE = NodeClass.create(TestMemory.class); + + public TestMemory() { + super(TYPE, StampFactory.forVoid()); + } + + @NodeIntrinsic + public static native Memory memory(); + } + + @NodeInfo(allowedUsageTypes = {Guard}) + private static class TestGuard extends FloatingNode implements GuardingNode { + private static final NodeClass TYPE = NodeClass.create(TestGuard.class); + + @Input(Memory) MemoryNode memory; + + public TestGuard(ValueNode memory) { + super(TYPE, StampFactory.forVoid()); + this.memory = (MemoryNode) memory; + } + + @NodeIntrinsic + public static native Guard guard(Memory memory); + } + + @NodeInfo + private static class TestValue extends FloatingNode { + private static final NodeClass TYPE = NodeClass.create(TestValue.class); + + @Input(Guard) GuardingNode guard; + + public TestValue(ValueNode guard) { + super(TYPE, StampFactory.forKind(Kind.Int)); + this.guard = (GuardingNode) guard; + } + + @NodeIntrinsic + public static native int value(Guard guard); + } + + private static class TestMethod { + + public static int test() { + return 42; + } + } + + @ClassSubstitution(TestMethod.class) + private static class TestMethodSubstitution { + + @MethodSubstitution + public static int test() { + Memory memory = TestMemory.memory(); + Guard guard = TestGuard.guard(memory); + return TestValue.value(guard); + } + } + + private static boolean substitutionsInstalled; + + public SubstitutionsTest() { + if (!substitutionsInstalled) { + getProviders().getReplacements().registerSubstitutions(TestMethod.class, TestMethodSubstitution.class); + substitutionsInstalled = true; + } + } + + public static int callTest() { + return TestMethod.test(); + } + + @Override + protected boolean checkHighTierGraph(StructuredGraph graph) { + // Check that the graph contains the expected test nodes. + NodeIterable retNodes = graph.getNodes().filter(ReturnNode.class); + Assert.assertTrue("expected exactly one ReturnNode", retNodes.count() == 1); + ReturnNode ret = retNodes.first(); + + Assert.assertThat(ret.result(), instanceOf(TestValue.class)); + TestValue value = (TestValue) ret.result(); + + Assert.assertThat(value.guard, instanceOf(TestGuard.class)); + TestGuard guard = (TestGuard) value.guard; + + Assert.assertThat(guard.memory, instanceOf(TestMemory.class)); + TestMemory memory = (TestMemory) guard.memory; + + // Remove the test nodes, replacing them by the constant 42. + // This implicitly makes sure that the rest of the graph is valid. + ret.replaceFirstInput(value, graph.unique(ConstantNode.forInt(42))); + value.safeDelete(); + guard.safeDelete(); + graph.removeFixed(memory); + + return true; + } + + @Test + public void snippetTest() { + test("callTest"); + } +} diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/NodeIntrinsicVerifier.java --- a/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/NodeIntrinsicVerifier.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/NodeIntrinsicVerifier.java Fri Mar 27 17:02:53 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, 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 @@ -34,6 +34,8 @@ import com.oracle.graal.graph.Node.ConstantNodeParameter; import com.oracle.graal.graph.Node.InjectedNodeParameter; import com.oracle.graal.graph.Node.NodeIntrinsic; +import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.nodeinfo.StructuralInput.MarkerType; public final class NodeIntrinsicVerifier extends AbstractVerifier { @@ -55,6 +57,10 @@ return env.getElementUtils().getTypeElement("com.oracle.graal.api.meta.ResolvedJavaType").asType(); } + private TypeMirror structuralInputType() { + return env.getElementUtils().getTypeElement("com.oracle.graal.nodeinfo.StructuralInput").asType(); + } + public NodeIntrinsicVerifier(ProcessingEnvironment env) { super(env); } @@ -100,6 +106,11 @@ if (nodeClass.getModifiers().contains(Modifier.ABSTRACT)) { env.getMessager().printMessage(Kind.ERROR, String.format("Cannot make @NodeIntrinsic for abstract node class %s.", nodeClass.getSimpleName()), element, annotation); } else { + TypeMirror ret = intrinsicMethod.getReturnType(); + if (env.getTypeUtils().isAssignable(ret, structuralInputType())) { + checkInputType(nodeClass, ret, element, annotation); + } + TypeMirror[] constructorSignature = constructorSignature(intrinsicMethod); findConstructor(nodeClass, constructorSignature, intrinsicMethod, annotation); } @@ -108,6 +119,39 @@ } } + private void checkInputType(TypeElement nodeClass, TypeMirror returnType, Element element, AnnotationMirror annotation) { + InputType inputType = getInputType(returnType, element, annotation); + if (inputType != InputType.Value) { + boolean allowed = false; + InputType[] allowedTypes = nodeClass.getAnnotation(NodeInfo.class).allowedUsageTypes(); + for (InputType allowedType : allowedTypes) { + if (inputType == allowedType) { + allowed = true; + break; + } + } + if (!allowed) { + env.getMessager().printMessage(Kind.ERROR, String.format("@NodeIntrinsic returns input type %s, but only %s is allowed.", inputType, Arrays.toString(allowedTypes)), element, + annotation); + } + } + } + + private InputType getInputType(TypeMirror type, Element element, AnnotationMirror annotation) { + TypeElement current = (TypeElement) env.getTypeUtils().asElement(type); + while (current != null) { + MarkerType markerType = current.getAnnotation(MarkerType.class); + if (markerType != null) { + return markerType.value(); + } + + current = (TypeElement) env.getTypeUtils().asElement(current.getSuperclass()); + } + + env.getMessager().printMessage(Kind.ERROR, String.format("The class %s is a subclass of StructuralInput, but isn't annotated with @MarkerType.", type), element, annotation); + return InputType.Value; + } + private boolean isNodeType(TypeElement nodeClass) { return env.getTypeUtils().isSubtype(nodeClass.asType(), nodeType()); } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultGenericInvocationPlugin.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultGenericInvocationPlugin.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultGenericInvocationPlugin.java Fri Mar 27 17:02:53 2015 +0100 @@ -29,9 +29,12 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.graphbuilderconf.*; +import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.nodeinfo.StructuralInput.MarkerType; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.word.*; @@ -44,15 +47,19 @@ protected final NodeIntrinsificationPhase nodeIntrinsification; protected final WordOperationPlugin wordOperationPlugin; - public DefaultGenericInvocationPlugin(NodeIntrinsificationPhase nodeIntrinsification, WordOperationPlugin wordOperationPlugin) { + private final ResolvedJavaType structuralInputType; + + public DefaultGenericInvocationPlugin(MetaAccessProvider metaAccess, NodeIntrinsificationPhase nodeIntrinsification, WordOperationPlugin wordOperationPlugin) { this.nodeIntrinsification = nodeIntrinsification; this.wordOperationPlugin = wordOperationPlugin; + + this.structuralInputType = metaAccess.lookupJavaType(StructuralInput.class); } public boolean apply(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) { - if (wordOperationPlugin.apply(b, method, args)) { + if (b.parsingReplacement() && wordOperationPlugin.apply(b, method, args)) { return true; - } else if (b.parsingReplacement() || b.eagerResolving()) { + } else if (b.parsingReplacement()) { NodeIntrinsic intrinsic = nodeIntrinsification.getIntrinsic(method); if (intrinsic != null) { Signature sig = method.getSignature(); @@ -78,8 +85,8 @@ if (!COULD_NOT_FOLD.equals(constant)) { if (constant != null) { // Replace the invoke with the result of the call - ConstantNode res = b.append(ConstantNode.forConstant(constant, b.getMetaAccess())); - b.push(res.getKind().getStackKind(), b.append(res)); + ConstantNode res = b.add(ConstantNode.forConstant(constant, b.getMetaAccess())); + b.addPush(res.getKind().getStackKind(), res); } else { // This must be a void invoke assert method.getSignature().getReturnKind() == Kind.Void; @@ -91,6 +98,24 @@ return false; } + private InputType getInputType(ObjectStamp stamp) { + ResolvedJavaType type = stamp.type(); + if (type != null && structuralInputType.isAssignableFrom(type)) { + while (type != null) { + MarkerType markerType = type.getAnnotation(MarkerType.class); + if (markerType != null) { + return markerType.value(); + } + + type = type.getSuperclass(); + } + + throw GraalInternalError.shouldNotReachHere(String.format("%s extends StructuralInput, but is not annotated with @MarkerType", stamp.type())); + } else { + return InputType.Value; + } + } + protected boolean processNodeIntrinsic(GraphBuilderContext b, ResolvedJavaMethod method, NodeIntrinsic intrinsic, List args, Kind returnKind, Stamp stamp) { ValueNode res = createNodeIntrinsic(b, method, intrinsic, args, stamp); if (res == null) { @@ -98,18 +123,25 @@ } if (res instanceof UnsafeCopyNode) { UnsafeCopyNode copy = (UnsafeCopyNode) res; - UnsafeLoadNode value = b.append(new UnsafeLoadNode(copy.sourceObject(), copy.sourceOffset(), copy.accessKind(), copy.getLocationIdentity())); - UnsafeStoreNode unsafeStore = new UnsafeStoreNode(copy.destinationObject(), copy.destinationOffset(), value, copy.accessKind(), copy.getLocationIdentity()); - b.append(unsafeStore); - unsafeStore.setStateAfter(b.createStateAfter()); + UnsafeLoadNode value = b.add(new UnsafeLoadNode(copy.sourceObject(), copy.sourceOffset(), copy.accessKind(), copy.getLocationIdentity())); + b.add(new UnsafeStoreNode(copy.destinationObject(), copy.destinationOffset(), value, copy.accessKind(), copy.getLocationIdentity())); return true; } else if (res instanceof ForeignCallNode) { ForeignCallNode foreign = (ForeignCallNode) res; foreign.setBci(b.bci()); } - res = b.append(res); - if (returnKind != Kind.Void) { + res = b.add(res); + + InputType inputType = InputType.Value; + if (returnKind == Kind.Object && stamp instanceof ObjectStamp) { + inputType = getInputType((ObjectStamp) stamp); + } + + if (inputType != InputType.Value) { + assert res.isAllowedUsageType(inputType); + b.push(Kind.Object, res); + } else if (returnKind != Kind.Void) { assert res.getKind().getStackKind() != Kind.Void; b.push(returnKind.getStackKind(), res); } else { diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultInlineInvokePlugin.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultInlineInvokePlugin.java Fri Mar 27 17:02:53 2015 +0100 @@ -0,0 +1,52 @@ +/* + * 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.replacements; + +import static com.oracle.graal.compiler.common.GraalOptions.*; +import static com.oracle.graal.java.AbstractBytecodeParser.Options.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graphbuilderconf.*; +import com.oracle.graal.nodes.*; + +public final class DefaultInlineInvokePlugin implements InlineInvokePlugin { + private final ReplacementsImpl replacements; + + public DefaultInlineInvokePlugin(ReplacementsImpl replacements) { + this.replacements = replacements; + } + + public InlineInfo getInlineInfo(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args, JavaType returnType) { + InlineInfo inlineInfo = replacements.getInlineInfo(b, method, args, returnType); + if (inlineInfo == null) { + if (InlineDuringParsing.getValue() && method.hasBytecodes() && method.getCode().length <= TrivialInliningSize.getValue() && b.getDepth() < InlineDuringParsingMaxDepth.getValue()) { + return new InlineInfo(method, false, false); + } + } + return inlineInfo; + } + + public void notifyOfNoninlinedInvoke(GraphBuilderContext b, ResolvedJavaMethod method, Invoke invoke) { + replacements.notifyOfNoninlinedInvoke(b, method, invoke); + } +} diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/MathSubstitutionsX86.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/MathSubstitutionsX86.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/MathSubstitutionsX86.java Fri Mar 27 17:02:53 2015 +0100 @@ -27,7 +27,6 @@ import com.oracle.graal.graph.Node.ConstantNodeParameter; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.replacements.nodes.MathIntrinsicNode.Operation; @@ -42,7 +41,6 @@ /** * Special cases from {@link Math#pow} and __ieee754_pow (in sharedRuntimeTrans.cpp). */ - @MacroSubstitution(macro = MathPowNode.class) @MethodSubstitution(guard = MathGuard.class) public static double pow(double x, double y) { // If the second argument is positive or negative zero, then the result is 1.0. diff -r d22307a9a025 -r eea134855f85 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 Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Fri Mar 27 17:02:53 2015 +0100 @@ -25,7 +25,9 @@ import static com.oracle.graal.api.meta.MetaUtil.*; import static com.oracle.graal.compiler.GraalCompiler.*; import static com.oracle.graal.compiler.common.GraalOptions.*; +import static com.oracle.graal.java.AbstractBytecodeParser.Options.*; import static com.oracle.graal.phases.common.DeadCodeEliminationPhase.Optionality.*; +import static java.lang.String.*; import java.lang.reflect.*; import java.util.*; @@ -42,8 +44,11 @@ import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.graph.*; +import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.graphbuilderconf.*; import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; +import com.oracle.graal.graphbuilderconf.GraphBuilderContext.*; +import com.oracle.graal.graphbuilderconf.InlineInvokePlugin.InlineInfo; import com.oracle.graal.java.AbstractBytecodeParser.IntrinsicContext; import com.oracle.graal.java.AbstractBytecodeParser.ReplacementContext; import com.oracle.graal.java.*; @@ -56,8 +61,9 @@ import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; import com.oracle.graal.phases.util.*; +import com.oracle.graal.word.*; -public class ReplacementsImpl implements Replacements { +public class ReplacementsImpl implements Replacements, InlineInvokePlugin { public final Providers providers; public final SnippetReflectionProvider snippetReflection; @@ -75,12 +81,61 @@ this.graphBuilderPlugins = plugins; } + protected boolean hasGenericInvocationPluginAnnotation(ResolvedJavaMethod method) { + return nodeIntrinsificationPhase.getIntrinsic(method) != null || method.getAnnotation(Word.Operation.class) != null || nodeIntrinsificationPhase.isFoldable(method); + } + + private static final int MAX_GRAPH_INLINING_DEPTH = 100; // more than enough + + /** + * Determines whether a given method should be inlined based on whether it has a substitution or + * whether the inlining context is already within a substitution. + * + * @return an {@link InlineInfo} object specifying how {@code method} is to be inlined or null + * if it should not be inlined based on substitution related criteria + */ + public InlineInfo getInlineInfo(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args, JavaType returnType) { + ResolvedJavaMethod subst = getMethodSubstitutionMethod(method); + if (subst != null) { + if (b.parsingReplacement() || InlineDuringParsing.getValue()) { + // Forced inlining of intrinsics + return new InlineInfo(subst, true, true); + } + return null; + } + if (b.parsingReplacement()) { + assert !hasGenericInvocationPluginAnnotation(method) : format("%s should have been handled by %s", method.format("%H.%n(%p)"), DefaultGenericInvocationPlugin.class.getName()); + + assert b.getDepth() < MAX_GRAPH_INLINING_DEPTH : "inlining limit exceeded"; + + if (method.getName().startsWith("$jacoco")) { + throw new GraalInternalError("Found call to JaCoCo instrumentation method " + method.format("%H.%n(%p)") + ". Placing \"//JaCoCo Exclude\" anywhere in " + + b.getMethod().getDeclaringClass().getSourceFileName() + " should fix this."); + } + + // Force inlining when parsing replacements + return new InlineInfo(method, true, true); + } else { + assert nodeIntrinsificationPhase.getIntrinsic(method) == null : String.format("@%s method %s must only be called from within a replacement%n%s", NodeIntrinsic.class.getSimpleName(), + method.format("%h.%n"), b); + } + return null; + } + + public void notifyOfNoninlinedInvoke(GraphBuilderContext b, ResolvedJavaMethod method, Invoke invoke) { + if (b.parsingReplacement()) { + boolean compilingSnippet = b.getRootMethod().getAnnotation(Snippet.class) != null; + Replacement replacement = b.getReplacement(); + assert compilingSnippet : format("All calls in the replacement %s must be inlined or intrinsified: found call to %s", replacement.getReplacementMethod().format("%H.%n(%p)"), + method.format("%h.%n(%p)")); + } + } + /** * Encapsulates method and macro substitutions for a single class. */ protected class ClassReplacements { public final Map methodSubstitutions = CollectionsFactory.newMap(); - public final Map> macroSubstitutions = CollectionsFactory.newMap(); public final Set forcedSubstitutions = new HashSet<>(); public ClassReplacements(Class[] substitutionClasses, AtomicReference ref) { @@ -94,8 +149,7 @@ return; } MethodSubstitution methodSubstitution = substituteMethod.getAnnotation(MethodSubstitution.class); - MacroSubstitution macroSubstitution = substituteMethod.getAnnotation(MacroSubstitution.class); - if (methodSubstitution == null && macroSubstitution == null) { + if (methodSubstitution == null) { continue; } @@ -110,9 +164,6 @@ guard = defaultGuard; } - if (macroSubstitution != null && macroSubstitution.isStatic() != methodSubstitution.isStatic()) { - throw new GraalInternalError("Macro and method substitution must agree on isStatic attribute: " + substituteMethod); - } if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) { throw new GraalInternalError("Substitution method must not be abstract or native: " + substituteMethod); } @@ -130,21 +181,6 @@ } } } - // We don't have per method guards for macro substitutions but at - // least respect the defaultGuard if there is one. - if (macroSubstitution != null && (defaultGuard == null || defaultGuard.execute())) { - String originalName = originalName(substituteMethod, macroSubstitution.value()); - JavaSignature originalSignature = originalSignature(substituteMethod, macroSubstitution.signature(), macroSubstitution.isStatic()); - Executable[] originalMethods = originalMethods(classSubstitution, macroSubstitution.optional(), originalName, originalSignature); - for (Executable originalMethod : originalMethods) { - if (originalMethod != null) { - ResolvedJavaMethod original = registerMacroSubstitution(this, originalMethod, macroSubstitution.macro()); - if (original != null && macroSubstitution.forced() && shouldIntrinsify(original)) { - forcedSubstitutions.add(original); - } - } - } - } } } } @@ -321,11 +357,6 @@ } - public Class getMacroSubstitution(ResolvedJavaMethod method) { - ClassReplacements cr = getClassReplacements(method.getDeclaringClass().getName()); - return cr == null ? null : cr.macroSubstitutions.get(method); - } - private SubstitutionGuard getGuard(Class guardClass) { if (guardClass != SubstitutionGuard.class) { Constructor[] constructors = guardClass.getConstructors(); @@ -409,20 +440,6 @@ } /** - * Registers a macro substitution. - * - * @param originalMethod a method or constructor being substituted - * @param macro the substitute macro node class - * @return the original method - */ - protected ResolvedJavaMethod registerMacroSubstitution(ClassReplacements cr, Executable originalMethod, Class macro) { - MetaAccessProvider metaAccess = providers.getMetaAccess(); - ResolvedJavaMethod originalJavaMethod = metaAccess.lookupJavaMethod(originalMethod); - cr.macroSubstitutions.put(originalJavaMethod, macro); - return originalJavaMethod; - } - - /** * Creates a preprocessed graph for a snippet or method substitution. * * @param method the snippet or method substitution for which a graph will be created @@ -770,7 +787,6 @@ for (String internalName : classReplacements.keySet()) { ClassReplacements cr = getClassReplacements(internalName); result.addAll(cr.methodSubstitutions.keySet()); - result.addAll(cr.macroSubstitutions.keySet()); } return result; } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java Fri Mar 27 17:02:53 2015 +0100 @@ -108,9 +108,7 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver unsafe, ValueNode object, ValueNode offset, ValueNode expected, ValueNode x) { // Emits a null-check for the otherwise unused receiver unsafe.get(); - CompareAndSwapNode compareAndSwap = new CompareAndSwapNode(object, offset, expected, x, kind, LocationIdentity.any()); - b.push(Kind.Boolean.getStackKind(), b.append(compareAndSwap)); - compareAndSwap.setStateAfter(b.createStateAfter()); + b.addPush(Kind.Int, new CompareAndSwapNode(object, offset, expected, x, kind, LocationIdentity.any())); return true; } }); @@ -120,9 +118,7 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver unsafe, ValueNode object, ValueNode offset, ValueNode value) { // Emits a null-check for the otherwise unused receiver unsafe.get(); - AtomicReadAndWriteNode atomicReadWrite = new AtomicReadAndWriteNode(object, offset, value, kind, LocationIdentity.any()); - b.push(kind.getStackKind(), b.append(atomicReadWrite)); - atomicReadWrite.setStateAfter(b.createStateAfter()); + b.addPush(kind.getStackKind(), new AtomicReadAndWriteNode(object, offset, value, kind, LocationIdentity.any())); return true; } }); @@ -131,9 +127,7 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver unsafe, ValueNode object, ValueNode offset, ValueNode delta) { // Emits a null-check for the otherwise unused receiver unsafe.get(); - AtomicReadAndAddNode atomicReadAdd = new AtomicReadAndAddNode(object, offset, delta, LocationIdentity.any()); - b.push(kind.getStackKind(), b.append(atomicReadAdd)); - atomicReadAdd.setStateAfter(b.createStateAfter()); + b.addPush(kind.getStackKind(), new AtomicReadAndAddNode(object, offset, delta, LocationIdentity.any())); return true; } }); @@ -186,9 +180,9 @@ r.register1("reverseBytes", char.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { // return (char) (Integer.reverse(i) >> 16); - ReverseBytesNode reverse = b.append(new ReverseBytesNode(value)); - RightShiftNode rightShift = b.append(new RightShiftNode(reverse, b.append(ConstantNode.forInt(16)))); - ZeroExtendNode charCast = b.append(new ZeroExtendNode(b.append(new NarrowNode(rightShift, 16)), 32)); + ReverseBytesNode reverse = b.add(new ReverseBytesNode(value)); + RightShiftNode rightShift = b.add(new RightShiftNode(reverse, b.add(ConstantNode.forInt(16)))); + ZeroExtendNode charCast = b.add(new ZeroExtendNode(b.add(new NarrowNode(rightShift, 16)), 32)); b.push(Kind.Char.getStackKind(), b.recursiveAppend(charCast.canonical(null, value))); return true; } @@ -200,9 +194,9 @@ r.register1("reverseBytes", short.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { // return (short) (Integer.reverse(i) >> 16); - ReverseBytesNode reverse = b.append(new ReverseBytesNode(value)); - RightShiftNode rightShift = b.append(new RightShiftNode(reverse, b.append(ConstantNode.forInt(16)))); - SignExtendNode charCast = b.append(new SignExtendNode(b.append(new NarrowNode(rightShift, 16)), 32)); + ReverseBytesNode reverse = b.add(new ReverseBytesNode(value)); + RightShiftNode rightShift = b.add(new RightShiftNode(reverse, b.add(ConstantNode.forInt(16)))); + SignExtendNode charCast = b.add(new SignExtendNode(b.add(new NarrowNode(rightShift, 16)), 32)); b.push(Kind.Short.getStackKind(), b.recursiveAppend(charCast.canonical(null, value))); return true; } @@ -261,6 +255,17 @@ return true; } }); + r.register2("pow", Double.TYPE, Double.TYPE, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode x, ValueNode y) { + ValueNode folded = MathPowNode.tryFold(x, y); + if (folded != null) { + b.addPush(Kind.Double, folded); + } else { + b.addPush(Kind.Double, new MathPowNode(b.getInvokeKind(), targetMethod, b.bci(), b.getInvokeReturnType(), x, y)); + } + return true; + } + }); if (getAndSetEnabled(arch)) { r.register1("log", Double.TYPE, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { @@ -302,7 +307,7 @@ } LogicNode compare = CompareNode.createCompareNode(graph, cond, lhs, rhs, b.getConstantReflection()); - b.push(Kind.Boolean.getStackKind(), b.append(new ConditionalNode(compare, trueValue, falseValue))); + b.addPush(Kind.Boolean.getStackKind(), new ConditionalNode(compare, trueValue, falseValue)); return true; } } @@ -358,9 +363,7 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { ValueNode object = receiver.get(); if (RegisterFinalizerNode.mayHaveFinalizer(object, b.getAssumptions())) { - RegisterFinalizerNode registerFinalizer = new RegisterFinalizerNode(object); - b.append(registerFinalizer); - registerFinalizer.setStateAfter(b.createStateAfter()); + b.add(new RegisterFinalizerNode(object)); } return true; } @@ -371,7 +374,7 @@ Registration r = new Registration(plugins, Class.class); r.register2("isInstance", Receiver.class, Object.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver type, ValueNode object) { - LogicNode condition = b.append(InstanceOfDynamicNode.create(b.getConstantReflection(), type.get(), object)); + LogicNode condition = b.add(InstanceOfDynamicNode.create(b.getConstantReflection(), type.get(), object)); b.push(Kind.Boolean.getStackKind(), b.recursiveAppend(new ConditionalNode(condition).canonical(null))); return true; } @@ -383,18 +386,6 @@ return true; } }); - r.register2("cast", Receiver.class, Object.class, new InvocationPlugin() { - public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode object) { - if (receiver.isConstant()) { - ResolvedJavaType type = b.getConstantReflection().asJavaType(receiver.get().asConstant()); - if (type != null && !type.isPrimitive()) { - b.push(Kind.Object, b.append(CheckCastNode.create(type, object, null, false, b.getAssumptions()))); - return true; - } - } - return false; - } - }); } /** @@ -409,18 +400,16 @@ for (Class c : new Class[]{Node.class, NodeList.class}) { r.register2("get" + c.getSimpleName() + "Unsafe", Node.class, long.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode node, ValueNode offset) { - ValueNode value = b.append(new UnsafeLoadNode(node, offset, Kind.Object, LocationIdentity.any())); + ValueNode value = b.add(new UnsafeLoadNode(node, offset, Kind.Object, LocationIdentity.any())); boolean exactType = false; boolean nonNull = false; - b.push(Kind.Object, b.append(new PiNode(value, metaAccess.lookupJavaType(c), exactType, nonNull))); + b.addPush(Kind.Object, new PiNode(value, metaAccess.lookupJavaType(c), exactType, nonNull)); return true; } }); r.register3("put" + c.getSimpleName() + "Unsafe", Node.class, long.class, c, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode node, ValueNode offset, ValueNode value) { - UnsafeStoreNode unsafeStore = new UnsafeStoreNode(node, offset, value, Kind.Object, LocationIdentity.any()); - b.append(unsafeStore); - unsafeStore.setStateAfter(b.createStateAfter()); + b.add(new UnsafeStoreNode(node, offset, value, Kind.Object, LocationIdentity.any())); return true; } }); @@ -445,7 +434,7 @@ } } ResolvedJavaType resultType = b.getMetaAccess().lookupJavaType(kind.toBoxedJavaClass()); - b.push(Kind.Object, b.append(new BoxNode(value, resultType, kind))); + b.addPush(Kind.Object, new BoxNode(value, resultType, kind)); return true; } @@ -472,7 +461,7 @@ } } ValueNode valueNode = UnboxNode.create(b.getMetaAccess(), b.getConstantReflection(), receiver.get(), kind); - b.push(kind.getStackKind(), b.append(valueNode)); + b.addPush(kind.getStackKind(), valueNode); return true; } @@ -495,7 +484,7 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver unsafe, ValueNode address) { // Emits a null-check for the otherwise unused receiver unsafe.get(); - b.push(returnKind.getStackKind(), b.append(new DirectReadNode(address, returnKind))); + b.addPush(returnKind.getStackKind(), new DirectReadNode(address, returnKind)); return true; } @@ -503,11 +492,11 @@ // Emits a null-check for the otherwise unused receiver unsafe.get(); if (isVolatile) { - b.append(new MembarNode(JMM_PRE_VOLATILE_READ)); + b.add(new MembarNode(JMM_PRE_VOLATILE_READ)); } - b.push(returnKind.getStackKind(), b.append(new UnsafeLoadNode(object, offset, returnKind, LocationIdentity.any()))); + b.addPush(returnKind.getStackKind(), new UnsafeLoadNode(object, offset, returnKind, LocationIdentity.any())); if (isVolatile) { - b.append(new MembarNode(JMM_POST_VOLATILE_READ)); + b.add(new MembarNode(JMM_POST_VOLATILE_READ)); } return true; } @@ -526,7 +515,7 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver unsafe, ValueNode address, ValueNode value) { // Emits a null-check for the otherwise unused receiver unsafe.get(); - b.append(new DirectStoreNode(address, value, kind)); + b.add(new DirectStoreNode(address, value, kind)); return true; } @@ -534,13 +523,11 @@ // Emits a null-check for the otherwise unused receiver unsafe.get(); if (isVolatile) { - b.append(new MembarNode(JMM_PRE_VOLATILE_WRITE)); + b.add(new MembarNode(JMM_PRE_VOLATILE_WRITE)); } - UnsafeStoreNode unsafeStore = new UnsafeStoreNode(object, offset, value, kind, LocationIdentity.any()); - b.append(unsafeStore); - unsafeStore.setStateAfter(b.createStateAfter()); + b.add(new UnsafeStoreNode(object, offset, value, kind, LocationIdentity.any())); if (isVolatile) { - b.append(new MembarNode(JMM_PRE_VOLATILE_WRITE)); + b.add(new MembarNode(JMM_PRE_VOLATILE_WRITE)); } return true; } @@ -550,42 +537,42 @@ Registration r = new Registration(plugins, GraalDirectives.class); r.register0("deoptimize", new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { - b.append(new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.TransferToInterpreter)); + b.add(new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.TransferToInterpreter)); return true; } }); r.register0("deoptimizeAndInvalidate", new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { - b.append(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TransferToInterpreter)); + b.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TransferToInterpreter)); return true; } }); r.register0("inCompiledCode", new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { - b.push(Kind.Int, b.append(ConstantNode.forInt(1))); + b.addPush(Kind.Int, ConstantNode.forInt(1)); return true; } }); r.register0("controlFlowAnchor", new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { - b.append(new ControlFlowAnchorNode()); + b.add(new ControlFlowAnchorNode()); return true; } }); r.register2("injectBranchProbability", double.class, boolean.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode probability, ValueNode condition) { - b.push(Kind.Int, b.append(new BranchProbabilityNode(probability, condition))); + b.addPush(Kind.Int, new BranchProbabilityNode(probability, condition)); return true; } }); InvocationPlugin blackholePlugin = new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { - b.append(new BlackholeNode(value)); + b.add(new BlackholeNode(value)); return true; } }; @@ -598,7 +585,7 @@ final Kind stackKind = kind.getStackKind(); r.register1("opaque", javaClass, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { - b.push(stackKind, b.append(new OpaqueNode(value))); + b.addPush(stackKind, new OpaqueNode(value)); return true; } }); @@ -610,7 +597,7 @@ InvocationPlugin blackholePlugin = new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver blackhole, ValueNode value) { blackhole.get(); - b.append(new BlackholeNode(value)); + b.add(new BlackholeNode(value)); return true; } }; diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/WordOperationPlugin.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/WordOperationPlugin.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/WordOperationPlugin.java Fri Mar 27 17:02:53 2015 +0100 @@ -81,7 +81,7 @@ ValueNode left = args[0]; ValueNode right = operation.rightOperandIsInt() ? toUnsigned(b, args[1], Kind.Int) : fromSigned(b, args[1]); - b.push(returnStackKind, b.append(createBinaryNodeInstance(operation.node(), left, right))); + b.addPush(returnStackKind, createBinaryNodeInstance(operation.node(), left, right)); break; case COMPARISON: @@ -91,7 +91,7 @@ case NOT: assert args.length == 1; - b.push(returnStackKind, b.append(new XorNode(args[0], b.append(forIntegerKind(wordKind, -1))))); + b.addPush(returnStackKind, new XorNode(args[0], b.add(forIntegerKind(wordKind, -1)))); break; case READ_POINTER: @@ -133,7 +133,7 @@ } case ZERO: assert args.length == 0; - b.push(returnStackKind, b.append(forIntegerKind(wordKind, 0L))); + b.addPush(returnStackKind, forIntegerKind(wordKind, 0L)); break; case FROM_UNSIGNED: @@ -158,18 +158,18 @@ case FROM_OBJECT: assert args.length == 1; - WordCastNode objectToWord = b.append(WordCastNode.objectToWord(args[0], wordKind)); + WordCastNode objectToWord = b.add(WordCastNode.objectToWord(args[0], wordKind)); b.push(returnStackKind, objectToWord); break; case FROM_ARRAY: assert args.length == 2; - b.push(returnStackKind, b.append(new ComputeAddressNode(args[0], args[1], StampFactory.forKind(wordKind)))); + b.addPush(returnStackKind, new ComputeAddressNode(args[0], args[1], StampFactory.forKind(wordKind))); break; case TO_OBJECT: assert args.length == 1; - WordCastNode wordToObject = b.append(WordCastNode.wordToObject(args[0], wordKind)); + WordCastNode wordToObject = b.add(WordCastNode.wordToObject(args[0], wordKind)); b.push(returnStackKind, wordToObject); break; @@ -210,15 +210,15 @@ comparison = new IntegerLessThanNode(a, b); } - ConstantNode trueValue = graph.append(forInt(1)); - ConstantNode falseValue = graph.append(forInt(0)); + ConstantNode trueValue = graph.add(forInt(1)); + ConstantNode falseValue = graph.add(forInt(0)); if (condition.canonicalNegate()) { ConstantNode temp = trueValue; trueValue = falseValue; falseValue = temp; } - ConditionalNode materialize = graph.append(new ConditionalNode(graph.append(comparison), trueValue, falseValue)); + ConditionalNode materialize = graph.add(new ConditionalNode(graph.add(comparison), trueValue, falseValue)); return materialize; } @@ -231,7 +231,7 @@ } public static ValueNode readOp(GraphBuilderContext b, Kind readKind, ValueNode base, LocationNode location, BarrierType barrierType, boolean compressible) { - JavaReadNode read = b.append(new JavaReadNode(readKind, base, location, barrierType, compressible)); + JavaReadNode read = b.add(new JavaReadNode(readKind, base, location, barrierType, compressible)); /* * The read must not float outside its block otherwise it may float above an explicit zero * check on its base address. @@ -245,20 +245,18 @@ final BarrierType barrier = (op == Opcode.WRITE_BARRIERED ? BarrierType.PRECISE : BarrierType.NONE); final boolean compressible = (op == Opcode.WRITE_OBJECT || op == Opcode.WRITE_BARRIERED); final boolean initialize = (op == Opcode.INITIALIZE); - JavaWriteNode writeNode = new JavaWriteNode(writeKind, base, value, location, barrier, compressible, initialize); - b.append(writeNode); - writeNode.setStateAfter(b.createStateAfter()); + b.add(new JavaWriteNode(writeKind, base, value, location, barrier, compressible, initialize)); } public LocationNode makeLocation(GraphBuilderContext b, ValueNode offset, LocationIdentity locationIdentity) { - return b.append(new IndexedLocationNode(locationIdentity, 0, fromSigned(b, offset), 1)); + return b.add(new IndexedLocationNode(locationIdentity, 0, fromSigned(b, offset), 1)); } public LocationNode makeLocation(GraphBuilderContext b, ValueNode offset, ValueNode locationIdentity) { if (locationIdentity.isConstant()) { return makeLocation(b, offset, snippetReflection.asObject(LocationIdentity.class, locationIdentity.asJavaConstant())); } - return b.append(new SnippetLocationNode(snippetReflection, locationIdentity, b.append(ConstantNode.forLong(0)), fromSigned(b, offset), b.append(ConstantNode.forInt(1)))); + return b.add(new SnippetLocationNode(snippetReflection, locationIdentity, b.add(ConstantNode.forLong(0)), fromSigned(b, offset), b.add(ConstantNode.forInt(1)))); } public ValueNode fromUnsigned(GraphBuilderContext b, ValueNode value) { @@ -280,14 +278,14 @@ if (toKind == Kind.Int) { assert value.getKind() == Kind.Long; - return b.append(new NarrowNode(value, 32)); + return b.add(new NarrowNode(value, 32)); } else { assert toKind == Kind.Long; assert value.getKind().getStackKind() == Kind.Int; if (unsigned) { - return b.append(new ZeroExtendNode(value, 64)); + return b.add(new ZeroExtendNode(value, 64)); } else { - return b.append(new SignExtendNode(value, 64)); + return b.add(new SignExtendNode(value, 64)); } } } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BasicArrayCopyNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BasicArrayCopyNode.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BasicArrayCopyNode.java Fri Mar 27 17:02:53 2015 +0100 @@ -27,6 +27,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.virtual.*; @@ -36,8 +37,8 @@ public static final NodeClass TYPE = NodeClass.create(BasicArrayCopyNode.class); - public BasicArrayCopyNode(NodeClass c, Invoke invoke) { - super(c, invoke); + public BasicArrayCopyNode(NodeClass c, InvokeKind invokeKind, ResolvedJavaMethod targetMethod, int bci, JavaType returnType, ValueNode... arguments) { + super(c, invokeKind, targetMethod, bci, returnType, arguments); } protected ValueNode getSource() { diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BasicObjectCloneNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BasicObjectCloneNode.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BasicObjectCloneNode.java Fri Mar 27 17:02:53 2015 +0100 @@ -30,6 +30,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.util.*; @@ -40,8 +41,8 @@ public static final NodeClass TYPE = NodeClass.create(BasicObjectCloneNode.class); - protected BasicObjectCloneNode(NodeClass c, Invoke invoke) { - super(c, invoke); + public BasicObjectCloneNode(NodeClass c, InvokeKind invokeKind, ResolvedJavaMethod targetMethod, int bci, JavaType returnType, ValueNode... arguments) { + super(c, invokeKind, targetMethod, bci, returnType, arguments); } @Override diff -r d22307a9a025 -r eea134855f85 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 Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java Fri Mar 27 17:02:53 2015 +0100 @@ -42,9 +42,8 @@ import com.oracle.graal.replacements.*; /** - * Macro nodes can be used to temporarily replace an invoke (usually by using the - * {@link MacroSubstitution} annotation). They can, for example, be used to implement constant - * folding for known JDK functions like {@link Class#isInterface()}.
+ * Macro nodes can be used to temporarily replace an invoke. They can, for example, be used to + * implement constant folding for known JDK functions like {@link Class#isInterface()}.
*
* During lowering, multiple sources are queried in order to look for a replacement: *

    @@ -77,6 +76,16 @@ this.invokeKind = methodCallTarget.invokeKind(); } + protected MacroNode(NodeClass c, InvokeKind invokeKind, ResolvedJavaMethod targetMethod, int bci, JavaType returnType, ValueNode... arguments) { + super(c, StampFactory.forKind(returnType.getKind())); + assert targetMethod.getSignature().getParameterCount(!targetMethod.isStatic()) == arguments.length; + this.arguments = new NodeInputList<>(this, arguments); + this.bci = bci; + this.targetMethod = targetMethod; + this.returnType = returnType; + this.invokeKind = invokeKind; + } + public int getBci() { return bci; } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroStateSplitNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroStateSplitNode.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroStateSplitNode.java Fri Mar 27 17:02:53 2015 +0100 @@ -28,6 +28,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.CallTargetNode.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; @@ -41,9 +42,8 @@ public static final NodeClass TYPE = NodeClass.create(MacroStateSplitNode.class); @OptionalInput(InputType.State) protected FrameState stateAfter; - public MacroStateSplitNode(NodeClass c, Invoke invoke) { - super(c, invoke); - this.stateAfter = invoke.stateAfter(); + protected MacroStateSplitNode(NodeClass c, InvokeKind invokeKind, ResolvedJavaMethod targetMethod, int bci, JavaType returnType, ValueNode... arguments) { + super(c, invokeKind, targetMethod, bci, returnType, arguments); } @Override diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathPowNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathPowNode.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathPowNode.java Fri Mar 27 17:02:53 2015 +0100 @@ -22,28 +22,34 @@ */ package com.oracle.graal.replacements.nodes; +import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; @NodeInfo public final class MathPowNode extends MacroStateSplitNode implements Canonicalizable.Binary { public static final NodeClass TYPE = NodeClass.create(MathPowNode.class); - public MathPowNode(Invoke i) { - super(TYPE, i); + public MathPowNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, int bci, JavaType returnType, ValueNode x, ValueNode y) { + super(TYPE, invokeKind, targetMethod, bci, returnType, x, y); } public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { - if (forX.isConstant() && forY.isConstant()) { - double x = forX.asJavaConstant().asDouble(); - double y = forY.asJavaConstant().asDouble(); - return ConstantNode.forDouble(Math.pow(x, y)); - } else { - return this; + ValueNode folded = tryFold(forX, forY); + return folded != null ? folded : this; + } + + public static ValueNode tryFold(ValueNode x, ValueNode y) { + if (x.isConstant() && y.isConstant()) { + double xPrim = x.asJavaConstant().asDouble(); + double yPrim = y.asJavaConstant().asDouble(); + return ConstantNode.forDouble(Math.pow(xPrim, yPrim)); } + return null; } public ValueNode getX() { diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MemoryAnchorNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MemoryAnchorNode.java Fri Mar 27 15:43:31 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2014, 2015, 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.nodes; - -import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.spi.*; -import com.oracle.graal.nodeinfo.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.spi.*; - -@NodeInfo(allowedUsageTypes = {InputType.Memory}) -public final class MemoryAnchorNode extends FixedWithNextNode implements LIRLowerable, MemoryNode, Canonicalizable { - - public static final NodeClass TYPE = NodeClass.create(MemoryAnchorNode.class); - - public MemoryAnchorNode() { - super(TYPE, StampFactory.forVoid()); - } - - public void generate(NodeLIRBuilderTool generator) { - // Nothing to emit, since this node is used for structural purposes only. - } - - @Override - public Node canonical(CanonicalizerTool tool) { - return hasNoUsages() ? null : this; - } -} diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/PureFunctionMacroNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/PureFunctionMacroNode.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/PureFunctionMacroNode.java Fri Mar 27 17:02:53 2015 +0100 @@ -27,6 +27,7 @@ import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; /** * This node class can be used to create {@link MacroNode}s for simple pure functions like @@ -37,8 +38,8 @@ public static final NodeClass TYPE = NodeClass.create(PureFunctionMacroNode.class); - protected PureFunctionMacroNode(NodeClass c, Invoke invoke) { - super(c, invoke); + public PureFunctionMacroNode(NodeClass c, InvokeKind invokeKind, ResolvedJavaMethod targetMethod, int bci, JavaType returnType, ValueNode... arguments) { + super(c, invokeKind, targetMethod, bci, returnType, arguments); } /** diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ConditionAnchoringTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ConditionAnchoringTest.java Fri Mar 27 17:02:53 2015 +0100 @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2015, 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.truffle.test; + +import static com.oracle.graal.graph.test.matchers.NodeIterableCount.*; +import static com.oracle.graal.graph.test.matchers.NodeIterableIsEmpty.*; +import static org.hamcrest.core.IsInstanceOf.*; +import static org.junit.Assert.*; + +import org.junit.*; + +import sun.misc.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.graph.iterators.*; +import com.oracle.graal.graphbuilderconf.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.LoweringTool.StandardLoweringStage; +import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; +import com.oracle.graal.truffle.nodes.*; +import com.oracle.graal.truffle.substitutions.*; +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.unsafe.*; + +public class ConditionAnchoringTest extends GraalCompilerTest { + private static final UnsafeAccess access; + private static final long offset; + private static final Object location = new Object(); + + static { + Unsafe unsafe = com.oracle.graal.compiler.common.UnsafeAccess.unsafe; + access = Truffle.getRuntime().getCapability(UnsafeAccessFactory.class).createUnsafeAccess(unsafe); + long fieldOffset = 0; + try { + fieldOffset = unsafe.objectFieldOffset(CheckedObject.class.getDeclaredField("field")); + } catch (NoSuchFieldException | SecurityException e) { + e.printStackTrace(); + } + offset = fieldOffset; + } + + private static class CheckedObject { + int id; + int iid; + @SuppressWarnings("unused") int field; + } + + public int checkedAccess(CheckedObject o) { + if (o.id == 42) { + return access.getInt(o, offset, o.id == 42, location); + } + return -1; + } + + // test with a different kind of condition (not a comparison against a constant) + public int checkedAccess2(CheckedObject o) { + if (o.id == o.iid) { + return access.getInt(o, offset, o.id == o.iid, location); + } + return -1; + } + + @Test + public void test() { + test("checkedAccess", 1); + } + + @Test + public void test2() { + test("checkedAccess2", 2); + } + + public void test(String name, int ids) { + StructuredGraph graph = parseEager(name, AllowAssumptions.YES); + + NodeIterable unsafeNodes = graph.getNodes().filter(UnsafeLoadNode.class); + assertThat(unsafeNodes, hasCount(1)); + + // lower unsafe load + PhaseContext context = new PhaseContext(getProviders()); + LoweringPhase lowering = new LoweringPhase(new CanonicalizerPhase(), StandardLoweringStage.HIGH_TIER); + lowering.apply(graph, context); + + unsafeNodes = graph.getNodes().filter(UnsafeLoadNode.class); + NodeIterable conditionAnchors = graph.getNodes().filter(ConditionAnchorNode.class); + NodeIterable reads = graph.getNodes().filter(ReadNode.class); + assertThat(unsafeNodes, isEmpty()); + assertThat(conditionAnchors, hasCount(1)); + assertThat(reads, hasCount(2 * ids + 1)); // 2 * ids id reads, 1 'field' access + + // float reads and canonicalize to give a chance to conditions to GVN + FloatingReadPhase floatingReadPhase = new FloatingReadPhase(); + floatingReadPhase.apply(graph); + CanonicalizerPhase canonicalizerPhase = new CanonicalizerPhase(); + canonicalizerPhase.apply(graph, context); + + NodeIterable floatingReads = graph.getNodes().filter(FloatingReadNode.class); + assertThat(floatingReads, hasCount(ids + 1)); // 1 id read, 1 'field' access + + // apply DominatorConditionalEliminationPhase + DominatorConditionalEliminationPhase conditionalElimination = new DominatorConditionalEliminationPhase(false); + conditionalElimination.apply(graph); + + floatingReads = graph.getNodes().filter(FloatingReadNode.class).filter(n -> ((FloatingReadNode) n).location().getLocationIdentity() instanceof ObjectLocationIdentity); + conditionAnchors = graph.getNodes().filter(ConditionAnchorNode.class); + assertThat(floatingReads, hasCount(1)); + assertThat(conditionAnchors, isEmpty()); + FloatingReadNode readNode = floatingReads.first(); + assertThat(readNode.getGuard(), instanceOf(BeginNode.class)); + assertThat(readNode.getGuard().asNode().predecessor(), instanceOf(IfNode.class)); + } + + @Override + protected GraphBuilderConfiguration editGraphBuilderConfiguration(GraphBuilderConfiguration conf) { + // get UnsafeAccessImpl.unsafeGetInt intrinsified + TruffleGraphBuilderPlugins.registerUnsafeAccessImplPlugins(conf.getPlugins().getInvocationPlugins()); + // get UnsafeAccess.getInt inlined + conf.getPlugins().setInlineInvokePlugin(new InlineEverythingPlugin()); + conf.getPlugins().setLoadFieldPlugin(new FoldLoadsPlugins(getMetaAccess(), getConstantReflection())); + return super.editGraphBuilderConfiguration(conf); + } + + private static final class InlineEverythingPlugin implements InlineInvokePlugin { + public InlineInfo getInlineInfo(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args, JavaType returnType) { + assert method.hasBytecodes(); + return new InlineInfo(method, false, false); + } + } + + private static final class FoldLoadsPlugins implements LoadFieldPlugin { + private final MetaAccessProvider metaAccess; + private final ConstantReflectionProvider constantReflection; + + public FoldLoadsPlugins(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection) { + this.metaAccess = metaAccess; + this.constantReflection = constantReflection; + } + + public boolean apply(GraphBuilderContext graphBuilderContext, ValueNode receiver, ResolvedJavaField field) { + if (receiver.isConstant()) { + JavaConstant asJavaConstant = receiver.asJavaConstant(); + return tryConstantFold(graphBuilderContext, metaAccess, constantReflection, field, asJavaConstant); + } + return false; + } + + public boolean apply(GraphBuilderContext graphBuilderContext, ResolvedJavaField staticField) { + return tryConstantFold(graphBuilderContext, metaAccess, constantReflection, staticField, null); + } + } +} diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java Fri Mar 27 17:02:53 2015 +0100 @@ -274,24 +274,24 @@ } private void verifySet(int slotIndex, byte tag) { - if (CompilerDirectives.inInterpreter() && slotIndex >= getTags().length) { - if (!resize()) { - throw new IllegalArgumentException(String.format("The frame slot '%s' is not known by the frame descriptor.", slotIndex)); - } - } + checkSlotIndex(slotIndex); getTags()[slotIndex] = tag; } private void verifyGet(int slotIndex, byte tag) throws FrameSlotTypeException { + checkSlotIndex(slotIndex); + if (getTags()[slotIndex] != tag) { + CompilerDirectives.transferToInterpreter(); + throw new FrameSlotTypeException(); + } + } + + private void checkSlotIndex(int slotIndex) { if (CompilerDirectives.inInterpreter() && slotIndex >= getTags().length) { if (!resize()) { throw new IllegalArgumentException(String.format("The frame slot '%s' is not known by the frame descriptor.", slotIndex)); } } - if (getTags()[slotIndex] != tag) { - CompilerDirectives.transferToInterpreter(); - throw new FrameSlotTypeException(); - } } private static long getPrimitiveOffset(int slotIndex) { diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Fri Mar 27 17:02:53 2015 +0100 @@ -162,8 +162,8 @@ public boolean apply(GraphBuilderContext builder, ResolvedJavaField staticField) { if (TruffleCompilerOptions.TruffleExcludeAssertions.getValue() && staticField.getName().equals("$assertionsDisabled")) { - ConstantNode trueNode = builder.append(ConstantNode.forBoolean(true)); - builder.push(trueNode.getKind().getStackKind(), trueNode); + ConstantNode trueNode = builder.add(ConstantNode.forBoolean(true)); + builder.addPush(trueNode); return true; } return tryConstantFold(builder, providers.getMetaAccess(), providers.getConstantReflection(), staticField, null); @@ -209,7 +209,7 @@ return inlineInfo; } } - if (replacements != null && (replacements.getMethodSubstitutionMethod(original) != null || replacements.getMacroSubstitution(original) != null)) { + if (replacements != null && replacements.getMethodSubstitutionMethod(original) != null) { return null; } assert !builder.parsingReplacement(); @@ -268,6 +268,9 @@ if (targetMethod != null) { // TODO maybe cast arguments + if (!targetMethod.canBeInlined()) { + return null; + } if (targetMethod.canBeStaticallyBound()) { return new InlineInfo(targetMethod, false, false); } @@ -337,14 +340,9 @@ new ConvertDeoptimizeToGuardPhase().apply(graph, tierContext); for (MethodCallTargetNode methodCallTargetNode : graph.getNodes(MethodCallTargetNode.TYPE)) { - Class macroSubstitution = providers.getReplacements().getMacroSubstitution(methodCallTargetNode.targetMethod()); - if (macroSubstitution != null) { - InliningUtil.inlineMacroNode(methodCallTargetNode.invoke(), methodCallTargetNode.targetMethod(), macroSubstitution); - } else { - StructuredGraph inlineGraph = providers.getReplacements().getMethodSubstitution(methodCallTargetNode.targetMethod()); - if (inlineGraph != null) { - InliningUtil.inline(methodCallTargetNode.invoke(), inlineGraph, true, null); - } + StructuredGraph inlineGraph = providers.getReplacements().getMethodSubstitution(methodCallTargetNode.targetMethod()); + if (inlineGraph != null) { + InliningUtil.inline(methodCallTargetNode.invoke(), inlineGraph, true, null); } } @@ -359,6 +357,9 @@ } catch (Throwable t) { Debug.handle(t); } + + // recompute loop frequencies now that BranchProbabilities have had time to canonicalize + ComputeLoopFrequenciesClosure.compute(graph); } private void partialEvaluation(final OptimizedCallTarget callTarget, final StructuredGraph graph, PhaseContext baseContext, HighTierContext tierContext) { @@ -513,12 +514,6 @@ } Replacements replacements = providers.getReplacements(); - Class macroSubstitution = replacements.getMacroSubstitution(methodCallTargetNode.targetMethod()); - if (macroSubstitution != null) { - InliningUtil.inlineMacroNode(methodCallTargetNode.invoke(), methodCallTargetNode.targetMethod(), macroSubstitution); - changed = changedInIteration = true; - continue; - } StructuredGraph inlineGraph = replacements.getMethodSubstitution(methodCallTargetNode.targetMethod()); ResolvedJavaMethod targetMethod = methodCallTargetNode.targetMethod(); diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java Fri Mar 27 17:02:53 2015 +0100 @@ -236,12 +236,7 @@ for (Node newNode : graph.getNewNodes(mark)) { if (newNode instanceof MethodCallTargetNode) { MethodCallTargetNode methodCallTargetNode = (MethodCallTargetNode) newNode; - Class macroSubstitution = providers.getReplacements().getMacroSubstitution(methodCallTargetNode.targetMethod()); - if (macroSubstitution != null) { - InliningUtil.inlineMacroNode(methodCallTargetNode.invoke(), methodCallTargetNode.targetMethod(), macroSubstitution); - } else { - tryCutOffRuntimeExceptionsAndErrors(methodCallTargetNode); - } + tryCutOffRuntimeExceptionsAndErrors(methodCallTargetNode); } } return graph.getMark(); diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java Fri Mar 27 17:02:53 2015 +0100 @@ -31,8 +31,6 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.util.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.truffle.substitutions.*; -import com.oracle.truffle.api.*; /** * Custom {@link Replacements} for Truffle compilation. @@ -44,15 +42,6 @@ protected TruffleReplacements(Providers providers, SnippetReflectionProvider snippetReflection) { super(providers, snippetReflection, providers.getCodeCache().getTarget()); this.graalReplacements = providers.getReplacements(); - - registerTruffleSubstitutions(); - } - - protected void registerTruffleSubstitutions() { - if (!TruffleCompilerOptions.FastPE.getValue()) { - registerSubstitutions(CompilerAsserts.class, CompilerAssertsSubstitutions.class); - registerSubstitutions(OptimizedAssumption.class, OptimizedAssumptionSubstitutions.class); - } } @Override @@ -70,15 +59,6 @@ } @Override - public Class getMacroSubstitution(ResolvedJavaMethod method) { - Class clazz = graalReplacements.getMacroSubstitution(method); - if (clazz == null) { - return super.getMacroSubstitution(method); - } - return clazz; - } - - @Override public Collection getAllReplacements() { throw GraalInternalError.shouldNotReachHere(); } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionNode.java Fri Mar 27 15:43:31 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2013, 2015, 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.truffle.nodes; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.replacements.*; -import com.oracle.graal.api.runtime.*; -import com.oracle.graal.compiler.common.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.spi.*; -import com.oracle.graal.nodeinfo.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.util.*; -import com.oracle.graal.replacements.nodes.*; -import com.oracle.graal.truffle.*; - -@NodeInfo -public final class AssumptionNode extends MacroNode implements Simplifiable { - - public static final NodeClass TYPE = NodeClass.create(AssumptionNode.class); - - public AssumptionNode(Invoke invoke) { - super(TYPE, invoke); - assert super.arguments.size() == 1; - } - - private ValueNode getAssumption() { - return arguments.first(); - } - - private static SnippetReflectionProvider getSnippetReflection() { - /* - * This class requires access to the objects encapsulated in Constants, and therefore breaks - * the compiler-VM separation of object constants. - */ - return Graal.getRequiredCapability(SnippetReflectionProvider.class); - } - - @Override - public void lower(LoweringTool tool) { - throw new GraalInternalError(GraphUtil.approxSourceException(this, new RuntimeException("assumption could not be evaluated to a constant"))); - } - - @Override - public void simplify(SimplifierTool tool) { - ValueNode assumption = getAssumption(); - Assumptions assumptions = graph().getAssumptions(); - if (assumption.isConstant()) { - JavaConstant c = assumption.asJavaConstant(); - assert c.getKind() == Kind.Object; - Object object = getSnippetReflection().asObject(Object.class, c); - OptimizedAssumption assumptionObject = (OptimizedAssumption) object; - StructuredGraph graph = graph(); - if (assumptionObject.isValid()) { - assumptions.record(new AssumptionValidAssumption(assumptionObject)); - if (super.getReturnType().getKind() == Kind.Boolean) { - graph.replaceFixedWithFloating(this, ConstantNode.forBoolean(true, graph())); - } else { - graph.removeFixed(this); - } - } else { - if (super.getReturnType().getKind() == Kind.Boolean) { - graph.replaceFixedWithFloating(this, ConstantNode.forBoolean(false, graph())); - } else { - tool.deleteBranch(this.next()); - this.replaceAndDelete(graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.None))); - } - } - } - } -} diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverInlineMacroNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverInlineMacroNode.java Fri Mar 27 15:43:31 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2013, 2015, 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.truffle.nodes.asserts; - -import com.oracle.graal.graph.*; -import com.oracle.graal.nodeinfo.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.replacements.nodes.*; - -@NodeInfo -public final class NeverInlineMacroNode extends MacroStateSplitNode implements com.oracle.graal.graph.IterableNodeType { - - public static final NodeClass TYPE = NodeClass.create(NeverInlineMacroNode.class); - - public NeverInlineMacroNode(Invoke invoke) { - super(TYPE, invoke); - } - - @Override - public void lower(LoweringTool tool) { - InvokeNode invoke = createInvoke(); - graph().replaceFixedWithFixed(this, invoke); - invoke.setUseForInlining(false); - invoke.lower(tool); - } -} diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverPartOfCompilationNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverPartOfCompilationNode.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverPartOfCompilationNode.java Fri Mar 27 17:02:53 2015 +0100 @@ -49,7 +49,4 @@ throw GraphUtil.approxSourceException(neverPartOfCompilationNode, exception); } } - - @NodeIntrinsic - public static native void apply(@ConstantNodeParameter String message); } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadMacroNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadMacroNode.java Fri Mar 27 15:43:31 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.truffle.nodes.typesystem; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.calc.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.spi.*; -import com.oracle.graal.nodeinfo.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.replacements.nodes.*; -import com.oracle.graal.truffle.nodes.*; - -/** - * Macro node for CompilerDirectives#unsafeGetInt*. - */ -@NodeInfo -public final class CustomizedUnsafeLoadMacroNode extends MacroStateSplitNode implements Canonicalizable { - public static final NodeClass TYPE = NodeClass.create(CustomizedUnsafeLoadMacroNode.class); - - private static final int ARGUMENT_COUNT = 4; - private static final int OBJECT_ARGUMENT_INDEX = 0; - private static final int OFFSET_ARGUMENT_INDEX = 1; - private static final int CONDITION_ARGUMENT_INDEX = 2; - private static final int LOCATION_ARGUMENT_INDEX = 3; - - public CustomizedUnsafeLoadMacroNode(Invoke invoke) { - super(TYPE, invoke); - assert arguments.size() == ARGUMENT_COUNT; - } - - @Override - public Node canonical(CanonicalizerTool tool) { - ValueNode locationArgument = arguments.get(LOCATION_ARGUMENT_INDEX); - if (locationArgument.isConstant()) { - ValueNode objectArgument = arguments.get(OBJECT_ARGUMENT_INDEX); - ValueNode offsetArgument = arguments.get(OFFSET_ARGUMENT_INDEX); - ValueNode conditionArgument = arguments.get(CONDITION_ARGUMENT_INDEX); - LocationIdentity locationIdentity; - if (locationArgument.isNullConstant()) { - locationIdentity = LocationIdentity.any(); - } else { - locationIdentity = ObjectLocationIdentity.create(locationArgument.asJavaConstant()); - } - LogicNode compare = CompareNode.createCompareNode(Condition.EQ, conditionArgument, ConstantNode.forBoolean(true), tool.getConstantReflection()); - Kind returnKind = this.getTargetMethod().getSignature().getReturnKind(); - return new UnsafeLoadNode(objectArgument, offsetArgument, returnKind, locationIdentity, compare); - } - return this; - } -} diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeStoreMacroNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeStoreMacroNode.java Fri Mar 27 15:43:31 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.truffle.nodes.typesystem; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.spi.*; -import com.oracle.graal.nodeinfo.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.replacements.nodes.*; -import com.oracle.graal.truffle.nodes.*; - -/** - * Macro node for method CompilerDirectives#unsafePut*. - */ -@NodeInfo -public final class CustomizedUnsafeStoreMacroNode extends MacroStateSplitNode implements Canonicalizable, StateSplit { - public static final NodeClass TYPE = NodeClass.create(CustomizedUnsafeStoreMacroNode.class); - private static final int ARGUMENT_COUNT = 4; - private static final int OBJECT_ARGUMENT_INDEX = 0; - private static final int OFFSET_ARGUMENT_INDEX = 1; - private static final int VALUE_ARGUMENT_INDEX = 2; - private static final int LOCATION_ARGUMENT_INDEX = 3; - - public CustomizedUnsafeStoreMacroNode(Invoke invoke) { - super(TYPE, invoke); - assert arguments.size() == ARGUMENT_COUNT; - } - - @Override - public Node canonical(CanonicalizerTool tool) { - ValueNode locationArgument = arguments.get(LOCATION_ARGUMENT_INDEX); - if (locationArgument.isConstant()) { - ValueNode objectArgument = arguments.get(OBJECT_ARGUMENT_INDEX); - ValueNode offsetArgument = arguments.get(OFFSET_ARGUMENT_INDEX); - ValueNode valueArgument = arguments.get(VALUE_ARGUMENT_INDEX); - LocationIdentity locationIdentity; - if (locationArgument.isNullConstant()) { - locationIdentity = LocationIdentity.any(); - } else { - locationIdentity = ObjectLocationIdentity.create(locationArgument.asJavaConstant()); - } - - return new UnsafeStoreNode(objectArgument, offsetArgument, valueArgument, this.getTargetMethod().getSignature().getParameterKind(VALUE_ARGUMENT_INDEX), locationIdentity, stateAfter()); - } - return this; - } -} diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/UnsafeTypeCastMacroNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/UnsafeTypeCastMacroNode.java Fri Mar 27 15:43:31 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2013, 2015, 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.truffle.nodes.typesystem; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.calc.*; -import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.spi.*; -import com.oracle.graal.nodeinfo.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.util.*; -import com.oracle.graal.replacements.nodes.*; - -/** - * Macro node for method CompilerDirectives#unsafeCast. - */ -@NodeInfo -public final class UnsafeTypeCastMacroNode extends MacroStateSplitNode implements Simplifiable { - - public static final NodeClass TYPE = NodeClass.create(UnsafeTypeCastMacroNode.class); - private static final int OBJECT_ARGUMENT_INDEX = 0; - private static final int CLASS_ARGUMENT_INDEX = 1; - private static final int CONDITION_ARGUMENT_INDEX = 2; - private static final int NONNULL_ARGUMENT_INDEX = 3; - private static final int ARGUMENT_COUNT = 4; - - public UnsafeTypeCastMacroNode(Invoke invoke) { - super(TYPE, invoke); - assert arguments.size() == ARGUMENT_COUNT; - } - - @Override - public void simplify(SimplifierTool tool) { - ValueNode classArgument = arguments.get(CLASS_ARGUMENT_INDEX); - ValueNode nonNullArgument = arguments.get(NONNULL_ARGUMENT_INDEX); - if (classArgument.isConstant() && nonNullArgument.isConstant()) { - ValueNode objectArgument = arguments.get(OBJECT_ARGUMENT_INDEX); - ValueNode conditionArgument = arguments.get(CONDITION_ARGUMENT_INDEX); - ResolvedJavaType lookupJavaType = tool.getConstantReflection().asJavaType(classArgument.asConstant()); - tool.addToWorkList(usages()); - if (lookupJavaType == null) { - replaceAtUsages(objectArgument); - GraphUtil.removeFixedWithUnusedInputs(this); - } else { - Stamp piStamp = StampFactory.declaredTrusted(lookupJavaType, nonNullArgument.asJavaConstant().asInt() != 0); - ConditionAnchorNode valueAnchorNode = graph().add( - new ConditionAnchorNode(CompareNode.createCompareNode(graph(), Condition.EQ, conditionArgument, ConstantNode.forBoolean(true, graph()), tool.getConstantReflection()))); - PiNode piCast = graph().unique(new PiNode(objectArgument, piStamp, valueAnchorNode)); - replaceAtUsages(piCast); - graph().replaceFixedWithFixed(this, valueAnchorNode); - } - } - } -} diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/ReplaceIntrinsicsPhase.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/ReplaceIntrinsicsPhase.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/ReplaceIntrinsicsPhase.java Fri Mar 27 17:02:53 2015 +0100 @@ -47,16 +47,10 @@ if (methodCallTarget.isAlive()) { InvokeKind invokeKind = methodCallTarget.invokeKind(); if (invokeKind.isDirect()) { - Class macroSubstitution = replacements.getMacroSubstitution(methodCallTarget.targetMethod()); - if (macroSubstitution != null) { - InliningUtil.inlineMacroNode(methodCallTarget.invoke(), methodCallTarget.targetMethod(), macroSubstitution); + StructuredGraph inlineGraph = replacements.getMethodSubstitution(methodCallTarget.targetMethod()); + if (inlineGraph != null) { + InliningUtil.inline(methodCallTarget.invoke(), inlineGraph, true, null); Debug.dump(graph, "After inlining %s", methodCallTarget.targetMethod().toString()); - } else { - StructuredGraph inlineGraph = replacements.getMethodSubstitution(methodCallTarget.targetMethod()); - if (inlineGraph != null) { - InliningUtil.inline(methodCallTarget.invoke(), inlineGraph, true, null); - Debug.dump(graph, "After inlining %s", methodCallTarget.targetMethod().toString()); - } } } } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerAssertsSubstitutions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerAssertsSubstitutions.java Fri Mar 27 15:43:31 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +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. - */ -package com.oracle.graal.truffle.substitutions; - -import com.oracle.graal.api.replacements.*; -import com.oracle.graal.truffle.nodes.asserts.*; -import com.oracle.truffle.api.*; - -@ClassSubstitution(CompilerAsserts.class) -public class CompilerAssertsSubstitutions { - - @MethodSubstitution - public static void neverPartOfCompilation(@SuppressWarnings("unused") String message) { - NeverPartOfCompilationNode.apply("Never part of compilation"); - } - -} diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedAssumptionSubstitutions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedAssumptionSubstitutions.java Fri Mar 27 15:43:31 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +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. - */ -package com.oracle.graal.truffle.substitutions; - -import com.oracle.graal.api.replacements.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.truffle.*; -import com.oracle.graal.truffle.nodes.*; - -@ClassSubstitution(OptimizedAssumption.class) -public class OptimizedAssumptionSubstitutions { - - @MacroSubstitution(macro = AssumptionNode.class, isStatic = false, forced = true) - public static native void check(OptimizedAssumption assumption); - - @MacroSubstitution(macro = AssumptionNode.class, isStatic = false, forced = true) - public static native boolean isValid(OptimizedAssumption assumption); -} diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java Fri Mar 27 17:02:53 2015 +0100 @@ -55,6 +55,7 @@ registerOptimizedAssumptionPlugins(plugins); registerExactMathPlugins(plugins); registerCompilerDirectivesPlugins(plugins); + registerCompilerAssertsPlugins(plugins); registerOptimizedCallTargetPlugins(metaAccess, plugins); registerUnsafeAccessImplPlugins(plugins); @@ -68,21 +69,34 @@ public static void registerOptimizedAssumptionPlugins(InvocationPlugins plugins) { Registration r = new Registration(plugins, OptimizedAssumption.class); - r.register1("isValid", Receiver.class, new InvocationPlugin() { + InvocationPlugin plugin = new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { if (receiver.isConstant()) { Constant constant = receiver.get().asConstant(); OptimizedAssumption assumption = b.getSnippetReflection().asObject(OptimizedAssumption.class, (JavaConstant) constant); - b.push(Kind.Boolean.getStackKind(), b.append(ConstantNode.forBoolean(assumption.isValid()))); if (assumption.isValid()) { + if (targetMethod.getName().equals("isValid")) { + b.addPush(ConstantNode.forBoolean(true)); + } else { + assert targetMethod.getName().equals("check") : targetMethod; + } b.getAssumptions().record(new AssumptionValidAssumption(assumption)); + } else { + if (targetMethod.getName().equals("isValid")) { + b.addPush(ConstantNode.forBoolean(false)); + } else { + assert targetMethod.getName().equals("check") : targetMethod; + b.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.None)); + } } } else { throw b.bailout("assumption could not be reduced to a constant"); } return true; } - }); + }; + r.register1("isValid", Receiver.class, plugin); + r.register1("check", Receiver.class, plugin); } public static void registerExactMathPlugins(InvocationPlugins plugins) { @@ -91,31 +105,31 @@ Class type = kind.toJavaClass(); r.register2("addExact", type, type, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode x, ValueNode y) { - b.push(kind.getStackKind(), b.append(new IntegerAddExactNode(x, y))); + b.addPush(kind.getStackKind(), new IntegerAddExactNode(x, y)); return true; } }); r.register2("subtractExact", type, type, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode x, ValueNode y) { - b.push(kind.getStackKind(), b.append(new IntegerSubExactNode(x, y))); + b.addPush(kind.getStackKind(), new IntegerSubExactNode(x, y)); return true; } }); r.register2("multiplyExact", type, type, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode x, ValueNode y) { - b.push(kind.getStackKind(), b.append(new IntegerMulExactNode(x, y))); + b.addPush(kind.getStackKind(), new IntegerMulExactNode(x, y)); return true; } }); r.register2("multiplyHigh", type, type, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode x, ValueNode y) { - b.push(kind.getStackKind(), b.append(new IntegerMulHighNode(x, y))); + b.addPush(kind.getStackKind(), new IntegerMulHighNode(x, y)); return true; } }); r.register2("multiplyHighUnsigned", type, type, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode x, ValueNode y) { - b.push(kind.getStackKind(), b.append(new UnsignedMulHighNode(x, y))); + b.addPush(kind.getStackKind(), new UnsignedMulHighNode(x, y)); return true; } }); @@ -126,25 +140,25 @@ Registration r = new Registration(plugins, CompilerDirectives.class); r.register0("inInterpreter", new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { - b.push(Kind.Boolean.getStackKind(), b.append(ConstantNode.forBoolean(false))); + b.addPush(Kind.Boolean.getStackKind(), ConstantNode.forBoolean(false)); return true; } }); r.register0("inCompiledCode", new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { - b.push(Kind.Boolean.getStackKind(), b.append(ConstantNode.forBoolean(true))); + b.addPush(Kind.Boolean.getStackKind(), ConstantNode.forBoolean(true)); return true; } }); r.register0("transferToInterpreter", new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { - b.append(new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.TransferToInterpreter)); + b.add(new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.TransferToInterpreter)); return true; } }); r.register0("transferToInterpreterAndInvalidate", new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { - b.append(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TransferToInterpreter)); + b.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TransferToInterpreter)); return true; } }); @@ -160,7 +174,7 @@ }); r.register2("injectBranchProbability", double.class, boolean.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode probability, ValueNode condition) { - b.push(Kind.Boolean.getStackKind(), b.append(new BranchProbabilityNode(probability, condition))); + b.addPush(Kind.Boolean.getStackKind(), new BranchProbabilityNode(probability, condition)); return true; } }); @@ -175,21 +189,23 @@ r.register1("isCompilationConstant", Object.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { if ((value instanceof BoxNode ? ((BoxNode) value).getValue() : value).isConstant()) { - b.push(Kind.Boolean.getStackKind(), b.append(ConstantNode.forBoolean(true))); + b.addPush(Kind.Boolean.getStackKind(), ConstantNode.forBoolean(true)); } else { - b.push(Kind.Boolean.getStackKind(), b.append(new IsCompilationConstantNode(value))); + b.addPush(Kind.Boolean.getStackKind(), new IsCompilationConstantNode(value)); } return true; } }); r.register1("materialize", Object.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { - b.append(new ForceMaterializeNode(value)); + b.add(new ForceMaterializeNode(value)); return true; } }); + } - r = new Registration(plugins, CompilerAsserts.class); + public static void registerCompilerAssertsPlugins(InvocationPlugins plugins) { + Registration r = new Registration(plugins, CompilerAsserts.class); r.register1("partialEvaluationConstant", Object.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { ValueNode curValue = value; @@ -219,7 +235,7 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode message) { if (message.isConstant()) { String messageString = message.asConstant().toValueString(); - b.append(new NeverPartOfCompilationNode(messageString)); + b.add(new NeverPartOfCompilationNode(messageString)); return true; } throw b.bailout("message for never part of compilation is non-constant"); @@ -232,13 +248,13 @@ r.register2("createFrame", FrameDescriptor.class, Object[].class, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode descriptor, ValueNode args) { Class frameClass = TruffleCompilerOptions.TruffleUseFrameWithoutBoxing.getValue() ? FrameWithoutBoxing.class : FrameWithBoxing.class; - b.push(Kind.Object, b.append(new NewFrameNode(StampFactory.exactNonNull(metaAccess.lookupJavaType(frameClass)), descriptor, args))); + b.addPush(Kind.Object, new NewFrameNode(StampFactory.exactNonNull(metaAccess.lookupJavaType(frameClass)), descriptor, args)); return true; } }); r.register2("castArrayFixedLength", Object[].class, int.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode args, ValueNode length) { - b.push(Kind.Object, b.append(new PiArrayNode(args, length, args.stamp()))); + b.addPush(Kind.Object, new PiArrayNode(args, length, args.stamp())); return true; } }); @@ -266,7 +282,7 @@ private static void registerMaterialize(Registration r) { r.register1("materialize", Receiver.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver frame) { - b.push(Kind.Object, b.append(new MaterializeFrameNode(frame.get()))); + b.addPush(Kind.Object, new MaterializeFrameNode(frame.get())); return true; } }); @@ -301,10 +317,9 @@ } ConditionAnchorNode valueAnchorNode = null; if (!skipAnchor) { - valueAnchorNode = b.append(new ConditionAnchorNode(compareNode)); + valueAnchorNode = b.add(new ConditionAnchorNode(compareNode)); } - PiNode piCast = b.append(new PiNode(object, piStamp, valueAnchorNode)); - b.push(Kind.Object, piCast); + b.addPush(Kind.Object, new PiNode(object, piStamp, valueAnchorNode)); } return true; } @@ -340,8 +355,8 @@ } else { locationIdentity = ObjectLocationIdentity.create(location.asJavaConstant()); } - LogicNode compare = b.append(CompareNode.createCompareNode(Condition.EQ, condition, ConstantNode.forBoolean(true, object.graph()), b.getConstantReflection())); - b.push(returnKind.getStackKind(), b.append(new UnsafeLoadNode(object, offset, returnKind, locationIdentity, compare))); + LogicNode compare = b.add(CompareNode.createCompareNode(Condition.EQ, condition, ConstantNode.forBoolean(true, object.graph()), b.getConstantReflection())); + b.addPush(returnKind.getStackKind(), b.add(new UnsafeLoadNode(object, offset, returnKind, locationIdentity, compare))); return true; } // TODO: should we throw GraalInternalError.shouldNotReachHere() here? @@ -367,9 +382,7 @@ locationIdentity = ObjectLocationIdentity.create(locationArgument.asJavaConstant()); } - UnsafeStoreNode unsafeStore = new UnsafeStoreNode(object, offset, value, kind, locationIdentity, null); - b.append(unsafeStore); - unsafeStore.setStateAfter(b.createStateAfter()); + b.add(new UnsafeStoreNode(object, offset, value, kind, locationIdentity, null)); return true; } // TODO: should we throw GraalInternalError.shouldNotReachHere() here? diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java Fri Mar 27 17:02:53 2015 +0100 @@ -83,33 +83,36 @@ schedule.apply(graph, false); cfg = schedule.getCFG(); } - - Closure closure = createEffectsClosure(context, schedule, cfg); - ReentrantBlockIterator.apply(closure, cfg.getStartBlock()); + try (Scope scheduleScope = Debug.scope("EffectsPhaseWithSchedule", schedule)) { + Closure closure = createEffectsClosure(context, schedule, cfg); + ReentrantBlockIterator.apply(closure, cfg.getStartBlock()); - if (!closure.hasChanged()) { - break; - } + if (!closure.hasChanged()) { + break; + } - // apply the effects collected during this iteration - HashSetNodeEventListener listener = new HashSetNodeEventListener(); - try (NodeEventScope nes = graph.trackNodeEvents(listener)) { - closure.applyEffects(); - } + // apply the effects collected during this iteration + HashSetNodeEventListener listener = new HashSetNodeEventListener(); + try (NodeEventScope nes = graph.trackNodeEvents(listener)) { + closure.applyEffects(); + } - if (Debug.isDumpEnabled()) { - Debug.dump(graph, "after " + getName() + " iteration"); - } + if (Debug.isDumpEnabled()) { + Debug.dump(graph, "after " + getName() + " iteration"); + } - new DeadCodeEliminationPhase(Required).apply(graph); + new DeadCodeEliminationPhase(Required).apply(graph); - Set changedNodes = listener.getNodes(); - for (Node node : graph.getNodes()) { - if (node instanceof Simplifiable) { - changedNodes.add(node); + Set changedNodes = listener.getNodes(); + for (Node node : graph.getNodes()) { + if (node instanceof Simplifiable) { + changedNodes.add(node); + } } + postIteration(graph, context, changedNodes); + } catch (Throwable t) { + throw Debug.handle(t); } - postIteration(graph, context, changedNodes); } changed = true; } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.graal.word/src/com/oracle/graal/word/WordTypes.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/WordTypes.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/WordTypes.java Fri Mar 27 17:02:53 2015 +0100 @@ -91,6 +91,7 @@ assert wordImplType.isLinked(); wordMethod = wordImplType.resolveConcreteMethod(targetMethod, callingContextType); } + assert wordMethod != null : targetMethod; assert wordMethod.getAnnotation(Operation.class) != null : wordMethod; return wordMethod; } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.truffle.api/.checkstyle_checks.xml --- a/graal/com.oracle.truffle.api/.checkstyle_checks.xml Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.truffle.api/.checkstyle_checks.xml Fri Mar 27 17:02:53 2015 +0100 @@ -5,7 +5,7 @@ This configuration file was written by the eclipse-cs plugin configuration editor --> @@ -122,8 +122,12 @@ + - + + + + diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java Fri Mar 27 17:02:53 2015 +0100 @@ -150,32 +150,27 @@ @Override public Object getValue(FrameSlot slot) { + int slotIndex = getSlotIndexChecked(slot); + return locals[slotIndex]; + } + + private int getSlotIndexChecked(FrameSlot slot) { int slotIndex = slot.getIndex(); if (slotIndex >= tags.length) { if (!resize()) { throw new IllegalArgumentException(String.format("The frame slot '%s' is not known by the frame descriptor.", slot)); } } - return locals[slotIndex]; + return slotIndex; } private void verifySet(FrameSlot slot, FrameSlotKind accessKind) { - int slotIndex = slot.getIndex(); - if (slotIndex >= tags.length) { - if (!resize()) { - throw new IllegalArgumentException(String.format("The frame slot '%s' is not known by the frame descriptor.", slot)); - } - } + int slotIndex = getSlotIndexChecked(slot); tags[slotIndex] = (byte) accessKind.ordinal(); } private void verifyGet(FrameSlot slot, FrameSlotKind accessKind) throws FrameSlotTypeException { - int slotIndex = slot.getIndex(); - if (slotIndex >= tags.length) { - if (!resize()) { - throw new IllegalArgumentException(String.format("The frame slot '%s' is not known by the frame descriptor.", slot)); - } - } + int slotIndex = getSlotIndexChecked(slot); byte tag = tags[slotIndex]; if (accessKind == FrameSlotKind.Object ? tag != 0 : tag != accessKind.ordinal()) { throw new FrameSlotTypeException(); @@ -195,12 +190,7 @@ } private byte getTag(FrameSlot slot) { - int slotIndex = slot.getIndex(); - if (slotIndex >= tags.length) { - if (!resize()) { - throw new IllegalArgumentException(String.format("The frame slot '%s' is not known by the frame descriptor.", slot)); - } - } + int slotIndex = getSlotIndexChecked(slot); return tags[slotIndex]; } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/Source.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/Source.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/Source.java Fri Mar 27 17:02:53 2015 +0100 @@ -81,10 +81,10 @@ /** * All Sources that have been created. */ - private static final List> allSources = new ArrayList<>(); + private static final List> allSources = Collections.synchronizedList(new ArrayList>()); // Files and pseudo files are indexed. - private static final Map> filePathToSource = new Hashtable<>(); + private static final Map> filePathToSource = new HashMap<>(); private static boolean fileCacheEnabled = true; @@ -273,11 +273,13 @@ */ public static Collection findSourcesTaggedAs(SourceTag tag) { final List taggedSources = new ArrayList<>(); - for (WeakReference ref : allSources) { - Source source = ref.get(); - if (source != null) { - if (tag == null || source.isTaggedAs(tag)) { - taggedSources.add(ref.get()); + synchronized (allSources) { + for (WeakReference ref : allSources) { + Source source = ref.get(); + if (source != null) { + if (tag == null || source.isTaggedAs(tag)) { + taggedSources.add(ref.get()); + } } } } diff -r d22307a9a025 -r eea134855f85 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java Fri Mar 27 15:43:31 2015 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java Fri Mar 27 17:02:53 2015 +0100 @@ -2118,7 +2118,7 @@ boolean elseIf = false; for (ExecutableTypeData executableType : executableTypes) { elseIf = builder.startIf(elseIf); - builder.string(implicitClassFieldName).string(" == ").typeLiteral(executableType.getType().getBoxedType()); + builder.string(implicitClassFieldName).string(" == ").typeLiteral(executableType.getType().getPrimitiveType()); builder.end(); builder.startBlock(); builder.startStatement().tree(assignment); diff -r d22307a9a025 -r eea134855f85 mx/mx_graal.py --- a/mx/mx_graal.py Fri Mar 27 15:43:31 2015 +0100 +++ b/mx/mx_graal.py Fri Mar 27 17:02:53 2015 +0100 @@ -1425,18 +1425,29 @@ mx.log('TOTAL TIME: ' + '[' + str(allDuration) + ']') class Task: + # None or a list of strings. If not None, only tasks whose title + # matches at least one of the substrings in this list will return + # a non-None value from __enter__. The body of a 'with Task(...) as t' + # statement should check 't' and exit immediately if it is None. + filters = None + def __init__(self, title, tasks=None): - self.start = time.time() + self.tasks = tasks self.title = title - self.end = None - self.duration = None - self.tasks = tasks - mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: BEGIN: ') + title) + self.skipped = tasks is not None and Task.filters is not None and not any([f in title for f in Task.filters]) + if not self.skipped: + self.start = time.time() + self.end = None + self.duration = None + mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: BEGIN: ') + title) def __enter__(self): assert self.tasks is not None, "using Task with 'with' statement requires to pass the tasks list in the constructor" + if self.skipped: + return None return self def __exit__(self, exc_type, exc_value, traceback): - self.tasks.append(self.stop()) + if not self.skipped: + self.tasks.append(self.stop()) def stop(self): self.end = time.time() self.duration = datetime.timedelta(seconds=self.end - self.start) @@ -1477,67 +1488,78 @@ vmargs += ['-G:CompileTheWorldClasspath=' + jar] else: vmargs += ['-Xbootclasspath/p:' + jar] + + # suppress menubar and dock when running on Mac + vmargs = ['-Djava.awt.headless=true'] + vmargs + vm(vmargs) def _basic_gate_body(args, tasks): # Build server-hosted-graal now so we can run the unit tests - with Task('BuildHotSpotGraalHosted: product', tasks): - buildvms(['--vms', 'server', '--builds', 'product']) + with Task('BuildHotSpotGraalHosted: product', tasks) as t: + if t: buildvms(['--vms', 'server', '--builds', 'product']) # Run unit tests on server-hosted-graal with VM('server', 'product'): - with Task('UnitTests:hosted-product', tasks): - unittest(['--enable-timing', '--verbose', '--fail-fast']) + with Task('UnitTests:hosted-product', tasks) as t: + if t: unittest(['--enable-timing', '--verbose', '--fail-fast']) + + # Run ctw against rt.jar on server-hosted-graal + with VM('server', 'product'): + with Task('CTW:hosted-product', tasks) as t: + if t: ctw(['--ctwopts', '-Inline +ExitVMOnException', '-esa', '-G:+CompileTheWorldMultiThreaded', '-G:-CompileTheWorldVerbose']) # Build the other VM flavors - with Task('BuildHotSpotGraalOthers: fastdebug,product', tasks): - buildvms(['--vms', 'graal,server', '--builds', 'fastdebug,product']) + with Task('BuildHotSpotGraalOthers: fastdebug,product', tasks) as t: + if t: buildvms(['--vms', 'graal,server', '--builds', 'fastdebug,product']) with VM('graal', 'fastdebug'): - with Task('BootstrapWithSystemAssertions:fastdebug', tasks): - vm(['-esa', '-XX:-TieredCompilation', '-version']) + with Task('BootstrapWithSystemAssertions:fastdebug', tasks) as t: + if t: vm(['-esa', '-XX:-TieredCompilation', '-version']) with VM('graal', 'fastdebug'): - with Task('BootstrapEconomyWithSystemAssertions:fastdebug', tasks): - vm(['-esa', '-XX:-TieredCompilation', '-G:CompilerConfiguration=economy', '-version']) + with Task('BootstrapEconomyWithSystemAssertions:fastdebug', tasks) as t: + if t: vm(['-esa', '-XX:-TieredCompilation', '-G:CompilerConfiguration=economy', '-version']) with VM('graal', 'fastdebug'): - with Task('BootstrapWithSystemAssertionsNoCoop:fastdebug', tasks): - vm(['-esa', '-XX:-TieredCompilation', '-XX:-UseCompressedOops', '-version']) + with Task('BootstrapWithSystemAssertionsNoCoop:fastdebug', tasks) as t: + if t: vm(['-esa', '-XX:-TieredCompilation', '-XX:-UseCompressedOops', '-version']) with VM('graal', 'product'): - with Task('BootstrapWithGCVerification:product', tasks): - out = mx.DuplicateSuppressingStream(['VerifyAfterGC:', 'VerifyBeforeGC:']).write - vm(['-XX:-TieredCompilation', '-XX:+UnlockDiagnosticVMOptions', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version'], out=out) + with Task('BootstrapWithGCVerification:product', tasks) as t: + if t: + out = mx.DuplicateSuppressingStream(['VerifyAfterGC:', 'VerifyBeforeGC:']).write + vm(['-XX:-TieredCompilation', '-XX:+UnlockDiagnosticVMOptions', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version'], out=out) with VM('graal', 'product'): - with Task('BootstrapWithG1GCVerification:product', tasks): - out = mx.DuplicateSuppressingStream(['VerifyAfterGC:', 'VerifyBeforeGC:']).write - vm(['-XX:-TieredCompilation', '-XX:+UnlockDiagnosticVMOptions', '-XX:-UseSerialGC', '-XX:+UseG1GC', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version'], out=out) + with Task('BootstrapWithG1GCVerification:product', tasks) as t: + if t: + out = mx.DuplicateSuppressingStream(['VerifyAfterGC:', 'VerifyBeforeGC:']).write + vm(['-XX:-TieredCompilation', '-XX:+UnlockDiagnosticVMOptions', '-XX:-UseSerialGC', '-XX:+UseG1GC', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version'], out=out) with VM('graal', 'product'): - with Task('BootstrapWithRegisterPressure:product', tasks): - vm(['-XX:-TieredCompilation', '-G:RegisterPressure=rbx,r11,r10,r14,xmm3,xmm11,xmm14', '-esa', '-version']) + with Task('BootstrapWithRegisterPressure:product', tasks) as t: + if t: vm(['-XX:-TieredCompilation', '-G:RegisterPressure=rbx,r11,r10,r14,xmm3,xmm11,xmm14', '-esa', '-version']) with VM('graal', 'product'): - with Task('BootstrapWithImmutableCode:product', tasks): - vm(['-XX:-TieredCompilation', '-G:+ImmutableCode', '-G:+VerifyPhases', '-esa', '-version']) + with Task('BootstrapWithImmutableCode:product', tasks) as t: + if t: vm(['-XX:-TieredCompilation', '-G:+ImmutableCode', '-G:+VerifyPhases', '-esa', '-version']) for vmbuild in ['fastdebug', 'product']: for test in sanitycheck.getDacapos(level=sanitycheck.SanityCheckLevel.Gate, gateBuildLevel=vmbuild) + sanitycheck.getScalaDacapos(level=sanitycheck.SanityCheckLevel.Gate, gateBuildLevel=vmbuild): with Task(str(test) + ':' + vmbuild, tasks) as t: - if not test.test('graal'): + if t and not test.test('graal'): t.abort(test.name + ' Failed') # ensure -Xbatch still works with VM('graal', 'product'): - with Task('DaCapo_pmd:BatchMode:product', tasks): - dacapo(['-Xbatch', 'pmd']) + with Task('DaCapo_pmd:BatchMode:product', tasks) as t: + if t: dacapo(['-Xbatch', 'pmd']) # ensure -Xcomp still works with VM('graal', 'product'): - with Task('XCompMode:product', tasks): - vm(['-Xcomp', '-version']) + with Task('XCompMode:product', tasks) as t: + if t: vm(['-Xcomp', '-version']) if args.jacocout is not None: jacocoreport([args.jacocout]) @@ -1545,17 +1567,19 @@ global _jacoco _jacoco = 'off' - with Task('CleanAndBuildIdealGraphVisualizer', tasks): - env = _igvFallbackJDK(os.environ) - buildxml = mx._cygpathU2W(join(_graal_home, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'build.xml')) - mx.run(['ant', '-f', buildxml, '-q', 'clean', 'build'], env=env) + with Task('CleanAndBuildIdealGraphVisualizer', tasks) as t: + if t: + env = _igvFallbackJDK(os.environ) + buildxml = mx._cygpathU2W(join(_graal_home, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'build.xml')) + mx.run(['ant', '-f', buildxml, '-q', 'clean', 'build'], env=env) # Prevent Graal modifications from breaking the standard builds if args.buildNonGraal: - with Task('BuildHotSpotVarieties', tasks): - buildvms(['--vms', 'client,server', '--builds', 'fastdebug,product']) - if mx.get_os() not in ['windows', 'cygwin']: - buildvms(['--vms', 'server-nograal', '--builds', 'product,optimized']) + with Task('BuildHotSpotVarieties', tasks) as t: + if t: + buildvms(['--vms', 'client,server', '--builds', 'fastdebug,product']) + if mx.get_os() not in ['windows', 'cygwin']: + buildvms(['--vms', 'server-nograal', '--builds', 'product,optimized']) for vmbuild in ['product', 'fastdebug']: for theVm in ['client', 'server']: @@ -1563,11 +1587,11 @@ mx.log('The' + theVm + ' VM is not supported on this platform') continue with VM(theVm, vmbuild): - with Task('DaCapo_pmd:' + theVm + ':' + vmbuild, tasks): - dacapo(['pmd']) - - with Task('UnitTests:' + theVm + ':' + vmbuild, tasks): - unittest(['-XX:CompileCommand=exclude,*::run*', 'graal.api']) + with Task('DaCapo_pmd:' + theVm + ':' + vmbuild, tasks) as t: + if t: dacapo(['pmd']) + + with Task('UnitTests:' + theVm + ':' + vmbuild, tasks) as t: + if t: unittest(['-XX:CompileCommand=exclude,*::run*', 'graal.api']) def gate(args, gate_body=_basic_gate_body): @@ -1580,61 +1604,67 @@ parser.add_argument('-j', '--omit-java-clean', action='store_false', dest='cleanJava', help='omit cleaning Java native code') parser.add_argument('-n', '--omit-native-clean', action='store_false', dest='cleanNative', help='omit cleaning and building native code') parser.add_argument('-g', '--only-build-graalvm', action='store_false', dest='buildNonGraal', help='only build the Graal VM') + parser.add_argument('-t', '--task-filter', help='comma separated list of substrings to select subset of tasks to be run') parser.add_argument('--jacocout', help='specify the output directory for jacoco report') args = parser.parse_args(args) global _jacoco + if args.task_filter: + Task.filters = args.task_filter.split(',') tasks = [] total = Task('Gate') try: - with Task('Pylint', tasks): - mx.pylint([]) + with Task('Pylint', tasks) as t: + if t: mx.pylint([]) def _clean(name='Clean'): - with Task(name, tasks): - cleanArgs = [] - if not args.cleanNative: - cleanArgs.append('--no-native') - if not args.cleanJava: - cleanArgs.append('--no-java') - clean(cleanArgs) + with Task(name, tasks) as t: + if t: + cleanArgs = [] + if not args.cleanNative: + cleanArgs.append('--no-native') + if not args.cleanJava: + cleanArgs.append('--no-java') + clean(cleanArgs) _clean() with Task('IDEConfigCheck', tasks): - mx.ideclean([]) - mx.ideinit([]) + if t: + mx.ideclean([]) + mx.ideinit([]) eclipse_exe = mx.get_env('ECLIPSE_EXE') if eclipse_exe is not None: with Task('CodeFormatCheck', tasks) as t: - if mx.eclipseformat(['-e', eclipse_exe]) != 0: + if t and mx.eclipseformat(['-e', eclipse_exe]) != 0: t.abort('Formatter modified files - run "mx eclipseformat", check in changes and repush') with Task('Canonicalization Check', tasks) as t: - mx.log(time.strftime('%d %b %Y %H:%M:%S - Ensuring mx/projects files are canonicalized...')) - if mx.canonicalizeprojects([]) != 0: - t.abort('Rerun "mx canonicalizeprojects" and check-in the modified mx/projects files.') + if t: + mx.log(time.strftime('%d %b %Y %H:%M:%S - Ensuring mx/projects files are canonicalized...')) + if mx.canonicalizeprojects([]) != 0: + t.abort('Rerun "mx canonicalizeprojects" and check-in the modified mx/projects files.') if mx.get_env('JDT'): with Task('BuildJavaWithEcj', tasks): - build(['-p', '--no-native', '--jdt-warning-as-error']) + if t: build(['-p', '--no-native', '--jdt-warning-as-error']) _clean('CleanAfterEcjBuild') with Task('BuildJavaWithJavac', tasks): - build(['-p', '--no-native', '--force-javac']) + if t: build(['-p', '--no-native', '--force-javac']) with Task('Checkstyle', tasks) as t: - if mx.checkstyle([]) != 0: + if t and mx.checkstyle([]) != 0: t.abort('Checkstyle warnings were found') with Task('Checkheaders', tasks) as t: - if checkheaders([]) != 0: + if t and checkheaders([]) != 0: t.abort('Checkheaders warnings were found') with Task('FindBugs', tasks) as t: - if findbugs([]) != 0: + if t and findbugs([]) != 0: t.abort('FindBugs warnings were found') if exists('jacoco.exec'): @@ -1663,6 +1693,9 @@ mx.log(' =======') mx.log(' ' + str(total.duration)) + if args.task_filter: + Task.filters = None + def deoptalot(args): """bootstrap a fastdebug Graal VM with DeoptimizeALot and VerifyOops on diff -r d22307a9a025 -r eea134855f85 mx/suite.py --- a/mx/suite.py Fri Mar 27 15:43:31 2015 +0100 +++ b/mx/suite.py Fri Mar 27 17:02:53 2015 +0100 @@ -139,21 +139,6 @@ ], }, - "ASM" : { - "path" : "lib/asm-5.0.3.jar", - "urls" : [ - "http://lafo.ssw.uni-linz.ac.at/graal-external-deps/asm-5.0.3.jar", - "https://search.maven.org/remotecontent?filepath=org/ow2/asm/asm/5.0.3/asm-5.0.3.jar", - ], - "sha1" : "dcc2193db20e19e1feca8b1240dbbc4e190824fa", - "sourcePath" : "lib/asm-5.0.3-sources.jar", - "sourceSha1" : "f0f24f6666c1a15c7e202e91610476bd4ce59368", - "sourceUrls" : [ - "http://lafo.ssw.uni-linz.ac.at/graal-external-deps/asm-5.0.3-sources.jar", - "https://search.maven.org/remotecontent?filepath=org/ow2/asm/asm/5.0.3/asm-5.0.3-sources.jar", - ], - }, - "JAVA_ALLOCATION_INSTRUMENTER" : { "path" : "lib/java-allocation-instrumenter.jar", "sourcePath" : "lib/java-allocation-instrumenter.jar", @@ -880,7 +865,6 @@ "sourceDirs" : ["src"], "dependencies" : [ "com.oracle.graal.compiler.test", - "ASM", ], "checkstyle" : "com.oracle.graal.graph", "javaCompliance" : "1.8", @@ -1079,6 +1063,7 @@ "sourceDirs" : ["src"], "dependencies" : [ "com.oracle.graal.truffle", + "com.oracle.graal.graph.test", "com.oracle.graal.compiler.test", "com.oracle.truffle.sl.test", ], diff -r d22307a9a025 -r eea134855f85 src/share/tools/IdealGraphVisualizer/Bytecodes/nbproject/project.xml --- a/src/share/tools/IdealGraphVisualizer/Bytecodes/nbproject/project.xml Fri Mar 27 15:43:31 2015 +0100 +++ b/src/share/tools/IdealGraphVisualizer/Bytecodes/nbproject/project.xml Fri Mar 27 17:02:53 2015 +0100 @@ -40,6 +40,14 @@ + org.openide.awt + + + + 7.39.1 + + + org.openide.explorer diff -r d22307a9a025 -r eea134855f85 src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputBlock.java --- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputBlock.java Fri Mar 27 15:43:31 2015 +0100 +++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputBlock.java Fri Mar 27 17:02:53 2015 +0100 @@ -88,12 +88,10 @@ } public void addNode(int id) { - InputNode n = graph.getNode(id); - assert n != null; - graph.setBlock(n, this); - final InputNode node = graph.getNode(id); + InputNode node = graph.getNode(id); assert node != null; assert !nodes.contains(node) : "duplicate : " + node; + graph.setBlock(node, this); nodes.add(node); } diff -r d22307a9a025 -r eea134855f85 src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/BinaryParser.java --- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/BinaryParser.java Fri Mar 27 15:43:31 2015 +0100 +++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/BinaryParser.java Fri Mar 27 17:02:53 2015 +0100 @@ -687,8 +687,17 @@ int nodeCount = readInt(); for (int j = 0; j < nodeCount; j++) { int nodeId = readInt(); - block.addNode(nodeId); - graph.getNode(nodeId).getProperties().setProperty("block", name); + if (nodeId < 0) { + continue; + } + final Properties properties = graph.getNode(nodeId).getProperties(); + final String oldBlock = properties.get("block"); + if(oldBlock != null) { + properties.setProperty("block", oldBlock + ", " + name); + } else { + block.addNode(nodeId); + properties.setProperty("block", name); + } } int edgeCount = readInt(); for (int j = 0; j < edgeCount; j++) { diff -r d22307a9a025 -r eea134855f85 src/share/tools/IdealGraphVisualizer/FilterWindow/nbproject/genfiles.properties --- a/src/share/tools/IdealGraphVisualizer/FilterWindow/nbproject/genfiles.properties Fri Mar 27 15:43:31 2015 +0100 +++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/nbproject/genfiles.properties Fri Mar 27 17:02:53 2015 +0100 @@ -1,5 +1,5 @@ # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=09ba2a87 +nbproject/build-impl.xml.data.CRC32=5b8e8a60 nbproject/build-impl.xml.script.CRC32=e4293f0e nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.67.1 diff -r d22307a9a025 -r eea134855f85 src/share/tools/IdealGraphVisualizer/FilterWindow/nbproject/project.xml --- a/src/share/tools/IdealGraphVisualizer/FilterWindow/nbproject/project.xml Fri Mar 27 15:43:31 2015 +0100 +++ b/src/share/tools/IdealGraphVisualizer/FilterWindow/nbproject/project.xml Fri Mar 27 17:02:53 2015 +0100 @@ -47,6 +47,14 @@ + org.openide.awt + + + + 7.39.1 + + + org.openide.dialogs diff -r d22307a9a025 -r eea134855f85 src/share/tools/IdealGraphVisualizer/Graal/nbproject/genfiles.properties --- a/src/share/tools/IdealGraphVisualizer/Graal/nbproject/genfiles.properties Fri Mar 27 15:43:31 2015 +0100 +++ b/src/share/tools/IdealGraphVisualizer/Graal/nbproject/genfiles.properties Fri Mar 27 17:02:53 2015 +0100 @@ -1,8 +1,8 @@ -build.xml.data.CRC32=79002a09 +build.xml.data.CRC32=92ea213f build.xml.script.CRC32=3534d355 -build.xml.stylesheet.CRC32=a56c6a5b@2.62.1 +build.xml.stylesheet.CRC32=a56c6a5b@2.67.1 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=79002a09 +nbproject/build-impl.xml.data.CRC32=92ea213f nbproject/build-impl.xml.script.CRC32=2867f2d5 nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.67.1 diff -r d22307a9a025 -r eea134855f85 src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/color.filter --- a/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/color.filter Fri Mar 27 15:43:31 2015 +0100 +++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/color.filter Fri Mar 27 17:02:53 2015 +0100 @@ -1,15 +1,11 @@ colorize("name", ".*", white); colorize("name", "Begin|KillingBegin|EndNode|LoopBegin|LoopEnd|LoopExit|Return", orange); -colorize("name", "Phi.*|ValueProxy", magenta); -colorize("name", "FrameState@.*", new java.awt.Color(0.5, 0.8, 1.0)); -colorize("name", "If|Merge", pink); -colorize("name", "const.*", new java.awt.Color(0.7, 0.7, 0.7)); -colorize("name", "Param", new java.awt.Color(0.85, 0.85, 0.85)); +colorize("class", "FrameState", new java.awt.Color(0.5, 0.8, 1.0)); +colorize("name", "If|Merge|(Integer|Type)Switch", pink); colorize("name", "\\+|-|\\*|/|&|\\||<<|>>|>>>", cyan); -colorize("name", "Comp .*", yellow); colorize("name", "Virtual.*", green); - -colorize("name", "ValuePhi.*|ValueProxy", magenta); -colorize("name", "Const.*", new java.awt.Color(0.7, 0.7, 0.7)); -colorize("name", "Param.*", new java.awt.Color(0.85, 0.85, 0.85)); -colorize("stamp", "Condition", yellow); +colorize("name", "(Φ|Proxy)\(.*\)", magenta); +colorize("name", "(Φ|Proxy)\(.*\) Identity\(.*\)", green); +colorize("name", "C\(.*\)", new java.awt.Color(0.7, 0.7, 0.7)); +colorize("name", "P\(.*\)", new java.awt.Color(0.85, 0.85, 0.85)); +colorize("name", "==|<|InstanceOf", yellow); diff -r d22307a9a025 -r eea134855f85 src/share/tools/IdealGraphVisualizer/Util/nbproject/project.xml --- a/src/share/tools/IdealGraphVisualizer/Util/nbproject/project.xml Fri Mar 27 15:43:31 2015 +0100 +++ b/src/share/tools/IdealGraphVisualizer/Util/nbproject/project.xml Fri Mar 27 17:02:53 2015 +0100 @@ -23,6 +23,14 @@ + org.openide.awt + + + + 7.39.1 + + + org.openide.nodes diff -r d22307a9a025 -r eea134855f85 src/share/vm/code/scopeDesc.cpp --- a/src/share/vm/code/scopeDesc.cpp Fri Mar 27 15:43:31 2015 +0100 +++ b/src/share/vm/code/scopeDesc.cpp Fri Mar 27 17:02:53 2015 +0100 @@ -232,6 +232,7 @@ for (int i = 0; i < _objects->length(); i++) { ObjectValue* sv = _objects->at(i)->as_ObjectValue(); tty->print(" - %d: ", sv->id()); + tty->print("%s ", java_lang_Class::as_Klass(sv->klass()->as_ConstantOopReadValue()->value()())->external_name()); sv->print_fields_on(tty); tty->cr(); } diff -r d22307a9a025 -r eea134855f85 src/share/vm/graal/graalCodeInstaller.cpp --- a/src/share/vm/graal/graalCodeInstaller.cpp Fri Mar 27 15:43:31 2015 +0100 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Fri Mar 27 17:02:53 2015 +0100 @@ -203,7 +203,7 @@ record_metadata_reference(HotSpotMetaspaceConstantImpl::metaspaceObject(constant), HotSpotMetaspaceConstantImpl::primitive(constant), HotSpotMetaspaceConstantImpl::compressed(constant), oop_recorder); } -ScopeValue* CodeInstaller::get_scope_value(oop value, int total_frame_size, GrowableArray* objects, ScopeValue* &second, OopRecorder* oop_recorder) { +ScopeValue* CodeInstaller::get_scope_value(oop value, GrowableArray* objects, ScopeValue* &second) { second = NULL; if (value == AbstractValue::ILLEGAL()) { return _illegal_value; @@ -282,7 +282,7 @@ } #endif if (StackSlot::addFrameSize(value)) { - offset += total_frame_size; + offset += _total_frame_size; } ScopeValue* value = new LocationValue(Location::new_stk_loc(locationType, offset)); if (type == T_DOUBLE || (type == T_LONG && !reference)) { @@ -290,7 +290,7 @@ } return value; } else if (value->is_a(JavaConstant::klass())){ - record_metadata_in_constant(value, oop_recorder); + record_metadata_in_constant(value, _oop_recorder); if (value->is_a(PrimitiveConstant::klass())) { assert(!reference, "unexpected primitive constant type"); if(value->is_a(RawConstant::klass())) { @@ -323,40 +323,10 @@ } } } else if (value->is_a(VirtualObject::klass())) { - oop type = VirtualObject::type(value); int id = VirtualObject::id(value); - oop javaMirror = HotSpotResolvedObjectTypeImpl::javaClass(type); - Klass* klass = java_lang_Class::as_Klass(javaMirror); - bool isLongArray = klass == Universe::longArrayKlassObj(); - - for (jint i = 0; i < objects->length(); i++) { - ObjectValue* obj = (ObjectValue*) objects->at(i); - if (obj->id() == id) { - return obj; - } - } - - ObjectValue* sv = new ObjectValue(id, new ConstantOopWriteValue(JNIHandles::make_local(Thread::current(), javaMirror))); - objects->append(sv); - - objArrayOop values = VirtualObject::values(value); - for (jint i = 0; i < values->length(); i++) { - ScopeValue* cur_second = NULL; - oop object = values->obj_at(i); - ScopeValue* value = get_scope_value(object, total_frame_size, objects, cur_second, oop_recorder); - - if (isLongArray && cur_second == NULL) { - // we're trying to put ints into a long array... this isn't really valid, but it's used for some optimizations. - // add an int 0 constant - cur_second = _int_0_scope_value; - } - - if (cur_second != NULL) { - sv->field_values()->append(cur_second); - } - sv->field_values()->append(value); - } - return sv; + ScopeValue* object = objects->at(id); + assert(object != NULL, "missing value"); + return object; } else { value->klass()->print(); value->print(); @@ -365,14 +335,41 @@ return NULL; } -MonitorValue* CodeInstaller::get_monitor_value(oop value, int total_frame_size, GrowableArray* objects, OopRecorder* oop_recorder) { +void CodeInstaller::record_object_value(ObjectValue* sv, oop value, GrowableArray* objects) { + oop type = VirtualObject::type(value); + int id = VirtualObject::id(value); + oop javaMirror = HotSpotResolvedObjectTypeImpl::javaClass(type); + Klass* klass = java_lang_Class::as_Klass(javaMirror); + bool isLongArray = klass == Universe::longArrayKlassObj(); + + objArrayOop values = VirtualObject::values(value); + for (jint i = 0; i < values->length(); i++) { + ScopeValue* cur_second = NULL; + oop object = values->obj_at(i); + ScopeValue* value = get_scope_value(object, objects, cur_second); + + if (isLongArray && cur_second == NULL) { + // we're trying to put ints into a long array... this isn't really valid, but it's used for some optimizations. + // add an int 0 constant + cur_second = _int_0_scope_value; + } + + if (cur_second != NULL) { + sv->field_values()->append(cur_second); + } + assert(value != NULL, "missing value"); + sv->field_values()->append(value); + } +} + +MonitorValue* CodeInstaller::get_monitor_value(oop value, GrowableArray* objects) { guarantee(value->is_a(StackLockValue::klass()), "Monitors must be of type MonitorValue"); ScopeValue* second = NULL; - ScopeValue* owner_value = get_scope_value(StackLockValue::owner(value), total_frame_size, objects, second, oop_recorder); + ScopeValue* owner_value = get_scope_value(StackLockValue::owner(value), objects, second); assert(second == NULL, "monitor cannot occupy two stack slots"); - ScopeValue* lock_data_value = get_scope_value(StackLockValue::slot(value), total_frame_size, objects, second, oop_recorder); + ScopeValue* lock_data_value = get_scope_value(StackLockValue::slot(value), objects, second); assert(second == lock_data_value, "monitor is LONG value that occupies two stack slots"); assert(lock_data_value->is_location(), "invalid monitor location"); Location lock_data_loc = ((LocationValue*)lock_data_value)->location(); @@ -727,6 +724,44 @@ return true; } +GrowableArray* CodeInstaller::record_virtual_objects(oop debug_info) { + objArrayOop virtualObjects = DebugInfo::virtualObjectMapping(debug_info); + if (virtualObjects == NULL) { + return NULL; + } + GrowableArray* objects = new GrowableArray(virtualObjects->length(), virtualObjects->length(), NULL); + // Create the unique ObjectValues + for (int i = 0; i < virtualObjects->length(); i++) { + oop value = virtualObjects->obj_at(i); + int id = VirtualObject::id(value); + oop type = VirtualObject::type(value); + oop javaMirror = HotSpotResolvedObjectTypeImpl::javaClass(type); + ObjectValue* sv = new ObjectValue(id, new ConstantOopWriteValue(JNIHandles::make_local(Thread::current(), javaMirror))); + assert(objects->at(id) == NULL, "once"); + objects->at_put(id, sv); + } + // All the values which could be referenced by the VirtualObjects + // exist, so now describe all the VirtualObjects themselves. + for (int i = 0; i < virtualObjects->length(); i++) { + oop value = virtualObjects->obj_at(i); + int id = VirtualObject::id(value); + record_object_value(objects->at(id)->as_ObjectValue(), value, objects); + } + _debug_recorder->dump_object_pool(objects); + return objects; +} + +void CodeInstaller::record_scope(jint pc_offset, oop debug_info) { + oop position = DebugInfo::bytecodePosition(debug_info); + if (position == NULL) { + // Stubs do not record scope info, just oop maps + return; + } + + GrowableArray* objectMapping = record_virtual_objects(debug_info); + record_scope(pc_offset, position, objectMapping); +} + void CodeInstaller::record_scope(jint pc_offset, oop position, GrowableArray* objects) { oop frame = NULL; if (position->is_a(BytecodeFrame::klass())) { @@ -785,21 +820,21 @@ for (jint i = 0; i < values->length(); i++) { ScopeValue* second = NULL; - oop value= values->obj_at(i); + oop value = values->obj_at(i); if (i < local_count) { - ScopeValue* first = get_scope_value(value, _total_frame_size, objects, second, _oop_recorder); + ScopeValue* first = get_scope_value(value, objects, second); if (second != NULL) { locals->append(second); } locals->append(first); } else if (i < local_count + expression_count) { - ScopeValue* first = get_scope_value(value, _total_frame_size, objects, second, _oop_recorder); + ScopeValue* first = get_scope_value(value, objects, second); if (second != NULL) { expressions->append(second); } expressions->append(first); } else { - monitors->append(get_monitor_value(value, _total_frame_size, objects, _oop_recorder)); + monitors->append(get_monitor_value(value, objects)); } if (second != NULL) { i++; @@ -808,8 +843,6 @@ } } - _debug_recorder->dump_object_pool(objects); - locals_token = _debug_recorder->create_scope_values(locals); expressions_token = _debug_recorder->create_scope_values(expressions); monitors_token = _debug_recorder->create_monitor_values(monitors); @@ -817,7 +850,8 @@ throw_exception = BytecodeFrame::rethrowException(frame) == JNI_TRUE; } - _debug_recorder->describe_scope(pc_offset, method, NULL, bci, reexecute, throw_exception, false, false, locals_token, expressions_token, monitors_token); + _debug_recorder->describe_scope(pc_offset, method, NULL, bci, reexecute, throw_exception, false, false, + locals_token, expressions_token, monitors_token); } void CodeInstaller::site_Safepoint(CodeBuffer& buffer, jint pc_offset, oop site) { @@ -827,14 +861,7 @@ // address instruction = _instructions->start() + pc_offset; // jint next_pc_offset = Assembler::locate_next_instruction(instruction) - _instructions->start(); _debug_recorder->add_safepoint(pc_offset, create_oop_map(_total_frame_size, _parameter_count, debug_info)); - - oop frame = DebugInfo::bytecodePosition(debug_info); - if (frame != NULL) { - record_scope(pc_offset, frame, new GrowableArray()); - } else { - // Stubs do not record scope info, just oop maps - } - + record_scope(pc_offset, debug_info); _debug_recorder->end_safepoint(pc_offset); } @@ -843,12 +870,7 @@ assert(debug_info != NULL, "debug info expected"); _debug_recorder->add_non_safepoint(pc_offset); - - oop position = DebugInfo::bytecodePosition(debug_info); - if (position != NULL) { - record_scope(pc_offset, position, NULL); - } - + record_scope(pc_offset, debug_info); _debug_recorder->end_non_safepoint(pc_offset); } @@ -873,13 +895,8 @@ jint next_pc_offset = CodeInstaller::pd_next_offset(inst, pc_offset, hotspot_method); if (debug_info != NULL) { - oop frame = DebugInfo::bytecodePosition(debug_info); _debug_recorder->add_safepoint(next_pc_offset, create_oop_map(_total_frame_size, _parameter_count, debug_info)); - if (frame != NULL) { - record_scope(next_pc_offset, frame, new GrowableArray()); - } else { - // Stubs do not record scope info, just oop maps - } + record_scope(next_pc_offset, debug_info); } if (foreign_call != NULL) { diff -r d22307a9a025 -r eea134855f85 src/share/vm/graal/graalCodeInstaller.hpp --- a/src/share/vm/graal/graalCodeInstaller.hpp Fri Mar 27 15:43:31 2015 +0100 +++ b/src/share/vm/graal/graalCodeInstaller.hpp Fri Mar 27 17:02:53 2015 +0100 @@ -114,12 +114,10 @@ static VMReg get_hotspot_reg(jint graalRegisterNumber); static bool is_general_purpose_reg(VMReg hotspotRegister); -protected: +private: + ScopeValue* get_scope_value(oop value, GrowableArray* objects, ScopeValue* &second); + MonitorValue* get_monitor_value(oop value, GrowableArray* objects); - virtual ScopeValue* get_scope_value(oop value, int total_frame_size, GrowableArray* objects, ScopeValue* &second, OopRecorder* oop_recorder); - virtual MonitorValue* get_monitor_value(oop value, int total_frame_size, GrowableArray* objects, OopRecorder* oop_recorder); - -private: // extract the fields of the CompilationResult void initialize_fields(oop target_method); void initialize_dependencies(oop target_method); @@ -141,7 +139,11 @@ void site_DataPatch(CodeBuffer& buffer, jint pc_offset, oop site); void site_Mark(CodeBuffer& buffer, jint pc_offset, oop site); + void record_scope(jint pc_offset, oop debug_info); void record_scope(jint pc_offset, oop code_pos, GrowableArray* objects); + void record_object_value(ObjectValue* sv, oop value, GrowableArray* objects); + + GrowableArray* record_virtual_objects(oop debug_info); void process_exception_handlers(); int estimateStubSpace(int static_call_stubs); diff -r d22307a9a025 -r eea134855f85 src/share/vm/graal/graalCompiler.cpp --- a/src/share/vm/graal/graalCompiler.cpp Fri Mar 27 15:43:31 2015 +0100 +++ b/src/share/vm/graal/graalCompiler.cpp Fri Mar 27 17:02:53 2015 +0100 @@ -155,7 +155,6 @@ tty->print_cr(" Graal code install time: %6.3f s", _codeInstallTimer.seconds()); } -#ifndef PRODUCT void GraalCompiler::compile_the_world() { HandleMark hm; JavaThread* THREAD = JavaThread::current(); @@ -167,4 +166,3 @@ args.push_oop(GraalRuntime::get_HotSpotGraalRuntime()); JavaCalls::call_special(&result, klass, compileTheWorld, vmSymbols::void_method_signature(), &args, CHECK_ABORT); } -#endif diff -r d22307a9a025 -r eea134855f85 src/share/vm/graal/graalCompiler.hpp --- a/src/share/vm/graal/graalCompiler.hpp Fri Mar 27 15:43:31 2015 +0100 +++ b/src/share/vm/graal/graalCompiler.hpp Fri Mar 27 17:02:53 2015 +0100 @@ -87,9 +87,7 @@ static elapsedTimer* codeInstallTimer() { return &_codeInstallTimer; } -#ifndef PRODUCT void compile_the_world(); -#endif }; #endif // SHARE_VM_GRAAL_GRAAL_COMPILER_HPP diff -r d22307a9a025 -r eea134855f85 src/share/vm/graal/graalJavaAccess.hpp --- a/src/share/vm/graal/graalJavaAccess.hpp Fri Mar 27 15:43:31 2015 +0100 +++ b/src/share/vm/graal/graalJavaAccess.hpp Fri Mar 27 17:02:53 2015 +0100 @@ -159,6 +159,7 @@ oop_field(DebugInfo, bytecodePosition, "Lcom/oracle/graal/api/code/BytecodePosition;") \ oop_field(DebugInfo, referenceMap, "Lcom/oracle/graal/api/code/ReferenceMap;") \ oop_field(DebugInfo, calleeSaveInfo, "Lcom/oracle/graal/api/code/RegisterSaveLayout;") \ + objArrayOop_field(DebugInfo, virtualObjectMapping, "[Lcom/oracle/graal/api/meta/Value;") \ end_class \ start_class(HotSpotReferenceMap) \ oop_field(HotSpotReferenceMap, registerRefMap, "Ljava/util/BitSet;") \ diff -r d22307a9a025 -r eea134855f85 src/share/vm/prims/jni.cpp --- a/src/share/vm/prims/jni.cpp Fri Mar 27 15:43:31 2015 +0100 +++ b/src/share/vm/prims/jni.cpp Fri Mar 27 17:02:53 2015 +0100 @@ -5199,7 +5199,7 @@ *vm = (JavaVM *)(&main_vm); *(JNIEnv**)penv = thread->jni_environment(); -#if defined(GRAAL) && !defined(PRODUCT) +#if defined(GRAAL) // We turn off CompileTheWorld so that compilation requests are not ignored during bootstrap or that Graal can be compiled by C1/C2. bool doCTW = CompileTheWorld; CompileTheWorld = false; @@ -5210,14 +5210,14 @@ if (FLAG_IS_DEFAULT(BootstrapGraal) ? !TieredCompilation : BootstrapGraal) { GraalCompiler::instance()->bootstrap(); } -#elif defined(GRAAL) && !defined(PRODUCT) +#elif defined(GRAAL) if (doCTW) { // required for hosted CTW. CompilationPolicy::completed_vm_startup(); } #endif -#if defined(GRAAL) && !defined(PRODUCT) +#if defined(GRAAL) if (doCTW) { GraalCompiler::instance()->compile_the_world(); } diff -r d22307a9a025 -r eea134855f85 src/share/vm/runtime/globals.hpp --- a/src/share/vm/runtime/globals.hpp Fri Mar 27 15:43:31 2015 +0100 +++ b/src/share/vm/runtime/globals.hpp Fri Mar 27 17:02:53 2015 +0100 @@ -2678,9 +2678,13 @@ "Delay invoking the compiler until main application class is " \ "loaded") \ \ - develop(bool, CompileTheWorld, false, \ + NOT_GRAAL(develop(bool, CompileTheWorld, false, \ "Compile all methods in all classes in bootstrap class path " \ - "(stress test)") \ + "(stress test)")) \ + \ + GRAAL_ONLY(product(bool, CompileTheWorld, false, \ + "Compile all methods in all classes in bootstrap class path " \ + "(stress test)")) \ \ develop(bool, CompileTheWorldPreloadClasses, true, \ "Preload all classes used by a class before start loading") \