# HG changeset patch # User Stefan Anzinger # Date 1426683203 -3600 # Node ID da997cdfb0d8162a9590cce98d4e0a86d2c4444d # Parent bcfca701c935411ccc1f56e4c472ef34c30405f4# Parent b6af1acf00d69a3d9e995f03e68b2a8568d53691 Merge diff -r bcfca701c935 -r da997cdfb0d8 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 Tue Mar 17 18:57:47 2015 +0100 +++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Wed Mar 18 13:53:23 2015 +0100 @@ -1943,6 +1943,10 @@ ADD.rmOp.emit(this, QWORD, dst, src); } + public final void addq(AMD64Address dst, Register src) { + ADD.mrOp.emit(this, QWORD, dst, src); + } + public final void andq(Register dst, int imm32) { AND.getMIOpcode(QWORD, isByte(imm32)).emit(this, QWORD, dst, imm32); } diff -r bcfca701c935 -r da997cdfb0d8 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 Tue Mar 17 18:57:47 2015 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Wed Mar 18 13:53:23 2015 +0100 @@ -346,7 +346,7 @@ AllocationContext allocContext = new AllocationContext(lirGen.getSpillMoveFactory()); lirSuites.getAllocationStage().apply(target, lirGenRes, codeEmittingOrder, linearScanOrder, allocContext); - PostAllocationOptimizationContext postAllocOptContext = new PostAllocationOptimizationContext(); + PostAllocationOptimizationContext postAllocOptContext = new PostAllocationOptimizationContext(lirGen); lirSuites.getPostAllocationOptimizationStage().apply(target, lirGenRes, codeEmittingOrder, linearScanOrder, postAllocOptContext); return lirGenRes; diff -r bcfca701c935 -r da997cdfb0d8 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCounterOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCounterOp.java Wed Mar 18 13:53:23 2015 +0100 @@ -0,0 +1,85 @@ +/* + * 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.hotspot.amd64; + +import static com.oracle.graal.amd64.AMD64.*; +import static com.oracle.graal.api.code.ValueUtil.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.asm.*; + +@Opcode("BenchMarkCounter") +public class AMD64HotSpotCounterOp extends HotSpotCounterOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64HotSpotCounterOp.class); + + @Alive({OperandFlag.STACK, OperandFlag.UNINITIALIZED}) private StackSlotValue backupSlot; + + public AMD64HotSpotCounterOp(String name, String group, Value increment, HotSpotRegistersProvider registers, HotSpotVMConfig config, StackSlotValue backupSlot) { + super(TYPE, name, group, increment, registers, config); + this.backupSlot = backupSlot; + } + + public AMD64HotSpotCounterOp(String[] names, String[] groups, Value[] increments, HotSpotRegistersProvider registers, HotSpotVMConfig config, StackSlotValue backupSlot) { + super(TYPE, names, groups, increments, registers, config); + this.backupSlot = backupSlot; + } + + @Override + public void emitCode(CompilationResultBuilder crb) { + AMD64MacroAssembler masm = (AMD64MacroAssembler) crb.asm; + TargetDescription target = crb.target; + + Register scratch = rax; + + // address for counters array + AMD64Address countersArrayAddr = new AMD64Address(thread, config.graalCountersThreadOffset); + Register countersArrayReg = scratch; + + // backup scratch register + masm.movq((AMD64Address) crb.asAddress(backupSlot), scratch); + + // load counters array + masm.movptr(countersArrayReg, countersArrayAddr); + + forEachCounter((name, group, increment) -> emitIncrement(masm, target, countersArrayReg, name, group, increment)); + + // 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) { + // address for counter value + AMD64Address counterAddr = new AMD64Address(countersArrayReg, getDisplacementForLongIndex(target, getIndex(name, group, increment))); + // increment counter (in memory) + if (isConstant(increment)) { + masm.incrementl(counterAddr, asInt(asConstant(increment))); + } else { + masm.addq(counterAddr, asRegister(increment)); + } + } +} diff -r bcfca701c935 -r da997cdfb0d8 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Tue Mar 17 18:57:47 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Wed Mar 18 13:53:23 2015 +0100 @@ -39,9 +39,11 @@ import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.spi.*; +import com.oracle.graal.debug.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding; import com.oracle.graal.hotspot.amd64.AMD64HotSpotMove.HotSpotStoreConstantOp; +import com.oracle.graal.hotspot.debug.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.lir.*; @@ -54,6 +56,8 @@ import com.oracle.graal.lir.amd64.AMD64Move.LoadOp; import com.oracle.graal.lir.amd64.AMD64Move.MoveFromRegOp; import com.oracle.graal.lir.amd64.AMD64Move.StoreOp; +import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.framemap.*; import com.oracle.graal.lir.gen.*; /** @@ -118,6 +122,41 @@ SaveRbp saveRbp; + private static final class RescueSlotDummyOp extends LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(RescueSlotDummyOp.class); + + @Alive({OperandFlag.STACK, OperandFlag.UNINITIALIZED}) private StackSlotValue slot; + + public RescueSlotDummyOp(FrameMapBuilder frameMapBuilder, LIRKind kind) { + super(TYPE); + slot = frameMapBuilder.allocateSpillSlot(kind); + } + + public StackSlotValue getSlot() { + return slot; + } + + @Override + public void emitCode(CompilationResultBuilder crb) { + } + } + + private RescueSlotDummyOp rescueSlotOp; + + private StackSlotValue getOrInitRescueSlot() { + if (rescueSlotOp == null) { + // create dummy instruction to keep the rescue slot alive + rescueSlotOp = new RescueSlotDummyOp(getResult().getFrameMapBuilder(), getLIRKindTool().getWordKind()); + // insert dummy instruction into the start block + LIR lir = getResult().getLIR(); + List instructions = lir.getLIRforBlock(lir.getControlFlowGraph().getStartBlock()); + // Note: we do not insert at position 1 to avoid interference with the save rpb op + instructions.add(instructions.size() - 1, rescueSlotOp); + Debug.dump(lir, "created rescue dummy op"); + } + return rescueSlotOp.getSlot(); + } + /** * List of epilogue operations that need to restore RBP. */ @@ -440,6 +479,10 @@ for (AMD64HotSpotEpilogueOp op : epilogueOps) { op.savedRbp = savedRbp; } + if (BenchmarkCounters.enabled) { + // ensure that the rescue slot is available + getOrInitRescueSlot(); + } } private static LIRKind toStackKind(LIRKind kind) { @@ -626,4 +669,20 @@ return super.canInlineConstant(c); } } + + @Override + public LIRInstruction createBenchmarkCounter(String name, String group, Value increment) { + if (BenchmarkCounters.enabled) { + return new AMD64HotSpotCounterOp(name, group, increment, getProviders().getRegisters(), config, getOrInitRescueSlot()); + } + return null; + } + + @Override + public LIRInstruction createMultiBenchmarkCounter(String[] names, String[] groups, Value[] increments) { + if (BenchmarkCounters.enabled) { + return new AMD64HotSpotCounterOp(names, groups, increments, getProviders().getRegisters(), config, getOrInitRescueSlot()); + } + return null; + } } diff -r bcfca701c935 -r da997cdfb0d8 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCounterOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCounterOp.java Wed Mar 18 13:53:23 2015 +0100 @@ -0,0 +1,84 @@ +/* + * 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.hotspot.sparc; + +import static com.oracle.graal.api.code.ValueUtil.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.sparc.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.asm.*; + +@Opcode("BenchMarkCounter") +public class SPARCHotSpotCounterOp extends HotSpotCounterOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCHotSpotCounterOp.class); + + @Temp({OperandFlag.REG}) private AllocatableValue scratch0; + @Temp({OperandFlag.REG}) private AllocatableValue scratch1; + + public SPARCHotSpotCounterOp(String name, String group, Value increment, HotSpotRegistersProvider registers, HotSpotVMConfig config, AllocatableValue scratch0, AllocatableValue scratch1) { + super(TYPE, name, group, increment, registers, config); + this.scratch0 = scratch0; + this.scratch1 = scratch1; + } + + public SPARCHotSpotCounterOp(String[] names, String[] groups, Value[] increments, HotSpotRegistersProvider registers, HotSpotVMConfig config, AllocatableValue scratch0, AllocatableValue scratch1) { + super(TYPE, names, groups, increments, registers, config); + this.scratch0 = scratch0; + this.scratch1 = scratch1; + } + + @Override + public void emitCode(CompilationResultBuilder crb) { + SPARCMacroAssembler masm = (SPARCMacroAssembler) crb.asm; + TargetDescription target = crb.target; + + // address for counters array + SPARCAddress countersArrayAddr = new SPARCAddress(thread, config.graalCountersThreadOffset); + Register countersArrayReg = asRegister(scratch0); + + // load counters array + masm.ldx(countersArrayAddr, countersArrayReg); + + forEachCounter((name, group, increment) -> emitIncrement(masm, target, countersArrayReg, name, group, increment)); + } + + 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))); + Register counterReg = asRegister(scratch1); + // load counter value + masm.ldx(counterAddr, counterReg); + // increment counter + if (isConstant(increment)) { + masm.add(counterReg, asInt(asConstant(increment)), counterReg); + } else { + masm.add(counterReg, asRegister(increment), counterReg); + } + // store counter value + masm.stx(counterReg, counterAddr); + } +} diff -r bcfca701c935 -r da997cdfb0d8 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java Tue Mar 17 18:57:47 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java Wed Mar 18 13:53:23 2015 +0100 @@ -37,6 +37,7 @@ import com.oracle.graal.compiler.sparc.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding; +import com.oracle.graal.hotspot.debug.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.lir.*; @@ -48,6 +49,7 @@ import com.oracle.graal.lir.sparc.SPARCMove.NullCheckOp; import com.oracle.graal.lir.sparc.SPARCMove.StoreConstantOp; import com.oracle.graal.lir.sparc.SPARCMove.StoreOp; +import com.oracle.graal.sparc.*; public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSpotLIRGenerator { @@ -362,4 +364,32 @@ assert kind == Kind.Object || kind == Kind.Long : address + " - " + kind + " not an object!"; append(new NullCheckOp(load(address), state)); } + + @Override + public LIRInstruction createBenchmarkCounter(String name, String group, Value increment) { + if (BenchmarkCounters.enabled) { + try (SPARCScratchRegister sc0 = SPARCScratchRegister.get()) { + RegisterValue scratch0 = sc0.getRegister().asValue(getLIRKindTool().getWordKind()); + try (SPARCScratchRegister sc1 = SPARCScratchRegister.get()) { + RegisterValue scratch1 = sc1.getRegister().asValue(getLIRKindTool().getWordKind()); + return new SPARCHotSpotCounterOp(name, group, increment, getProviders().getRegisters(), config, scratch0, scratch1); + } + } + } + return null; + } + + @Override + public LIRInstruction createMultiBenchmarkCounter(String[] names, String[] groups, Value[] increments) { + if (BenchmarkCounters.enabled) { + try (SPARCScratchRegister sc0 = SPARCScratchRegister.get()) { + RegisterValue scratch0 = sc0.getRegister().asValue(getLIRKindTool().getWordKind()); + try (SPARCScratchRegister sc1 = SPARCScratchRegister.get()) { + RegisterValue scratch1 = sc1.getRegister().asValue(getLIRKindTool().getWordKind()); + return new SPARCHotSpotCounterOp(names, groups, increments, getProviders().getRegisters(), config, scratch0, scratch1); + } + } + } + return null; + } } diff -r bcfca701c935 -r da997cdfb0d8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCounterOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCounterOp.java Wed Mar 18 13:53:23 2015 +0100 @@ -0,0 +1,112 @@ +/* + * 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.hotspot; + +import static com.oracle.graal.api.code.ValueUtil.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.hotspot.debug.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.lir.*; + +public abstract class HotSpotCounterOp extends LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(HotSpotCounterOp.class); + + private final String[] names; + private final String[] groups; + protected final Register thread; + protected final HotSpotVMConfig config; + @Alive({OperandFlag.CONST, OperandFlag.REG}) protected Value[] increments; + + public HotSpotCounterOp(LIRInstructionClass c, String name, String group, Value increment, HotSpotRegistersProvider registers, HotSpotVMConfig config) { + this(c, new String[]{name}, new String[]{group}, new Value[]{increment}, registers, config); + } + + public HotSpotCounterOp(LIRInstructionClass c, String[] names, String[] groups, Value[] increments, HotSpotRegistersProvider registers, HotSpotVMConfig config) { + super(c); + + assert names.length == groups.length; + assert groups.length == increments.length; + + this.names = names; + this.groups = groups; + this.increments = increments; + this.thread = registers.getThreadRegister(); + this.config = config; + } + + protected static int getDisplacementForLongIndex(TargetDescription target, long index) { + long finalDisp = index * target.getSizeInBytes(Kind.Long); + if (!NumUtil.isInt(finalDisp)) { + throw GraalInternalError.unimplemented("cannot deal with indices that big: " + index); + } + return (int) finalDisp; + } + + protected interface CounterProcedure { + void apply(String name, String group, Value increment); + } + + protected void forEachCounter(CounterProcedure proc) { + for (int i = 0; i < names.length; i++) { + proc.apply(names[i], groups[i], increments[i]); + } + } + + protected int getIndex(String name, String group, Value increment) { + if (isConstant(increment)) { + // get index for the counter + return BenchmarkCounters.getIndexConstantIncrement(name, group, config, asLong(asConstant(increment))); + } + assert isRegister(increment) : "Unexpected Value: " + increment; + // get index for the counter + return BenchmarkCounters.getIndex(name, group, config); + } + + private static long asLong(JavaConstant value) { + Kind kind = value.getKind(); + switch (kind) { + case Byte: + case Short: + case Char: + case Int: + return value.asInt(); + case Long: + return value.asLong(); + default: + throw new IllegalArgumentException("not an integer kind: " + kind); + } + } + + protected static int asInt(JavaConstant value) { + long l = asLong(value); + if (!NumUtil.isInt(l)) { + throw GraalInternalError.shouldNotReachHere("value does not fit into int: " + l); + } + return (int) l; + } + +} diff -r bcfca701c935 -r da997cdfb0d8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java Tue Mar 17 18:57:47 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java Wed Mar 18 13:53:23 2015 +0100 @@ -27,26 +27,13 @@ import java.util.concurrent.*; import java.util.concurrent.atomic.*; -import sun.misc.*; - -import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; -import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; -import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.bridge.*; -import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.replacements.*; -import com.oracle.graal.nodeinfo.*; -import com.oracle.graal.nodes.HeapAccess.BarrierType; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.debug.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.spi.*; import com.oracle.graal.options.*; -import com.oracle.graal.replacements.nodes.*; import edu.umd.cs.findbugs.annotations.*; @@ -98,6 +85,8 @@ " dacapo = 'err, starting =====, PASSED in'%n" + " specjvm2008 = 'out,Iteration ~ (~s) begins:,Iteration ~ (~s) ends:'", type = OptionType.Debug) private static final OptionValue BenchmarkDynamicCounters = new OptionValue<>(null); + @Option(help = "Use grouping separators for number printing", type = OptionType.Debug) + private static final OptionValue DynamicCountersPrintGroupSeparator = new OptionValue<>(true); //@formatter:on } @@ -105,59 +94,62 @@ public static boolean enabled = false; - public static final ConcurrentHashMap indexes = new ConcurrentHashMap<>(); - public static final ArrayList groups = new ArrayList<>(); + private static class Counter { + public final int index; + public final String group; + public final AtomicLong staticCounters; + + public Counter(int index, String group, AtomicLong staticCounters) { + this.index = index; + this.group = group; + this.staticCounters = staticCounters; + } + } + + public static final ConcurrentHashMap counterMap = new ConcurrentHashMap<>(); public static long[] delta; - public static final ArrayList staticCounters = new ArrayList<>(); + + public static int getIndexConstantIncrement(String name, String group, HotSpotVMConfig config, long increment) { + Counter counter = getCounter(name, group, config); + counter.staticCounters.addAndGet(increment); + return counter.index; + } + + public static int getIndex(String name, String group, HotSpotVMConfig config) { + Counter counter = getCounter(name, group, config); + return counter.index; + } @SuppressFBWarnings(value = "AT_OPERATION_SEQUENCE_ON_CONCURRENT_ABSTRACTION", justification = "concurrent abstraction calls are in synchronized block") - private static int getIndex(DynamicCounterNode counter, StructuredGraph currentGraph) { + private static Counter getCounter(String name, String group, HotSpotVMConfig config) throws GraalInternalError { if (!enabled) { - throw new GraalInternalError("counter nodes shouldn't exist when counters are not enabled: " + counter.getGroup() + ", " + counter.getName()); + throw new GraalInternalError("cannot access count index when counters are not enabled: " + group + ", " + name); } - String name; - String group = counter.getGroup(); - if (counter.isWithContext()) { - name = counter.getName() + " @ "; - if (currentGraph.method() != null) { - StackTraceElement stackTraceElement = currentGraph.method().asStackTraceElement(0); - if (stackTraceElement != null) { - name += " " + stackTraceElement.toString(); - } else { - name += currentGraph.method().format("%h.%n"); - } - } - if (currentGraph.name != null) { - name += " (" + currentGraph.name + ")"; - } - name += "#" + group; - - } else { - name = counter.getName() + "#" + group; - } - Integer index = indexes.get(name); - if (index == null) { + String nameGroup = name + "#" + group; + Counter counter = counterMap.get(nameGroup); + if (counter == null) { synchronized (BenchmarkCounters.class) { - index = indexes.get(name); - if (index == null) { - index = indexes.size(); - indexes.put(name, index); - groups.add(group); - staticCounters.add(new AtomicLong()); + counter = counterMap.get(nameGroup); + if (counter == null) { + counter = new Counter(counterMap.size(), group, new AtomicLong()); + counterMap.put(nameGroup, counter); } } } - assert groups.get(index).equals(group) : "mismatching groups: " + groups.get(index) + " vs. " + group; - if (counter.getIncrement().isConstant()) { - staticCounters.get(index).addAndGet(counter.getIncrement().asJavaConstant().asLong()); + assert counter.group.equals(group) : "mismatching groups: " + counter.group + " vs. " + group; + int countersSize = config.graalCountersSize; + if (counter.index >= countersSize) { + throw new GraalInternalError("too many counters, reduce number of counters or increase -XX:GraalCounterSize=... (current value: " + countersSize + ")"); } - return index; + return counter; } private static synchronized void dump(PrintStream out, double seconds, long[] counters, int maxRows) { - if (!groups.isEmpty()) { - out.println("====== dynamic counters (" + staticCounters.size() + " in total) ======"); - for (String group : new TreeSet<>(groups)) { + if (!counterMap.isEmpty()) { + out.println("====== dynamic counters (" + counterMap.size() + " in total) ======"); + TreeSet set = new TreeSet<>(); + counterMap.forEach((nameGroup, counter) -> set.add(counter.group)); + for (String group : set) { if (group != null) { if (DUMP_STATIC) { dumpCounters(out, seconds, counters, true, group, maxRows); @@ -181,9 +173,9 @@ // collect the numbers long[] array; if (staticCounter) { - array = new long[indexes.size()]; - for (int i = 0; i < array.length; i++) { - array[i] = staticCounters.get(i).get(); + array = new long[counterMap.size()]; + for (Counter counter : counterMap.values()) { + array[counter.index] = counter.staticCounters.get(); } } else { array = counters.clone(); @@ -193,9 +185,10 @@ } // sort the counters by putting them into a sorted map long sum = 0; - for (Map.Entry entry : indexes.entrySet()) { - int index = entry.getValue(); - if (groups.get(index).equals(group)) { + for (Map.Entry entry : counterMap.entrySet()) { + Counter counter = entry.getValue(); + int index = counter.index; + if (counter.group.equals(group)) { sum += array[index]; sorted.put(array[index] * array.length + index, entry.getKey().substring(0, entry.getKey().length() - group.length() - 1)); } @@ -216,28 +209,29 @@ cnt--; } + String numFmt = Options.DynamicCountersPrintGroupSeparator.getValue() ? "%,19d" : "%19d"; if (staticCounter) { out.println("=========== " + group + " (static counters):"); for (Map.Entry entry : sorted.entrySet()) { long counter = entry.getKey() / array.length; - out.format(Locale.US, "%,19d %3d%% %s\n", counter, percentage(counter, sum), entry.getValue()); + out.format(Locale.US, numFmt + " %3d%% %s\n", counter, percentage(counter, sum), entry.getValue()); } - out.format(Locale.US, "%,19d total\n", sum); + out.format(Locale.US, numFmt + " total\n", sum); } else { if (group.startsWith("~")) { out.println("=========== " + group + " (dynamic counters), time = " + seconds + " s:"); for (Map.Entry entry : sorted.entrySet()) { long counter = entry.getKey() / array.length; - out.format(Locale.US, "%,19d/s %3d%% %s\n", (long) (counter / seconds), percentage(counter, sum), entry.getValue()); + out.format(Locale.US, numFmt + "/s %3d%% %s\n", (long) (counter / seconds), percentage(counter, sum), entry.getValue()); } - out.format(Locale.US, "%,19d/s total\n", (long) (sum / seconds)); + out.format(Locale.US, numFmt + "/s total\n", (long) (sum / seconds)); } else { out.println("=========== " + group + " (dynamic counters):"); for (Map.Entry entry : sorted.entrySet()) { long counter = entry.getKey() / array.length; - out.format(Locale.US, "%,19d %3d%% %s\n", counter, percentage(counter, sum), entry.getValue()); + out.format(Locale.US, numFmt + " %3d%% %s\n", counter, percentage(counter, sum), entry.getValue()); } - out.format(Locale.US, "%,19d total\n", sum); + out.format(Locale.US, numFmt + " total\n", sum); } } } @@ -383,51 +377,4 @@ dump(TTY.cachedOut, (System.nanoTime() - compilerStartTime) / 1000000000d, compilerToVM.collectCounters(), 100); } } - - private static final LocationIdentity COUNTER_ARRAY_LOCATION = NamedLocationIdentity.mutable("COUNTER_ARRAY_LOCATION"); - private static final LocationIdentity COUNTER_LOCATION = NamedLocationIdentity.mutable("COUNTER_LOCATION"); - - @NodeInfo(nameTemplate = "CounterIndex") - private static final class CounterIndexNode extends FloatingNode implements LIRLowerable { - - public static final NodeClass TYPE = NodeClass.create(CounterIndexNode.class); - protected final Object counter; - protected final int countersSize; - - protected CounterIndexNode(Stamp stamp, DynamicCounterNode counter, int countersSize) { - super(TYPE, stamp); - this.countersSize = countersSize; - this.counter = counter; - } - - @Override - public void generate(NodeLIRBuilderTool generator) { - int index = BenchmarkCounters.getIndex((DynamicCounterNode) counter, graph()); - if (index >= countersSize) { - throw new GraalInternalError("too many counters, reduce number of counters or increase -XX:GraalCounterSize=... (current value: " + countersSize + ")"); - } - - generator.setResult(this, JavaConstant.forIntegerKind(getKind(), index)); - } - } - - public static void lower(DynamicCounterNode counter, HotSpotRegistersProvider registers, HotSpotVMConfig config, Kind wordKind) { - StructuredGraph graph = counter.graph(); - - ReadRegisterNode thread = graph.add(new ReadRegisterNode(registers.getThreadRegister(), wordKind, true, false)); - - CounterIndexNode index = graph.unique(new CounterIndexNode(StampFactory.forKind(wordKind), counter, config.graalCountersSize)); - ConstantLocationNode arrayLocation = graph.unique(new ConstantLocationNode(COUNTER_ARRAY_LOCATION, config.graalCountersThreadOffset)); - ReadNode readArray = graph.add(new ReadNode(thread, arrayLocation, StampFactory.forKind(wordKind), BarrierType.NONE)); - IndexedLocationNode location = graph.unique(new IndexedLocationNode(COUNTER_LOCATION, 0, index, Unsafe.ARRAY_LONG_INDEX_SCALE)); - ReadNode read = graph.add(new ReadNode(readArray, location, StampFactory.forKind(Kind.Long), BarrierType.NONE)); - AddNode add = graph.unique(new AddNode(read, counter.getIncrement())); - WriteNode write = graph.add(new WriteNode(readArray, add, location, BarrierType.NONE)); - - graph.addBeforeFixed(counter, thread); - graph.addBeforeFixed(counter, readArray); - graph.addBeforeFixed(counter, read); - graph.addBeforeFixed(counter, write); - graph.removeFixed(counter); - } } diff -r bcfca701c935 -r da997cdfb0d8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java Tue Mar 17 18:57:47 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java Wed Mar 18 13:53:23 2015 +0100 @@ -36,7 +36,6 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.debug.*; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.hotspot.nodes.type.*; import com.oracle.graal.hotspot.replacements.*; @@ -105,8 +104,6 @@ lowerStoreHubNode((StoreHubNode) n, graph); } else if (n instanceof OSRStartNode) { lowerOSRStartNode((OSRStartNode) n); - } else if (n instanceof DynamicCounterNode) { - lowerDynamicCounterNode((DynamicCounterNode) n); } else if (n instanceof BytecodeExceptionNode) { lowerBytecodeExceptionNode((BytecodeExceptionNode) n); } else if (n instanceof CheckCastDynamicNode) { @@ -369,13 +366,6 @@ } } - private void lowerDynamicCounterNode(DynamicCounterNode n) { - StructuredGraph graph = n.graph(); - if (graph.getGuardsStage().areFrameStatesAtDeopts()) { - BenchmarkCounters.lower(n, registers, runtime.getConfig(), runtime.getTarget().wordKind); - } - } - static final class Exceptions { protected static final ArrayIndexOutOfBoundsException cachedArrayIndexOutOfBoundsException; protected static final NullPointerException cachedNullPointerException; diff -r bcfca701c935 -r da997cdfb0d8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaFieldImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaFieldImpl.java Tue Mar 17 18:57:47 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaFieldImpl.java Wed Mar 18 13:53:23 2015 +0100 @@ -149,9 +149,9 @@ @Override public JavaType getType() { - if (!(type instanceof ResolvedJavaType)) { + if (type instanceof HotSpotUnresolvedJavaType) { // Don't allow unresolved types to hang around forever - ResolvedJavaType resolved = type.resolve(holder); + ResolvedJavaType resolved = ((HotSpotUnresolvedJavaType) type).reresolve(holder); if (resolved != null) { type = resolved; } @@ -204,7 +204,7 @@ } try { return holder.mirror().getDeclaredField(name); - } catch (NoSuchFieldException e) { + } catch (NoSuchFieldException | NoClassDefFoundError e) { return null; } } diff -r bcfca701c935 -r da997cdfb0d8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotUnresolvedJavaType.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotUnresolvedJavaType.java Tue Mar 17 18:57:47 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotUnresolvedJavaType.java Wed Mar 18 13:53:23 2015 +0100 @@ -88,4 +88,18 @@ public ResolvedJavaType resolve(ResolvedJavaType accessingClass) { return (ResolvedJavaType) runtime.lookupType(getName(), (HotSpotResolvedObjectType) accessingClass, true); } + + /** + * Try to find a loaded version of this class. + * + * @param accessingClass + * @return the resolved class or null. + */ + ResolvedJavaType reresolve(HotSpotResolvedObjectType accessingClass) { + JavaType type = runtime.lookupType(getName(), accessingClass, false); + if (type instanceof ResolvedJavaType) { + return (ResolvedJavaType) type; + } + return null; + } } diff -r bcfca701c935 -r da997cdfb0d8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Tue Mar 17 18:57:47 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Wed Mar 18 13:53:23 2015 +0100 @@ -157,7 +157,8 @@ public static native Object newInstance(@ConstantNodeParameter ForeignCallDescriptor descriptor, KlassPointer hub); @Snippet - public static Object allocateInstanceDynamic(Class type, @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter String typeContext) { + public static Object allocateInstanceDynamic(Class type, @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, + @SuppressWarnings("unused") @ConstantParameter String typeContext) { KlassPointer hub = ClassGetHubNode.readClass(type); if (probability(FAST_PATH_PROBABILITY, !hub.isNull())) { if (probability(FAST_PATH_PROBABILITY, isInstanceKlassFullyInitialized(hub))) { @@ -170,7 +171,11 @@ */ if (probability(FAST_PATH_PROBABILITY, (layoutHelper & 1) == 0)) { Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION); - return allocateInstance(layoutHelper, hub, prototypeMarkWord, fillContents, threadRegister, false, typeContext); + /* + * FIXME(je,ds): we should actually pass typeContext instead of "" but late + * binding of parameters is not yet supported by the GraphBuilderPlugin system. + */ + return allocateInstance(layoutHelper, hub, prototypeMarkWord, fillContents, threadRegister, false, ""); } } } diff -r bcfca701c935 -r da997cdfb0d8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Tue Mar 17 18:57:47 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Wed Mar 18 13:53:23 2015 +0100 @@ -40,6 +40,8 @@ import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.lir.phases.*; +import com.oracle.graal.lir.phases.PostAllocationOptimizationPhase.PostAllocationOptimizationContext; +import com.oracle.graal.lir.profiling.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.schedule.*; @@ -180,7 +182,7 @@ Suites suites = new Suites(new PhaseSuite<>(), defaultSuites.getMidTier(), defaultSuites.getLowTier()); SchedulePhase schedule = emitFrontEnd(providers, target, graph, null, providers.getSuites().getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL, getProfilingInfo(graph), null, suites); - LIRSuites lirSuites = providers.getSuites().getDefaultLIRSuites(); + LIRSuites lirSuites = createLIRSuites(); emitBackEnd(graph, Stub.this, incomingCc, getInstalledCodeOwner(), backend, target, compResult, CompilationResultBuilderFactory.Default, schedule, getRegisterConfig(), lirSuites); } catch (Throwable e) { throw Debug.handle(e); @@ -210,6 +212,15 @@ return code; } + private LIRSuites createLIRSuites() { + LIRSuites lirSuites = new LIRSuites(providers.getSuites().getDefaultLIRSuites()); + ListIterator> moveProfiling = lirSuites.getPostAllocationOptimizationStage().findPhase(MoveProfiling.class); + if (moveProfiling != null) { + moveProfiling.remove(); + } + return lirSuites; + } + /** * Gets the compilation result for this stub, compiling it first if necessary, and installing it * in code. diff -r bcfca701c935 -r da997cdfb0d8 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ControlFlowOptimizer.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ControlFlowOptimizer.java Tue Mar 17 18:57:47 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ControlFlowOptimizer.java Wed Mar 18 13:53:23 2015 +0100 @@ -41,7 +41,8 @@ * Performs control flow optimizations on the given LIR graph. */ @Override - protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder) { + protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, + BenchmarkCounterFactory counterFactory) { LIR lir = lirGenRes.getLIR(); new Optimizer(lir).deleteEmptyBlocks(codeEmittingOrder); } diff -r bcfca701c935 -r da997cdfb0d8 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/EdgeMoveOptimizer.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/EdgeMoveOptimizer.java Tue Mar 17 18:57:47 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/EdgeMoveOptimizer.java Wed Mar 18 13:53:23 2015 +0100 @@ -51,7 +51,8 @@ public final class EdgeMoveOptimizer extends PostAllocationOptimizationPhase { @Override - protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder) { + protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, + BenchmarkCounterFactory counterFactory) { LIR ir = lirGenRes.getLIR(); Optimizer optimizer = new Optimizer(ir); diff -r bcfca701c935 -r da997cdfb0d8 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/NullCheckOptimizer.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/NullCheckOptimizer.java Tue Mar 17 18:57:47 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/NullCheckOptimizer.java Wed Mar 18 13:53:23 2015 +0100 @@ -34,7 +34,8 @@ public final class NullCheckOptimizer extends PostAllocationOptimizationPhase { @Override - protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder) { + protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, + BenchmarkCounterFactory counterFactory) { LIR ir = lirGenRes.getLIR(); List> blocks = ir.codeEmittingOrder(); NullCheckOptimizer.foldNullChecks(ir, blocks, target.implicitNullCheckLimit); diff -r bcfca701c935 -r da997cdfb0d8 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/RedundantMoveElimination.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/RedundantMoveElimination.java Tue Mar 17 18:57:47 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/RedundantMoveElimination.java Wed Mar 18 13:53:23 2015 +0100 @@ -44,7 +44,8 @@ public final class RedundantMoveElimination extends PostAllocationOptimizationPhase { @Override - protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder) { + protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, + BenchmarkCounterFactory counterFactory) { Optimization redundantMoveElimination = new Optimization(); redundantMoveElimination.doOptimize(lirGenRes.getLIR(), lirGenRes.getFrameMap()); } diff -r bcfca701c935 -r da997cdfb0d8 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/BenchmarkCounterFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/BenchmarkCounterFactory.java Wed Mar 18 13:53:23 2015 +0100 @@ -0,0 +1,32 @@ +/* + * 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.lir.gen; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.lir.*; + +public interface BenchmarkCounterFactory { + LIRInstruction createBenchmarkCounter(String name, String group, Value increment); + + LIRInstruction createMultiBenchmarkCounter(String[] names, String[] groups, Value[] increments); +} diff -r bcfca701c935 -r da997cdfb0d8 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerator.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerator.java Tue Mar 17 18:57:47 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerator.java Wed Mar 18 13:53:23 2015 +0100 @@ -391,4 +391,12 @@ public void emitBlackhole(Value operand) { append(new StandardOp.BlackholeOp(operand)); } + + public LIRInstruction createBenchmarkCounter(String name, String group, Value increment) { + throw GraalInternalError.unimplemented(); + } + + public LIRInstruction createMultiBenchmarkCounter(String[] names, String[] groups, Value[] increments) { + throw GraalInternalError.unimplemented(); + } } diff -r bcfca701c935 -r da997cdfb0d8 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGeneratorTool.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGeneratorTool.java Tue Mar 17 18:57:47 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGeneratorTool.java Wed Mar 18 13:53:23 2015 +0100 @@ -30,7 +30,7 @@ import com.oracle.graal.compiler.common.spi.*; import com.oracle.graal.lir.*; -public interface LIRGeneratorTool extends ArithmeticLIRGenerator { +public interface LIRGeneratorTool extends ArithmeticLIRGenerator, BenchmarkCounterFactory { public interface SpillMoveFactory { diff -r bcfca701c935 -r da997cdfb0d8 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRPhaseSuite.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRPhaseSuite.java Tue Mar 17 18:57:47 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRPhaseSuite.java Wed Mar 18 13:53:23 2015 +0100 @@ -28,7 +28,7 @@ import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.lir.gen.*; -public abstract class LIRPhaseSuite extends LIRPhase { +public class LIRPhaseSuite extends LIRPhase { private final List> phases; public LIRPhaseSuite() { @@ -75,4 +75,9 @@ } } + public LIRPhaseSuite copy() { + LIRPhaseSuite suite = new LIRPhaseSuite<>(); + suite.phases.addAll(phases); + return suite; + } } diff -r bcfca701c935 -r da997cdfb0d8 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRSuites.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRSuites.java Tue Mar 17 18:57:47 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRSuites.java Wed Mar 18 13:53:23 2015 +0100 @@ -41,6 +41,10 @@ this.postAllocStage = postAllocStage; } + public LIRSuites(LIRSuites other) { + this(other.getPreAllocationOptimizationStage().copy(), other.getAllocationStage().copy(), other.getPostAllocationOptimizationStage().copy()); + } + /** * {@link PreAllocationOptimizationPhase}s are executed between {@link LIR} generation and * register allocation. diff -r bcfca701c935 -r da997cdfb0d8 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/PostAllocationOptimizationPhase.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/PostAllocationOptimizationPhase.java Tue Mar 17 18:57:47 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/PostAllocationOptimizationPhase.java Wed Mar 18 13:53:23 2015 +0100 @@ -31,14 +31,20 @@ public abstract class PostAllocationOptimizationPhase extends LIRPhase { public static final class PostAllocationOptimizationContext { + private final BenchmarkCounterFactory counterFactory; + + public PostAllocationOptimizationContext(BenchmarkCounterFactory counterFactory) { + this.counterFactory = counterFactory; + } } @Override protected final > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, PostAllocationOptimizationContext context) { - run(target, lirGenRes, codeEmittingOrder, linearScanOrder); + run(target, lirGenRes, codeEmittingOrder, linearScanOrder, context.counterFactory); } - protected abstract > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder); + protected abstract > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, + BenchmarkCounterFactory counterFactory); } diff -r bcfca701c935 -r da997cdfb0d8 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/PostAllocationOptimizationStage.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/PostAllocationOptimizationStage.java Tue Mar 17 18:57:47 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/PostAllocationOptimizationStage.java Wed Mar 18 13:53:23 2015 +0100 @@ -25,7 +25,8 @@ import static com.oracle.graal.lir.phases.LIRPhase.Options.*; import com.oracle.graal.lir.*; -import com.oracle.graal.lir.phases.PostAllocationOptimizationPhase.*; +import com.oracle.graal.lir.phases.PostAllocationOptimizationPhase.PostAllocationOptimizationContext; +import com.oracle.graal.lir.profiling.*; import com.oracle.graal.options.*; public class PostAllocationOptimizationStage extends LIRPhaseSuite { @@ -39,6 +40,8 @@ public static final NestedBooleanOptionValue LIROptRedundantMoveElimination = new NestedBooleanOptionValue(LIROptimization, true); @Option(help = "", type = OptionType.Debug) public static final NestedBooleanOptionValue LIROptNullCheckOptimizer = new NestedBooleanOptionValue(LIROptimization, true); + @Option(help = "", type = OptionType.Debug) + public static final OptionValue LIROptMoveProfiling = new OptionValue<>(false); // @formatter:on } @@ -55,5 +58,8 @@ if (Options.LIROptNullCheckOptimizer.getValue()) { appendPhase(new NullCheckOptimizer()); } + if (Options.LIROptMoveProfiling.getValue()) { + appendPhase(new MoveProfiling()); + } } } diff -r bcfca701c935 -r da997cdfb0d8 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/profiling/MoveProfiling.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/profiling/MoveProfiling.java Wed Mar 18 13:53:23 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.lir.profiling; + +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.compiler.common.*; +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.StandardOp.MoveOp; +import com.oracle.graal.lir.gen.*; +import com.oracle.graal.lir.phases.*; + +public class MoveProfiling extends PostAllocationOptimizationPhase { + + @Override + protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, + BenchmarkCounterFactory counterFactory) { + new Analyzer(lirGenRes.getLIR(), counterFactory).run(); + } + + private static enum MoveType { + REG2REG("Reg", "Reg"), + STACK2REG("Reg", "Stack"), + CONST2REG("Reg", "Const"), + REG2STACK("Stack", "Reg"), + CONST2STACK("Stack", "Const"); + + private final String name; + + MoveType(String dst, String src) { + this.name = String.format("%5s <- %s", dst, src); + } + + @Override + public String toString() { + return name; + } + + public static MoveType get(MoveOp move) { + AllocatableValue dst = move.getResult(); + Value src = move.getInput(); + if (isRegister(dst)) { + if (isRegister(src)) { + return REG2REG; + } + if (isStackSlot(src)) { + return STACK2REG; + } + if (isConstant(src)) { + return CONST2REG; + } + } else if (isStackSlot(dst)) { + if (isRegister(src)) { + return REG2STACK; + } + if (isConstant(src)) { + return CONST2STACK; + } + } + throw GraalInternalError.shouldNotReachHere(String.format("Unrecognized Move: %s dst=%s, src=%s", move, dst, src)); + } + } + + private static class Analyzer { + private final LIR lir; + private final BenchmarkCounterFactory counterFactory; + private final LIRInsertionBuffer buffer; + private final int[] cnt; + + public Analyzer(LIR lir, BenchmarkCounterFactory counterFactory) { + this.lir = lir; + this.counterFactory = counterFactory; + this.buffer = new LIRInsertionBuffer(); + cnt = new int[MoveType.values().length]; + } + + 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); + + // reset counters + Arrays.fill(cnt, 0); + // analysis phase + for (LIRInstruction inst : instructions) { + if (inst instanceof MoveOp) { + cnt[MoveType.get((MoveOp) inst).ordinal()]++; + } + } + + // counter insertion phase + List names = new ArrayList<>(); + List increments = new ArrayList<>(); + for (MoveType type : MoveType.values()) { + int i = cnt[type.ordinal()]; + if (i > 0) { + names.add(type.toString()); + increments.add(JavaConstant.forInt(i)); + } + } + 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(); + } + } + +} diff -r bcfca701c935 -r da997cdfb0d8 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java Tue Mar 17 18:57:47 2015 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java Wed Mar 18 13:53:23 2015 +0100 @@ -60,6 +60,7 @@ if (iv.direction() == Direction.Up) { range = add(graph, range, ConstantNode.forIntegerStamp(stamp, 1, graph)); } else { + assert iv.direction() == Direction.Down; range = sub(graph, range, ConstantNode.forIntegerStamp(stamp, 1, graph)); } } @@ -76,6 +77,7 @@ } public long constantMaxTripCount() { + assert iv.direction() != null; long off = oneOff ? iv.direction() == Direction.Up ? 1 : -1 : 0; long max = (((ConstantNode) end).asJavaConstant().asLong() + off - iv.constantInit()) / iv.constantStride(); return Math.max(0, max); diff -r bcfca701c935 -r da997cdfb0d8 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java Tue Mar 17 18:57:47 2015 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java Wed Mar 18 13:53:23 2015 +0100 @@ -218,11 +218,12 @@ if (initStamp.upperBound() > limitStamp.lowerBound()) { return false; } - } else { - assert iv.direction() == Direction.Down; + } else if (iv.direction() == Direction.Down) { if (initStamp.lowerBound() < limitStamp.upperBound()) { return false; } + } else { + return false; } oneOff = true; break; @@ -265,9 +266,12 @@ if (loop().getExits().contains(b)) { exits.add((LoopExitNode) b.getBeginNode()); } else { - assert loop().getBlocks().contains(b); blocks.add(b.getBeginNode()); - work.addAll(b.getDominated()); + for (Block d : b.getDominated()) { + if (loop.getBlocks().contains(d)) { + work.add(d); + } + } } } return LoopFragment.computeNodes(branch.graph(), blocks, exits); diff -r bcfca701c935 -r da997cdfb0d8 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java Tue Mar 17 18:57:47 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java Wed Mar 18 13:53:23 2015 +0100 @@ -22,8 +22,11 @@ */ package com.oracle.graal.nodes.debug; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -37,7 +40,7 @@ * value of withContext, the name of the root method is added to the counter's name. */ @NodeInfo -public class DynamicCounterNode extends FixedWithNextNode implements Lowerable { +public class DynamicCounterNode extends FixedWithNextNode implements LIRLowerable { public static final NodeClass TYPE = NodeClass.create(DynamicCounterNode.class); @Input ValueNode increment; @@ -74,11 +77,6 @@ return withContext; } - @Override - public void lower(LoweringTool tool) { - tool.getLowerer().lower(this, tool); - } - public static void addCounterBefore(String group, String name, long increment, boolean withContext, FixedNode position) { StructuredGraph graph = position.graph(); graph.addBeforeFixed(position, position.graph().add(new DynamicCounterNode(name, group, ConstantNode.forLong(increment, position.graph()), withContext))); @@ -87,4 +85,32 @@ @NodeIntrinsic public static native void counter(@ConstantNodeParameter String name, @ConstantNodeParameter String group, long increment, @ConstantNodeParameter boolean addContext); + public void generate(NodeLIRBuilderTool generator) { + LIRGeneratorTool lirGen = generator.getLIRGeneratorTool(); + String nameWithContext; + if (isWithContext()) { + nameWithContext = getName() + " @ "; + if (graph().method() != null) { + StackTraceElement stackTraceElement = graph().method().asStackTraceElement(0); + if (stackTraceElement != null) { + nameWithContext += " " + stackTraceElement.toString(); + } else { + nameWithContext += graph().method().format("%h.%n"); + } + } + if (graph().name != null) { + nameWithContext += " (" + graph().name + ")"; + } + + } else { + nameWithContext = getName(); + } + LIRInstruction counterOp = lirGen.createBenchmarkCounter(nameWithContext, getGroup(), generator.operand(increment)); + if (counterOp != null) { + lirGen.append(counterOp); + } else { + throw GraalInternalError.unimplemented("Benchmark counters not enabled or not implemented by the back end."); + } + } + } diff -r bcfca701c935 -r da997cdfb0d8 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/MemoryScheduleVerification.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/MemoryScheduleVerification.java Tue Mar 17 18:57:47 2015 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/MemoryScheduleVerification.java Wed Mar 18 13:53:23 2015 +0100 @@ -31,6 +31,7 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.graph.*; import com.oracle.graal.phases.graph.ReentrantBlockIterator.BlockIteratorClosure; @@ -78,6 +79,8 @@ } addFloatingReadUsages(currentState, n); + } else if (n instanceof MemoryProxy) { + addFloatingReadUsages(currentState, n); } else if (n instanceof FloatingReadNode) { FloatingReadNode floatingReadNode = (FloatingReadNode) n; if (floatingReadNode.getLastLocationAccess() != null && floatingReadNode.getLocationIdentity().isMutable()) { diff -r bcfca701c935 -r da997cdfb0d8 graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java --- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java Tue Mar 17 18:57:47 2015 +0100 +++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java Wed Mar 18 13:53:23 2015 +0100 @@ -253,7 +253,7 @@ } else { // silently ignored } - } catch (InterruptedException e) { + } catch (InterruptedException | CancellationException e) { // silently ignored } } diff -r bcfca701c935 -r da997cdfb0d8 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 Tue Mar 17 18:57:47 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Wed Mar 18 13:53:23 2015 +0100 @@ -319,11 +319,18 @@ plugins.setLoadFieldPlugin(new InterceptLoadFieldPlugin()); plugins.setParameterPlugin(new InterceptReceiverPlugin(callTarget)); callTarget.setInlining(new TruffleInlining(callTarget, new DefaultInliningPolicy())); - plugins.setInlineInvokePlugin(new PEInlineInvokePlugin(callTarget.getInlining(), providers.getReplacements())); + InlineInvokePlugin inlinePlugin = new PEInlineInvokePlugin(callTarget.getInlining(), providers.getReplacements()); + if (PrintTruffleExpansionHistogram.getValue()) { + inlinePlugin = new HistogramInlineInvokePlugin(graph, inlinePlugin); + } + plugins.setInlineInvokePlugin(inlinePlugin); plugins.setLoopExplosionPlugin(new PELoopExplosionPlugin()); InvocationPlugins invocationPlugins = newConfig.getPlugins().getInvocationPlugins(); new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), this.snippetReflection, providers.getConstantReflection(), newConfig, TruffleCompilerImpl.Optimizations, null).apply(graph); + if (PrintTruffleExpansionHistogram.getValue()) { + ((HistogramInlineInvokePlugin) inlinePlugin).print(callTarget, System.out); + } Debug.dump(graph, "After FastPE"); // Perform deoptimize to guard conversion. diff -r bcfca701c935 -r da997cdfb0d8 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java Tue Mar 17 18:57:47 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java Wed Mar 18 13:53:23 2015 +0100 @@ -156,6 +156,9 @@ @Option(help = "Print source secions for printed expansion trees", type = OptionType.Debug) public static final OptionValue TraceTruffleExpansionSource = new OptionValue<>(false); + @Option(help = "Prints a histogram of all expanded Java methods.", type = OptionType.Debug) + public static final OptionValue PrintTruffleExpansionHistogram = new OptionValue<>(false); + @Option(help = "Print detailed information for the Truffle compilation cache", type = OptionType.Debug) public static final OptionValue TraceTruffleCacheDetails = new OptionValue<>(false); diff -r bcfca701c935 -r da997cdfb0d8 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/debug/HistogramInlineInvokePlugin.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/debug/HistogramInlineInvokePlugin.java Wed Mar 18 13:53:23 2015 +0100 @@ -0,0 +1,179 @@ +/* + * 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.debug; + +import java.io.*; +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graphbuilderconf.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.truffle.*; + +public class HistogramInlineInvokePlugin implements InlineInvokePlugin { + + private final Map histogram = new HashMap<>(); + private final StructuredGraph graph; + private final InlineInvokePlugin delegate; + + private HistogramInlineInvokePlugin.MethodStatistic currentStatistic; + + public HistogramInlineInvokePlugin(StructuredGraph graph, InlineInvokePlugin delegate) { + this.graph = graph; + this.delegate = delegate; + } + + public InlineInfo getInlineInfo(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args, JavaType returnType) { + InlineInfo inlineInfo = delegate.getInlineInfo(b, method, args, returnType); + if (inlineInfo != null) { + currentStatistic = new MethodStatistic(currentStatistic, inlineInfo.methodToInline, graph.getNodeCount(), graph.getNodes(MethodCallTargetNode.TYPE).count()); + } + return inlineInfo; + } + + public void postInline(ResolvedJavaMethod inlinedTargetMethod) { + delegate.postInline(inlinedTargetMethod); + + if (currentStatistic != null) { + currentStatistic.applyNodeCountAfter(graph.getNodeCount()); + currentStatistic.applyCallsAfter(graph.getNodes(MethodCallTargetNode.TYPE).count()); + accept(currentStatistic); + currentStatistic = currentStatistic.getParent(); + } + } + + private void accept(MethodStatistic current) { + ResolvedJavaMethod method = current.getMethod(); + HistogramInlineInvokePlugin.MethodStatistics statistics = histogram.get(method); + if (statistics == null) { + statistics = new MethodStatistics(method); + histogram.put(method, statistics); + } + statistics.accept(current); + } + + public void print(OptimizedCallTarget target, PrintStream out) { + out.printf("Truffle expansion histogram for %s", target); + out.println(" Invocations = Number of expanded invocations"); + out.println(" Nodes = Number of Graal nodes created for this method during partial evaluation."); + out.println(" Calls = Number of not expanded calls created for this method during partial evaluation."); + out.printf(" %-11s |Nodes %5s %5s %5s %8s |Calls %5s %5s %5s %8s | Method Name%n", "Invocations", "Sum", "Min", "Max", "Avg", "Sum", "Min", "Max", "Avg"); + histogram.values().stream().sorted().forEach(statistics -> statistics.print(out)); + } + + private static class MethodStatistics implements Comparable { + + private final ResolvedJavaMethod method; + + private int count; + private final IntSummaryStatistics shallowCount = new IntSummaryStatistics(); + private final IntSummaryStatistics callCount = new IntSummaryStatistics(); + + public MethodStatistics(ResolvedJavaMethod method) { + this.method = method; + } + + public void print(PrintStream out) { + out.printf(" %11d | %5d %5d %5d %8.2f | %5d %5d %5d %8.2f | %s%n", // + count, shallowCount.getSum(), shallowCount.getMin(), shallowCount.getMax(), // + shallowCount.getAverage(), callCount.getSum(), callCount.getMin(), callCount.getMax(), // + callCount.getAverage(), method.format("%h.%n(%p)")); + } + + public int compareTo(MethodStatistics o) { + int result = (int) (o.shallowCount.getSum() - shallowCount.getSum()); + if (result == 0) { + return o.count - count; + } + return result; + } + + public void accept(MethodStatistic statistic) { + if (!statistic.method.equals(method)) { + throw new IllegalArgumentException("invalid statistic"); + } + count++; + callCount.accept(statistic.getShallowCallCount()); + shallowCount.accept(statistic.getShallowNodeCount()); + } + } + + private static class MethodStatistic { + + private final MethodStatistic parent; + private final List children = new ArrayList<>(); + + private final ResolvedJavaMethod method; + private int deepNodeCount; + private int callCount; + + public MethodStatistic(MethodStatistic parent, ResolvedJavaMethod method, int nodeCountBefore, int callsBefore) { + this.parent = parent; + this.method = method; + this.callCount = callsBefore; + this.deepNodeCount = nodeCountBefore; + if (parent != null) { + this.parent.getChildren().add(this); + } + } + + public ResolvedJavaMethod getMethod() { + return method; + } + + public List getChildren() { + return children; + } + + public int getShallowNodeCount() { + int shallowCount = deepNodeCount; + for (MethodStatistic child : children) { + shallowCount -= child.deepNodeCount; + } + return shallowCount; + } + + public int getShallowCallCount() { + int shallowCount = callCount; + for (MethodStatistic child : children) { + shallowCount -= child.callCount; + } + return shallowCount; + } + + public void applyNodeCountAfter(int nodeCountAfter) { + deepNodeCount = nodeCountAfter - this.deepNodeCount; + } + + public void applyCallsAfter(int callsAfter) { + callCount = callsAfter - this.callCount; + } + + public MethodStatistic getParent() { + return parent; + } + + } + +} diff -r bcfca701c935 -r da997cdfb0d8 mxtool/mx.py --- a/mxtool/mx.py Tue Mar 17 18:57:47 2015 +0100 +++ b/mxtool/mx.py Wed Mar 18 13:53:23 2015 +0100 @@ -2823,7 +2823,7 @@ else: # Using just SC_ARG_MAX without extra downwards adjustment # results in "[Errno 7] Argument list too long" on MacOS. - commandLinePrefixAllowance -= 20000 + commandLinePrefixAllowance = 20000 syslimit = os.sysconf('SC_ARG_MAX') if syslimit == -1: syslimit = 262144 # we could use sys.maxint but we prefer a more robust smaller value diff -r bcfca701c935 -r da997cdfb0d8 src/share/vm/graal/graalRuntime.cpp --- a/src/share/vm/graal/graalRuntime.cpp Tue Mar 17 18:57:47 2015 +0100 +++ b/src/share/vm/graal/graalRuntime.cpp Wed Mar 18 13:53:23 2015 +0100 @@ -626,6 +626,7 @@ // private static GraalRuntime Graal.initializeRuntime() JVM_ENTRY(jobject, JVM_GetGraalRuntime(JNIEnv *env, jclass c)) + GraalRuntime::initialize_HotSpotGraalRuntime(); return GraalRuntime::get_HotSpotGraalRuntime_jobject(); JVM_END @@ -688,21 +689,43 @@ } } -Handle GraalRuntime::get_HotSpotGraalRuntime() { +Handle GraalRuntime::callInitializer(const char* className, const char* methodName, const char* returnType) { + guarantee(!_HotSpotGraalRuntime_initialized, "cannot reinitialize HotSpotGraalRuntime"); + Thread* THREAD = Thread::current(); + check_generated_sources_sha1(CHECK_ABORT_(Handle())); + + TempNewSymbol name = SymbolTable::new_symbol(className, CHECK_ABORT_(Handle())); + KlassHandle klass = load_required_class(name); + TempNewSymbol runtime = SymbolTable::new_symbol(methodName, CHECK_ABORT_(Handle())); + TempNewSymbol sig = SymbolTable::new_symbol(returnType, CHECK_ABORT_(Handle())); + JavaValue result(T_OBJECT); + JavaCalls::call_static(&result, klass, runtime, sig, CHECK_ABORT_(Handle())); + return Handle((oop)result.get_jobject()); +} + +void GraalRuntime::initialize_HotSpotGraalRuntime() { if (JNIHandles::resolve(_HotSpotGraalRuntime_instance) == NULL) { - guarantee(!_HotSpotGraalRuntime_initialized, "cannot reinitialize HotSpotGraalRuntime"); +#ifdef ASSERT + // This should only be called in the context of the Graal class being initialized Thread* THREAD = Thread::current(); - check_generated_sources_sha1(CHECK_ABORT_(Handle())); - TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/HotSpotGraalRuntime", CHECK_ABORT_(Handle())); - KlassHandle klass = load_required_class(name); - TempNewSymbol runtime = SymbolTable::new_symbol("runtime", CHECK_ABORT_(Handle())); - TempNewSymbol sig = SymbolTable::new_symbol("()Lcom/oracle/graal/hotspot/HotSpotGraalRuntime;", CHECK_ABORT_(Handle())); - JavaValue result(T_OBJECT); - JavaCalls::call_static(&result, klass, runtime, sig, CHECK_ABORT_(Handle())); - _HotSpotGraalRuntime_instance = JNIHandles::make_global((oop) result.get_jobject()); + TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/api/runtime/Graal", CHECK_ABORT); + instanceKlassHandle klass = InstanceKlass::cast(load_required_class(name)); + assert(klass->is_being_initialized() && klass->is_reentrant_initialization(THREAD), + "HotSpotGraalRuntime initialization should only be triggered through Graal initialization"); +#endif + + Handle result = callInitializer("com/oracle/graal/hotspot/HotSpotGraalRuntime", "runtime", + "()Lcom/oracle/graal/hotspot/HotSpotGraalRuntime;"); _HotSpotGraalRuntime_initialized = true; + _HotSpotGraalRuntime_instance = JNIHandles::make_global(result()); } - return Handle(JNIHandles::resolve_non_null(_HotSpotGraalRuntime_instance)); +} + +void GraalRuntime::initialize_Graal() { + if (JNIHandles::resolve(_HotSpotGraalRuntime_instance) == NULL) { + callInitializer("com/oracle/graal/api/runtime/Graal", "getRuntime", "()Lcom/oracle/graal/api/runtime/GraalRuntime;"); + } + assert(_HotSpotGraalRuntime_initialized == true, "what?"); } // private static void CompilerToVMImpl.init() diff -r bcfca701c935 -r da997cdfb0d8 src/share/vm/graal/graalRuntime.hpp --- a/src/share/vm/graal/graalRuntime.hpp Tue Mar 17 18:57:47 2015 +0100 +++ b/src/share/vm/graal/graalRuntime.hpp Wed Mar 18 13:53:23 2015 +0100 @@ -138,13 +138,29 @@ /** * Gets the singleton HotSpotGraalRuntime instance, initializing it if necessary */ - static Handle get_HotSpotGraalRuntime(); + static Handle get_HotSpotGraalRuntime() { + initialize_Graal(); + return Handle(JNIHandles::resolve_non_null(_HotSpotGraalRuntime_instance)); + } static jobject get_HotSpotGraalRuntime_jobject() { - get_HotSpotGraalRuntime(); + initialize_Graal(); + assert(_HotSpotGraalRuntime_initialized, "must be"); return _HotSpotGraalRuntime_instance; } + static Handle callInitializer(const char* className, const char* methodName, const char* returnType); + + /** + * Trigger initialization of HotSpotGraalRuntime through Graal.runtime() + */ + static void initialize_Graal(); + + /** + * Explicitly initialize HotSpotGraalRuntime itself + */ + static void initialize_HotSpotGraalRuntime(); + static void shutdown(); static bool shutdown_called() {