--- old/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java 2017-07-07 09:29:19.000000000 -0700 +++ new/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java 2017-07-07 09:29:19.000000000 -0700 @@ -27,8 +27,7 @@ import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.GraalCompiler; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.hotspot.HotSpotCompiledCodeBuilder; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; @@ -82,6 +81,10 @@ return backend; } + public HotSpotProviders getProviders() { + return providers; + } + private Suites getSuites() { // create suites every time, as we modify options for the compiler return backend.getSuites().getDefaultSuites(graalOptions); @@ -93,10 +96,10 @@ } @SuppressWarnings("try") - public CompilationResult compileMethod(ResolvedJavaMethod resolvedMethod) { - StructuredGraph graph = buildStructuredGraph(resolvedMethod); + public CompilationResult compileMethod(ResolvedJavaMethod resolvedMethod, DebugContext debug) { + StructuredGraph graph = buildStructuredGraph(resolvedMethod, debug); if (graph != null) { - return compileGraph(resolvedMethod, graph); + return compileGraph(resolvedMethod, graph, debug); } return null; } @@ -105,12 +108,13 @@ * Build a structured graph for the member. * * @param javaMethod method for whose code the graph is to be created + * @param debug * @return structured graph */ @SuppressWarnings("try") - private StructuredGraph buildStructuredGraph(ResolvedJavaMethod javaMethod) { - try (Scope s = Debug.scope("AOTParseMethod")) { - StructuredGraph graph = new StructuredGraph.Builder(graalOptions).method(javaMethod).useProfilingInfo(false).build(); + private StructuredGraph buildStructuredGraph(ResolvedJavaMethod javaMethod, DebugContext debug) { + try (DebugContext.Scope s = debug.scope("AOTParseMethod")) { + StructuredGraph graph = new StructuredGraph.Builder(graalOptions, debug).method(javaMethod).useProfilingInfo(false).build(); graphBuilderSuite.apply(graph, highTierContext); return graph; } catch (Throwable e) { @@ -120,8 +124,8 @@ } @SuppressWarnings("try") - private CompilationResult compileGraph(ResolvedJavaMethod resolvedMethod, StructuredGraph graph) { - try (Scope s = Debug.scope("AOTCompileMethod")) { + private CompilationResult compileGraph(ResolvedJavaMethod resolvedMethod, StructuredGraph graph, DebugContext debug) { + try (DebugContext.Scope s = debug.scope("AOTCompileMethod")) { ProfilingInfo profilingInfo = DefaultProfilingInfo.get(TriState.FALSE); final boolean isImmutablePIC = true; --- old/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompilationTask.java 2017-07-07 09:29:20.000000000 -0700 +++ new/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompilationTask.java 2017-07-07 09:29:20.000000000 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -26,14 +26,15 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.GraalCompilerOptions; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugEnvironment; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Management; import org.graalvm.compiler.debug.TTY; -import org.graalvm.compiler.debug.internal.DebugScope; +import org.graalvm.compiler.debug.DebugContext.Activation; import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.printer.GraalDebugHandlersFactory; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; @@ -88,15 +89,12 @@ /** * Compile a method or a constructor. */ + @SuppressWarnings("try") public void run() { // Ensure a JVMCI runtime is initialized prior to Debug being initialized as the former // may include processing command line options used by the latter. HotSpotJVMCIRuntime.runtime(); - // Ensure a debug configuration for this thread is initialized - if (Debug.isEnabled() && DebugScope.getConfig() == null) { - DebugEnvironment.ensureInitialized(graalOptions); - } AOTCompiler.logCompilation(MiscUtils.uniqueMethodName(method), "Compiling"); final long threadId = Thread.currentThread().getId(); @@ -117,8 +115,12 @@ allocatedBytesBefore = 0L; } + CompilationResult compResult = null; final long startTime = System.currentTimeMillis(); - CompilationResult compResult = aotBackend.compileMethod(method); + SnippetReflectionProvider snippetReflection = aotBackend.getProviders().getSnippetReflection(); + try (DebugContext debug = DebugContext.create(graalOptions, new GraalDebugHandlersFactory(snippetReflection)); Activation a = debug.activate()) { + compResult = aotBackend.compileMethod(method, debug); + } final long endTime = System.currentTimeMillis(); if (printAfterCompilation || printCompilation) { --- old/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataBuilder.java 2017-07-07 09:29:20.000000000 -0700 +++ new/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataBuilder.java 2017-07-07 09:29:20.000000000 -0700 @@ -33,8 +33,7 @@ import jdk.tools.jaotc.binformat.HeaderContainer; import jdk.tools.jaotc.utils.Timer; import org.graalvm.compiler.code.CompilationResult; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.hotspot.HotSpotHostBackend; import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider; import org.graalvm.compiler.hotspot.stubs.Stub; @@ -124,10 +123,12 @@ /** * Prepare data with all compiled classes and stubs. * + * @param debug + * * @throws Exception */ @SuppressWarnings("try") - public void prepareData() throws Exception { + public void prepareData(DebugContext debug) throws Exception { try (Timer t = new Timer(main, "Parsing compiled code")) { /* * Copy compiled code into code section container and calls stubs (PLT trampoline). @@ -142,7 +143,7 @@ } } - AOTCompiledClass stubCompiledCode = retrieveStubCode(); + AOTCompiledClass stubCompiledCode = retrieveStubCode(debug); // Free memory! try (Timer t = main.options.verbose ? new Timer(main, "Freeing memory") : null) { @@ -177,18 +178,20 @@ /** * Get all stubs from Graal and add them to the code section. + * + * @param debug */ @SuppressWarnings("try") - private AOTCompiledClass retrieveStubCode() { + private AOTCompiledClass retrieveStubCode(DebugContext debug) { ArrayList stubs = new ArrayList<>(); HotSpotForeignCallsProvider foreignCallsProvider = backend.getProviders().getForeignCalls(); for (Stub stub : foreignCallsProvider.getStubs()) { - try (Scope scope = Debug.scope("CompileStubs")) { - CompilationResult result = stub.getCompilationResult(backend); + try (DebugContext.Scope scope = debug.scope("CompileStubs")) { + CompilationResult result = stub.getCompilationResult(debug, backend); CompiledMethodInfo cm = new CompiledMethodInfo(result, new AOTStub(stub, backend)); stubs.add(cm); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } AOTCompiledClass stubCompiledCode = new AOTCompiledClass(stubs); --- old/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java 2017-07-07 09:29:20.000000000 -0700 +++ new/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java 2017-07-07 09:29:20.000000000 -0700 @@ -59,7 +59,10 @@ import jdk.tools.jaotc.collect.module.ModuleSourceProvider; import jdk.tools.jaotc.utils.Timer; +import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.api.runtime.GraalJVMCICompiler; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DebugContext.Activation; import org.graalvm.compiler.hotspot.CompilerConfigurationFactory; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotGraalCompilerFactory; @@ -72,6 +75,7 @@ import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.tiers.HighTierContext; +import org.graalvm.compiler.printer.GraalDebugHandlersFactory; import org.graalvm.compiler.runtime.RuntimeProvider; import jdk.vm.ci.meta.MetaAccessProvider; @@ -467,6 +471,7 @@ } AOTBackend aotBackend = new AOTBackend(this, graalOptions, backend, filters); + SnippetReflectionProvider snippetReflection = aotBackend.getProviders().getSnippetReflection(); AOTCompiler compiler = new AOTCompiler(this, graalOptions, aotBackend, options.threads); classes = compiler.compileClasses(classes); @@ -485,7 +490,10 @@ BinaryContainer binaryContainer = new BinaryContainer(graalOptions, graalHotSpotVMConfig, graphBuilderConfig, JVM_VERSION); DataBuilder dataBuilder = new DataBuilder(this, backend, classes, binaryContainer); - dataBuilder.prepareData(); + + try (DebugContext debug = DebugContext.create(graalOptions, new GraalDebugHandlersFactory(snippetReflection)); Activation a = debug.activate()) { + dataBuilder.prepareData(debug); + } // Print information about section sizes printContainerInfo(binaryContainer.getHeaderContainer().getContainer()); --- old/src/jdk.internal.vm.compiler/.mx.graal/suite.py 2017-07-07 09:29:21.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/.mx.graal/suite.py 2017-07-07 09:29:21.000000000 -0700 @@ -70,15 +70,15 @@ "exports" : [ "", # exports all packages containing package-info.java ], - "checkstyle" : "org.graalvm.api.word", + "checkstyle" : "org.graalvm.word", "javaCompliance" : "1.8", "workingSets" : "API,SDK", }, - "org.graalvm.api.word" : { + "org.graalvm.word" : { "subDir" : "share/classes", "sourceDirs" : ["src"], "dependencies" : [], - "checkstyle" : "org.graalvm.api.word", + "checkstyle" : "org.graalvm.word", "javaCompliance" : "1.8", "workingSets" : "API,SDK", }, @@ -142,8 +142,7 @@ "sourceDirs" : ["src"], "checkstyle" : "org.graalvm.compiler.graph", "uses" : [ - "org.graalvm.compiler.debug.DebugConfigCustomizer", - "org.graalvm.compiler.debug.DebugInitializationParticipant", + "org.graalvm.compiler.debug.DebugHandlersFactory", "org.graalvm.compiler.debug.TTYStreamProvider", ], "dependencies" : [ @@ -792,6 +791,36 @@ "workingSets" : "Graal,Phases", }, + "org.graalvm.compiler.virtual.bench" : { + "subDir" : "share/classes", + "sourceDirs" : ["src"], + "dependencies" : ["mx:JMH_1_18", "org.graalvm.compiler.microbenchmarks"], + "checkstyle" : "org.graalvm.compiler.graph", + "javaCompliance" : "1.8", + "annotationProcessors" : ["mx:JMH_1_18"], + "findbugsIgnoresGenerated" : True, + "workingSets" : "Graal,Bench", + "isTestProject" : True, + }, + + "org.graalvm.compiler.microbenchmarks" : { + "subDir" : "share/classes", + "sourceDirs" : ["src"], + "dependencies" : [ + "mx:JMH_1_18", + "org.graalvm.compiler.api.test", + "org.graalvm.compiler.java", + "org.graalvm.compiler.runtime", + ], + "checkstyle" : "org.graalvm.compiler.graph", + "javaCompliance" : "1.8", + "checkPackagePrefix" : "false", + "annotationProcessors" : ["mx:JMH_1_18"], + "findbugsIgnoresGenerated" : True, + "workingSets" : "Graal,Bench", + "isTestProject" : True, + }, + "org.graalvm.compiler.loop" : { "subDir" : "share/classes", "sourceDirs" : ["src"], @@ -970,7 +999,7 @@ "sourceDirs" : ["src"], "dependencies" : [ "org.graalvm.compiler.debug", - "org.graalvm.api.word", + "org.graalvm.word", ], "annotationProcessors" : ["GRAAL_OPTIONS_PROCESSOR"], "checkstyle" : "org.graalvm.compiler.graph", @@ -998,6 +1027,7 @@ "subDir" : "share/classes", "sourceDirs" : ["src"], "dependencies" : [ + "org.graalvm.compiler.debug", "org.graalvm.util", "mx:JUNIT", ], --- old/src/jdk.internal.vm.compiler/share/classes/module-info.java 2017-07-07 09:29:21.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/module-info.java 2017-07-07 09:29:21.000000000 -0700 @@ -32,8 +32,6 @@ uses org.graalvm.compiler.code.DisassemblerProvider; uses org.graalvm.compiler.core.match.MatchStatementSet; - uses org.graalvm.compiler.debug.DebugConfigCustomizer; - uses org.graalvm.compiler.debug.DebugInitializationParticipant; uses org.graalvm.compiler.debug.TTYStreamProvider; uses org.graalvm.compiler.hotspot.CompilerConfigurationFactory; uses org.graalvm.compiler.hotspot.HotSpotBackendFactory; @@ -51,7 +49,6 @@ exports org.graalvm.compiler.core.common to jdk.aot; exports org.graalvm.compiler.core.target to jdk.aot; exports org.graalvm.compiler.debug to jdk.aot; - exports org.graalvm.compiler.debug.internal to jdk.aot; exports org.graalvm.compiler.graph to jdk.aot; exports org.graalvm.compiler.hotspot to jdk.aot; exports org.graalvm.compiler.hotspot.meta to jdk.aot; @@ -66,6 +63,7 @@ exports org.graalvm.compiler.options to jdk.aot; exports org.graalvm.compiler.phases to jdk.aot; exports org.graalvm.compiler.phases.tiers to jdk.aot; + exports org.graalvm.compiler.printer to jdk.aot; exports org.graalvm.compiler.runtime to jdk.aot; exports org.graalvm.compiler.replacements to jdk.aot; exports org.graalvm.compiler.word to jdk.aot; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/ControlFlowAnchorDirectiveTest.java 2017-07-07 09:29:22.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/ControlFlowAnchorDirectiveTest.java 2017-07-07 09:29:22.000000000 -0700 @@ -220,7 +220,7 @@ @Test public void testClone() { StructuredGraph g = parseEager("preventPeelSnippet", AllowAssumptions.NO); - g.copy(); + g.copy(g.getDebug()); } private static List getNodeCountAnnotations(StructuredGraph graph) { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java 2017-07-07 09:29:22.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java 2017-07-07 09:29:22.000000000 -0700 @@ -22,6 +22,7 @@ */ package org.graalvm.compiler.asm.aarch64; +import static jdk.vm.ci.aarch64.AArch64.cpuRegisters; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ADD; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ADDS; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ADR; @@ -1010,6 +1011,100 @@ loadStoreInstruction(LDRS, rt, address, generalFromSize(targetSize), transferSize); } + public enum PrefetchMode { + PLDL1KEEP(0b00000), + PLDL1STRM(0b00001), + PLDL2KEEP(0b00010), + PLDL2STRM(0b00011), + PLDL3KEEP(0b00100), + PLDL3STRM(0b00101), + + PLIL1KEEP(0b01000), + PLIL1STRM(0b01001), + PLIL2KEEP(0b01010), + PLIL2STRM(0b01011), + PLIL3KEEP(0b01100), + PLIL3STRM(0b01101), + + PSTL1KEEP(0b10000), + PSTL1STRM(0b10001), + PSTL2KEEP(0b10010), + PSTL2STRM(0b10011), + PSTL3KEEP(0b10100), + PSTL3STRM(0b10101); + + private final int encoding; + + PrefetchMode(int encoding) { + this.encoding = encoding; + } + + private static PrefetchMode[] modes = { + PLDL1KEEP, + PLDL1STRM, + PLDL2KEEP, + PLDL2STRM, + PLDL3KEEP, + PLDL3STRM, + + null, + null, + + PLIL1KEEP, + PLIL1STRM, + PLIL2KEEP, + PLIL2STRM, + PLIL3KEEP, + PLIL3STRM, + + null, + null, + + PSTL1KEEP, + PSTL1STRM, + PSTL2KEEP, + PSTL2STRM, + PSTL3KEEP, + PSTL3STRM + }; + + public static PrefetchMode lookup(int enc) { + assert enc >= 00 && enc < modes.length; + return modes[enc]; + } + + public Register toRegister() { + return cpuRegisters.get(encoding); + } + } + + /* + * implements a prefetch at a 64-bit aligned address using a scaled 12 bit or unscaled 9 bit + * displacement addressing mode + * + * @param rt general purpose register. May not be null, zr or stackpointer. + * + * @param address only displacement addressing modes allowed. May not be null. + */ + public void prfm(AArch64Address address, PrefetchMode mode) { + assert (address.getAddressingMode() == AddressingMode.IMMEDIATE_SCALED || + address.getAddressingMode() == AddressingMode.IMMEDIATE_UNSCALED || + address.getAddressingMode() == AddressingMode.REGISTER_OFFSET); + assert mode != null; + final int srcSize = 64; + final int transferSize = NumUtil.log2Ceil(srcSize / 8); + final Register rt = mode.toRegister(); + // this looks weird but that's because loadStoreInstruction is weird + // instruction select fields are size [31:30], v [26] and opc [25:24] + // prfm requires size == 0b11, v == 0b0 and opc == 0b11 + // passing LDRS ensures opc[1] == 0b1 + // (n.b. passing LDR/STR makes no difference to opc[1:0]!!) + // passing General64 ensures opc[0] == 0b1 and v = 0b0 + // (n.b. passing General32 ensures opc[0] == 0b0 and v = 0b0) + // srcSize 64 ensures size == 0b11 + loadStoreInstruction(LDRS, rt, address, General64, transferSize); + } + /** * Stores register rt into memory pointed by address. * --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java 2017-07-07 09:29:23.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java 2017-07-07 09:29:22.000000000 -0700 @@ -146,10 +146,10 @@ return new AddressGenerationPlan(ADD_TO_BASE, REGISTER_OFFSET, needsScratch); } } else { - if (NumUtil.isSignedNbit(9, displacement)) { - return new AddressGenerationPlan(NO_WORK, IMMEDIATE_UNSCALED, false); - } else if (displacementScalable && NumUtil.isUnsignedNbit(12, scaledDisplacement)) { + if (displacementScalable && NumUtil.isUnsignedNbit(12, scaledDisplacement)) { return new AddressGenerationPlan(NO_WORK, IMMEDIATE_SCALED, false); + } else if (NumUtil.isSignedNbit(9, displacement)) { + return new AddressGenerationPlan(NO_WORK, IMMEDIATE_UNSCALED, false); } else { boolean needsScratch = !isArithmeticImmediate(displacement); return new AddressGenerationPlan(ADD_TO_BASE, REGISTER_OFFSET, needsScratch); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.test/src/org/graalvm/compiler/asm/test/AssemblerTest.java 2017-07-07 09:29:23.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.test/src/org/graalvm/compiler/asm/test/AssemblerTest.java 2017-07-07 09:29:23.000000000 -0700 @@ -31,8 +31,7 @@ import org.graalvm.compiler.code.DisassemblerProvider; import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.target.Backend; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.runtime.RuntimeProvider; @@ -83,10 +82,12 @@ @SuppressWarnings("try") protected InstalledCode assembleMethod(Method m, CodeGenTest test) { ResolvedJavaMethod method = getMetaAccess().lookupJavaMethod(m); - try (Scope s = Debug.scope("assembleMethod", method, codeCache)) { + OptionValues options = getInitialOptions(); + DebugContext debug = getDebugContext(options); + try (DebugContext.Scope s = debug.scope("assembleMethod", method, codeCache)) { RegisterConfig registerConfig = codeCache.getRegisterConfig(); CompilationIdentifier compilationId = backend.getCompilationIdentifier(method); - StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions()).method(method).compilationId(compilationId).build(); + StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(method).compilationId(compilationId).build(); CallingConvention cc = backend.newLIRGenerationResult(compilationId, null, null, graph, null).getCallingConvention(); CompilationResult compResult = new CompilationResult(); @@ -95,7 +96,7 @@ compResult.setTotalFrameSize(0); compResult.close(); - InstalledCode code = backend.addInstalledCode(method, asCompilationRequest(compilationId), compResult); + InstalledCode code = backend.addInstalledCode(debug, method, asCompilationRequest(compilationId), compResult); for (DisassemblerProvider dis : GraalServices.load(DisassemblerProvider.class)) { String disasm1 = dis.disassembleCompiledCode(codeCache, compResult); @@ -105,7 +106,7 @@ } return code; } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.bytecode/src/org/graalvm/compiler/bytecode/BytecodeDisassembler.java 2017-07-07 09:29:23.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.bytecode/src/org/graalvm/compiler/bytecode/BytecodeDisassembler.java 2017-07-07 09:29:23.000000000 -0700 @@ -165,7 +165,7 @@ stream.next(); opcode = stream.currentBC(); } - } catch (RuntimeException e) { + } catch (Throwable e) { throw new RuntimeException(String.format("Error disassembling %s%nPartial disassembly:%n%s", method.format("%H.%n(%p)"), buf.toString()), e); } return buf.toString(); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressLowering.java 2017-07-07 09:29:24.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressLowering.java 2017-07-07 09:29:24.000000000 -0700 @@ -28,6 +28,7 @@ import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.amd64.AMD64Address.Scale; import org.graalvm.compiler.core.common.type.IntegerStamp; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.AddNode; import org.graalvm.compiler.nodes.calc.LeftShiftNode; @@ -47,12 +48,15 @@ AMD64AddressNode ret = new AMD64AddressNode(base, offset); boolean changed; do { - changed = improve(ret); + changed = improve(base.getDebug(), ret); } while (changed); return base.graph().unique(ret); } - protected boolean improve(AMD64AddressNode ret) { + /** + * @param debug + */ + protected boolean improve(DebugContext debug, AMD64AddressNode ret) { ValueNode newBase = improveInput(ret, ret.getBase(), 0); if (newBase != ret.getBase()) { ret.setBase(newBase); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressNode.java 2017-07-07 09:29:24.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressNode.java 2017-07-07 09:29:24.000000000 -0700 @@ -26,10 +26,16 @@ import org.graalvm.compiler.asm.amd64.AMD64Address.Scale; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.graph.spi.Simplifiable; +import org.graalvm.compiler.graph.spi.SimplifierTool; import org.graalvm.compiler.lir.amd64.AMD64AddressValue; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.LoopBeginNode; +import org.graalvm.compiler.nodes.PhiNode; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.calc.AddNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -42,7 +48,7 @@ * optional. */ @NodeInfo -public class AMD64AddressNode extends AddressNode implements LIRLowerable { +public class AMD64AddressNode extends AddressNode implements Simplifiable, LIRLowerable { public static final NodeClass TYPE = NodeClass.create(AMD64AddressNode.class); @@ -64,6 +70,28 @@ this.scale = Scale.Times1; } + public void canonicalizeIndex(SimplifierTool tool) { + if (index instanceof AddNode) { + AddNode add = (AddNode) index; + ValueNode valX = add.getX(); + if (valX instanceof PhiNode) { + PhiNode phi = (PhiNode) valX; + if (phi.merge() instanceof LoopBeginNode) { + LoopBeginNode loopNode = (LoopBeginNode) phi.merge(); + if (!loopNode.isSimpleLoop()) { + ValueNode valY = add.getY(); + if (valY instanceof ConstantNode) { + int addBy = valY.asJavaConstant().asInt(); + displacement = displacement + scale.value * addBy; + replaceFirstInput(index, phi); + tool.addToWorkList(index); + } + } + } + } + } + } + @Override public void generate(NodeLIRBuilderTool gen) { LIRGeneratorTool tool = gen.getLIRGeneratorTool(); @@ -135,4 +163,9 @@ public long getMaxConstantDisplacement() { return displacement; } + + @Override + public void simplify(SimplifierTool tool) { + canonicalizeIndex(tool); + } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java 2017-07-07 09:29:25.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java 2017-07-07 09:29:24.000000000 -0700 @@ -36,7 +36,6 @@ import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.SD; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.SS; -import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RRMOp; @@ -44,12 +43,12 @@ import org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize; import org.graalvm.compiler.asm.amd64.AMD64Assembler.SSEOp; import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.core.gen.NodeLIRBuilder; import org.graalvm.compiler.core.gen.NodeMatchRules; import org.graalvm.compiler.core.match.ComplexMatchResult; import org.graalvm.compiler.core.match.MatchRule; -import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.lir.LIRFrameState; import org.graalvm.compiler.lir.LIRValueUtil; @@ -147,7 +146,7 @@ matchedAsConstant = true; } if (kind.isXMM()) { - Debug.log("Skipping constant compares for float kinds"); + ifNode.getDebug().log("Skipping constant compares for float kinds"); return null; } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java 2017-07-07 09:29:25.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java 2017-07-07 09:29:25.000000000 -0700 @@ -24,8 +24,8 @@ import org.graalvm.compiler.debug.Assertions; import org.graalvm.compiler.options.Option; -import org.graalvm.compiler.options.OptionType; import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionType; /** * This class encapsulates options that control the behavior of the Graal compiler. @@ -109,6 +109,9 @@ @Option(help = "", type = OptionType.Debug) public static final OptionKey LoopUnswitch = new OptionKey<>(true); + @Option(help = "", type = OptionType.Debug) + public static final OptionKey PartialUnroll = new OptionKey<>(true); + @Option(help = "", type = OptionType.Expert) public static final OptionKey MinimumPeelProbability = new OptionKey<>(0.35f); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/BiDirectionalTraceBuilder.java 2017-07-07 09:29:25.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/BiDirectionalTraceBuilder.java 2017-07-07 09:29:25.000000000 -0700 @@ -31,7 +31,7 @@ import org.graalvm.compiler.core.common.alloc.TraceBuilderResult.TrivialTracePredicate; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; /** @@ -40,8 +40,8 @@ */ public final class BiDirectionalTraceBuilder { - public static TraceBuilderResult computeTraces(AbstractBlockBase startBlock, AbstractBlockBase[] blocks, TrivialTracePredicate pred) { - return new BiDirectionalTraceBuilder(blocks).build(startBlock, blocks, pred); + public static TraceBuilderResult computeTraces(DebugContext debug, AbstractBlockBase startBlock, AbstractBlockBase[] blocks, TrivialTracePredicate pred) { + return new BiDirectionalTraceBuilder(blocks).build(debug, startBlock, blocks, pred); } private final Deque> worklist; @@ -69,22 +69,22 @@ } @SuppressWarnings("try") - private TraceBuilderResult build(AbstractBlockBase startBlock, AbstractBlockBase[] blocks, TrivialTracePredicate pred) { - try (Indent indent = Debug.logAndIndent("BiDirectionalTraceBuilder: start trace building")) { - ArrayList traces = buildTraces(); + private TraceBuilderResult build(DebugContext debug, AbstractBlockBase startBlock, AbstractBlockBase[] blocks, TrivialTracePredicate pred) { + try (Indent indent = debug.logAndIndent("BiDirectionalTraceBuilder: start trace building")) { + ArrayList traces = buildTraces(debug); assert traces.get(0).getBlocks()[0].equals(startBlock) : "The first traces always contains the start block"; - return TraceBuilderResult.create(blocks, traces, blockToTrace, pred); + return TraceBuilderResult.create(debug, blocks, traces, blockToTrace, pred); } } - protected ArrayList buildTraces() { + protected ArrayList buildTraces(DebugContext debug) { ArrayList traces = new ArrayList<>(); // process worklist while (!worklist.isEmpty()) { AbstractBlockBase block = worklist.pollFirst(); assert block != null; if (!processed(block)) { - Trace trace = new Trace(startTrace(block)); + Trace trace = new Trace(startTrace(debug, block)); for (AbstractBlockBase traceBlock : trace.getBlocks()) { blockToTrace[traceBlock.getId()] = trace; } @@ -97,14 +97,16 @@ /** * Build a new trace starting at {@code block}. + * + * @param debug */ @SuppressWarnings("try") - private Collection> startTrace(AbstractBlockBase block) { + private Collection> startTrace(DebugContext debug, AbstractBlockBase block) { ArrayDeque> trace = new ArrayDeque<>(); - try (Indent i = Debug.logAndIndent("StartTrace: %s", block)) { - try (Indent indentFront = Debug.logAndIndent("Head:")) { + try (Indent i = debug.logAndIndent("StartTrace: %s", block)) { + try (Indent indentFront = debug.logAndIndent("Head:")) { for (AbstractBlockBase currentBlock = block; currentBlock != null; currentBlock = selectPredecessor(currentBlock)) { - addBlockToTrace(currentBlock); + addBlockToTrace(debug, currentBlock); trace.addFirst(currentBlock); } } @@ -114,21 +116,21 @@ b.setLinearScanNumber(blockNr++); } - try (Indent indentBack = Debug.logAndIndent("Tail:")) { + try (Indent indentBack = debug.logAndIndent("Tail:")) { for (AbstractBlockBase currentBlock = selectSuccessor(block); currentBlock != null; currentBlock = selectSuccessor(currentBlock)) { - addBlockToTrace(currentBlock); + addBlockToTrace(debug, currentBlock); trace.addLast(currentBlock); /* This time we can number the blocks immediately as we go forwards. */ currentBlock.setLinearScanNumber(blockNr++); } } } - Debug.log("Trace: %s", trace); + debug.log("Trace: %s", trace); return trace; } - private void addBlockToTrace(AbstractBlockBase currentBlock) { - Debug.log("add %s (prob: %f)", currentBlock, currentBlock.probability()); + private void addBlockToTrace(DebugContext debug, AbstractBlockBase currentBlock) { + debug.log("add %s (prob: %f)", currentBlock, currentBlock.probability()); processed.set(currentBlock.getId()); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/SingleBlockTraceBuilder.java 2017-07-07 09:29:26.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/SingleBlockTraceBuilder.java 2017-07-07 09:29:26.000000000 -0700 @@ -26,17 +26,18 @@ import org.graalvm.compiler.core.common.alloc.TraceBuilderResult.TrivialTracePredicate; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.debug.DebugContext; /** * Builds traces consisting of a single basic block. */ public final class SingleBlockTraceBuilder { - public static TraceBuilderResult computeTraces(AbstractBlockBase startBlock, AbstractBlockBase[] blocks, TrivialTracePredicate pred) { - return build(startBlock, blocks, pred); + public static TraceBuilderResult computeTraces(DebugContext debug, AbstractBlockBase startBlock, AbstractBlockBase[] blocks, TrivialTracePredicate pred) { + return build(debug, startBlock, blocks, pred); } - private static TraceBuilderResult build(AbstractBlockBase startBlock, AbstractBlockBase[] blocks, TrivialTracePredicate pred) { + private static TraceBuilderResult build(DebugContext debug, AbstractBlockBase startBlock, AbstractBlockBase[] blocks, TrivialTracePredicate pred) { Trace[] blockToTrace = new Trace[blocks.length]; ArrayList traces = new ArrayList<>(blocks.length); @@ -49,7 +50,7 @@ } assert traces.get(0).getBlocks()[0].equals(startBlock) : "The first traces always contains the start block"; - return TraceBuilderResult.create(blocks, traces, blockToTrace, pred); + return TraceBuilderResult.create(debug, blocks, traces, blockToTrace, pred); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/TraceBuilderResult.java 2017-07-07 09:29:26.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/TraceBuilderResult.java 2017-07-07 09:29:26.000000000 -0700 @@ -27,7 +27,7 @@ import java.util.BitSet; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; public final class TraceBuilderResult { @@ -39,9 +39,9 @@ private final ArrayList traces; private final Trace[] blockToTrace; - static TraceBuilderResult create(AbstractBlockBase[] blocks, ArrayList traces, Trace[] blockToTrace, TrivialTracePredicate pred) { + static TraceBuilderResult create(DebugContext debug, AbstractBlockBase[] blocks, ArrayList traces, Trace[] blockToTrace, TrivialTracePredicate pred) { connect(traces, blockToTrace); - ArrayList newTraces = reorderTraces(traces, pred); + ArrayList newTraces = reorderTraces(debug, traces, pred); TraceBuilderResult traceBuilderResult = new TraceBuilderResult(newTraces, blockToTrace); traceBuilderResult.numberTraces(); assert verify(traceBuilderResult, blocks.length); @@ -157,11 +157,11 @@ } @SuppressWarnings("try") - private static ArrayList reorderTraces(ArrayList oldTraces, TrivialTracePredicate pred) { + private static ArrayList reorderTraces(DebugContext debug, ArrayList oldTraces, TrivialTracePredicate pred) { if (pred == null) { return oldTraces; } - try (Indent indent = Debug.logAndIndent("ReorderTrace")) { + try (Indent indent = debug.logAndIndent("ReorderTrace")) { ArrayList newTraces = new ArrayList<>(oldTraces.size()); for (int oldTraceIdx = 0; oldTraceIdx < oldTraces.size(); oldTraceIdx++) { Trace currentTrace = oldTraces.get(oldTraceIdx); @@ -171,7 +171,7 @@ addTrace(newTraces, currentTrace); for (Trace succTrace : currentTrace.getSuccessors()) { if (pred.isTrivialTrace(succTrace) && !alreadyProcessed(newTraces, succTrace)) { - Debug.log("Moving trivial trace from %d to %d", succTrace.getId(), newTraces.size()); + debug.log("Moving trivial trace from %d to %d", succTrace.getId(), newTraces.size()); // add trivial successor trace addTrace(newTraces, succTrace); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/TraceStatisticsPrinter.java 2017-07-07 09:29:27.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/TraceStatisticsPrinter.java 2017-07-07 09:29:26.000000000 -0700 @@ -25,33 +25,32 @@ import java.util.List; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; public final class TraceStatisticsPrinter { private static final String SEP = ";"; @SuppressWarnings("try") - public static void printTraceStatistics(TraceBuilderResult result, String compilationUnitName) { - try (Scope s = Debug.scope("DumpTraceStatistics")) { - if (Debug.isLogEnabled(Debug.VERBOSE_LEVEL)) { - print(result, compilationUnitName); + public static void printTraceStatistics(DebugContext debug, TraceBuilderResult result, String compilationUnitName) { + try (DebugContext.Scope s = debug.scope("DumpTraceStatistics")) { + if (debug.isLogEnabled(DebugContext.VERBOSE_LEVEL)) { + print(debug, result, compilationUnitName); } } catch (Throwable e) { - Debug.handle(e); + debug.handle(e); } } @SuppressWarnings("try") - protected static void print(TraceBuilderResult result, String compilationUnitName) { + protected static void print(DebugContext debug, TraceBuilderResult result, String compilationUnitName) { List traces = result.getTraces(); int numTraces = traces.size(); - try (Indent indent0 = Debug.logAndIndent(Debug.VERBOSE_LEVEL, "")) { - Debug.log(Debug.VERBOSE_LEVEL, "%s", compilationUnitName != null ? compilationUnitName : "null"); - try (Indent indent1 = Debug.logAndIndent(Debug.VERBOSE_LEVEL, "")) { - printRawLine("tracenumber", "total", "min", "max", "numBlocks"); + try (Indent indent0 = debug.logAndIndent(DebugContext.VERBOSE_LEVEL, "")) { + debug.log(DebugContext.VERBOSE_LEVEL, "%s", compilationUnitName != null ? compilationUnitName : "null"); + try (Indent indent1 = debug.logAndIndent(DebugContext.VERBOSE_LEVEL, "")) { + printRawLine(debug, "tracenumber", "total", "min", "max", "numBlocks"); for (int i = 0; i < numTraces; i++) { AbstractBlockBase[] t = traces.get(i).getBlocks(); double total = 0; @@ -67,20 +66,20 @@ max = probability; } } - printLine(i, total, min, max, t.length); + printLine(debug, i, total, min, max, t.length); } } - Debug.log(Debug.VERBOSE_LEVEL, ""); + debug.log(DebugContext.VERBOSE_LEVEL, ""); } - Debug.log(Debug.VERBOSE_LEVEL, ""); + debug.log(DebugContext.VERBOSE_LEVEL, ""); } - private static void printRawLine(Object tracenr, Object totalTime, Object minProb, Object maxProb, Object numBlocks) { - Debug.log(Debug.VERBOSE_LEVEL, "%s", String.join(SEP, tracenr.toString(), totalTime.toString(), minProb.toString(), maxProb.toString(), numBlocks.toString())); + private static void printRawLine(DebugContext debug, Object tracenr, Object totalTime, Object minProb, Object maxProb, Object numBlocks) { + debug.log(DebugContext.VERBOSE_LEVEL, "%s", String.join(SEP, tracenr.toString(), totalTime.toString(), minProb.toString(), maxProb.toString(), numBlocks.toString())); } - private static void printLine(int tracenr, double totalTime, double minProb, double maxProb, int numBlocks) { - printRawLine(tracenr, totalTime, minProb, maxProb, numBlocks); + private static void printLine(DebugContext debug, int tracenr, double totalTime, double minProb, double maxProb, int numBlocks) { + printRawLine(debug, tracenr, totalTime, minProb, maxProb, numBlocks); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/UniDirectionalTraceBuilder.java 2017-07-07 09:29:27.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/UniDirectionalTraceBuilder.java 2017-07-07 09:29:27.000000000 -0700 @@ -29,7 +29,7 @@ import org.graalvm.compiler.core.common.alloc.TraceBuilderResult.TrivialTracePredicate; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; /** @@ -37,8 +37,8 @@ */ public final class UniDirectionalTraceBuilder { - public static TraceBuilderResult computeTraces(AbstractBlockBase startBlock, AbstractBlockBase[] blocks, TrivialTracePredicate pred) { - return new UniDirectionalTraceBuilder(blocks).build(startBlock, blocks, pred); + public static TraceBuilderResult computeTraces(DebugContext debug, AbstractBlockBase startBlock, AbstractBlockBase[] blocks, TrivialTracePredicate pred) { + return new UniDirectionalTraceBuilder(blocks).build(debug, startBlock, blocks, pred); } private final PriorityQueue> worklist; @@ -71,14 +71,14 @@ } @SuppressWarnings("try") - private TraceBuilderResult build(AbstractBlockBase startBlock, AbstractBlockBase[] blocks, TrivialTracePredicate pred) { - try (Indent indent = Debug.logAndIndent("UniDirectionalTraceBuilder: start trace building: %s", startBlock)) { - ArrayList traces = buildTraces(startBlock); - return TraceBuilderResult.create(blocks, traces, blockToTrace, pred); + private TraceBuilderResult build(DebugContext debug, AbstractBlockBase startBlock, AbstractBlockBase[] blocks, TrivialTracePredicate pred) { + try (Indent indent = debug.logAndIndent("UniDirectionalTraceBuilder: start trace building: %s", startBlock)) { + ArrayList traces = buildTraces(debug, startBlock); + return TraceBuilderResult.create(debug, blocks, traces, blockToTrace, pred); } } - protected ArrayList buildTraces(AbstractBlockBase startBlock) { + protected ArrayList buildTraces(DebugContext debug, AbstractBlockBase startBlock) { ArrayList traces = new ArrayList<>(); // add start block worklist.add(startBlock); @@ -87,7 +87,7 @@ AbstractBlockBase block = worklist.poll(); assert block != null; if (!processed(block)) { - Trace trace = new Trace(startTrace(block)); + Trace trace = new Trace(startTrace(debug, block)); for (AbstractBlockBase traceBlock : trace.getBlocks()) { blockToTrace[traceBlock.getId()] = trace; } @@ -102,13 +102,13 @@ * Build a new trace starting at {@code block}. */ @SuppressWarnings("try") - private List> startTrace(AbstractBlockBase block) { + private List> startTrace(DebugContext debug, AbstractBlockBase block) { assert checkPredecessorsProcessed(block); ArrayList> trace = new ArrayList<>(); int blockNumber = 0; - try (Indent i = Debug.logAndIndent("StartTrace: %s", block)) { + try (Indent i = debug.logAndIndent("StartTrace: %s", block)) { for (AbstractBlockBase currentBlock = block; currentBlock != null; currentBlock = selectNext(currentBlock)) { - Debug.log("add %s (prob: %f)", currentBlock, currentBlock.probability()); + debug.log("add %s (prob: %f)", currentBlock, currentBlock.probability()); processed.set(currentBlock.getId()); trace.add(currentBlock); unblock(currentBlock); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/Loop.java 2017-07-07 09:29:27.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/Loop.java 2017-07-07 09:29:27.000000000 -0700 @@ -87,6 +87,10 @@ return exits; } + public void addExit(T t) { + exits.add(t); + } + /** * Determines if one loop is a transitive parent of another loop. * --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java 2017-07-07 09:29:28.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java 2017-07-07 09:29:28.000000000 -0700 @@ -22,8 +22,6 @@ */ package org.graalvm.compiler.core.test; -import static org.graalvm.compiler.debug.DelegatingDebugConfig.Feature.INTERCEPT; - import java.io.File; import java.io.IOException; import java.io.PrintWriter; @@ -48,14 +46,11 @@ import org.graalvm.compiler.api.test.Graal; import org.graalvm.compiler.bytecode.BridgeMethodUtils; import org.graalvm.compiler.core.CompilerThreadFactory; -import org.graalvm.compiler.core.CompilerThreadFactory.DebugConfigAccess; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.type.ArithmeticOpTable; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugConfigScope; -import org.graalvm.compiler.debug.DebugEnvironment; -import org.graalvm.compiler.debug.DelegatingDebugConfig; -import org.graalvm.compiler.debug.GraalDebugConfig; +import org.graalvm.compiler.debug.DebugCloseable; +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; @@ -203,12 +198,7 @@ String[] filters = property == null ? null : property.split(","); OptionValues options = getInitialOptions(); - CompilerThreadFactory factory = new CompilerThreadFactory("CheckInvariantsThread", new DebugConfigAccess() { - @Override - public GraalDebugConfig getDebugConfig() { - return DebugEnvironment.ensureInitialized(options); - } - }); + CompilerThreadFactory factory = new CompilerThreadFactory("CheckInvariantsThread"); int availableProcessors = Runtime.getRuntime().availableProcessors(); ThreadPoolExecutor executor = new ThreadPoolExecutor(availableProcessors, availableProcessors, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), factory); @@ -216,17 +206,19 @@ for (Method m : BadUsageWithEquals.class.getDeclaredMethods()) { ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m); - StructuredGraph graph = new StructuredGraph.Builder(options, AllowAssumptions.YES).method(method).build(); - try (DebugConfigScope s = Debug.setConfig(new DelegatingDebugConfig().disable(INTERCEPT)); Debug.Scope ds = Debug.scope("CheckingGraph", graph, method)) { - graphBuilderSuite.apply(graph, context); - // update phi stamps - graph.getNodes().filter(PhiNode.class).forEach(PhiNode::inferStamp); - checkGraph(context, graph); - errors.add(String.format("Expected error while checking %s", m)); - } catch (VerificationError e) { - // expected! - } catch (Throwable e) { - errors.add(String.format("Error while checking %s:%n%s", m, printStackTraceToString(e))); + try (DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER)) { + StructuredGraph graph = new StructuredGraph.Builder(options, debug, AllowAssumptions.YES).method(method).build(); + try (DebugCloseable s = debug.disableIntercept(); DebugContext.Scope ds = debug.scope("CheckingGraph", graph, method)) { + graphBuilderSuite.apply(graph, context); + // update phi stamps + graph.getNodes().filter(PhiNode.class).forEach(PhiNode::inferStamp); + checkGraph(context, graph); + errors.add(String.format("Expected error while checking %s", m)); + } catch (VerificationError e) { + // expected! + } catch (Throwable e) { + errors.add(String.format("Error while checking %s:%n%s", m, printStackTraceToString(e))); + } } } if (errors.isEmpty()) { @@ -251,26 +243,29 @@ String methodName = className + "." + m.getName(); if (matches(filters, methodName)) { executor.execute(() -> { - ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m); - StructuredGraph graph = new StructuredGraph.Builder(options).method(method).build(); - try (DebugConfigScope s = Debug.setConfig(new DelegatingDebugConfig().disable(INTERCEPT)); Debug.Scope ds = Debug.scope("CheckingGraph", graph, method)) { - checkMethod(method); - graphBuilderSuite.apply(graph, context); - // update phi stamps - graph.getNodes().filter(PhiNode.class).forEach(PhiNode::inferStamp); - checkGraph(context, graph); - } catch (VerificationError e) { - errors.add(e.getMessage()); - } catch (LinkageError e) { - // suppress linkages errors resulting from eager resolution - } catch (BailoutException e) { - // Graal bail outs on certain patterns in Java bytecode (e.g., - // unbalanced monitors introduced by jacoco). - } catch (Throwable e) { - try { - tool.handleParsingException(e); - } catch (Throwable t) { - errors.add(String.format("Error while checking %s:%n%s", methodName, printStackTraceToString(e))); + try (DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER)) { + ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m); + StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(method).build(); + try (DebugCloseable s = debug.disableIntercept(); DebugContext.Scope ds = debug.scope("CheckingGraph", graph, method)) { + checkMethod(method); + graphBuilderSuite.apply(graph, context); + // update phi stamps + graph.getNodes().filter(PhiNode.class).forEach(PhiNode::inferStamp); + checkGraph(context, graph); + } catch (VerificationError e) { + errors.add(e.getMessage()); + } catch (LinkageError e) { + // suppress linkages errors resulting from eager resolution + } catch (BailoutException e) { + // Graal bail outs on certain patterns in Java bytecode + // (e.g., + // unbalanced monitors introduced by jacoco). + } catch (Throwable e) { + try { + tool.handleParsingException(e); + } catch (Throwable t) { + errors.add(String.format("Error while checking %s:%n%s", methodName, printStackTraceToString(e))); + } } } }); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest13.java 2017-07-07 09:29:28.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest13.java 2017-07-07 09:29:28.000000000 -0700 @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.core.test; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; @@ -310,7 +310,8 @@ super.prepareGraph(graph, canonicalizer, context, applyLowering); graph.clearAllStateAfter(); graph.setGuardsStage(StructuredGraph.GuardsStage.AFTER_FSA); - Debug.dump(Debug.BASIC_LEVEL, graph, "After preparation"); + DebugContext debug = graph.getDebug(); + debug.dump(DebugContext.BASIC_LEVEL, graph, "After preparation"); canonicalizer.apply(graph, context); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java 2017-07-07 09:29:28.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java 2017-07-07 09:29:28.000000000 -0700 @@ -22,16 +22,16 @@ */ package org.graalvm.compiler.core.test; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.ProxyNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.phases.common.CanonicalizerPhase; +import org.graalvm.compiler.phases.common.ConditionalEliminationPhase; import org.graalvm.compiler.phases.common.ConvertDeoptimizeToGuardPhase; import org.graalvm.compiler.phases.common.IterativeConditionalEliminationPhase; import org.graalvm.compiler.phases.common.LoweringPhase; -import org.graalvm.compiler.phases.common.ConditionalEliminationPhase; import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.graalvm.compiler.phases.tiers.PhaseContext; import org.junit.Assert; @@ -52,21 +52,22 @@ @SuppressWarnings("try") protected void testConditionalElimination(String snippet, String referenceSnippet, boolean applyConditionalEliminationOnReference, boolean applyLowering) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); - Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); + DebugContext debug = graph.getDebug(); + debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); PhaseContext context = new PhaseContext(getProviders()); CanonicalizerPhase canonicalizer1 = new CanonicalizerPhase(); CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); - try (Debug.Scope scope = Debug.scope("ConditionalEliminationTest", graph)) { + try (DebugContext.Scope scope = debug.scope("ConditionalEliminationTest", graph)) { prepareGraph(graph, canonicalizer1, context, applyLowering); new IterativeConditionalEliminationPhase(canonicalizer, true).apply(graph, context); canonicalizer.apply(graph, context); canonicalizer.apply(graph, context); new ConvertDeoptimizeToGuardPhase().apply(graph, context); } catch (Throwable t) { - Debug.handle(t); + debug.handle(t); } StructuredGraph referenceGraph = parseEager(referenceSnippet, AllowAssumptions.YES); - try (Debug.Scope scope = Debug.scope("ConditionalEliminationTest.ReferenceGraph", referenceGraph)) { + try (DebugContext.Scope scope = debug.scope("ConditionalEliminationTest.ReferenceGraph", referenceGraph)) { prepareGraph(referenceGraph, canonicalizer, context, applyLowering); if (applyConditionalEliminationOnReference) { new ConditionalEliminationPhase(true).apply(referenceGraph, context); @@ -75,7 +76,7 @@ canonicalizer.apply(referenceGraph, context); new ConvertDeoptimizeToGuardPhase().apply(graph, context); } catch (Throwable t) { - Debug.handle(t); + debug.handle(t); } assertEquals(referenceGraph, graph); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DegeneratedLoopsTest.java 2017-07-07 09:29:29.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DegeneratedLoopsTest.java 2017-07-07 09:29:29.000000000 -0700 @@ -22,16 +22,14 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugDumpScope; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.inlining.InliningPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; +import org.junit.Test; /** * In the following tests, the usages of local variable "a" are replaced with the integer constant @@ -81,17 +79,18 @@ @SuppressWarnings("try") private void test(final String snippet) { - try (Scope s = Debug.scope("DegeneratedLoopsTest", new DebugDumpScope(snippet))) { + DebugContext debug = getDebugContext(); + try (DebugContext.Scope s = debug.scope("DegeneratedLoopsTest", new DebugDumpScope(snippet))) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); HighTierContext context = getDefaultHighTierContext(); new InliningPhase(new CanonicalizerPhase()).apply(graph, context); new CanonicalizerPhase().apply(graph, context); - Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); + debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET, AllowAssumptions.YES); - Debug.dump(Debug.BASIC_LEVEL, referenceGraph, "ReferenceGraph"); + debug.dump(DebugContext.BASIC_LEVEL, referenceGraph, "ReferenceGraph"); assertEquals(referenceGraph, graph); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DontReuseArgumentSpaceTest.java 2017-07-07 09:29:29.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DontReuseArgumentSpaceTest.java 2017-07-07 09:29:29.000000000 -0700 @@ -28,6 +28,7 @@ import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.phases.HighTier; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.options.OptionValues; @@ -72,7 +73,8 @@ ResolvedJavaMethod javaMethod = getResolvedJavaMethod("killArguments"); StructuredGraph graph = parseEager(javaMethod, AllowAssumptions.YES); CompilationResult compilationResult = compile(javaMethod, graph); - getBackend().createDefaultInstalledCode(javaMethod, compilationResult); + DebugContext debug = getDebugContext(); + getBackend().createDefaultInstalledCode(debug, javaMethod, compilationResult); test("callTwice", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FinalizableSubclassTest.java 2017-07-07 09:29:30.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FinalizableSubclassTest.java 2017-07-07 09:29:30.000000000 -0700 @@ -28,25 +28,25 @@ import java.lang.reflect.Constructor; import java.util.HashMap; -import jdk.vm.ci.meta.Assumptions; -import jdk.vm.ci.meta.Assumptions.Assumption; -import jdk.vm.ci.meta.Assumptions.LeafType; -import jdk.vm.ci.meta.Assumptions.NoFinalizableSubclass; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -import org.junit.Assert; -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.java.GraphBuilderPhase; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.java.RegisterFinalizerNode; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.inlining.InliningPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; +import org.junit.Assert; +import org.junit.Test; + +import jdk.vm.ci.meta.Assumptions; +import jdk.vm.ci.meta.Assumptions.Assumption; +import jdk.vm.ci.meta.Assumptions.LeafType; +import jdk.vm.ci.meta.Assumptions.NoFinalizableSubclass; +import jdk.vm.ci.meta.ResolvedJavaMethod; public class FinalizableSubclassTest extends GraalCompilerTest { @@ -71,7 +71,8 @@ Constructor[] constructors = cl.getConstructors(); Assert.assertTrue(constructors.length == 1); final ResolvedJavaMethod javaMethod = getMetaAccess().lookupJavaMethod(constructors[0]); - StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions(), allowAssumptions).method(javaMethod).build(); + OptionValues options = getInitialOptions(); + StructuredGraph graph = new StructuredGraph.Builder(options, getDebugContext(options), allowAssumptions).method(javaMethod).build(); GraphBuilderConfiguration conf = GraphBuilderConfiguration.getSnippetDefault(getDefaultGraphBuilderPlugins()); new GraphBuilderPhase.Instance(getMetaAccess(), getProviders().getStampProvider(), getProviders().getConstantReflection(), getProviders().getConstantFieldProvider(), conf, @@ -107,8 +108,9 @@ */ @Test public void test1() throws ClassNotFoundException { + DebugContext debug = getDebugContext(); for (int i = 0; i < 2; i++) { - ClassTemplateLoader loader = new ClassTemplateLoader(); + ClassTemplateLoader loader = new ClassTemplateLoader(debug); checkForRegisterFinalizeNode(loader.findClass("NoFinalizerEverAAAA"), true, AllowAssumptions.NO); checkForRegisterFinalizeNode(loader.findClass("NoFinalizerEverAAAA"), false, AllowAssumptions.YES); @@ -126,8 +128,11 @@ private final String replaceTo; private HashMap> cache = new HashMap<>(); - ClassTemplateLoader() { + private final DebugContext debug; + + ClassTemplateLoader(DebugContext debug) { loaderInstance++; + this.debug = debug; replaceTo = String.format("%04d", loaderInstance); } @@ -155,14 +160,15 @@ } catch (IOException e) { Assert.fail("can't access class: " + name); } - dumpStringsInByteArray(classData); + + dumpStringsInByteArray(debug, classData); // replace all occurrences of "AAAA" in classfile int index = -1; while ((index = indexOfAAAA(classData, index + 1)) != -1) { replaceAAAA(classData, index, replaceTo); } - dumpStringsInByteArray(classData); + dumpStringsInByteArray(debug, classData); Class c = defineClass(null, classData, 0, classData.length); cache.put(nameReplaced, c); @@ -192,14 +198,14 @@ } } - private static void dumpStringsInByteArray(byte[] b) { + private static void dumpStringsInByteArray(DebugContext debug, byte[] b) { boolean wasChar = true; StringBuilder sb = new StringBuilder(); for (Byte x : b) { // check for [a-zA-Z0-9] if ((x >= 0x41 && x <= 0x7a) || (x >= 0x30 && x <= 0x39)) { if (!wasChar) { - Debug.log(sb + ""); + debug.log(sb + ""); sb.setLength(0); } sb.append(String.format("%c", x)); @@ -208,7 +214,7 @@ wasChar = false; } } - Debug.log(sb + ""); + debug.log(sb + ""); } } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FindUniqueDefaultMethodTest.java 2017-07-07 09:29:30.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FindUniqueDefaultMethodTest.java 2017-07-07 09:29:30.000000000 -0700 @@ -22,18 +22,16 @@ */ package org.graalvm.compiler.core.test; -import jdk.vm.ci.meta.Assumptions.AssumptionResult; -import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaType; - -import org.junit.Ignore; -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.junit.Ignore; +import org.junit.Test; + +import jdk.vm.ci.meta.Assumptions.AssumptionResult; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; /** * This test illustrates problems and limitations with class hierarchy analysis when default methods @@ -139,13 +137,14 @@ @SuppressWarnings("try") protected StructuredGraph buildGraph(final String snippet) { - try (Scope s = Debug.scope("InstanceOfTest", getMetaAccess().lookupJavaMethod(getMethod(snippet)))) { - StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); + DebugContext debug = getDebugContext(); + try (DebugContext.Scope s = debug.scope("InstanceOfTest", getMetaAccess().lookupJavaMethod(getMethod(snippet)))) { + StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES, debug); compile(graph.method(), graph); - Debug.dump(Debug.BASIC_LEVEL, graph, snippet); + debug.dump(DebugContext.BASIC_LEVEL, graph, snippet); return graph; } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FloatingReadTest.java 2017-07-07 09:29:30.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FloatingReadTest.java 2017-07-07 09:29:30.000000000 -0700 @@ -22,11 +22,7 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Assert; -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugDumpScope; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.ReturnNode; @@ -39,6 +35,8 @@ import org.graalvm.compiler.phases.common.FloatingReadPhase; import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Assert; +import org.junit.Test; public class FloatingReadTest extends GraphScheduleTest { @@ -63,7 +61,8 @@ @SuppressWarnings("try") private void test(final String snippet) { - try (Scope s = Debug.scope("FloatingReadTest", new DebugDumpScope(snippet))) { + DebugContext debug = getDebugContext(); + try (DebugContext.Scope s = debug.scope("FloatingReadTest", new DebugDumpScope(snippet))) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); PhaseContext context = new PhaseContext(getProviders()); @@ -82,7 +81,7 @@ } } - Debug.dump(Debug.BASIC_LEVEL, graph, "After lowering"); + debug.dump(DebugContext.BASIC_LEVEL, graph, "After lowering"); Assert.assertNotNull(returnNode); Assert.assertNotNull(monitorexit); @@ -92,7 +91,7 @@ assertOrderedAfterSchedule(graph, read, (Node) monitorexit); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerAssumptionsTest.java 2017-07-07 09:29:31.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerAssumptionsTest.java 2017-07-07 09:29:31.000000000 -0700 @@ -65,7 +65,7 @@ checkGraph(expectedAssumption, graph); CompilationResult compilationResult = compile(javaMethod, graph); - final InstalledCode installedCode = getBackend().createDefaultInstalledCode(javaMethod, compilationResult); + final InstalledCode installedCode = getBackend().createDefaultInstalledCode(graph.getDebug(), javaMethod, compilationResult); assertTrue(installedCode.isValid()); if (classToLoad != null) { String fullName = getClass().getName() + "$" + classToLoad; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java 2017-07-07 09:29:31.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java 2017-07-07 09:29:31.000000000 -0700 @@ -37,6 +37,7 @@ import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.EnumMap; import java.util.HashMap; @@ -55,10 +56,10 @@ import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.target.Backend; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DebugDumpHandler; import org.graalvm.compiler.debug.DebugDumpScope; -import org.graalvm.compiler.debug.DebugEnvironment; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.graph.Node; @@ -85,6 +86,7 @@ import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.nodes.StructuredGraph.Builder; import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.cfg.Block; @@ -111,13 +113,13 @@ import org.graalvm.compiler.phases.tiers.Suites; import org.graalvm.compiler.phases.tiers.TargetProvider; import org.graalvm.compiler.phases.util.Providers; +import org.graalvm.compiler.printer.GraalDebugHandlersFactory; import org.graalvm.compiler.runtime.RuntimeProvider; import org.graalvm.compiler.test.AddExports; import org.graalvm.compiler.test.GraalTest; import org.graalvm.compiler.test.JLModule; import org.junit.After; import org.junit.Assert; -import org.junit.Before; import org.junit.Test; import org.junit.internal.AssumptionViolatedException; @@ -364,14 +366,7 @@ this.providers = backend.getProviders(); } - private Scope debugScope; - - @Before - public void beforeTest() { - assert debugScope == null; - debugScope = Debug.scope(getClass()); - } - + @Override @After public void afterTest() { if (invocationPluginExtensions != null) { @@ -383,10 +378,21 @@ } } } - if (debugScope != null) { - debugScope.close(); - } - debugScope = null; + super.afterTest(); + } + + /** + * Gets a {@link DebugContext} object corresponding to {@code options}, creating a new one if + * none currently exists. Debug contexts created by this method will have their + * {@link DebugDumpHandler}s closed in {@link #afterTest()}. + */ + protected DebugContext getDebugContext() { + return getDebugContext(getInitialOptions()); + } + + @Override + protected Collection getDebugHandlersFactories() { + return Collections.singletonList(new GraalDebugHandlersFactory(getSnippetReflection())); } protected void assertEquals(StructuredGraph expected, StructuredGraph graph) { @@ -413,13 +419,13 @@ String mismatchString = compareGraphStrings(expected, expectedString, graph, actualString); if (!excludeVirtual && getNodeCountExcludingUnusedConstants(expected) != getNodeCountExcludingUnusedConstants(graph)) { - Debug.dump(Debug.BASIC_LEVEL, expected, "Node count not matching - expected"); - Debug.dump(Debug.BASIC_LEVEL, graph, "Node count not matching - actual"); + expected.getDebug().dump(DebugContext.BASIC_LEVEL, expected, "Node count not matching - expected"); + graph.getDebug().dump(DebugContext.BASIC_LEVEL, graph, "Node count not matching - actual"); Assert.fail("Graphs do not have the same number of nodes: " + expected.getNodeCount() + " vs. " + graph.getNodeCount() + "\n" + mismatchString); } if (!expectedString.equals(actualString)) { - Debug.dump(Debug.BASIC_LEVEL, expected, "mismatching graphs - expected"); - Debug.dump(Debug.BASIC_LEVEL, graph, "mismatching graphs - actual"); + expected.getDebug().dump(DebugContext.BASIC_LEVEL, expected, "mismatching graphs - expected"); + graph.getDebug().dump(DebugContext.BASIC_LEVEL, graph, "mismatching graphs - actual"); Assert.fail(mismatchString); } } @@ -932,24 +938,27 @@ final CompilationIdentifier id = getOrCreateCompilationId(installedCodeOwner, graph); InstalledCode installedCode = null; - try (AllocSpy spy = AllocSpy.open(installedCodeOwner); Scope ds = Debug.scope("Compiling", new DebugDumpScope(id.toString(CompilationIdentifier.Verbosity.ID), true))) { + StructuredGraph graphToCompile = graph == null ? parseForCompile(installedCodeOwner, id, options) : graph; + DebugContext debug = graphToCompile.getDebug(); + try (AllocSpy spy = AllocSpy.open(installedCodeOwner); DebugContext.Scope ds = debug.scope("Compiling", new DebugDumpScope(id.toString(CompilationIdentifier.Verbosity.ID), true))) { final boolean printCompilation = PrintCompilation.getValue(options) && !TTY.isSuppressed(); if (printCompilation) { TTY.println(String.format("@%-6s Graal %-70s %-45s %-50s ...", id, installedCodeOwner.getDeclaringClass().getName(), installedCodeOwner.getName(), installedCodeOwner.getSignature())); } long start = System.currentTimeMillis(); - CompilationResult compResult = compile(installedCodeOwner, graph, new CompilationResult(), id, options); + CompilationResult compResult = compile(installedCodeOwner, graphToCompile, new CompilationResult(), id, options); if (printCompilation) { TTY.println(String.format("@%-6s Graal %-70s %-45s %-50s | %4dms %5dB", id, "", "", "", System.currentTimeMillis() - start, compResult.getTargetCodeSize())); } - try (Scope s = Debug.scope("CodeInstall", getCodeCache(), installedCodeOwner, compResult)) { + try (DebugContext.Scope s = debug.scope("CodeInstall", getCodeCache(), installedCodeOwner, compResult); + DebugContext.Activation a = debug.activate()) { try { if (installAsDefault) { - installedCode = addDefaultMethod(installedCodeOwner, compResult); + installedCode = addDefaultMethod(debug, installedCodeOwner, compResult); } else { - installedCode = addMethod(installedCodeOwner, compResult); + installedCode = addMethod(debug, installedCodeOwner, compResult); } if (installedCode == null) { throw new GraalError("Could not install code for " + installedCodeOwner.format("%H.%n(%p)")); @@ -963,10 +972,10 @@ throw e; } } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } if (!forceCompile) { @@ -988,6 +997,10 @@ return parseEager(method, AllowAssumptions.YES, getCompilationId(method), options); } + protected final StructuredGraph parseForCompile(ResolvedJavaMethod method, DebugContext debug) { + return parseEager(method, AllowAssumptions.YES, debug); + } + protected final StructuredGraph parseForCompile(ResolvedJavaMethod method) { return parseEager(method, AllowAssumptions.YES, getCompilationId(method), getInitialOptions()); } @@ -1032,13 +1045,14 @@ protected CompilationResult compile(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, CompilationResult compilationResult, CompilationIdentifier compilationId, OptionValues options) { StructuredGraph graphToCompile = graph == null ? parseForCompile(installedCodeOwner, compilationId, options) : graph; lastCompiledGraph = graphToCompile; - try (Scope s = Debug.scope("Compile", graphToCompile)) { + DebugContext debug = graphToCompile.getDebug(); + try (DebugContext.Scope s = debug.scope("Compile", graphToCompile)) { assert options != null; Request request = new Request<>(graphToCompile, installedCodeOwner, getProviders(), getBackend(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL, graphToCompile.getProfilingInfo(), createSuites(options), createLIRSuites(options), compilationResult, CompilationResultBuilderFactory.Default); return GraalCompiler.compile(request); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } @@ -1048,12 +1062,12 @@ return null; } - protected InstalledCode addMethod(final ResolvedJavaMethod method, final CompilationResult compilationResult) { - return backend.addInstalledCode(method, null, compilationResult); + protected InstalledCode addMethod(DebugContext debug, final ResolvedJavaMethod method, final CompilationResult compilationResult) { + return backend.addInstalledCode(debug, method, null, compilationResult); } - protected InstalledCode addDefaultMethod(final ResolvedJavaMethod method, final CompilationResult compilationResult) { - return backend.createDefaultInstalledCode(method, compilationResult); + protected InstalledCode addDefaultMethod(DebugContext debug, final ResolvedJavaMethod method, final CompilationResult compilationResult) { + return backend.createDefaultInstalledCode(debug, method, compilationResult); } private final Map methodMap = new HashMap<>(); @@ -1108,7 +1122,8 @@ * @param allowAssumptions specifies if {@link Assumption}s can be made compiling the graph */ protected final StructuredGraph parseProfiled(String methodName, AllowAssumptions allowAssumptions) { - return parseProfiled(getResolvedJavaMethod(methodName), allowAssumptions); + ResolvedJavaMethod method = getResolvedJavaMethod(methodName); + return parse(builder(method, allowAssumptions), getDefaultGraphBuilderSuite()); } /** @@ -1119,7 +1134,7 @@ * @param allowAssumptions specifies if {@link Assumption}s can be made compiling the graph */ protected final StructuredGraph parseProfiled(ResolvedJavaMethod method, AllowAssumptions allowAssumptions) { - return parse1(method, getDefaultGraphBuilderSuite(), allowAssumptions, getCompilationId(method), getInitialOptions()); + return parse(builder(method, allowAssumptions), getDefaultGraphBuilderSuite()); } /** @@ -1130,7 +1145,8 @@ * @param allowAssumptions specifies if {@link Assumption}s can be made compiling the graph */ protected final StructuredGraph parseEager(String methodName, AllowAssumptions allowAssumptions) { - return parseEager(getResolvedJavaMethod(methodName), allowAssumptions, getInitialOptions()); + ResolvedJavaMethod method = getResolvedJavaMethod(methodName); + return parse(builder(method, allowAssumptions), getEagerGraphBuilderSuite()); } /** @@ -1142,7 +1158,13 @@ * @param options the option values to be used when compiling the graph */ protected final StructuredGraph parseEager(String methodName, AllowAssumptions allowAssumptions, OptionValues options) { - return parseEager(getResolvedJavaMethod(methodName), allowAssumptions, options); + ResolvedJavaMethod method = getResolvedJavaMethod(methodName); + return parse(builder(method, allowAssumptions, options), getEagerGraphBuilderSuite()); + } + + protected final StructuredGraph parseEager(String methodName, AllowAssumptions allowAssumptions, DebugContext debug) { + ResolvedJavaMethod method = getResolvedJavaMethod(methodName); + return parse(builder(method, allowAssumptions, debug), getEagerGraphBuilderSuite()); } /** @@ -1153,7 +1175,11 @@ * @param allowAssumptions specifies if {@link Assumption}s can be made compiling the graph */ protected final StructuredGraph parseEager(ResolvedJavaMethod method, AllowAssumptions allowAssumptions) { - return parseEager(method, allowAssumptions, getCompilationId(method), getInitialOptions()); + return parse(builder(method, allowAssumptions), getEagerGraphBuilderSuite()); + } + + protected final StructuredGraph parseEager(ResolvedJavaMethod method, AllowAssumptions allowAssumptions, DebugContext debug) { + return parse(builder(method, allowAssumptions, debug), getEagerGraphBuilderSuite()); } /** @@ -1165,7 +1191,7 @@ * @param options the option values to be used when compiling the graph */ protected final StructuredGraph parseEager(ResolvedJavaMethod method, AllowAssumptions allowAssumptions, OptionValues options) { - return parseEager(method, allowAssumptions, getCompilationId(method), options); + return parse(builder(method, allowAssumptions, options), getEagerGraphBuilderSuite()); } /** @@ -1177,43 +1203,53 @@ * @param compilationId the compilation identifier to be associated with the graph * @param options the option values to be used when compiling the graph */ - protected StructuredGraph parseEager(ResolvedJavaMethod method, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId, OptionValues options) { - return parse1(method, getCustomGraphBuilderSuite(GraphBuilderConfiguration.getDefault(getDefaultGraphBuilderPlugins()).withEagerResolving(true)), allowAssumptions, compilationId, options); + protected final StructuredGraph parseEager(ResolvedJavaMethod method, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId, OptionValues options) { + return parse(builder(method, allowAssumptions, compilationId, options), getEagerGraphBuilderSuite()); } - /** - * Parses a Java method using {@linkplain GraphBuilderConfiguration#withFullInfopoints(boolean) - * full debug} set to true to produce a graph. - * - * @param method the method to be parsed - * @param allowAssumptions specifies if {@link Assumption}s can be made compiling the graph - */ - protected StructuredGraph parseDebug(ResolvedJavaMethod method, AllowAssumptions allowAssumptions) { - return parse1(method, getCustomGraphBuilderSuite(GraphBuilderConfiguration.getDefault(getDefaultGraphBuilderPlugins()).withFullInfopoints(true)), allowAssumptions, getCompilationId(method), - getInitialOptions()); + protected final Builder builder(ResolvedJavaMethod method, AllowAssumptions allowAssumptions, DebugContext debug) { + OptionValues options = debug.getOptions(); + return new Builder(options, debug, allowAssumptions).method(method).compilationId(getCompilationId(method)); + } + + protected final Builder builder(ResolvedJavaMethod method, AllowAssumptions allowAssumptions) { + OptionValues options = getInitialOptions(); + return new Builder(options, getDebugContext(options), allowAssumptions).method(method).compilationId(getCompilationId(method)); + } + + protected final Builder builder(ResolvedJavaMethod method, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId, OptionValues options) { + return new Builder(options, getDebugContext(options), allowAssumptions).method(method).compilationId(compilationId); + } + + protected final Builder builder(ResolvedJavaMethod method, AllowAssumptions allowAssumptions, OptionValues options) { + return new Builder(options, getDebugContext(options), allowAssumptions).method(method).compilationId(getCompilationId(method)); + } + + protected PhaseSuite getDebugGraphBuilderSuite() { + return getCustomGraphBuilderSuite(GraphBuilderConfiguration.getDefault(getDefaultGraphBuilderPlugins()).withFullInfopoints(true)); } @SuppressWarnings("try") - private StructuredGraph parse1(ResolvedJavaMethod javaMethod, PhaseSuite graphBuilderSuite, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId, - OptionValues options) { + protected StructuredGraph parse(StructuredGraph.Builder builder, PhaseSuite graphBuilderSuite) { + ResolvedJavaMethod javaMethod = builder.getMethod(); + if (builder.getCancellable() == null) { + builder.cancellable(getCancellable(javaMethod)); + } assert javaMethod.getAnnotation(Test.class) == null : "shouldn't parse method with @Test annotation: " + javaMethod; - // @formatter:off - StructuredGraph graph = new StructuredGraph.Builder(options, allowAssumptions). - method(javaMethod). - speculationLog(getSpeculationLog()). - useProfilingInfo(true). - compilationId(compilationId). - cancellable(getCancellable(javaMethod)). - build(); - // @formatter:on - try (Scope ds = Debug.scope("Parsing", javaMethod, graph)) { + StructuredGraph graph = builder.build(); + DebugContext debug = graph.getDebug(); + try (DebugContext.Scope ds = debug.scope("Parsing", javaMethod, graph)) { graphBuilderSuite.apply(graph, getDefaultHighTierContext()); return graph; } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } + protected PhaseSuite getEagerGraphBuilderSuite() { + return getCustomGraphBuilderSuite(GraphBuilderConfiguration.getDefault(getDefaultGraphBuilderPlugins()).withEagerResolving(true)); + } + /** * Gets the cancellable that should be associated with a graph being created by any of the * {@code parse...()} methods. @@ -1385,6 +1421,6 @@ public static void initializeForTimeout() { // timeout tests run in a separate thread which needs the DebugEnvironment to be // initialized - DebugEnvironment.ensureInitialized(getInitialOptions()); + // DebugEnvironment.ensureInitialized(getInitialOptions()); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardedIntrinsicTest.java 2017-07-07 09:29:32.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardedIntrinsicTest.java 2017-07-07 09:29:32.000000000 -0700 @@ -112,7 +112,7 @@ @Override protected StructuredGraph parseForCompile(ResolvedJavaMethod method, CompilationIdentifier compilationId, OptionValues options) { graph = super.parseForCompile(method, compilationId, options); - parsedForCompile = (StructuredGraph) graph.copy(); + parsedForCompile = (StructuredGraph) graph.copy(graph.getDebug()); return graph; } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IfCanonicalizerTest.java 2017-07-07 09:29:32.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IfCanonicalizerTest.java 2017-07-07 09:29:32.000000000 -0700 @@ -22,9 +22,7 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.FrameState; @@ -40,6 +38,7 @@ import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.tiers.MidTierContext; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Test; /** * In the following tests, the usages of local variable "a" are replaced with the integer constant @@ -237,6 +236,7 @@ private void test(String snippet) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); + DebugContext debug = graph.getDebug(); ParameterNode param = graph.getNodes(ParameterNode.TYPE).iterator().next(); ConstantNode constant = ConstantNode.forInt(0, graph); for (Node n : param.usages().snapshot()) { @@ -244,7 +244,7 @@ n.replaceFirstInput(param, constant); } } - Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); + debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); for (FrameState fs : param.usages().filter(FrameState.class).snapshot()) { fs.replaceFirstInput(param, null); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ImplicitNullCheckTest.java 2017-07-07 09:29:32.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ImplicitNullCheckTest.java 2017-07-07 09:29:32.000000000 -0700 @@ -22,13 +22,8 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Assert; -import org.junit.Ignore; -import org.junit.Test; - import org.graalvm.compiler.api.directives.GraalDirectives; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugDumpScope; import org.graalvm.compiler.nodes.DeoptimizeNode; import org.graalvm.compiler.nodes.StructuredGraph; @@ -42,6 +37,9 @@ import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.tiers.MidTierContext; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; /** * Tests that the hub access and the null check are folded. @@ -68,8 +66,9 @@ @SuppressWarnings("try") private void test(final String snippet) { - try (Scope s = Debug.scope("FloatingReadTest", new DebugDumpScope(snippet))) { - StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); + DebugContext debug = getDebugContext(); + try (DebugContext.Scope s = debug.scope("FloatingReadTest", new DebugDumpScope(snippet))) { + StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES, debug); PhaseContext context = new PhaseContext(getProviders()); new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); new FloatingReadPhase().apply(graph); @@ -80,7 +79,7 @@ Assert.assertTrue(graph.getNodes().filter(ReadNode.class).first().canNullCheck()); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InfopointReasonTest.java 2017-07-07 09:29:33.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InfopointReasonTest.java 2017-07-07 09:29:33.000000000 -0700 @@ -76,7 +76,7 @@ @Test public void lineInfopoints() { final ResolvedJavaMethod method = getResolvedJavaMethod("testMethod"); - final StructuredGraph graph = parseDebug(method, AllowAssumptions.ifTrue(OptAssumptions.getValue(getInitialOptions()))); + final StructuredGraph graph = parse(builder(method, AllowAssumptions.ifTrue(OptAssumptions.getValue(getInitialOptions()))), getDebugGraphBuilderSuite()); int graphLineSPs = 0; for (FullInfopointNode ipn : graph.getNodes().filter(FullInfopointNode.class)) { if (ipn.getReason() == InfopointReason.BYTECODE_POSITION) { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InterfaceMethodHandleTest.java 2017-07-07 09:29:33.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InterfaceMethodHandleTest.java 2017-07-07 09:29:33.000000000 -0700 @@ -27,6 +27,7 @@ import java.lang.invoke.MethodType; import org.graalvm.compiler.code.CompilationResult; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.test.ExportingClassLoader; import org.junit.Test; import org.objectweb.asm.ClassWriter; @@ -104,12 +105,12 @@ } @Override - protected InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult) { + protected InstalledCode addMethod(DebugContext debug, ResolvedJavaMethod method, CompilationResult compResult) { if (method.getDeclaringClass().equals(getMetaAccess().lookupJavaType(M2Thrower.class))) { // Make sure M2Thrower.m2 is invoked from normal code - return getBackend().createDefaultInstalledCode(method, compResult); + return getBackend().createDefaultInstalledCode(debug, method, compResult); } - return super.addMethod(method, compResult); + return super.addMethod(debug, method, compResult); } /** --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LongNodeChainTest.java 2017-07-07 09:29:34.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LongNodeChainTest.java 2017-07-07 09:29:34.000000000 -0700 @@ -26,13 +26,15 @@ import org.junit.Assert; import org.junit.Test; - +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.AddNode; import org.graalvm.compiler.nodes.debug.OpaqueNode; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy; @@ -52,7 +54,8 @@ private void longAddChain(boolean reverse) { HighTierContext context = getDefaultHighTierContext(); - StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions()).build(); + OptionValues options = getInitialOptions(); + StructuredGraph graph = new StructuredGraph.Builder(options, DebugContext.create(options, DebugHandlersFactory.LOADER)).build(); ValueNode constant = graph.unique(ConstantNode.forPrimitive(JavaConstant.INT_1)); ValueNode value = null; if (reverse) { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LoopFullUnrollTest.java 2017-07-07 09:29:34.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LoopFullUnrollTest.java 2017-07-07 09:29:34.000000000 -0700 @@ -22,8 +22,7 @@ */ package org.graalvm.compiler.core.test; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugDumpScope; import org.graalvm.compiler.loop.DefaultLoopPolicies; import org.graalvm.compiler.loop.phases.LoopFullUnrollPhase; @@ -83,15 +82,16 @@ @SuppressWarnings("try") private void test(String snippet, int loopCount) { - try (Scope s = Debug.scope(getClass().getSimpleName(), new DebugDumpScope(snippet))) { - final StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); + DebugContext debug = getDebugContext(); + try (DebugContext.Scope s = debug.scope(getClass().getSimpleName(), new DebugDumpScope(snippet))) { + final StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO, debug); PhaseContext context = new PhaseContext(getProviders()); new LoopFullUnrollPhase(new CanonicalizerPhase(), new DefaultLoopPolicies()).apply(graph, context); assertTrue(graph.getNodes().filter(LoopBeginNode.class).count() == loopCount); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LoopUnswitchTest.java 2017-07-07 09:29:34.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LoopUnswitchTest.java 2017-07-07 09:29:34.000000000 -0700 @@ -22,10 +22,7 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugDumpScope; import org.graalvm.compiler.loop.DefaultLoopPolicies; import org.graalvm.compiler.loop.phases.LoopUnswitchingPhase; @@ -33,6 +30,7 @@ import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Test; public class LoopUnswitchTest extends GraalCompilerTest { @@ -124,6 +122,7 @@ @SuppressWarnings("try") private void test(String snippet, String referenceSnippet) { + DebugContext debug = getDebugContext(); final StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); final StructuredGraph referenceGraph = parseEager(referenceSnippet, AllowAssumptions.NO); @@ -135,10 +134,10 @@ new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); new CanonicalizerPhase().apply(referenceGraph, new PhaseContext(getProviders())); - try (Scope s = Debug.scope("Test", new DebugDumpScope("Test:" + snippet))) { + try (DebugContext.Scope s = debug.scope("Test", new DebugDumpScope("Test:" + snippet))) { assertEquals(referenceGraph, graph); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryScheduleTest.java 2017-07-07 09:29:35.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryScheduleTest.java 2017-07-07 09:29:35.000000000 -0700 @@ -31,12 +31,8 @@ import java.util.ArrayList; import java.util.List; -import org.junit.Assert; -import org.junit.Test; - import org.graalvm.compiler.api.directives.GraalDirectives; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.iterators.NodeIterable; import org.graalvm.compiler.nodes.ReturnNode; @@ -60,6 +56,8 @@ import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.tiers.MidTierContext; +import org.junit.Assert; +import org.junit.Test; /** * In these test the FrameStates are explicitly cleared out, so that the scheduling of @@ -706,7 +704,8 @@ private ScheduleResult getFinalSchedule(final String snippet, final TestMode mode, final SchedulingStrategy schedulingStrategy) { OptionValues options = new OptionValues(getInitialOptions(), OptScheduleOutOfLoops, schedulingStrategy == SchedulingStrategy.LATEST_OUT_OF_LOOPS, OptImplicitNullChecks, false); final StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO, options); - try (Scope d = Debug.scope("FloatingReadTest", graph)) { + DebugContext debug = graph.getDebug(); + try (DebugContext.Scope d = debug.scope("FloatingReadTest", graph)) { HighTierContext context = getDefaultHighTierContext(); CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); canonicalizer.apply(graph, context); @@ -717,7 +716,7 @@ if (mode == TestMode.WITHOUT_FRAMESTATES || mode == TestMode.INLINED_WITHOUT_FRAMESTATES) { graph.clearAllStateAfter(); } - Debug.dump(Debug.BASIC_LEVEL, graph, "after removal of framestates"); + debug.dump(DebugContext.BASIC_LEVEL, graph, "after removal of framestates"); new FloatingReadPhase().apply(graph); new RemoveValueProxyPhase().apply(graph); @@ -732,7 +731,7 @@ assertDeepEquals(1, graph.getNodes().filter(StartNode.class).count()); return graph.getLastSchedule(); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MergeCanonicalizerTest.java 2017-07-07 09:29:35.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MergeCanonicalizerTest.java 2017-07-07 09:29:35.000000000 -0700 @@ -22,14 +22,13 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Test; public class MergeCanonicalizerTest extends GraalCompilerTest { @@ -61,7 +60,7 @@ StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); - Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); + graph.getDebug().dump(DebugContext.BASIC_LEVEL, graph, "Graph"); assertDeepEquals(returnCount, graph.getNodes(ReturnNode.TYPE).count()); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NestedLoopTest.java 2017-07-07 09:29:36.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NestedLoopTest.java 2017-07-07 09:29:36.000000000 -0700 @@ -22,11 +22,8 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Assert; -import org.junit.Test; - import org.graalvm.compiler.core.common.cfg.Loop; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.StructuredGraph; @@ -34,6 +31,8 @@ import org.graalvm.compiler.nodes.cfg.Block; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.nodes.java.MethodCallTargetNode; +import org.junit.Assert; +import org.junit.Test; public class NestedLoopTest extends GraalCompilerTest { @@ -142,7 +141,8 @@ private void test(String snippet, int rootExits, int nestedExits, int innerExits) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); - Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); + DebugContext debug = graph.getDebug(); + debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, true); Assert.assertEquals(3, cfg.getLoops().size()); @@ -162,7 +162,7 @@ Assert.assertEquals(rootExits, rootLoop.getExits().size()); Assert.assertEquals(nestedExits, nestedLoop.getExits().size()); Assert.assertEquals(innerExits, innerMostLoop.getExits().size()); - Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); + debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); } private static boolean contains(Loop loop, Invoke node, ControlFlowGraph cfg) { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NodePropertiesTest.java 2017-07-07 09:29:36.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NodePropertiesTest.java 2017-07-07 09:29:36.000000000 -0700 @@ -23,7 +23,6 @@ package org.graalvm.compiler.core.test; import org.graalvm.compiler.api.directives.GraalDirectives; -import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.iterators.NodeIterable; import org.graalvm.compiler.graph.spi.Canonicalizable; @@ -196,7 +195,7 @@ GraphCostPhase gc2 = new GraphCostPhase(); gc1.apply(g1, htc); gc2.apply(g2, htc); - Debug.log("Test testDifferentLoopFaster --> 1.Graph cycles:%f size:%f vs. 2.Graph cycles:%f size:%f\n", gc1.finalCycles, gc1.finalSize, gc2.finalCycles, gc2.finalSize); + g1.getDebug().log("Test testDifferentLoopFaster --> 1.Graph cycles:%f size:%f vs. 2.Graph cycles:%f size:%f\n", gc1.finalCycles, gc1.finalSize, gc2.finalCycles, gc2.finalSize); Assert.assertTrue(gc2.finalCycles > gc1.finalCycles); Assert.assertTrue(gc2.finalSize == gc1.finalSize); } @@ -214,7 +213,7 @@ GraphCostPhase gc2 = new GraphCostPhase(); gc1.apply(g1, htc); gc2.apply(g2, htc); - Debug.log("Test testSameLoopMoreIterationsCostlier --> 1.Graph cycles:%f size:%f vs. 2.Graph cycles:%f size:%f\n", gc1.finalCycles, gc1.finalSize, gc2.finalCycles, gc2.finalSize); + g1.getDebug().log("Test testSameLoopMoreIterationsCostlier --> 1.Graph cycles:%f size:%f vs. 2.Graph cycles:%f size:%f\n", gc1.finalCycles, gc1.finalSize, gc2.finalCycles, gc2.finalSize); Assert.assertTrue(gc2.finalCycles > gc1.finalCycles); Assert.assertTrue(gc2.finalSize == gc1.finalSize); } @@ -231,7 +230,7 @@ GraphCostPhase gc2 = new GraphCostPhase(); gc1.apply(g1, htc); gc2.apply(g2, htc); - Debug.log("Test testDifferentLoopsInnerOuter --> 1.Graph cycles:%f size:%f vs. 2.Graph cycles:%f size:%f\n", gc1.finalCycles, gc1.finalSize, gc2.finalCycles, gc2.finalSize); + g1.getDebug().log("Test testDifferentLoopsInnerOuter --> 1.Graph cycles:%f size:%f vs. 2.Graph cycles:%f size:%f\n", gc1.finalCycles, gc1.finalSize, gc2.finalCycles, gc2.finalSize); Assert.assertTrue(gc2.finalSize > gc1.finalSize); } @@ -246,7 +245,7 @@ GraphCostPhase gc2 = new GraphCostPhase(); gc1.apply(g1, htc); gc2.apply(g2, htc); - Debug.log("Test Graph Cost --> 1.Graph cost:%f vs. 2.Graph cost:%f\n", gc1.finalCycles, gc2.finalCycles); + g1.getDebug().log("Test Graph Cost --> 1.Graph cost:%f vs. 2.Graph cost:%f\n", gc1.finalCycles, gc2.finalCycles); Assert.assertTrue(gc2.finalCycles > gc1.finalCycles); Assert.assertTrue(gc2.finalSize == gc1.finalSize); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PhiCreationTests.java 2017-07-07 09:29:36.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PhiCreationTests.java 2017-07-07 09:29:36.000000000 -0700 @@ -22,13 +22,12 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Assert; -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.ValuePhiNode; +import org.junit.Assert; +import org.junit.Test; /** * In the following tests, the correct removal of redundant phis during graph building is tested. @@ -70,7 +69,8 @@ @Test public void test3() { StructuredGraph graph = parseEager("test3Snippet", AllowAssumptions.YES); - Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); + DebugContext debug = graph.getDebug(); + debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); Assert.assertFalse(graph.getNodes().filter(ValuePhiNode.class).iterator().hasNext()); } @@ -86,7 +86,8 @@ @Test public void test4() { StructuredGraph graph = parseEager("test4Snippet", AllowAssumptions.YES); - Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); + DebugContext debug = graph.getDebug(); + debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); Assert.assertFalse(graph.getNodes().filter(ValuePhiNode.class).iterator().hasNext()); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PushNodesThroughPiTest.java 2017-07-07 09:29:37.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PushNodesThroughPiTest.java 2017-07-07 09:29:37.000000000 -0700 @@ -22,15 +22,7 @@ */ package org.graalvm.compiler.core.test; -import jdk.vm.ci.meta.ResolvedJavaField; -import jdk.vm.ci.meta.ResolvedJavaType; - -import org.junit.Assert; -import org.junit.Ignore; -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugDumpScope; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.PiNode; @@ -44,6 +36,12 @@ import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; + +import jdk.vm.ci.meta.ResolvedJavaField; +import jdk.vm.ci.meta.ResolvedJavaType; public class PushNodesThroughPiTest extends GraalCompilerTest { @@ -77,7 +75,8 @@ @SuppressWarnings("try") public void test1() { final String snippet = "test1Snippet"; - try (Scope s = Debug.scope("PushThroughPi", new DebugDumpScope(snippet))) { + DebugContext debug = getDebugContext(); + try (DebugContext.Scope s = debug.scope("PushThroughPi", new DebugDumpScope(snippet))) { StructuredGraph graph = compileTestSnippet(snippet); for (ReadNode rn : graph.getNodes().filter(ReadNode.class)) { OffsetAddressNode address = (OffsetAddressNode) rn.getAddress(); @@ -96,7 +95,7 @@ Assert.assertTrue(graph.getNodes().filter(IsNullNode.class).count() == 1); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PushThroughIfTest.java 2017-07-07 09:29:37.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PushThroughIfTest.java 2017-07-07 09:29:37.000000000 -0700 @@ -22,15 +22,14 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.util.GraphUtil; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Test; public class PushThroughIfTest extends GraalCompilerTest { @@ -59,7 +58,8 @@ private void test(String snippet, String reference) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); - Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); + DebugContext debug = graph.getDebug(); + debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); for (FrameState fs : graph.getNodes(FrameState.TYPE).snapshot()) { fs.replaceAtUsages(null); GraphUtil.killWithUnusedFloatingInputs(fs); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReadAfterCheckCastTest.java 2017-07-07 09:29:38.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReadAfterCheckCastTest.java 2017-07-07 09:29:37.000000000 -0700 @@ -22,11 +22,7 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Assert; -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugDumpScope; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.StructuredGraph; @@ -37,6 +33,8 @@ import org.graalvm.compiler.phases.common.FloatingReadPhase; import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Assert; +import org.junit.Test; /* consider * B b = (B) a; @@ -84,7 +82,8 @@ @SuppressWarnings("try") private void test(final String snippet) { - try (Scope s = Debug.scope("ReadAfterCheckCastTest", new DebugDumpScope(snippet))) { + DebugContext debug = getDebugContext(); + try (DebugContext.Scope s = debug.scope("ReadAfterCheckCastTest", new DebugDumpScope(snippet))) { // check shape of graph, with lots of assumptions. will probably fail if graph // structure changes significantly StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); @@ -94,7 +93,7 @@ new FloatingReadPhase().apply(graph); canonicalizer.apply(graph, context); - Debug.dump(Debug.BASIC_LEVEL, graph, "After lowering"); + debug.dump(DebugContext.BASIC_LEVEL, graph, "After lowering"); for (FloatingReadNode node : graph.getNodes(ParameterNode.TYPE).first().usages().filter(FloatingReadNode.class)) { // Checking that the parameter a is not directly used for the access to field @@ -102,7 +101,7 @@ Assert.assertTrue(node.getLocationIdentity().isImmutable()); } } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ScalarTypeSystemTest.java 2017-07-07 09:29:38.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ScalarTypeSystemTest.java 2017-07-07 09:29:38.000000000 -0700 @@ -22,13 +22,12 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Test; /** * In the following tests, the scalar type system of the compiler should be complete enough to see @@ -131,7 +130,7 @@ private void test(final String snippet, final String referenceSnippet) { // No debug scope to reduce console noise for @Test(expected = ...) tests StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); - Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); + graph.getDebug().dump(DebugContext.BASIC_LEVEL, graph, "Graph"); PhaseContext context = new PhaseContext(getProviders()); new CanonicalizerPhase().apply(graph, context); StructuredGraph referenceGraph = parseEager(referenceSnippet, AllowAssumptions.NO); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest2.java 2017-07-07 09:29:38.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest2.java 2017-07-07 09:29:38.000000000 -0700 @@ -24,10 +24,8 @@ import java.util.List; -import org.junit.Test; - import org.graalvm.compiler.core.common.cfg.BlockMap; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeMap; import org.graalvm.compiler.nodes.BeginNode; @@ -51,6 +49,7 @@ import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy; import org.graalvm.compiler.phases.tiers.MidTierContext; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Test; public class SchedulingTest2 extends GraphScheduleTest { @@ -65,11 +64,12 @@ @Test public void testValueProxyInputs() { StructuredGraph graph = parseEager("testSnippet", AllowAssumptions.YES); + DebugContext debug = graph.getDebug(); ReturnNode returnNode = graph.getNodes(ReturnNode.TYPE).first(); BeginNode beginNode = graph.add(new BeginNode()); returnNode.replaceAtPredecessor(beginNode); beginNode.setNext(returnNode); - Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); + debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); SchedulePhase schedulePhase = new SchedulePhase(SchedulingStrategy.EARLIEST); schedulePhase.apply(graph); ScheduleResult schedule = graph.getLastSchedule(); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SimpleCFGTest.java 2017-07-07 09:29:39.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SimpleCFGTest.java 2017-07-07 09:29:39.000000000 -0700 @@ -22,10 +22,7 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Assert; -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.AbstractBeginNode; import org.graalvm.compiler.nodes.AbstractMergeNode; import org.graalvm.compiler.nodes.BeginNode; @@ -37,16 +34,23 @@ import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.cfg.Block; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.printer.GraalDebugHandlersFactory; +import org.junit.Assert; +import org.junit.Test; public class SimpleCFGTest extends GraalCompilerTest { private static void dumpGraph(final StructuredGraph graph) { - Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); + DebugContext debug = graph.getDebug(); + debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); } @Test public void testImplies() { - StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions(), AllowAssumptions.YES).build(); + OptionValues options = getInitialOptions(); + DebugContext debug = DebugContext.create(options, new GraalDebugHandlersFactory(getSnippetReflection())); + StructuredGraph graph = new StructuredGraph.Builder(options, debug, AllowAssumptions.YES).build(); EndNode trueEnd = graph.add(new EndNode()); EndNode falseEnd = graph.add(new EndNode()); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StaticInterfaceFieldTest.java 2017-07-07 09:29:39.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StaticInterfaceFieldTest.java 2017-07-07 09:29:39.000000000 -0700 @@ -23,19 +23,19 @@ package org.graalvm.compiler.core.test; import static org.graalvm.compiler.core.test.GraalCompilerTest.getInitialOptions; -import static org.graalvm.compiler.debug.DelegatingDebugConfig.Feature.INTERCEPT; import java.lang.reflect.Method; import org.graalvm.compiler.api.test.Graal; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugConfigScope; -import org.graalvm.compiler.debug.DelegatingDebugConfig; +import org.graalvm.compiler.debug.DebugCloseable; +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.java.GraphBuilderPhase; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.VerifyPhase; @@ -90,11 +90,13 @@ final Method m = getMethod(clazz, methodName); ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m); - StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions()).method(method).build(); - try (DebugConfigScope s = Debug.setConfig(new DelegatingDebugConfig().disable(INTERCEPT)); Debug.Scope ds = Debug.scope("GraphBuilding", graph, method)) { + OptionValues options = getInitialOptions(); + DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER); + StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(method).build(); + try (DebugCloseable s = debug.disableIntercept(); DebugContext.Scope ds = debug.scope("GraphBuilding", graph, method)) { graphBuilderSuite.apply(graph, context); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StraighteningTest.java 2017-07-07 09:29:40.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StraighteningTest.java 2017-07-07 09:29:39.000000000 -0700 @@ -22,13 +22,12 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Test; public class StraighteningTest extends GraalCompilerTest { @@ -88,7 +87,8 @@ private void test(final String snippet) { // No debug scope to reduce console noise for @Test(expected = ...) tests StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); - Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); + DebugContext debug = graph.getDebug(); + debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET, AllowAssumptions.YES); assertEquals(referenceGraph, graph); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeSystemTest.java 2017-07-07 09:29:40.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeSystemTest.java 2017-07-07 09:29:40.000000000 -0700 @@ -28,7 +28,7 @@ import java.io.IOException; import java.io.InputStream; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodeinfo.Verbosity; @@ -179,7 +179,8 @@ private void test(String snippet, String referenceSnippet) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); - Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); + DebugContext debug = graph.getDebug(); + debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); /* * When using FlowSensitiveReductionPhase instead of ConditionalEliminationPhase, * tail-duplication gets activated thus resulting in a graph with more nodes than the @@ -198,9 +199,10 @@ @Override protected void assertEquals(StructuredGraph expected, StructuredGraph graph) { + DebugContext debug = graph.getDebug(); if (getNodeCountExcludingUnusedConstants(expected) != getNodeCountExcludingUnusedConstants(graph)) { - Debug.dump(Debug.BASIC_LEVEL, expected, "expected (node count)"); - Debug.dump(Debug.BASIC_LEVEL, graph, "graph (node count)"); + debug.dump(DebugContext.BASIC_LEVEL, expected, "expected (node count)"); + debug.dump(DebugContext.BASIC_LEVEL, graph, "graph (node count)"); Assert.fail("Graphs do not have the same number of nodes: " + expected.getNodeCount() + " vs. " + graph.getNodeCount()); } } @@ -243,7 +245,8 @@ StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); - Debug.dump(Debug.BASIC_LEVEL, graph, "Graph " + snippet); + DebugContext debug = graph.getDebug(); + debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph " + snippet); Assert.assertFalse("shouldn't have nodes of type " + clazz, graph.getNodes().filter(clazz).iterator().hasNext()); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnbalancedMonitorsTest.java 2017-07-07 09:29:40.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnbalancedMonitorsTest.java 2017-07-07 09:29:40.000000000 -0700 @@ -27,6 +27,7 @@ import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.junit.Test; import org.objectweb.asm.ClassWriter; @@ -85,7 +86,8 @@ private void checkForBailout(String name) throws ClassNotFoundException { ResolvedJavaMethod method = getResolvedJavaMethod(LOADER.findClass(INNER_CLASS_NAME), name); try { - StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions()).method(method).build(); + OptionValues options = getInitialOptions(); + StructuredGraph graph = new StructuredGraph.Builder(options, getDebugContext(options)).method(method).build(); Plugins plugins = new Plugins(new InvocationPlugins()); GraphBuilderConfiguration graphBuilderConfig = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true); OptimisticOptimizations optimisticOpts = OptimisticOptimizations.NONE; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyBailoutUsageTest.java 2017-07-07 09:29:41.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyBailoutUsageTest.java 2017-07-07 09:29:41.000000000 -0700 @@ -27,19 +27,19 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import org.junit.Test; - import org.graalvm.compiler.api.test.Graal; import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.core.common.RetryableBailoutException; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugConfigScope; +import org.graalvm.compiler.debug.DebugCloseable; +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.java.GraphBuilderPhase; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.Phase; import org.graalvm.compiler.phases.PhaseSuite; @@ -48,6 +48,7 @@ import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.phases.verify.VerifyBailoutUsage; import org.graalvm.compiler.runtime.RuntimeProvider; +import org.junit.Test; import jdk.vm.ci.code.BailoutException; import jdk.vm.ci.meta.MetaAccessProvider; @@ -125,12 +126,14 @@ GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true); graphBuilderSuite.appendPhase(new GraphBuilderPhase(config)); HighTierContext context = new HighTierContext(providers, graphBuilderSuite, OptimisticOptimizations.NONE); + OptionValues options = getInitialOptions(); + DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER); for (Method m : c.getDeclaredMethods()) { if (!Modifier.isNative(m.getModifiers()) && !Modifier.isAbstract(m.getModifiers())) { ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m); - StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions()).method(method).build(); + StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(method).build(); graphBuilderSuite.apply(graph, context); - try (DebugConfigScope s = Debug.disableIntercept()) { + try (DebugCloseable s = debug.disableIntercept()) { new VerifyBailoutUsage().apply(graph, context); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyDebugUsageTest.java 2017-07-07 09:29:41.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyDebugUsageTest.java 2017-07-07 09:29:41.000000000 -0700 @@ -27,11 +27,10 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import org.junit.Test; - import org.graalvm.compiler.api.test.Graal; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugConfigScope; +import org.graalvm.compiler.debug.DebugCloseable; +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.graph.Node; @@ -40,6 +39,7 @@ import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.Phase; import org.graalvm.compiler.phases.PhaseSuite; @@ -48,6 +48,7 @@ import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.phases.verify.VerifyDebugUsage; import org.graalvm.compiler.runtime.RuntimeProvider; +import org.junit.Test; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -58,8 +59,9 @@ @Override protected void run(StructuredGraph graph) { + DebugContext debug = graph.getDebug(); for (Node n : graph.getNodes()) { - Debug.log("%s", n.toString()); + debug.log("%s", n.toString()); } } @@ -70,9 +72,10 @@ @Override @SuppressWarnings("try") protected void run(StructuredGraph graph) { - try (Indent i = Debug.logAndIndent("%s", graph.toString())) { + DebugContext debug = graph.getDebug(); + try (Indent i = debug.logAndIndent("%s", graph.toString())) { for (Node n : graph.getNodes()) { - Debug.log("%s", n); + debug.log("%s", n); } } } @@ -83,7 +86,8 @@ @Override protected void run(StructuredGraph graph) { - Debug.dump(Debug.BASIC_LEVEL, graph, "%s", graph.toString()); + DebugContext debug = graph.getDebug(); + debug.dump(DebugContext.BASIC_LEVEL, graph, "%s", graph.toString()); } } @@ -91,7 +95,8 @@ @Override protected void run(StructuredGraph graph) { - Debug.dump(Debug.VERY_DETAILED_LEVEL + 1, graph, "%s", graph); + DebugContext debug = graph.getDebug(); + debug.dump(DebugContext.VERY_DETAILED_LEVEL + 1, graph, "%s", graph); } } @@ -99,7 +104,8 @@ @Override protected void run(StructuredGraph graph) { - Debug.dump(getLevel(), graph, "%s", graph); + DebugContext debug = graph.getDebug(); + debug.dump(getLevel(), graph, "%s", graph); } int getLevel() { @@ -111,7 +117,8 @@ @Override protected void run(StructuredGraph graph) { - Debug.verify(graph, "%s", graph.toString()); + DebugContext debug = graph.getDebug(); + debug.verify(graph, "%s", graph.toString()); } } @@ -120,8 +127,9 @@ @Override protected void run(StructuredGraph graph) { + DebugContext debug = graph.getDebug(); for (Node n : graph.getNodes()) { - Debug.log("error " + n); + debug.log("error " + n); } } @@ -132,9 +140,10 @@ @Override @SuppressWarnings("try") protected void run(StructuredGraph graph) { - try (Indent i = Debug.logAndIndent("error " + graph)) { + DebugContext debug = graph.getDebug(); + try (Indent i = debug.logAndIndent("error " + graph)) { for (Node n : graph.getNodes()) { - Debug.log("%s", n); + debug.log("%s", n); } } } @@ -145,7 +154,8 @@ @Override protected void run(StructuredGraph graph) { - Debug.dump(Debug.BASIC_LEVEL, graph, "error " + graph); + DebugContext debug = graph.getDebug(); + debug.dump(DebugContext.BASIC_LEVEL, graph, "error " + graph); } } @@ -154,7 +164,8 @@ @Override protected void run(StructuredGraph graph) { - Debug.verify(graph, "error " + graph); + DebugContext debug = graph.getDebug(); + debug.verify(graph, "error " + graph); } } @@ -163,8 +174,9 @@ @Override protected void run(StructuredGraph graph) { + DebugContext debug = graph.getDebug(); for (Node n : graph.getNodes()) { - Debug.log("%s", n); + debug.log("%s", n); } } @@ -175,9 +187,10 @@ @Override @SuppressWarnings("try") protected void run(StructuredGraph graph) { - try (Indent i = Debug.logAndIndent("%s", graph)) { + DebugContext debug = graph.getDebug(); + try (Indent i = debug.logAndIndent("%s", graph)) { for (Node n : graph.getNodes()) { - Debug.log("%s", n); + debug.log("%s", n); } } } @@ -188,7 +201,8 @@ @Override protected void run(StructuredGraph graph) { - Debug.dump(Debug.BASIC_LEVEL, graph, "%s", graph); + DebugContext debug = graph.getDebug(); + debug.dump(DebugContext.BASIC_LEVEL, graph, "%s", graph); } } @@ -197,7 +211,8 @@ @Override protected void run(StructuredGraph graph) { - Debug.verify(graph, "%s", graph); + DebugContext debug = graph.getDebug(); + debug.verify(graph, "%s", graph); } } @@ -332,12 +347,14 @@ GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true); graphBuilderSuite.appendPhase(new GraphBuilderPhase(config)); HighTierContext context = new HighTierContext(providers, graphBuilderSuite, OptimisticOptimizations.NONE); + OptionValues options = getInitialOptions(); + DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER); for (Method m : c.getDeclaredMethods()) { if (!Modifier.isNative(m.getModifiers()) && !Modifier.isAbstract(m.getModifiers())) { ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m); - StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions()).method(method).build(); + StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(method).build(); graphBuilderSuite.apply(graph, context); - try (DebugConfigScope s = Debug.disableIntercept()) { + try (DebugCloseable s = debug.disableIntercept()) { new VerifyDebugUsage().apply(graph, context); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyVirtualizableTest.java 2017-07-07 09:29:42.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyVirtualizableTest.java 2017-07-07 09:29:41.000000000 -0700 @@ -29,12 +29,11 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import org.junit.Test; - import org.graalvm.compiler.api.test.Graal; import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugConfigScope; +import org.graalvm.compiler.debug.DebugCloseable; +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.java.GraphBuilderPhase; import org.graalvm.compiler.nodeinfo.NodeInfo; @@ -47,6 +46,7 @@ import org.graalvm.compiler.nodes.java.ArrayLengthNode; import org.graalvm.compiler.nodes.spi.Virtualizable; import org.graalvm.compiler.nodes.spi.VirtualizerTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.VerifyPhase.VerificationError; @@ -54,6 +54,7 @@ import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.phases.verify.VerifyVirtualizableUsage; import org.graalvm.compiler.runtime.RuntimeProvider; +import org.junit.Test; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -270,12 +271,14 @@ GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true); graphBuilderSuite.appendPhase(new GraphBuilderPhase(config)); HighTierContext context = new HighTierContext(providers, graphBuilderSuite, OptimisticOptimizations.NONE); + OptionValues options = getInitialOptions(); + DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER); for (Method m : c.getDeclaredMethods()) { if (!Modifier.isNative(m.getModifiers()) && !Modifier.isAbstract(m.getModifiers())) { ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m); - StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions()).method(method).build(); + StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(method).build(); graphBuilderSuite.apply(graph, context); - try (DebugConfigScope s = Debug.disableIntercept()) { + try (DebugCloseable s = debug.disableIntercept()) { new VerifyVirtualizableUsage().apply(graph, context); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/AllocatorTest.java 2017-07-07 09:29:42.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/AllocatorTest.java 2017-07-07 09:29:42.000000000 -0700 @@ -24,15 +24,8 @@ import java.util.HashSet; -import jdk.vm.ci.code.Register; -import jdk.vm.ci.code.ValueUtil; -import jdk.vm.ci.meta.Value; - -import org.junit.Assert; - import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.LIRValueUtil; @@ -40,23 +33,29 @@ import org.graalvm.compiler.lir.ValueProcedure; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.junit.Assert; + +import jdk.vm.ci.code.Register; +import jdk.vm.ci.code.ValueUtil; +import jdk.vm.ci.meta.Value; public class AllocatorTest extends BackendTest { @SuppressWarnings("try") protected void testAllocation(String snippet, final int expectedRegisters, final int expectedRegRegMoves, final int expectedSpillMoves) { final StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); - try (Scope s = Debug.scope("AllocatorTest", graph, graph.method(), getCodeCache())) { + DebugContext debug = graph.getDebug(); + try (DebugContext.Scope s = debug.scope("AllocatorTest", graph, graph.method(), getCodeCache())) { final RegisterStats stats = new RegisterStats(getLIRGenerationResult(graph).getLIR()); - try (Scope s2 = Debug.scope("Assertions", stats.lir)) { + try (DebugContext.Scope s2 = debug.scope("Assertions", stats.lir)) { Assert.assertEquals("register count", expectedRegisters, stats.registers.size()); Assert.assertEquals("reg-reg moves", expectedRegRegMoves, stats.regRegMoves); Assert.assertEquals("spill moves", expectedSpillMoves, stats.spillMoves); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/BackendTest.java 2017-07-07 09:29:42.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/BackendTest.java 2017-07-07 09:29:42.000000000 -0700 @@ -22,16 +22,15 @@ */ package org.graalvm.compiler.core.test.backend; -import jdk.vm.ci.code.Architecture; - import org.graalvm.compiler.core.GraalCompiler; import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.lir.gen.LIRGenerationResult; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.phases.OptimisticOptimizations; +import jdk.vm.ci.code.Architecture; + public abstract class BackendTest extends GraalCompilerTest { public BackendTest() { @@ -44,10 +43,11 @@ @SuppressWarnings("try") protected LIRGenerationResult getLIRGenerationResult(final StructuredGraph graph) { - try (Scope s = Debug.scope("FrontEnd")) { + DebugContext debug = graph.getDebug(); + try (DebugContext.Scope s = debug.scope("FrontEnd")) { GraalCompiler.emitFrontEnd(getProviders(), getBackend(), graph, getDefaultGraphBuilderSuite(), OptimisticOptimizations.NONE, graph.getProfilingInfo(), createSuites(graph.getOptions())); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } LIRGenerationResult lirGen = GraalCompiler.emitLIR(getBackend(), graph, null, null, createLIRSuites(graph.getOptions())); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/MonitorDeoptTest.java 2017-07-07 09:29:43.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/MonitorDeoptTest.java 2017-07-07 09:29:43.000000000 -0700 @@ -189,7 +189,7 @@ removeLoopSafepoint(graph); CompilationResult compilationResult = compile(javaMethod, graph); - final InstalledCode installedCode = getBackend().createDefaultInstalledCode(javaMethod, compilationResult); + final InstalledCode installedCode = getBackend().createDefaultInstalledCode(graph.getDebug(), javaMethod, compilationResult); final Monitor monitor = new Monitor(); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/SynchronizedMethodDeoptimizationTest.java 2017-07-07 09:29:43.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/SynchronizedMethodDeoptimizationTest.java 2017-07-07 09:29:43.000000000 -0700 @@ -22,6 +22,7 @@ */ package org.graalvm.compiler.core.test.deopt; +import org.junit.Assume; import org.junit.Test; import org.graalvm.compiler.core.test.GraalCompilerTest; @@ -44,6 +45,9 @@ @Test public void test1() { + // https://bugs.openjdk.java.net/browse/JDK-8182755 + Assume.assumeTrue(Java8OrEarlier); + test("testMethodSynchronized", "test"); test("testMethodSynchronized", (Object) null); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EATestBase.java 2017-07-07 09:29:44.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EATestBase.java 2017-07-07 09:29:43.000000000 -0700 @@ -24,14 +24,8 @@ import java.util.List; -import jdk.vm.ci.meta.JavaConstant; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -import org.junit.Assert; - import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; @@ -43,6 +37,10 @@ import org.graalvm.compiler.phases.common.inlining.InliningPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; +import org.junit.Assert; + +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.ResolvedJavaMethod; //JaCoCo Exclude @@ -154,8 +152,9 @@ @SuppressWarnings("try") protected void prepareGraph(String snippet, boolean iterativeEscapeAnalysis) { ResolvedJavaMethod method = getResolvedJavaMethod(snippet); - try (Scope s = Debug.scope(getClass(), method, getCodeCache())) { - graph = parseEager(method, AllowAssumptions.YES); + DebugContext debug = getDebugContext(); + try (DebugContext.Scope s = debug.scope(getClass(), method, getCodeCache())) { + graph = parseEager(method, AllowAssumptions.YES, debug); context = getDefaultHighTierContext(); new InliningPhase(new CanonicalizerPhase()).apply(graph, context); new DeadCodeEliminationPhase().apply(graph); @@ -163,7 +162,7 @@ new PartialEscapePhase(iterativeEscapeAnalysis, false, new CanonicalizerPhase(), null, graph.getOptions()).apply(graph, context); returnNodes = graph.getNodes(ReturnNode.TYPE).snapshot(); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PoorMansEATest.java 2017-07-07 09:29:44.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PoorMansEATest.java 2017-07-07 09:29:44.000000000 -0700 @@ -22,11 +22,8 @@ */ package org.graalvm.compiler.core.test.ea; -import org.junit.Test; - import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugDumpScope; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.FrameState; @@ -40,6 +37,7 @@ import org.graalvm.compiler.phases.common.inlining.InliningPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Test; /** * Tests {@link AbstractNewObjectNode#simplify(org.graalvm.compiler.graph.spi.SimplifierTool)}. @@ -63,7 +61,8 @@ @SuppressWarnings("try") private void test(final String snippet) { - try (Scope s = Debug.scope("PoorMansEATest", new DebugDumpScope(snippet))) { + DebugContext debug = getDebugContext(); + try (DebugContext.Scope s = debug.scope("PoorMansEATest", new DebugDumpScope(snippet))) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); HighTierContext highTierContext = getDefaultHighTierContext(); new InliningPhase(new CanonicalizerPhase()).apply(graph, highTierContext); @@ -82,7 +81,7 @@ } new CanonicalizerPhase().apply(graph, context); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/InliningTest.java 2017-07-07 09:29:44.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/InliningTest.java 2017-07-07 09:29:44.000000000 -0700 @@ -22,21 +22,15 @@ */ package org.graalvm.compiler.core.test.inlining; -import jdk.vm.ci.code.site.InfopointReason; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -import org.junit.Ignore; -import org.junit.Test; - import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugDumpScope; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.FullInfopointNode; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.nodes.StructuredGraph.Builder; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.PhaseSuite; @@ -44,6 +38,11 @@ import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; import org.graalvm.compiler.phases.common.inlining.InliningPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; +import org.junit.Ignore; +import org.junit.Test; + +import jdk.vm.ci.code.site.InfopointReason; +import jdk.vm.ci.meta.ResolvedJavaMethod; public class InliningTest extends GraalCompilerTest { @@ -236,24 +235,26 @@ @SuppressWarnings("try") private StructuredGraph getGraph(final String snippet, final boolean eagerInfopointMode) { - try (Scope s = Debug.scope("InliningTest", new DebugDumpScope(snippet, true))) { + DebugContext debug = getDebugContext(); + try (DebugContext.Scope s = debug.scope("InliningTest", new DebugDumpScope(snippet, true))) { ResolvedJavaMethod method = getResolvedJavaMethod(snippet); - StructuredGraph graph = eagerInfopointMode ? parseDebug(method, AllowAssumptions.YES) : parseEager(method, AllowAssumptions.YES); - try (Scope s2 = Debug.scope("Inlining", graph)) { + Builder builder = builder(method, AllowAssumptions.YES, debug); + StructuredGraph graph = eagerInfopointMode ? parse(builder, getDebugGraphBuilderSuite()) : parse(builder, getEagerGraphBuilderSuite()); + try (DebugContext.Scope s2 = debug.scope("Inlining", graph)) { PhaseSuite graphBuilderSuite = eagerInfopointMode ? getCustomGraphBuilderSuite(GraphBuilderConfiguration.getDefault(getDefaultGraphBuilderPlugins()).withFullInfopoints(true)) : getDefaultGraphBuilderSuite(); HighTierContext context = new HighTierContext(getProviders(), graphBuilderSuite, OptimisticOptimizations.ALL); - Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); + debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); new CanonicalizerPhase().apply(graph, context); new InliningPhase(new CanonicalizerPhase()).apply(graph, context); - Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); + debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); new CanonicalizerPhase().apply(graph, context); new DeadCodeEliminationPhase().apply(graph); return graph; } } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/NestedLoopEffectsPhaseComplexityTest.java 2017-07-07 09:29:45.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/NestedLoopEffectsPhaseComplexityTest.java 2017-07-07 09:29:45.000000000 -0700 @@ -25,13 +25,14 @@ import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Optional; import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.java.MethodCallTargetNode; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.PhaseSuite; @@ -100,10 +101,9 @@ } private void testAndTime(String snippet) { - initializeForTimeout(); for (int i = InliningCountLowerBound; i < InliningCountUpperBound; i++) { StructuredGraph g1 = prepareGraph(snippet, i); - StructuredGraph g2 = (StructuredGraph) g1.copy(); + StructuredGraph g2 = (StructuredGraph) g1.copy(g1.getDebug()); ResolvedJavaMethod method = g1.method(); long elapsedRE = runAndTimePhase(g1, new EarlyReadEliminationPhase(new CanonicalizerPhase())); long elapsedPEA = runAndTimePhase(g2, new PartialEscapePhase(true, new CanonicalizerPhase(), g1.getOptions())); @@ -121,7 +121,8 @@ long start = System.currentTimeMillis(); phase.apply(g, context); long end = System.currentTimeMillis(); - Debug.dump(Debug.DETAILED_LEVEL, g, "After %s", phase.contractorName()); + DebugContext debug = g.getDebug(); + debug.dump(DebugContext.DETAILED_LEVEL, g, "After %s", phase.contractorName()); return end - start; } @@ -138,13 +139,14 @@ next = callerGraph.getNodes(MethodCallTargetNode.TYPE).first().invoke(); EconomicSet canonicalizeNodes = InliningUtil.inlineForCanonicalization(next, calleeGraph, false, calleeMethod); canonicalizer.applyIncremental(callerGraph, context, canonicalizeNodes); - Debug.dump(Debug.DETAILED_LEVEL, callerGraph, "After inlining %s into %s iteration %d", calleeMethod, callerMethod, i); + callerGraph.getDebug().dump(DebugContext.DETAILED_LEVEL, callerGraph, "After inlining %s into %s iteration %d", calleeMethod, callerMethod, i); } return callerGraph; } - private static StructuredGraph parseBytecodes(ResolvedJavaMethod method, HighTierContext context, CanonicalizerPhase canonicalizer) { - StructuredGraph newGraph = new StructuredGraph.Builder(getInitialOptions(), AllowAssumptions.NO).method(method).build(); + private StructuredGraph parseBytecodes(ResolvedJavaMethod method, HighTierContext context, CanonicalizerPhase canonicalizer) { + OptionValues options = getInitialOptions(); + StructuredGraph newGraph = new StructuredGraph.Builder(options, getDebugContext(options), AllowAssumptions.NO).method(method).build(); context.getGraphBuilderSuite().apply(newGraph, context); new DeadCodeEliminationPhase(Optional).apply(newGraph); canonicalizer.apply(newGraph, context); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/InvokeGraal.java 2017-07-07 09:29:45.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/InvokeGraal.java 2017-07-07 09:29:45.000000000 -0700 @@ -24,6 +24,7 @@ import static org.graalvm.compiler.core.common.CompilationRequestIdentifier.asCompilationRequest; import static org.graalvm.compiler.core.test.GraalCompilerTest.getInitialOptions; + import java.lang.reflect.Method; import org.graalvm.compiler.api.test.Graal; @@ -31,8 +32,8 @@ import org.graalvm.compiler.core.GraalCompiler; import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.target.Backend; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugDumpScope; import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; import org.graalvm.compiler.lir.phases.LIRSuites; @@ -85,7 +86,8 @@ /* Create a unique compilation identifier, visible in IGV. */ CompilationIdentifier compilationId = backend.getCompilationIdentifier(method); OptionValues options = getInitialOptions(); - try (Scope s = Debug.scope("compileAndInstallMethod", new DebugDumpScope(String.valueOf(compilationId), true))) { + DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER); + try (DebugContext.Scope s = debug.scope("compileAndInstallMethod", new DebugDumpScope(String.valueOf(compilationId), true))) { /* * The graph that is compiled. We leave it empty (no nodes added yet). This means that @@ -93,7 +95,7 @@ * that we want the compilation to make optimistic assumptions about runtime state such * as the loaded class hierarchy. */ - StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions(), AllowAssumptions.YES).method(method).compilationId(compilationId).build(); + StructuredGraph graph = new StructuredGraph.Builder(options, debug, AllowAssumptions.YES).method(method).compilationId(compilationId).build(); /* * The phases used to build the graph. Usually this is just the GraphBuilderPhase. If @@ -131,9 +133,9 @@ * Install the compilation result into the VM, i.e., copy the byte[] array that contains * the machine code into an actual executable memory location. */ - return backend.addInstalledCode(method, asCompilationRequest(compilationId), compilationResult); + return backend.addInstalledCode(debug, method, asCompilationRequest(compilationId), compilationResult); } catch (Throwable ex) { - throw Debug.handle(ex); + throw debug.handle(ex); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/StaticAnalysis.java 2017-07-07 09:29:45.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/StaticAnalysis.java 2017-07-07 09:29:45.000000000 -0700 @@ -32,9 +32,9 @@ import java.util.Map; import java.util.Set; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.debug.Debug.Scope; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeMap; import org.graalvm.compiler.java.GraphBuilderPhase; @@ -58,6 +58,7 @@ import org.graalvm.compiler.nodes.java.StoreFieldNode; import org.graalvm.compiler.nodes.spi.StampProvider; import org.graalvm.compiler.nodes.util.GraphUtil; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.graph.StatelessPostOrderNodeIterator; @@ -240,12 +241,14 @@ * Build the Graal graph for the method using the bytecode parser provided by Graal. */ - StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions()).method(method).build(); + OptionValues options = getInitialOptions(); + DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER); + StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(method).build(); /* * Support for graph dumping, IGV uses this information to show the method name of a * graph. */ - try (Scope scope = Debug.scope("graph building", graph)) { + try (DebugContext.Scope scope = debug.scope("graph building", graph)) { /* * We want all types to be resolved by the graph builder, i.e., we want classes * referenced by the bytecodes to be loaded and initialized. Since we do not run @@ -271,7 +274,7 @@ GraphBuilderPhase.Instance graphBuilder = new GraphBuilderPhase.Instance(metaAccess, stampProvider, null, null, graphBuilderConfig, optimisticOpts, null); graphBuilder.apply(graph); } catch (Throwable ex) { - Debug.handle(ex); + debug.handle(ex); } /* --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilerThread.java 2017-07-07 09:29:46.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilerThread.java 2017-07-07 09:29:46.000000000 -0700 @@ -22,42 +22,21 @@ */ package org.graalvm.compiler.core; -import org.graalvm.compiler.core.CompilerThreadFactory.DebugConfigAccess; -import org.graalvm.compiler.debug.DebugConfig; -import org.graalvm.compiler.debug.DebugDumpHandler; -import org.graalvm.compiler.debug.GraalDebugConfig; - /** - * A compiler thread is a daemon thread that runs at {@link Thread#MAX_PRIORITY} and executes in the - * context of a thread-local {@linkplain GraalDebugConfig debug configuration}. + * A compiler thread is a daemon thread that runs at {@link Thread#MAX_PRIORITY}. */ public class CompilerThread extends Thread { - private final DebugConfigAccess debugConfigAccess; - - public CompilerThread(Runnable r, String namePrefix, DebugConfigAccess debugConfigAccess) { + public CompilerThread(Runnable r, String namePrefix) { super(r); this.setName(namePrefix + "-" + this.getId()); this.setPriority(Thread.MAX_PRIORITY); this.setDaemon(true); - this.debugConfigAccess = debugConfigAccess; } @Override public void run() { - DebugConfig debugConfig = debugConfigAccess.getDebugConfig(); setContextClassLoader(getClass().getClassLoader()); - try { - super.run(); - } finally { - if (debugConfig != null) { - for (DebugDumpHandler dumpHandler : debugConfig.dumpHandlers()) { - try { - dumpHandler.close(); - } catch (Throwable t) { - } - } - } - } + super.run(); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilerThreadFactory.java 2017-07-07 09:29:46.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilerThreadFactory.java 2017-07-07 09:29:46.000000000 -0700 @@ -24,34 +24,19 @@ import java.util.concurrent.ThreadFactory; -import org.graalvm.compiler.debug.DebugConfig; - /** * Facility for creating {@linkplain CompilerThread compiler threads}. */ public class CompilerThreadFactory implements ThreadFactory { - /** - * Capability to get a thread-local debug configuration for the current thread. - */ - public interface DebugConfigAccess { - /** - * Get a thread-local debug configuration for the current thread. This will be null if - * debugging is disabled. - */ - DebugConfig getDebugConfig(); - } - protected final String threadNamePrefix; - protected final DebugConfigAccess debugConfigAccess; - public CompilerThreadFactory(String threadNamePrefix, DebugConfigAccess debugConfigAccess) { + public CompilerThreadFactory(String threadNamePrefix) { this.threadNamePrefix = threadNamePrefix; - this.debugConfigAccess = debugConfigAccess; } @Override public Thread newThread(Runnable r) { - return new CompilerThread(r, threadNamePrefix, debugConfigAccess); + return new CompilerThread(r, threadNamePrefix); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java 2017-07-07 09:29:47.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java 2017-07-07 09:29:46.000000000 -0700 @@ -33,14 +33,12 @@ import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; import org.graalvm.compiler.core.common.util.CompilationAlarm; import org.graalvm.compiler.core.target.Backend; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.CounterKey; import org.graalvm.compiler.debug.DebugCloseable; -import org.graalvm.compiler.debug.DebugCounter; -import org.graalvm.compiler.debug.DebugTimer; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.MethodFilter; -import org.graalvm.compiler.debug.internal.method.MethodMetricsRootScopeInfo; +import org.graalvm.compiler.debug.TimerKey; import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.alloc.OutOfRegistersException; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; @@ -85,11 +83,11 @@ */ public class GraalCompiler { - private static final DebugTimer CompilerTimer = Debug.timer("GraalCompiler"); - private static final DebugTimer FrontEnd = Debug.timer("FrontEnd"); - private static final DebugTimer BackEnd = Debug.timer("BackEnd"); - private static final DebugTimer EmitLIR = Debug.timer("EmitLIR"); - private static final DebugTimer EmitCode = Debug.timer("EmitCode"); + private static final TimerKey CompilerTimer = DebugContext.timer("GraalCompiler").doc("Time spent in compilation (excludes code installation)."); + private static final TimerKey FrontEnd = DebugContext.timer("FrontEnd").doc("Time spent processing HIR."); + private static final TimerKey EmitLIR = DebugContext.timer("EmitLIR").doc("Time spent generating LIR from HIR."); + private static final TimerKey EmitCode = DebugContext.timer("EmitCode").doc("Time spent generating machine code from LIR."); + private static final TimerKey BackEnd = DebugContext.timer("BackEnd").doc("Time spent in EmitLIR and EmitCode."); /** * Encapsulates all the inputs to a {@linkplain GraalCompiler#compile(Request) compilation}. @@ -167,14 +165,14 @@ */ @SuppressWarnings("try") public static T compile(Request r) { - try (Scope s = MethodMetricsRootScopeInfo.createRootScopeIfAbsent(r.installedCodeOwner); - CompilationAlarm alarm = CompilationAlarm.trackCompilationPeriod(r.graph.getOptions())) { + DebugContext debug = r.graph.getDebug(); + try (CompilationAlarm alarm = CompilationAlarm.trackCompilationPeriod(r.graph.getOptions())) { assert !r.graph.isFrozen(); - try (Scope s0 = Debug.scope("GraalCompiler", r.graph, r.providers.getCodeCache()); DebugCloseable a = CompilerTimer.start()) { + try (DebugContext.Scope s0 = debug.scope("GraalCompiler", r.graph, r.providers.getCodeCache()); DebugCloseable a = CompilerTimer.start(debug)) { emitFrontEnd(r.providers, r.backend, r.graph, r.graphBuilderSuite, r.optimisticOpts, r.profilingInfo, r.suites); emitBackEnd(r.graph, null, r.installedCodeOwner, r.backend, r.compilationResult, r.factory, null, r.lirSuites); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } checkForRequestedCrash(r.graph); return r.compilationResult; @@ -217,32 +215,33 @@ @SuppressWarnings("try") public static void emitFrontEnd(Providers providers, TargetProvider target, StructuredGraph graph, PhaseSuite graphBuilderSuite, OptimisticOptimizations optimisticOpts, ProfilingInfo profilingInfo, Suites suites) { - try (Scope s = Debug.scope("FrontEnd"); DebugCloseable a = FrontEnd.start()) { + DebugContext debug = graph.getDebug(); + try (DebugContext.Scope s = debug.scope("FrontEnd"); DebugCloseable a = FrontEnd.start(debug)) { HighTierContext highTierContext = new HighTierContext(providers, graphBuilderSuite, optimisticOpts); if (graph.start().next() == null) { graphBuilderSuite.apply(graph, highTierContext); new DeadCodeEliminationPhase(DeadCodeEliminationPhase.Optionality.Optional).apply(graph); - Debug.dump(Debug.BASIC_LEVEL, graph, "After parsing"); + debug.dump(DebugContext.BASIC_LEVEL, graph, "After parsing"); } else { - Debug.dump(Debug.INFO_LEVEL, graph, "initial state"); + debug.dump(DebugContext.INFO_LEVEL, graph, "initial state"); } suites.getHighTier().apply(graph, highTierContext); graph.maybeCompress(); - Debug.dump(Debug.BASIC_LEVEL, graph, "After high tier"); + debug.dump(DebugContext.BASIC_LEVEL, graph, "After high tier"); MidTierContext midTierContext = new MidTierContext(providers, target, optimisticOpts, profilingInfo); suites.getMidTier().apply(graph, midTierContext); graph.maybeCompress(); - Debug.dump(Debug.BASIC_LEVEL, graph, "After mid tier"); + debug.dump(DebugContext.BASIC_LEVEL, graph, "After mid tier"); LowTierContext lowTierContext = new LowTierContext(providers, target); suites.getLowTier().apply(graph, lowTierContext); - Debug.dump(Debug.BASIC_LEVEL, graph, "After low tier"); + debug.dump(DebugContext.BASIC_LEVEL, graph, "After low tier"); - Debug.dump(Debug.BASIC_LEVEL, graph.getLastSchedule(), "Final HIR schedule"); + debug.dump(DebugContext.BASIC_LEVEL, graph.getLastSchedule(), "Final HIR schedule"); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } finally { graph.checkCancellation(); } @@ -251,18 +250,19 @@ @SuppressWarnings("try") public static void emitBackEnd(StructuredGraph graph, Object stub, ResolvedJavaMethod installedCodeOwner, Backend backend, T compilationResult, CompilationResultBuilderFactory factory, RegisterConfig registerConfig, LIRSuites lirSuites) { - try (Scope s = Debug.scope("BackEnd", graph.getLastSchedule()); DebugCloseable a = BackEnd.start()) { + DebugContext debug = graph.getDebug(); + try (DebugContext.Scope s = debug.scope("BackEnd", graph.getLastSchedule()); DebugCloseable a = BackEnd.start(debug)) { LIRGenerationResult lirGen = null; lirGen = emitLIR(backend, graph, stub, registerConfig, lirSuites); - try (Scope s2 = Debug.scope("CodeGen", lirGen, lirGen.getLIR())) { + try (DebugContext.Scope s2 = debug.scope("CodeGen", lirGen, lirGen.getLIR())) { int bytecodeSize = graph.method() == null ? 0 : graph.getBytecodeSize(); compilationResult.setHasUnsafeAccess(graph.hasUnsafeAccess()); emitCode(backend, graph.getAssumptions(), graph.method(), graph.getMethods(), graph.getFields(), bytecodeSize, lirGen, compilationResult, installedCodeOwner, factory); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } finally { graph.checkCancellation(); } @@ -289,7 +289,8 @@ @SuppressWarnings("try") private static LIRGenerationResult emitLIR0(Backend backend, StructuredGraph graph, Object stub, RegisterConfig registerConfig, LIRSuites lirSuites, String[] allocationRestrictedTo) { - try (Scope ds = Debug.scope("EmitLIR"); DebugCloseable a = EmitLIR.start()) { + DebugContext debug = graph.getDebug(); + try (DebugContext.Scope ds = debug.scope("EmitLIR"); DebugCloseable a = EmitLIR.start(debug)) { assert !graph.hasValueProxies(); ScheduleResult schedule = graph.getLastSchedule(); Block[] blocks = schedule.getCFG().getBlocks(); @@ -299,7 +300,7 @@ AbstractBlockBase[] codeEmittingOrder = ComputeBlockOrder.computeCodeEmittingOrder(blocks.length, startBlock); AbstractBlockBase[] linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blocks.length, startBlock); - LIR lir = new LIR(schedule.getCFG(), linearScanOrder, codeEmittingOrder, graph.getOptions()); + LIR lir = new LIR(schedule.getCFG(), linearScanOrder, codeEmittingOrder, graph.getOptions(), graph.getDebug()); FrameMapBuilder frameMapBuilder = backend.newFrameMapBuilder(registerConfig); LIRGenerationResult lirGenRes = backend.newLIRGenerationResult(graph.compilationId(), lir, frameMapBuilder, graph, stub); @@ -310,16 +311,16 @@ LIRGenerationContext context = new LIRGenerationContext(lirGen, nodeLirGen, graph, schedule); new LIRGenerationPhase().apply(backend.getTarget(), lirGenRes, context); - try (Scope s = Debug.scope("LIRStages", nodeLirGen, lirGenRes, lir)) { + try (DebugContext.Scope s = debug.scope("LIRStages", nodeLirGen, lirGenRes, lir)) { // Dump LIR along with HIR (the LIR is looked up from context) - Debug.dump(Debug.BASIC_LEVEL, graph.getLastSchedule(), "After LIR generation"); + debug.dump(DebugContext.BASIC_LEVEL, graph.getLastSchedule(), "After LIR generation"); LIRGenerationResult result = emitLowLevel(backend.getTarget(), lirGenRes, lirGen, lirSuites, backend.newRegisterAllocationConfig(registerConfig, allocationRestrictedTo)); return result; } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } finally { graph.checkCancellation(); } @@ -338,17 +339,18 @@ public static LIRGenerationResult emitLowLevel(TargetDescription target, LIRGenerationResult lirGenRes, LIRGeneratorTool lirGen, LIRSuites lirSuites, RegisterAllocationConfig registerAllocationConfig) { + DebugContext debug = lirGenRes.getLIR().getDebug(); PreAllocationOptimizationContext preAllocOptContext = new PreAllocationOptimizationContext(lirGen); lirSuites.getPreAllocationOptimizationStage().apply(target, lirGenRes, preAllocOptContext); - Debug.dump(Debug.BASIC_LEVEL, lirGenRes.getLIR(), "After PreAllocationOptimizationStage"); + debug.dump(DebugContext.BASIC_LEVEL, lirGenRes.getLIR(), "After PreAllocationOptimizationStage"); AllocationContext allocContext = new AllocationContext(lirGen.getSpillMoveFactory(), registerAllocationConfig); lirSuites.getAllocationStage().apply(target, lirGenRes, allocContext); - Debug.dump(Debug.BASIC_LEVEL, lirGenRes.getLIR(), "After AllocationStage"); + debug.dump(DebugContext.BASIC_LEVEL, lirGenRes.getLIR(), "After AllocationStage"); PostAllocationOptimizationContext postAllocOptContext = new PostAllocationOptimizationContext(lirGen); lirSuites.getPostAllocationOptimizationStage().apply(target, lirGenRes, postAllocOptContext); - Debug.dump(Debug.BASIC_LEVEL, lirGenRes.getLIR(), "After PostAllocationOptimizationStage"); + debug.dump(DebugContext.BASIC_LEVEL, lirGenRes.getLIR(), "After PostAllocationOptimizationStage"); return lirGenRes; } @@ -357,7 +359,8 @@ public static void emitCode(Backend backend, Assumptions assumptions, ResolvedJavaMethod rootMethod, Collection inlinedMethods, EconomicSet accessedFields, int bytecodeSize, LIRGenerationResult lirGenRes, CompilationResult compilationResult, ResolvedJavaMethod installedCodeOwner, CompilationResultBuilderFactory factory) { - try (DebugCloseable a = EmitCode.start()) { + DebugContext debug = lirGenRes.getLIR().getDebug(); + try (DebugCloseable a = EmitCode.start(debug)) { FrameMap frameMap = lirGenRes.getFrameMap(); CompilationResultBuilder crb = backend.newCompilationResultBuilder(lirGenRes, frameMap, compilationResult, factory); backend.emitCode(crb, lirGenRes.getLIR(), installedCodeOwner); @@ -370,12 +373,12 @@ compilationResult.setBytecodeSize(bytecodeSize); } crb.finish(); - if (Debug.isCountEnabled()) { + if (debug.isCountEnabled()) { List ldp = compilationResult.getDataPatches(); JavaKind[] kindValues = JavaKind.values(); - DebugCounter[] dms = new DebugCounter[kindValues.length]; + CounterKey[] dms = new CounterKey[kindValues.length]; for (int i = 0; i < dms.length; i++) { - dms[i] = Debug.counter("DataPatches-%s", kindValues[i]); + dms[i] = DebugContext.counter("DataPatches-%s", kindValues[i]); } for (DataPatch dp : ldp) { @@ -386,17 +389,17 @@ kind = ((JavaConstant) constant).getJavaKind(); } } - dms[kind.ordinal()].add(1); + dms[kind.ordinal()].add(debug, 1); } - Debug.counter("CompilationResults").increment(); - Debug.counter("CodeBytesEmitted").add(compilationResult.getTargetCodeSize()); - Debug.counter("InfopointsEmitted").add(compilationResult.getInfopoints().size()); - Debug.counter("DataPatches").add(ldp.size()); - Debug.counter("ExceptionHandlersEmitted").add(compilationResult.getExceptionHandlers().size()); + DebugContext.counter("CompilationResults").increment(debug); + DebugContext.counter("CodeBytesEmitted").add(debug, compilationResult.getTargetCodeSize()); + DebugContext.counter("InfopointsEmitted").add(debug, compilationResult.getInfopoints().size()); + DebugContext.counter("DataPatches").add(debug, ldp.size()); + DebugContext.counter("ExceptionHandlersEmitted").add(debug, compilationResult.getExceptionHandlers().size()); } - Debug.dump(Debug.BASIC_LEVEL, compilationResult, "After code generation"); + debug.dump(DebugContext.BASIC_LEVEL, compilationResult, "After code generation"); } } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/LIRGenerationPhase.java 2017-07-07 09:29:47.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/LIRGenerationPhase.java 2017-07-07 09:29:47.000000000 -0700 @@ -26,9 +26,10 @@ import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; import org.graalvm.compiler.core.common.cfg.BlockMap; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.gen.LIRGenerationResult; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import org.graalvm.compiler.lir.phases.LIRPhase; @@ -56,8 +57,8 @@ } } - private static final DebugCounter instructionCounter = Debug.counter("GeneratedLIRInstructions"); - private static final DebugCounter nodeCount = Debug.counter("FinalNodeCount"); + private static final CounterKey instructionCounter = DebugContext.counter("GeneratedLIRInstructions"); + private static final CounterKey nodeCount = DebugContext.counter("FinalNodeCount"); @Override protected final void run(TargetDescription target, LIRGenerationResult lirGenRes, LIRGenerationPhase.LIRGenerationContext context) { @@ -69,18 +70,16 @@ } context.lirGen.beforeRegisterAllocation(); assert SSAUtil.verifySSAForm(lirGenRes.getLIR()); - if (nodeCount.isEnabled()) { - nodeCount.add(graph.getNodeCount()); - } + nodeCount.add(graph.getDebug(), graph.getNodeCount()); } private static void emitBlock(NodeLIRBuilderTool nodeLirGen, LIRGenerationResult lirGenRes, Block b, StructuredGraph graph, BlockMap> blockMap) { assert !isProcessed(lirGenRes, b) : "Block already processed " + b; assert verifyPredecessors(lirGenRes, b); nodeLirGen.doBlock(b, graph, blockMap); - if (instructionCounter.isEnabled()) { - instructionCounter.add(lirGenRes.getLIR().getLIRforBlock(b).size()); - } + LIR lir = lirGenRes.getLIR(); + DebugContext debug = lir.getDebug(); + instructionCounter.add(debug, lir.getLIRforBlock(b).size()); } private static boolean verifyPredecessors(LIRGenerationResult lirGenRes, Block block) { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java 2017-07-07 09:29:47.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java 2017-07-07 09:29:47.000000000 -0700 @@ -26,8 +26,8 @@ import java.util.Arrays; import java.util.Queue; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.lir.ConstantValue; import org.graalvm.compiler.lir.LIRFrameState; @@ -42,8 +42,8 @@ import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; import org.graalvm.compiler.virtual.nodes.MaterializedObjectState; import org.graalvm.compiler.virtual.nodes.VirtualObjectState; -import org.graalvm.util.Equivalence; import org.graalvm.util.EconomicMap; +import org.graalvm.util.Equivalence; import jdk.vm.ci.code.BytecodeFrame; import jdk.vm.ci.code.VirtualObject; @@ -61,9 +61,11 @@ public class DebugInfoBuilder { protected final NodeValueMap nodeValueMap; + protected final DebugContext debug; - public DebugInfoBuilder(NodeValueMap nodeValueMap) { + public DebugInfoBuilder(NodeValueMap nodeValueMap, DebugContext debug) { this.nodeValueMap = nodeValueMap; + this.debug = debug; } private static final JavaValue[] NO_JAVA_VALUES = {}; @@ -276,10 +278,10 @@ return toJavaValue(state.lockAt(i)); } - private static final DebugCounter STATE_VIRTUAL_OBJECTS = Debug.counter("StateVirtualObjects"); - private static final DebugCounter STATE_ILLEGALS = Debug.counter("StateIllegals"); - private static final DebugCounter STATE_VARIABLES = Debug.counter("StateVariables"); - private static final DebugCounter STATE_CONSTANTS = Debug.counter("StateConstants"); + private static final CounterKey STATE_VIRTUAL_OBJECTS = DebugContext.counter("StateVirtualObjects"); + private static final CounterKey STATE_ILLEGALS = DebugContext.counter("StateIllegals"); + private static final CounterKey STATE_VARIABLES = DebugContext.counter("StateVariables"); + private static final CounterKey STATE_CONSTANTS = DebugContext.counter("StateConstants"); private static JavaKind toSlotKind(ValueNode value) { if (value == null) { @@ -308,18 +310,18 @@ virtualObjects.put(obj, vobject); pendingVirtualObjects.add(obj); } - STATE_VIRTUAL_OBJECTS.increment(); + STATE_VIRTUAL_OBJECTS.increment(debug); return vobject; } } else { // Remove proxies from constants so the constant can be directly embedded. ValueNode unproxied = GraphUtil.unproxify(value); if (unproxied instanceof ConstantNode) { - STATE_CONSTANTS.increment(); + STATE_CONSTANTS.increment(debug); return unproxied.asJavaConstant(); } else if (value != null) { - STATE_VARIABLES.increment(); + STATE_VARIABLES.increment(debug); Value operand = nodeValueMap.operand(value); if (operand instanceof ConstantValue && ((ConstantValue) operand).isJavaConstant()) { return ((ConstantValue) operand).getJavaConstant(); @@ -330,7 +332,7 @@ } else { // return a dummy value because real value not needed - STATE_ILLEGALS.increment(); + STATE_ILLEGALS.increment(debug); return Value.ILLEGAL; } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java 2017-07-07 09:29:48.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java 2017-07-07 09:29:48.000000000 -0700 @@ -26,12 +26,13 @@ import static jdk.vm.ci.code.ValueUtil.isLegal; import static jdk.vm.ci.code.ValueUtil.isRegister; import static org.graalvm.compiler.core.common.GraalOptions.MatchExpressions; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.LogVerbose; +import static org.graalvm.compiler.debug.DebugOptions.LogVerbose; import static org.graalvm.compiler.lir.LIR.verifyBlock; import java.util.ArrayList; import java.util.Collection; import java.util.List; + import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; @@ -41,8 +42,7 @@ import org.graalvm.compiler.core.match.MatchPattern; import org.graalvm.compiler.core.match.MatchRuleRegistry; import org.graalvm.compiler.core.match.MatchStatement; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.graph.GraalGraphError; @@ -135,7 +135,7 @@ this.debugInfoBuilder = createDebugInfoBuilder(graph, this); OptionValues options = graph.getOptions(); if (MatchExpressions.getValue(options)) { - matchRules = MatchRuleRegistry.lookup(nodeMatchRules.getClass(), options); + matchRules = MatchRuleRegistry.lookup(nodeMatchRules.getClass(), options, graph.getDebug()); } traceLIRGeneratorLevel = TTY.isSuppressed() ? 0 : Options.TraceLIRGeneratorLevel.getValue(options); @@ -147,9 +147,8 @@ return nodeMatchRules; } - @SuppressWarnings({"unused"}) protected DebugInfoBuilder createDebugInfoBuilder(StructuredGraph graph, NodeValueMap nodeValueMap) { - return new DebugInfoBuilder(nodeValueMap); + return new DebugInfoBuilder(nodeValueMap, graph.getDebug()); } /** @@ -351,6 +350,7 @@ for (int i = 0; i < nodes.size(); i++) { Node node = nodes.get(i); if (node instanceof ValueNode) { + DebugContext debug = node.getDebug(); ValueNode valueNode = (ValueNode) node; if (trace) { TTY.println("LIRGen for " + valueNode); @@ -368,9 +368,9 @@ } } else if (ComplexMatchValue.INTERIOR_MATCH.equals(operand)) { // Doesn't need to be evaluated - Debug.log("interior match for %s", valueNode); + debug.log("interior match for %s", valueNode); } else if (operand instanceof ComplexMatchValue) { - Debug.log("complex match for %s", valueNode); + debug.log("complex match for %s", valueNode); ComplexMatchValue match = (ComplexMatchValue) operand; operand = match.evaluate(this); if (operand != null) { @@ -403,11 +403,12 @@ @SuppressWarnings("try") protected void matchComplexExpressions(List nodes) { if (matchRules != null) { - try (Scope s = Debug.scope("MatchComplexExpressions")) { + DebugContext debug = gen.getResult().getLIR().getDebug(); + try (DebugContext.Scope s = debug.scope("MatchComplexExpressions")) { if (LogVerbose.getValue(nodeOperands.graph().getOptions())) { int i = 0; for (Node node : nodes) { - Debug.log("%d: (%s) %1S", i++, node.getUsageCount(), node); + debug.log("%d: (%s) %1S", i++, node.getUsageCount(), node); } } @@ -439,15 +440,15 @@ TTY.println("Emitting LIR for instruction " + instr); } currentInstruction = instr; - - Debug.log("Visiting %s", instr); + DebugContext debug = instr.getDebug(); + debug.log("Visiting %s", instr); emitNode(instr); - Debug.log("Operand for %s = %s", instr, getOperand(instr)); + debug.log("Operand for %s = %s", instr, getOperand(instr)); } protected void emitNode(ValueNode node) { - if (Debug.isLogEnabled() && node.stamp().isEmpty()) { - Debug.log("This node has an empty stamp, we are emitting dead code(?): %s", node); + if (node.getDebug().isLogEnabled() && node.stamp().isEmpty()) { + node.getDebug().log("This node has an empty stamp, we are emitting dead code(?): %s", node); } setSourcePosition(node.getNodeSourcePosition()); if (node instanceof LIRLowerable) { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java 2017-07-07 09:29:48.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java 2017-07-07 09:29:48.000000000 -0700 @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.core.match; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.LogVerbose; +import static org.graalvm.compiler.debug.DebugOptions.LogVerbose; import java.util.ArrayList; import java.util.Arrays; @@ -30,13 +30,13 @@ import org.graalvm.compiler.core.gen.NodeLIRBuilder; import org.graalvm.compiler.core.match.MatchPattern.Result; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; -import org.graalvm.util.Equivalence; import org.graalvm.util.EconomicMap; +import org.graalvm.util.Equivalence; /** * Container for state captured during a match. @@ -110,10 +110,11 @@ continue; } else if ((consumed == null || !consumed.contains(node)) && node != root) { if (LogVerbose.getValue(root.getOptions())) { - Debug.log("unexpected node %s", node); + DebugContext debug = root.getDebug(); + debug.log("unexpected node %s", node); for (int j = startIndex; j <= endIndex; j++) { Node theNode = nodes.get(j); - Debug.log("%s(%s) %1s", (consumed != null && consumed.contains(theNode) || theNode == root) ? "*" : " ", theNode.getUsageCount(), theNode); + debug.log("%s(%s) %1s", (consumed != null && consumed.contains(theNode) || theNode == root) ? "*" : " ", theNode.getUsageCount(), theNode); } } return Result.notSafe(node, rule.getPattern()); @@ -130,9 +131,10 @@ */ public void setResult(ComplexMatchResult result) { ComplexMatchValue value = new ComplexMatchValue(result); - if (Debug.isLogEnabled()) { - Debug.log("matched %s %s", rule.getName(), rule.getPattern()); - Debug.log("with nodes %s", rule.formatMatch(root)); + DebugContext debug = root.getDebug(); + if (debug.isLogEnabled()) { + debug.log("matched %s %s", rule.getName(), rule.getPattern()); + debug.log("with nodes %s", rule.formatMatch(root)); } if (consumed != null) { for (Node node : consumed) { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchPattern.java 2017-07-07 09:29:49.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchPattern.java 2017-07-07 09:29:49.000000000 -0700 @@ -22,8 +22,8 @@ */ package org.graalvm.compiler.core.match; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.Position; import org.graalvm.compiler.nodeinfo.InputType; @@ -62,12 +62,12 @@ this.matcher = matcher; } - private static final DebugCounter MatchResult_WRONG_CLASS = Debug.counter("MatchResult_WRONG_CLASS"); - private static final DebugCounter MatchResult_NAMED_VALUE_MISMATCH = Debug.counter("MatchResult_NAMED_VALUE_MISMATCH"); - private static final DebugCounter MatchResult_TOO_MANY_USERS = Debug.counter("MatchResult_TOO_MANY_USERS"); - private static final DebugCounter MatchResult_NOT_IN_BLOCK = Debug.counter("MatchResult_NOT_IN_BLOCK"); - private static final DebugCounter MatchResult_NOT_SAFE = Debug.counter("MatchResult_NOT_SAFE"); - private static final DebugCounter MatchResult_ALREADY_USED = Debug.counter("MatchResult_ALREADY_USED"); + private static final CounterKey MatchResult_WRONG_CLASS = DebugContext.counter("MatchResult_WRONG_CLASS"); + private static final CounterKey MatchResult_NAMED_VALUE_MISMATCH = DebugContext.counter("MatchResult_NAMED_VALUE_MISMATCH"); + private static final CounterKey MatchResult_TOO_MANY_USERS = DebugContext.counter("MatchResult_TOO_MANY_USERS"); + private static final CounterKey MatchResult_NOT_IN_BLOCK = DebugContext.counter("MatchResult_NOT_IN_BLOCK"); + private static final CounterKey MatchResult_NOT_SAFE = DebugContext.counter("MatchResult_NOT_SAFE"); + private static final CounterKey MatchResult_ALREADY_USED = DebugContext.counter("MatchResult_ALREADY_USED"); static final Result OK = new Result(MatchResultCode.OK, null, null); private static final Result CACHED_WRONG_CLASS = new Result(MatchResultCode.WRONG_CLASS, null, null); @@ -78,33 +78,33 @@ private static final Result CACHED_ALREADY_USED = new Result(MatchResultCode.ALREADY_USED, null, null); static Result wrongClass(Node node, MatchPattern matcher) { - MatchResult_WRONG_CLASS.increment(); - return Debug.isLogEnabled() ? new Result(MatchResultCode.WRONG_CLASS, node, matcher) : CACHED_WRONG_CLASS; + MatchResult_WRONG_CLASS.increment(node.getDebug()); + return node.getDebug().isLogEnabled() ? new Result(MatchResultCode.WRONG_CLASS, node, matcher) : CACHED_WRONG_CLASS; } static Result namedValueMismatch(Node node, MatchPattern matcher) { - MatchResult_NAMED_VALUE_MISMATCH.increment(); - return Debug.isLogEnabled() ? new Result(MatchResultCode.NAMED_VALUE_MISMATCH, node, matcher) : CACHED_NAMED_VALUE_MISMATCH; + MatchResult_NAMED_VALUE_MISMATCH.increment(node.getDebug()); + return node.getDebug().isLogEnabled() ? new Result(MatchResultCode.NAMED_VALUE_MISMATCH, node, matcher) : CACHED_NAMED_VALUE_MISMATCH; } static Result tooManyUsers(Node node, MatchPattern matcher) { - MatchResult_TOO_MANY_USERS.increment(); - return Debug.isLogEnabled() ? new Result(MatchResultCode.TOO_MANY_USERS, node, matcher) : CACHED_TOO_MANY_USERS; + MatchResult_TOO_MANY_USERS.increment(node.getDebug()); + return node.getDebug().isLogEnabled() ? new Result(MatchResultCode.TOO_MANY_USERS, node, matcher) : CACHED_TOO_MANY_USERS; } static Result notInBlock(Node node, MatchPattern matcher) { - MatchResult_NOT_IN_BLOCK.increment(); - return Debug.isLogEnabled() ? new Result(MatchResultCode.NOT_IN_BLOCK, node, matcher) : CACHED_NOT_IN_BLOCK; + MatchResult_NOT_IN_BLOCK.increment(node.getDebug()); + return node.getDebug().isLogEnabled() ? new Result(MatchResultCode.NOT_IN_BLOCK, node, matcher) : CACHED_NOT_IN_BLOCK; } static Result notSafe(Node node, MatchPattern matcher) { - MatchResult_NOT_SAFE.increment(); - return Debug.isLogEnabled() ? new Result(MatchResultCode.NOT_SAFE, node, matcher) : CACHED_NOT_SAFE; + MatchResult_NOT_SAFE.increment(node.getDebug()); + return node.getDebug().isLogEnabled() ? new Result(MatchResultCode.NOT_SAFE, node, matcher) : CACHED_NOT_SAFE; } static Result alreadyUsed(Node node, MatchPattern matcher) { - MatchResult_ALREADY_USED.increment(); - return Debug.isLogEnabled() ? new Result(MatchResultCode.ALREADY_USED, node, matcher) : CACHED_ALREADY_USED; + MatchResult_ALREADY_USED.increment(node.getDebug()); + return node.getDebug().isLogEnabled() ? new Result(MatchResultCode.ALREADY_USED, node, matcher) : CACHED_ALREADY_USED; } @Override --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchRuleRegistry.java 2017-07-07 09:29:49.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchRuleRegistry.java 2017-07-07 09:29:49.000000000 -0700 @@ -22,13 +22,13 @@ */ package org.graalvm.compiler.core.match; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.LogVerbose; +import static org.graalvm.compiler.debug.DebugOptions.LogVerbose; + import java.util.ArrayList; import java.util.List; import org.graalvm.compiler.core.gen.NodeMatchRules; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Edges; import org.graalvm.compiler.graph.Node; @@ -36,8 +36,8 @@ import org.graalvm.compiler.graph.Position; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.serviceprovider.GraalServices; -import org.graalvm.util.Equivalence; import org.graalvm.util.EconomicMap; +import org.graalvm.util.Equivalence; import org.graalvm.util.MapCursor; public class MatchRuleRegistry { @@ -77,7 +77,7 @@ * @return the set of {@link MatchStatement}s applicable to theClass. */ @SuppressWarnings("try") - public static synchronized EconomicMap, List> lookup(Class theClass, OptionValues options) { + public static synchronized EconomicMap, List> lookup(Class theClass, OptionValues options, DebugContext debug) { EconomicMap, List> result = registry.get(theClass); if (result == null) { @@ -87,13 +87,13 @@ result = rules; if (LogVerbose.getValue(options)) { - try (Scope s = Debug.scope("MatchComplexExpressions")) { - Debug.log("Match rules for %s", theClass.getSimpleName()); + try (DebugContext.Scope s = debug.scope("MatchComplexExpressions")) { + debug.log("Match rules for %s", theClass.getSimpleName()); MapCursor, List> cursor = result.getEntries(); while (cursor.advance()) { - Debug.log(" For node class: %s", cursor.getKey()); + debug.log(" For node class: %s", cursor.getKey()); for (MatchStatement statement : cursor.getValue()) { - Debug.log(" %s", statement.getPattern()); + debug.log(" %s", statement.getPattern()); } } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchStatement.java 2017-07-07 09:29:49.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchStatement.java 2017-07-07 09:29:49.000000000 -0700 @@ -22,28 +22,28 @@ */ package org.graalvm.compiler.core.match; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.LogVerbose; +import static org.graalvm.compiler.debug.DebugOptions.LogVerbose; import java.util.List; -import jdk.vm.ci.meta.Value; - import org.graalvm.compiler.core.gen.NodeLIRBuilder; import org.graalvm.compiler.core.match.MatchPattern.MatchResultCode; import org.graalvm.compiler.core.match.MatchPattern.Result; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.GraalGraphError; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodeinfo.Verbosity; +import jdk.vm.ci.meta.Value; + /** * A named {@link MatchPattern} along with a {@link MatchGenerator} that can be evaluated to replace * one or more {@link Node}s with a single {@link Value}. */ public class MatchStatement { - private static final DebugCounter MatchStatementSuccess = Debug.counter("MatchStatementSuccess"); + private static final CounterKey MatchStatementSuccess = DebugContext.counter("MatchStatementSuccess"); /** * A printable name for this statement. Usually it's just the name of the method doing the @@ -83,6 +83,7 @@ * evaluated by the NodeLIRBuilder. */ public boolean generate(NodeLIRBuilder builder, int index, Node node, List nodes) { + DebugContext debug = node.getDebug(); assert index == nodes.indexOf(node); // Check that the basic shape matches Result result = pattern.matchShape(node, this); @@ -97,19 +98,19 @@ ComplexMatchResult value = generatorMethod.match(builder.getNodeMatchRules(), buildArgList(context)); if (value != null) { context.setResult(value); - MatchStatementSuccess.increment(); - Debug.counter("MatchStatement[%s]", getName()).increment(); + MatchStatementSuccess.increment(debug); + DebugContext.counter("MatchStatement[%s]", getName()).increment(debug); return true; } // The pattern matched but some other code generation constraint disallowed code // generation for the pattern. if (LogVerbose.getValue(node.getOptions())) { - Debug.log("while matching %s|%s %s %s returned null", context.getRoot().toString(Verbosity.Id), context.getRoot().getClass().getSimpleName(), getName(), generatorMethod.getName()); - Debug.log("with nodes %s", formatMatch(node)); + debug.log("while matching %s|%s %s %s returned null", context.getRoot().toString(Verbosity.Id), context.getRoot().getClass().getSimpleName(), getName(), generatorMethod.getName()); + debug.log("with nodes %s", formatMatch(node)); } } else { if (LogVerbose.getValue(node.getOptions()) && result.code != MatchResultCode.WRONG_CLASS) { - Debug.log("while matching %s|%s %s %s", context.getRoot().toString(Verbosity.Id), context.getRoot().getClass().getSimpleName(), getName(), result); + debug.log("while matching %s|%s %s %s", context.getRoot().toString(Verbosity.Id), context.getRoot().getClass().getSimpleName(), getName(), result); } } return false; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyCompilerConfiguration.java 2017-07-07 09:29:50.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyCompilerConfiguration.java 2017-07-07 09:29:50.000000000 -0700 @@ -60,7 +60,7 @@ @Override public LIRPhaseSuite createAllocationStage(OptionValues options) { - return new EconomyAllocationStage(); + return new EconomyAllocationStage(options); } @Override --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/GraphChangeMonitoringPhase.java 2017-07-07 09:29:50.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/GraphChangeMonitoringPhase.java 2017-07-07 09:29:50.000000000 -0700 @@ -22,8 +22,7 @@ */ package org.graalvm.compiler.core.phases; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Graph.NodeEvent; import org.graalvm.compiler.graph.Graph.NodeEventScope; import org.graalvm.compiler.graph.Node; @@ -33,8 +32,8 @@ import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.util.HashSetNodeEventListener; import org.graalvm.compiler.phases.tiers.PhaseContext; -import org.graalvm.util.Equivalence; import org.graalvm.util.EconomicSet; +import org.graalvm.util.Equivalence; /** * A utility phase for detecting when a phase would change the graph and reporting extra information @@ -68,12 +67,13 @@ * having their inputs change are the main interesting differences. */ HashSetNodeEventListener listener = new HashSetNodeEventListener().exclude(NodeEvent.NODE_ADDED); - StructuredGraph graphCopy = (StructuredGraph) graph.copy(); + StructuredGraph graphCopy = (StructuredGraph) graph.copy(graph.getDebug()); + DebugContext debug = graph.getDebug(); try (NodeEventScope s = graphCopy.trackNodeEvents(listener)) { - try (Scope s2 = Debug.sandbox("WithoutMonitoring", null)) { + try (DebugContext.Scope s2 = debug.sandbox("WithoutMonitoring", null)) { super.run(graphCopy, context); } catch (Throwable t) { - Debug.handle(t); + debug.handle(t); } } @@ -90,15 +90,15 @@ /* rerun it on the real graph in a new Debug scope so Dump and Log can find it. */ listener = new HashSetNodeEventListener(); try (NodeEventScope s = graph.trackNodeEvents(listener)) { - try (Scope s2 = Debug.scope("WithGraphChangeMonitoring")) { - if (Debug.isDumpEnabled(Debug.DETAILED_LEVEL)) { - Debug.dump(Debug.DETAILED_LEVEL, graph, "*** Before phase %s", getName()); + try (DebugContext.Scope s2 = debug.scope("WithGraphChangeMonitoring")) { + if (debug.isDumpEnabled(DebugContext.DETAILED_LEVEL)) { + debug.dump(DebugContext.DETAILED_LEVEL, graph, "*** Before phase %s", getName()); } super.run(graph, context); - if (Debug.isDumpEnabled(Debug.DETAILED_LEVEL)) { - Debug.dump(Debug.DETAILED_LEVEL, graph, "*** After phase %s %s", getName(), filteredNodes); + if (debug.isDumpEnabled(DebugContext.DETAILED_LEVEL)) { + debug.dump(DebugContext.DETAILED_LEVEL, graph, "*** After phase %s %s", getName(), filteredNodes); } - Debug.log("*** %s %s %s\n", message, graph, filteredNodes); + debug.log("*** %s %s %s\n", message, graph, filteredNodes); } } } else { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/MidTier.java 2017-07-07 09:29:51.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/MidTier.java 2017-07-07 09:29:50.000000000 -0700 @@ -26,9 +26,14 @@ import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; import static org.graalvm.compiler.core.common.GraalOptions.OptDeoptimizationGrouping; import static org.graalvm.compiler.core.common.GraalOptions.OptFloatingReads; +import static org.graalvm.compiler.core.common.GraalOptions.OptLoopTransform; +import static org.graalvm.compiler.core.common.GraalOptions.PartialUnroll; import static org.graalvm.compiler.core.common.GraalOptions.ReassociateInvariants; import static org.graalvm.compiler.core.common.GraalOptions.VerifyHeapAtReturn; +import org.graalvm.compiler.loop.DefaultLoopPolicies; +import org.graalvm.compiler.loop.LoopPolicies; +import org.graalvm.compiler.loop.phases.LoopPartialUnrollPhase; import org.graalvm.compiler.loop.phases.LoopSafepointEliminationPhase; import org.graalvm.compiler.loop.phases.ReassociateInvariantPhase; import org.graalvm.compiler.nodes.spi.LoweringTool; @@ -79,6 +84,12 @@ appendPhase(new FrameStateAssignmentPhase()); + LoopPolicies loopPolicies = createLoopPolicies(); + if (OptLoopTransform.getValue(options)) { + if (PartialUnroll.getValue(options)) { + appendPhase(new LoopPartialUnrollPhase(loopPolicies, canonicalizer)); + } + } if (ReassociateInvariants.getValue(options)) { appendPhase(new ReassociateInvariantPhase()); } @@ -89,4 +100,8 @@ appendPhase(canonicalizer); } + + public LoopPolicies createLoopPolicies() { + return new DefaultLoopPolicies(); + } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java 2017-07-07 09:29:51.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java 2017-07-07 09:29:51.000000000 -0700 @@ -22,6 +22,8 @@ */ package org.graalvm.compiler.core.target; +import java.util.ArrayList; + import org.graalvm.compiler.asm.Assembler; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.common.CompilationIdentifier; @@ -29,8 +31,7 @@ import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; @@ -60,8 +61,6 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.SpeculationLog; -import java.util.ArrayList; - /** * Represents a compiler backend for Graal. */ @@ -155,22 +154,22 @@ protected abstract CompiledCode createCompiledCode(ResolvedJavaMethod method, CompilationRequest compilationRequest, CompilationResult compilationResult); /** - * @see #createInstalledCode(ResolvedJavaMethod, CompilationRequest, CompilationResult, - * SpeculationLog, InstalledCode, boolean) + * @see #createInstalledCode(DebugContext, ResolvedJavaMethod, CompilationRequest, + * CompilationResult, SpeculationLog, InstalledCode, boolean, Object[]) */ - public InstalledCode createInstalledCode(ResolvedJavaMethod method, CompilationResult compilationResult, + public InstalledCode createInstalledCode(DebugContext debug, ResolvedJavaMethod method, CompilationResult compilationResult, SpeculationLog speculationLog, InstalledCode predefinedInstalledCode, boolean isDefault) { - return createInstalledCode(method, null, compilationResult, speculationLog, predefinedInstalledCode, isDefault); + return createInstalledCode(debug, method, null, compilationResult, speculationLog, predefinedInstalledCode, isDefault, null); } /** - * @see #createInstalledCode(ResolvedJavaMethod, CompilationRequest, CompilationResult, - * SpeculationLog, InstalledCode, boolean, Object[]) + * @see #createInstalledCode(DebugContext, ResolvedJavaMethod, CompilationRequest, + * CompilationResult, SpeculationLog, InstalledCode, boolean, Object[]) */ @SuppressWarnings("try") - public InstalledCode createInstalledCode(ResolvedJavaMethod method, CompilationRequest compilationRequest, CompilationResult compilationResult, + public InstalledCode createInstalledCode(DebugContext debug, ResolvedJavaMethod method, CompilationRequest compilationRequest, CompilationResult compilationResult, SpeculationLog speculationLog, InstalledCode predefinedInstalledCode, boolean isDefault) { - return createInstalledCode(method, compilationRequest, compilationResult, speculationLog, predefinedInstalledCode, isDefault, null); + return createInstalledCode(debug, method, compilationRequest, compilationResult, speculationLog, predefinedInstalledCode, isDefault, null); } /** @@ -188,19 +187,20 @@ * {@code compRequest.getMethod()}. The default implementation for a method is the * code executed for standard calls to the method. This argument is ignored if * {@code compRequest == null}. - * @param context a custom debug context to use for the code installation. + * @param context a custom debug context to use for the code installation * @return a reference to the compiled and ready-to-run installed code * @throws BailoutException if the code installation failed */ @SuppressWarnings("try") - public InstalledCode createInstalledCode(ResolvedJavaMethod method, CompilationRequest compilationRequest, CompilationResult compilationResult, + public InstalledCode createInstalledCode(DebugContext debug, ResolvedJavaMethod method, CompilationRequest compilationRequest, CompilationResult compilationResult, SpeculationLog speculationLog, InstalledCode predefinedInstalledCode, boolean isDefault, Object[] context) { Object[] debugContext = context != null ? context : new Object[]{getProviders().getCodeCache(), method, compilationResult}; CodeInstallationTask[] tasks = new CodeInstallationTask[codeInstallationTaskFactories.size()]; for (int i = 0; i < codeInstallationTaskFactories.size(); i++) { tasks[i] = codeInstallationTaskFactories.get(i).create(); } - try (Scope s = Debug.scope("CodeInstall", debugContext)) { + try (DebugContext.Scope s2 = debug.scope("CodeInstall", debugContext); + DebugContext.Activation a = debug.activate()) { for (CodeInstallationTask task : tasks) { task.preProcess(compilationResult); } @@ -222,7 +222,7 @@ } return installedCode; } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } @@ -236,8 +236,8 @@ * @return a reference to the compiled and ready-to-run installed code * @throws BailoutException if the code installation failed */ - public InstalledCode addInstalledCode(ResolvedJavaMethod method, CompilationRequest compilationRequest, CompilationResult compilationResult) { - return createInstalledCode(method, compilationRequest, compilationResult, null, null, false); + public InstalledCode addInstalledCode(DebugContext debug, ResolvedJavaMethod method, CompilationRequest compilationRequest, CompilationResult compilationResult) { + return createInstalledCode(debug, method, compilationRequest, compilationResult, null, null, false); } /** @@ -250,8 +250,8 @@ * @return a reference to the compiled and ready-to-run installed code * @throws BailoutException if the code installation failed */ - public InstalledCode createDefaultInstalledCode(ResolvedJavaMethod method, CompilationResult compilationResult) { - return createInstalledCode(method, compilationResult, null, null, true); + public InstalledCode createDefaultInstalledCode(DebugContext debug, ResolvedJavaMethod method, CompilationResult compilationResult) { + return createInstalledCode(debug, method, compilationResult, null, null, true); } /** --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/CSVUtil.java 2017-07-07 09:29:51.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/CSVUtil.java 2017-07-07 09:29:51.000000000 -0700 @@ -84,7 +84,11 @@ return out; } - private static Object[] escapeArgs(char separator, char quote, char escape, Object... args) { + public static Object[] escapeArgs(Object... args) { + return escapeArgs(SEPARATOR, QUOTE, ESCAPE, args); + } + + public static Object[] escapeArgs(char separator, char quote, char escape, Object... args) { String separatorStr = String.valueOf(separator); for (int i = 0; i < args.length; i++) { Object obj = args[i]; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugCloseable.java 2017-07-07 09:29:52.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugCloseable.java 2017-07-07 09:29:52.000000000 -0700 @@ -34,6 +34,13 @@ } }; + /** + * Gets the debug context associated with this object. + */ + default DebugContext getDebug() { + return null; + } + @Override void close(); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfig.java 2017-07-07 09:29:52.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfig.java 2017-07-07 09:29:52.000000000 -0700 @@ -25,86 +25,68 @@ import java.io.PrintStream; import java.util.Collection; +import org.graalvm.compiler.debug.DebugContext.Scope; import org.graalvm.compiler.options.OptionValues; +import jdk.vm.ci.meta.JavaMethod; + public interface DebugConfig { /** - * Returns the option values that can be used to configure details of debug clients. + * Returns the option values used to configure this object. */ OptionValues getOptions(); /** - * Determines the current log level in the {@linkplain Debug#currentScope() current debug scope} - * . + * Determines the current log level in {@code scope}. */ - int getLogLevel(); + int getLogLevel(DebugContext.Scope scope); /** - * Determines the current dump level in the {@linkplain Debug#currentScope() current debug - * scope}. + * Determines the current dump level in {@code scope}. */ - int getDumpLevel(); + int getDumpLevel(DebugContext.Scope scope); /** - * Determines if logging can be enabled in the current method, regardless of the - * {@linkplain Debug#currentScope() current debug scope}. + * Determines if logging is enabled for any {@link JavaMethod} in {@code scope}'s + * {@linkplain Scope#getCurrentContext() context}. */ - boolean isLogEnabledForMethod(); + boolean isLogEnabledForMethod(DebugContext.Scope scope); /** - * Determines if counting is enabled in the {@linkplain Debug#currentScope() current debug - * scope}. + * Determines if counting is enabled in {@code scope}. * - * @see Debug#counter(CharSequence) + * @see DebugContext#counter(CharSequence) */ - boolean isCountEnabled(); + boolean isCountEnabled(DebugContext.Scope scope); /** - * Determines if memory use tracking is enabled in the {@linkplain Debug#currentScope() current - * debug scope}. + * Determines if memory use tracking is {@code scope}. * - * @see Debug#memUseTracker(CharSequence) + * @see DebugContext#memUseTracker(CharSequence) */ - boolean isMemUseTrackingEnabled(); + boolean isMemUseTrackingEnabled(DebugContext.Scope scope); /** - * Determines if dumping can be enabled in the current method, regardless of the - * {@linkplain Debug#currentScope() current debug scope}. + * Determines if dumping is enabled for any {@link JavaMethod} in {@code scope}'s + * {@linkplain Scope#getCurrentContext() context}. */ - boolean isDumpEnabledForMethod(); + boolean isDumpEnabledForMethod(DebugContext.Scope scope); /** - * @see Debug#isVerifyEnabled() + * @see DebugContext#isVerifyEnabled() */ - boolean isVerifyEnabled(); + boolean isVerifyEnabled(DebugContext.Scope scope); /** - * @see Debug#isVerifyEnabledForMethod() + * @see DebugContext#isVerifyEnabledForMethod() */ - boolean isVerifyEnabledForMethod(); + boolean isVerifyEnabledForMethod(DebugContext.Scope scope); /** - * @see Debug#isMethodMeterEnabled() + * @see DebugContext#timer(CharSequence) */ - boolean isMethodMeterEnabled(); - - /** - * Adds an object the context used by this configuration to do filtering. - */ - void addToContext(Object o); - - /** - * Removes an object the context used by this configuration to do filtering. - * - * This should only removes extra context added by {@link #addToContext(Object)}. - */ - void removeFromContext(Object o); - - /** - * @see Debug#timer(CharSequence) - */ - boolean isTimeEnabled(); + boolean isTimeEnabled(DebugContext.Scope scope); /** * Handles notification of an exception occurring within a debug scope. @@ -112,18 +94,47 @@ * @return the exception object that is to be propagated to parent scope. A value of * {@code null} indicates that {@code e} is to be propagated. */ - RuntimeException interceptException(Throwable e); + RuntimeException interceptException(DebugContext debug, Throwable e); /** - * Gets the modifiable collection of dump handlers registered with this configuration. + * Gets an unmodifiable view of the dump handlers registered with this configuration. */ Collection dumpHandlers(); + /** + * Gets the {@link PrintStream} for logging. + */ PrintStream output(); /** - * Gets the modifiable collection of verify handlers registered with this configuration. + * Gets an unmodifiable view of the verify handlers registered with this configuration. */ Collection verifyHandlers(); + default void closeDumpHandlers(boolean ignoreErrors) { + for (DebugDumpHandler handler : dumpHandlers()) { + try { + handler.close(); + } catch (Throwable e) { + if (!ignoreErrors) { + throw e; + } + } + } + } + + /** + * Extracts a {@link JavaMethod} from an opaque debug context. + * + * @return the {@link JavaMethod} represented by {@code context} or null + */ + static JavaMethod asJavaMethod(Object context) { + if (context instanceof JavaMethodContext) { + return ((JavaMethodContext) context).asJavaMethod(); + } + if (context instanceof JavaMethod) { + return (JavaMethod) context; + } + return null; + } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugDumpHandler.java 2017-07-07 09:29:53.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugDumpHandler.java 2017-07-07 09:29:52.000000000 -0700 @@ -24,23 +24,34 @@ import java.io.Closeable; -public interface DebugDumpHandler extends Closeable { - - void dump(Object object, String format, Object... arguments); +/** + * Interface implemented by classes that provide an external visualization of selected object types + * such as compiler graphs and nodes. The format and client required to consume the visualizations + * is determined by the implementation. For example, a dumper may convert a compiler node to a human + * readable string and print it to the console. A more sophisticated dumper may serialize a compiler + * graph and send it over the network to a tool (e.g., https://github.com/graalvm/visualizer) that + * can display graphs. + */ +public interface DebugDumpHandler extends Closeable, DebugHandler { /** - * Add arbitrary capability for use by the handler. + * If the type of {@code object} is supported by this dumper, then a representation of + * {@code object} is sent to some consumer in a format determined by this object. * - * @param capability + * @param debug the debug context requesting the dump + * @param object the object to be dumped + * @param format a format string specifying a title that describes the context of the dump + * (e.g., the compiler phase in which request is made) + * @param arguments arguments referenced by the format specifiers in {@code format} */ - default void addCapability(Object capability) { - } + void dump(DebugContext debug, Object object, String format, Object... arguments); /** * Flushes and releases resources managed by this dump handler. A subsequent call to - * {@link #dump(java.lang.Object, java.lang.String, java.lang.Object...)} will create and open - * new resources. That is, this method can be used to reset the handler. + * {@link #dump} will create and open new resources. That is, this method can be used to reset + * the handler. */ @Override - void close(); + default void close() { + } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugFilter.java 2017-07-07 09:29:53.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugFilter.java 2017-07-07 09:29:53.000000000 -0700 @@ -25,44 +25,43 @@ import java.util.Arrays; import java.util.regex.Pattern; -import org.graalvm.compiler.debug.GraalDebugConfig.Options; -import org.graalvm.compiler.debug.internal.DebugScope; +import org.graalvm.compiler.debug.DebugContext.Scope; /** - * Implements the filter specified by the {@link Options#Dump}, {@link Options#Log}, - * {@link Options#Count},{@link Options#MethodMeter} and {@link Options#Time} options. + * Implements the filter specified by the {@link DebugOptions#Dump}, {@link DebugOptions#Log}, + * {@link DebugOptions#Count} and {@link DebugOptions#Time} options. *

* These options enable the associated debug facility if their filter matches the - * {@linkplain DebugScope#getQualifiedName() name} of the {@linkplain Debug#currentScope() current - * scope}. For the {@link Options#Dump} and {@link Options#Log} options, the log or dump level is - * set. The {@link Options#Count},{@link Options#MethodMeter} and {@link Options#Time} options don't - * have a level, for them {@code level = 0} means disabled and a {@code level > 0} means enabled. + * {@linkplain Scope#getQualifiedName() name} of the current scope. For the + * {@link DebugOptions#Dump} and {@link DebugOptions#Log} options, the log or dump level is set. The + * {@link DebugOptions#Count} and {@link DebugOptions#Time} options don't have a level, for them + * {@code level = 0} means disabled and a {@code level > 0} means enabled. *

* A filter is a list of comma-separated terms of the form {@code [:]}. {@code * } is interpreted as a glob pattern if it contains a "*" or "?" character. Otherwise, it * is interpreted as a substring. If {@code } is empty, it matches every scope. If {@code : - * } is omitted, it defaults to {@link Debug#BASIC_LEVEL}. The term {@code ~} is a - * shorthand for {@code :0} to disable a debug facility for a pattern. + * } is omitted, it defaults to {@link DebugContext#BASIC_LEVEL}. The term {@code ~} + * is a shorthand for {@code :0} to disable a debug facility for a pattern. *

* The resulting log level of a scope is determined by the last matching term. If no term * matches, the log level is 0 (disabled). A filter with no terms matches every scope with a log - * level of {@link Debug#BASIC_LEVEL}. + * level of {@link DebugContext#BASIC_LEVEL}. * *

Examples of filters

* *
    *
  • (empty string)
    - * Matches any scope with log level {@link Debug#BASIC_LEVEL}. + * Matches any scope with log level {@link DebugContext#BASIC_LEVEL}. * *
  • {@code :1}
    * Matches any scope with log level 1. * *
  • {@code *}
    - * Matches any scope with log level {@link Debug#BASIC_LEVEL}. + * Matches any scope with log level {@link DebugContext#BASIC_LEVEL}. * *
  • {@code CodeGen,CodeInstall}
    * Matches scopes containing "CodeGen" or "CodeInstall", both with log level - * {@link Debug#BASIC_LEVEL}. + * {@link DebugContext#BASIC_LEVEL}. * *
  • {@code CodeGen:2,CodeInstall:1}
    * Matches scopes containing "CodeGen" with log level 2, or "CodeInstall" with log level 1. @@ -74,10 +73,10 @@ * Matches all scopes with log level 1, except those containing "Dead". * *
  • {@code Code*}
    - * Matches scopes starting with "Code" with log level {@link Debug#BASIC_LEVEL}. + * Matches scopes starting with "Code" with log level {@link DebugContext#BASIC_LEVEL}. * *
  • {@code Code,~Dead}
    - * Matches scopes containing "Code" but not "Dead", with log level {@link Debug#BASIC_LEVEL}. + * Matches scopes containing "Code" but not "Dead", with log level {@link DebugContext#BASIC_LEVEL}. *
*/ final class DebugFilter { @@ -108,7 +107,7 @@ level = 0; } else { pattern = t; - level = Debug.BASIC_LEVEL; + level = DebugContext.BASIC_LEVEL; } } else { pattern = t.substring(0, idx); @@ -119,13 +118,13 @@ } catch (NumberFormatException e) { switch (levelString) { case "basic": - level = Debug.BASIC_LEVEL; + level = DebugContext.BASIC_LEVEL; break; case "info": - level = Debug.INFO_LEVEL; + level = DebugContext.INFO_LEVEL; break; case "verbose": - level = Debug.VERBOSE_LEVEL; + level = DebugContext.VERBOSE_LEVEL; break; default: throw new IllegalArgumentException("Unknown dump level: \"" + levelString + "\" expected basic, info, verbose or an integer"); @@ -133,7 +132,7 @@ } } else { - level = Debug.BASIC_LEVEL; + level = DebugContext.BASIC_LEVEL; } } @@ -147,7 +146,7 @@ */ public int matchLevel(String input) { if (terms == null) { - return Debug.BASIC_LEVEL; + return DebugContext.BASIC_LEVEL; } else { int level = 0; for (Term t : terms) { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugMemUseTracker.java 2017-07-07 09:29:53.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugMemUseTracker.java 2017-07-07 09:29:53.000000000 -0700 @@ -38,7 +38,7 @@ /** * Creates a point from which memory usage will be recorded if memory use tracking is - * {@linkplain Debug#isMemUseTrackingEnabled() enabled}. + * {@linkplain DebugContext#isMemUseTrackingEnabled() enabled}. * * @return an object that must be closed once the activity has completed to add the memory used * since this call to the total for this tracker --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugRetryableTask.java 2017-07-07 09:29:54.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugRetryableTask.java 2017-07-07 09:29:54.000000000 -0700 @@ -22,28 +22,26 @@ */ package org.graalvm.compiler.debug; -import org.graalvm.compiler.debug.Debug.Scope; - /** * A mechanism for re-executing a task upon failure. */ -public abstract class DebugRetryableTask extends DelegatingDebugConfig { +public abstract class DebugRetryableTask { /** * Calls {@link #run} on this task and if it results in an exception, calls - * {@link #onRetry(Throwable)} and if that returns {@code true}, calls {@link #run}. + * {@link #getRetryContext} and if that returns a non-null value, + * {@link #run(DebugContext, Throwable)} is called with it. + * + * @param initialDebug the debug context to be used for the initial execution */ @SuppressWarnings("try") - public final T execute() { + public final T runWithRetry(DebugContext initialDebug) { try { - return run(null); + return run(initialDebug, null); } catch (Throwable t) { - if (onRetry(t)) { - try (Scope d = Debug.sandbox("Retrying: " + this, this)) { - return run(t); - } catch (Throwable t2) { - throw Debug.handle(t2); - } + DebugContext retryDebug = getRetryContext(initialDebug, t); + if (retryDebug != null) { + return run(retryDebug, t); } else { throw t; } @@ -51,22 +49,24 @@ } /** - * Runs this task. + * Runs this body of this task. * - * @param failure the cause of the first execution to fail or {@code null} if this is the first - * execution of {@link #run(Throwable)} + * @param debug the debug context to use for the execution + * @param failure {@code null} if this is the first execution otherwise the cause of the first + * execution to fail */ - protected abstract T run(Throwable failure); + protected abstract T run(DebugContext debug, Throwable failure); /** - * Notifies this object that the initial execution failed with exception {@code t} and is about - * to be re-executed. The re-execution will use this object as the active {@link DebugConfig}. - * As such, this method can be overridden to enable more detailed debug facilities. + * Notifies this object that the initial execution failed with exception {@code t} and requests + * a debug context to be used for re-execution. * + * @param initialDebug the debug context used for the initial execution * @param t an exception that terminated the first execution of this task - * @return whether this task should be re-executed. If false, {@code t} will be re-thrown. + * @return the debug context to be used for re-executing this task or {@code null} if {@code t} + * should immediately be re-thrown without re-executing this task */ - protected boolean onRetry(Throwable t) { - return true; + protected DebugContext getRetryContext(DebugContext initialDebug, Throwable t) { + return null; } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugVerifyHandler.java 2017-07-07 09:29:54.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugVerifyHandler.java 2017-07-07 09:29:54.000000000 -0700 @@ -25,14 +25,16 @@ /** * Performs some kind of verification on an object. */ -public interface DebugVerifyHandler { +public interface DebugVerifyHandler extends DebugHandler { /** * Verifies that a given object satisfies some invariants. * * @param object object to verify - * @param format description of verification context - * @param args arguments for the format + * @param debug the debug context requesting the dump + * @param format a format string specifying a title that describes the context of the + * verification (e.g., the compiler phase in which request is made) + * @param arguments arguments referenced by the format specifiers in {@code format} */ - void verify(Object object, String format, Object... args); + void verify(DebugContext debug, Object object, String format, Object... arguments); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Indent.java 2017-07-07 09:29:55.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Indent.java 2017-07-07 09:29:54.000000000 -0700 @@ -23,7 +23,7 @@ package org.graalvm.compiler.debug; /** - * Object used to close a debug {@link Debug#indent() indentation} scope. + * Object used to close a debug {@link DebugContext#indent() indentation} scope. *

* Example usage: * --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/JavaMethodContext.java 2017-07-07 09:29:55.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/JavaMethodContext.java 2017-07-07 09:29:55.000000000 -0700 @@ -25,8 +25,8 @@ import jdk.vm.ci.meta.JavaMethod; /** - * Interface for objects used in Debug {@linkplain Debug#context() context} that can provide a - * {@link JavaMethod}. + * Interface for objects used in Debug {@linkplain DebugContext#context() context} that can provide + * a {@link JavaMethod}. */ public interface JavaMethodContext { JavaMethod asJavaMethod(); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/GraphTest.java 2017-07-07 09:29:55.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/GraphTest.java 2017-07-07 09:29:55.000000000 -0700 @@ -23,11 +23,41 @@ package org.graalvm.compiler.graph.test; import org.graalvm.compiler.api.test.Graal; +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.options.OptionValues; +import org.junit.After; public abstract class GraphTest { static OptionValues getOptions() { return Graal.getRequiredCapability(OptionValues.class); } + + private final ThreadLocal cachedDebug = new ThreadLocal<>(); + + protected DebugContext getDebug(OptionValues options) { + DebugContext cached = cachedDebug.get(); + if (cached != null) { + if (cached.getOptions() == options) { + return cached; + } + throw new AssertionError("At most one " + DebugContext.class.getName() + " object should be created per test"); + } + DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER); + cachedDebug.set(debug); + return debug; + } + + protected DebugContext getDebug() { + return getDebug(getOptions()); + } + + @After + public void afterTest() { + DebugContext cached = cachedDebug.get(); + if (cached != null) { + cached.closeDumpHandlers(true); + } + } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeMapTest.java 2017-07-07 09:29:56.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeMapTest.java 2017-07-07 09:29:56.000000000 -0700 @@ -37,6 +37,7 @@ import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.NodeMap; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.options.OptionValues; public class NodeMapTest extends GraphTest { @@ -58,7 +59,8 @@ // Need to initialize HotSpotGraalRuntime before any Node class is initialized. Graal.getRuntime(); - graph = new Graph(getOptions()); + OptionValues options = getOptions(); + graph = new Graph(options, getDebug(options)); for (int i = 0; i < nodes.length; i++) { nodes[i] = graph.add(new TestNode()); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeUsagesTests.java 2017-07-07 09:29:56.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeUsagesTests.java 2017-07-07 09:29:56.000000000 -0700 @@ -36,6 +36,7 @@ import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.options.OptionValues; public class NodeUsagesTests extends GraphTest { @@ -66,7 +67,8 @@ @Test public void testReplaceAtUsages() { - Graph graph = new Graph(getOptions()); + OptionValues options = getOptions(); + Graph graph = new Graph(options, getDebug(options)); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -95,7 +97,8 @@ @Test public void testReplaceAtUsagesWithPredicateAll() { - Graph graph = new Graph(getOptions()); + OptionValues options = getOptions(); + Graph graph = new Graph(options, getDebug(options)); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -124,7 +127,8 @@ @Test public void testReplaceAtUsagesWithPredicateNone() { - Graph graph = new Graph(getOptions()); + OptionValues options = getOptions(); + Graph graph = new Graph(options, getDebug(options)); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -153,7 +157,8 @@ @Test public void testReplaceAtUsagesWithPredicate1() { - Graph graph = new Graph(getOptions()); + OptionValues options = getOptions(); + Graph graph = new Graph(options, getDebug(options)); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -184,7 +189,8 @@ @Test public void testReplaceAtUsagesWithPredicate2() { - Graph graph = new Graph(getOptions()); + OptionValues options = getOptions(); + Graph graph = new Graph(options, getDebug(options)); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -215,7 +221,8 @@ @Test public void testReplaceAtUsagesWithPredicate0() { - Graph graph = new Graph(getOptions()); + OptionValues options = getOptions(); + Graph graph = new Graph(options, getDebug(options)); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -246,7 +253,8 @@ @Test public void testReplaceAtUsagesWithPredicate02() { - Graph graph = new Graph(getOptions()); + OptionValues options = getOptions(); + Graph graph = new Graph(options, getDebug(options)); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -277,7 +285,8 @@ @Test public void testReplaceAtUsagesWithPredicate023() { - Graph graph = new Graph(getOptions()); + OptionValues options = getOptions(); + Graph graph = new Graph(options, getDebug(options)); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -311,7 +320,8 @@ @Test public void testReplaceAtUsagesWithPredicate013() { - Graph graph = new Graph(getOptions()); + OptionValues options = getOptions(); + Graph graph = new Graph(options, getDebug(options)); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -345,7 +355,8 @@ @Test public void testReplaceAtUsagesWithPredicate203() { - Graph graph = new Graph(getOptions()); + OptionValues options = getOptions(); + Graph graph = new Graph(options, getDebug(options)); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -379,7 +390,8 @@ @Test public void testReplaceAtUsagesWithPredicate01() { - Graph graph = new Graph(getOptions()); + OptionValues options = getOptions(); + Graph graph = new Graph(options, getDebug(options)); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -410,7 +422,8 @@ @Test public void testReplaceAtUsagesWithPredicate12() { - Graph graph = new Graph(getOptions()); + OptionValues options = getOptions(); + Graph graph = new Graph(options, getDebug(options)); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeValidationChecksTest.java 2017-07-07 09:29:56.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeValidationChecksTest.java 2017-07-07 09:29:56.000000000 -0700 @@ -51,7 +51,7 @@ @Test public void testInputNotAlive() { - Graph graph = new Graph(getOptions()); + Graph graph = new Graph(getOptions(), getDebug()); TestNode node = new TestNode(null, null); try { graph.add(new TestNode(node, null)); @@ -64,7 +64,7 @@ @Test public void testSuccessorNotAlive() { - Graph graph = new Graph(getOptions()); + Graph graph = new Graph(getOptions(), getDebug()); TestNode node = new TestNode(null, null); try { graph.add(new TestNode(null, node)); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/TypedNodeIteratorTest.java 2017-07-07 09:29:57.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/TypedNodeIteratorTest.java 2017-07-07 09:29:57.000000000 -0700 @@ -62,8 +62,8 @@ @Test public void singleNodeTest() { - getOptions(); - Graph graph = new Graph(getOptions()); + OptionValues options = getOptions(); + Graph graph = new Graph(options, getDebug(options)); graph.add(new TestNode("a")); assertTrue(graph.hasNode(TestNode.TYPE)); assertEquals("a", toString(graph.getNodes(TestNode.TYPE))); @@ -76,7 +76,8 @@ @Test public void deletingNodeTest() { TestNode testNode = new TestNode("a"); - Graph graph = new Graph(getOptions()); + OptionValues options = getOptions(); + Graph graph = new Graph(options, getDebug(options)); graph.add(testNode); testNode.safeDelete(); assertEquals("", toString(graph.getNodes(TestNode.TYPE))); @@ -85,7 +86,8 @@ @Test public void deleteAndAddTest() { TestNode testNode = new TestNode("b"); - Graph graph = new Graph(getOptions()); + OptionValues options = getOptions(); + Graph graph = new Graph(options, getDebug(options)); graph.add(new TestNode("a")); graph.add(testNode); testNode.safeDelete(); @@ -96,7 +98,8 @@ @Test public void iteratorBehaviorTest() { - Graph graph = new Graph(getOptions()); + OptionValues options = getOptions(); + Graph graph = new Graph(options, getDebug(options)); graph.add(new TestNode("a")); Iterator iterator = graph.getNodes(TestNode.TYPE).iterator(); assertTrue(iterator.hasNext()); @@ -115,7 +118,8 @@ @Test public void complicatedIterationTest() { - Graph graph = new Graph(getOptions()); + OptionValues options = getOptions(); + Graph graph = new Graph(options, getDebug(options)); graph.add(new TestNode("a")); for (TestNode tn : graph.getNodes(TestNode.TYPE)) { String name = tn.getName(); @@ -154,7 +158,8 @@ @Test public void addingNodeDuringIterationTest() { - Graph graph = new Graph(getOptions()); + OptionValues options = getOptions(); + Graph graph = new Graph(options, getDebug(options)); graph.add(new TestNode("a")); StringBuilder sb = new StringBuilder(); int z = 0; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/TypedNodeIteratorTest2.java 2017-07-07 09:29:57.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/TypedNodeIteratorTest2.java 2017-07-07 09:29:57.000000000 -0700 @@ -99,7 +99,7 @@ @Test public void simpleSubclassTest() { - Graph graph = new Graph(getOptions()); + Graph graph = new Graph(getOptions(), getDebug()); graph.add(new NodeB("b")); graph.add(new NodeD("d")); @@ -109,7 +109,7 @@ @Test public void addingNodeDuringIterationTest() { - Graph graph = new Graph(getOptions()); + Graph graph = new Graph(getOptions(), getDebug()); graph.add(new NodeB("b1")); NodeD d1 = graph.add(new NodeD("d1")); StringBuilder sb = new StringBuilder(); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/CachedGraph.java 2017-07-07 09:29:58.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/CachedGraph.java 2017-07-07 09:29:58.000000000 -0700 @@ -62,7 +62,9 @@ @SuppressWarnings("unchecked") public G getMutableCopy(Consumer> duplicationMapCallback) { if (!hasMutableCopy()) { - mutableCopy = (G) readonlyCopy.copy(duplicationMapCallback); + // Sharing the debug context with the copy is safe since both graphs are + // only used in the current thread. + mutableCopy = (G) readonlyCopy.copy(duplicationMapCallback, readonlyCopy.getDebug()); } return mutableCopy; } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java 2017-07-07 09:29:58.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java 2017-07-07 09:29:58.000000000 -0700 @@ -22,11 +22,19 @@ */ package org.graalvm.compiler.graph; -import org.graalvm.compiler.debug.Debug; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.function.Consumer; + +import org.graalvm.compiler.debug.CounterKey; import org.graalvm.compiler.debug.DebugCloseable; -import org.graalvm.compiler.debug.DebugCounter; -import org.graalvm.compiler.debug.DebugTimer; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.debug.TimerKey; import org.graalvm.compiler.graph.Node.ValueNumberable; import org.graalvm.compiler.graph.iterators.NodeIterable; import org.graalvm.compiler.options.Option; @@ -37,14 +45,6 @@ import org.graalvm.util.Equivalence; import org.graalvm.util.UnmodifiableEconomicMap; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.function.Consumer; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED; - /** * This class is a graph container, it contains the set of nodes that belong to this graph. */ @@ -147,6 +147,11 @@ */ private final OptionValues options; + /** + * The {@link DebugContext} used while compiling this graph. + */ + private final DebugContext debug; + private class NodeSourcePositionScope implements DebugCloseable { private final NodeSourcePosition previous; @@ -156,6 +161,11 @@ } @Override + public DebugContext getDebug() { + return debug; + } + + @Override public void close() { currentNodeSourcePosition = previous; } @@ -217,8 +227,8 @@ /** * Creates an empty Graph with no name. */ - public Graph(OptionValues options) { - this(null, options); + public Graph(OptionValues options, DebugContext debug) { + this(null, options, debug); } /** @@ -239,12 +249,14 @@ * * @param name the name of the graph, used for debugging purposes */ - public Graph(String name, OptionValues options) { + public Graph(String name, OptionValues options, DebugContext debug) { nodes = new Node[INITIAL_NODES_SIZE]; iterableNodesFirst = new ArrayList<>(NodeClass.allocatedNodeIterabledIds()); iterableNodesLast = new ArrayList<>(NodeClass.allocatedNodeIterabledIds()); this.name = name; this.options = options; + assert debug != null; + this.debug = debug; if (isModificationCountsEnabled()) { nodeModCounts = new int[INITIAL_NODES_SIZE]; @@ -302,27 +314,37 @@ /** * Creates a copy of this graph. + * + * @param debugForCopy the debug context for the graph copy. This must not be the debug for this + * graph if this graph can be accessed from multiple threads (e.g., it's in a cache + * accessed by multiple threads). */ - public final Graph copy() { - return copy(name, null); + public final Graph copy(DebugContext debugForCopy) { + return copy(name, null, debugForCopy); } /** * Creates a copy of this graph. * * @param duplicationMapCallback consumer of the duplication map created during the copying + * @param debugForCopy the debug context for the graph copy. This must not be the debug for this + * graph if this graph can be accessed from multiple threads (e.g., it's in a cache + * accessed by multiple threads). */ - public final Graph copy(Consumer> duplicationMapCallback) { - return copy(name, duplicationMapCallback); + public final Graph copy(Consumer> duplicationMapCallback, DebugContext debugForCopy) { + return copy(name, duplicationMapCallback, debugForCopy); } /** * Creates a copy of this graph. * * @param newName the name of the copy, used for debugging purposes (can be null) + * @param debugForCopy the debug context for the graph copy. This must not be the debug for this + * graph if this graph can be accessed from multiple threads (e.g., it's in a cache + * accessed by multiple threads). */ - public final Graph copy(String newName) { - return copy(newName, null); + public final Graph copy(String newName, DebugContext debugForCopy) { + return copy(newName, null, debugForCopy); } /** @@ -330,9 +352,12 @@ * * @param newName the name of the copy, used for debugging purposes (can be null) * @param duplicationMapCallback consumer of the duplication map created during the copying + * @param debugForCopy the debug context for the graph copy. This must not be the debug for this + * graph if this graph can be accessed from multiple threads (e.g., it's in a cache + * accessed by multiple threads). */ - protected Graph copy(String newName, Consumer> duplicationMapCallback) { - Graph copy = new Graph(newName, options); + protected Graph copy(String newName, Consumer> duplicationMapCallback, DebugContext debugForCopy) { + Graph copy = new Graph(newName, options, debugForCopy); UnmodifiableEconomicMap duplicates = copy.addDuplicates(getNodes(), this, this.getNodeCount(), (EconomicMap) null); if (duplicationMapCallback != null) { duplicationMapCallback.accept(duplicates); @@ -344,6 +369,10 @@ return options; } + public DebugContext getDebug() { + return debug; + } + @Override public String toString() { return name == null ? super.toString() : "Graph " + name; @@ -806,7 +835,7 @@ } - private static final DebugCounter GraphCompressions = Debug.counter("GraphCompressions"); + private static final CounterKey GraphCompressions = DebugContext.counter("GraphCompressions"); /** * If the {@linkplain Options#GraphCompressionThreshold compression threshold} is met, the list @@ -814,7 +843,7 @@ * preserving the ordering between the nodes within the list. */ public boolean maybeCompress() { - if (Debug.isDumpEnabledForMethod() || Debug.isLogEnabledForMethod()) { + if (debug.isDumpEnabledForMethod() || debug.isLogEnabledForMethod()) { return false; } int liveNodeCount = getNodeCount(); @@ -823,7 +852,7 @@ if (compressionThreshold == 0 || liveNodePercent >= compressionThreshold) { return false; } - GraphCompressions.increment(); + GraphCompressions.increment(debug); int nextId = 0; for (int i = 0; nextId < liveNodeCount; i++) { Node n = nodes[i]; @@ -1077,7 +1106,7 @@ } /** - * Adds duplicates of the nodes in {@code nodes} to this graph. This will recreate any edges + * Adds duplicates of the nodes in {@code newNodes} to this graph. This will recreate any edges * between the duplicate nodes. The {@code replacement} map can be used to replace a node from * the source graph by a given node (which must already be in this graph). Edges between * duplicate and replacement nodes will also be recreated so care should be taken regarding the @@ -1118,11 +1147,11 @@ } - private static final DebugTimer DuplicateGraph = Debug.timer("DuplicateGraph"); + private static final TimerKey DuplicateGraph = DebugContext.timer("DuplicateGraph"); @SuppressWarnings({"all", "try"}) public EconomicMap addDuplicates(Iterable newNodes, final Graph oldGraph, int estimatedNodeCount, DuplicationReplacement replacements) { - try (DebugCloseable s = DuplicateGraph.start()) { + try (DebugCloseable s = DuplicateGraph.start(getDebug())) { return NodeClass.addGraphDuplicate(this, oldGraph, estimatedNodeCount, newNodes, replacements); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java 2017-07-07 09:29:59.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java 2017-07-07 09:29:58.000000000 -0700 @@ -43,6 +43,7 @@ import org.graalvm.compiler.core.common.type.AbstractPointerStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.debug.DebugCloseable; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Graph.NodeEventListener; import org.graalvm.compiler.graph.Graph.Options; import org.graalvm.compiler.graph.iterators.NodeIterable; @@ -263,6 +264,13 @@ } /** + * Gets the debug context associated with this node's graph. + */ + public final DebugContext getDebug() { + return graph.getDebug(); + } + + /** * Returns an {@link NodeIterable iterable} which can be used to traverse all non-null input * edges of this node. * --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java 2017-07-07 09:29:59.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java 2017-07-07 09:29:59.000000000 -0700 @@ -45,11 +45,11 @@ import org.graalvm.compiler.core.common.FieldIntrospection; import org.graalvm.compiler.core.common.Fields; import org.graalvm.compiler.core.common.FieldsScanner; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.CounterKey; import org.graalvm.compiler.debug.DebugCloseable; -import org.graalvm.compiler.debug.DebugCounter; -import org.graalvm.compiler.debug.DebugTimer; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.debug.TimerKey; import org.graalvm.compiler.graph.Edges.Type; import org.graalvm.compiler.graph.Graph.DuplicationReplacement; import org.graalvm.compiler.graph.Node.EdgeVisitor; @@ -79,13 +79,13 @@ public final class NodeClass extends FieldIntrospection { // Timers for creation of a NodeClass instance - private static final DebugTimer Init_FieldScanning = Debug.timer("NodeClass.Init.FieldScanning"); - private static final DebugTimer Init_FieldScanningInner = Debug.timer("NodeClass.Init.FieldScanning.Inner"); - private static final DebugTimer Init_AnnotationParsing = Debug.timer("NodeClass.Init.AnnotationParsing"); - private static final DebugTimer Init_Edges = Debug.timer("NodeClass.Init.Edges"); - private static final DebugTimer Init_Data = Debug.timer("NodeClass.Init.Data"); - private static final DebugTimer Init_AllowedUsages = Debug.timer("NodeClass.Init.AllowedUsages"); - private static final DebugTimer Init_IterableIds = Debug.timer("NodeClass.Init.IterableIds"); + private static final TimerKey Init_FieldScanning = DebugContext.timer("NodeClass.Init.FieldScanning"); + private static final TimerKey Init_FieldScanningInner = DebugContext.timer("NodeClass.Init.FieldScanning.Inner"); + private static final TimerKey Init_AnnotationParsing = DebugContext.timer("NodeClass.Init.AnnotationParsing"); + private static final TimerKey Init_Edges = DebugContext.timer("NodeClass.Init.Edges"); + private static final TimerKey Init_Data = DebugContext.timer("NodeClass.Init.Data"); + private static final TimerKey Init_AllowedUsages = DebugContext.timer("NodeClass.Init.AllowedUsages"); + private static final TimerKey Init_IterableIds = DebugContext.timer("NodeClass.Init.IterableIds"); public static final long MAX_EDGES = 8; public static final long MAX_LIST_EDGES = 6; @@ -94,8 +94,8 @@ public static final long NEXT_EDGE = 0x08; @SuppressWarnings("try") - private static T getAnnotationTimed(AnnotatedElement e, Class annotationClass) { - try (DebugCloseable s = Init_AnnotationParsing.start()) { + private static T getAnnotationTimed(AnnotatedElement e, Class annotationClass, DebugContext debug) { + try (DebugCloseable s = Init_AnnotationParsing.start(debug)) { return e.getAnnotation(annotationClass); } } @@ -144,8 +144,7 @@ private final long inputsIteration; private final long successorIteration; - private static final DebugCounter ITERABLE_NODE_TYPES = Debug.counter("IterableNodeTypes"); - private final DebugCounter nodeIterableCount; + private static final CounterKey ITERABLE_NODE_TYPES = DebugContext.counter("IterableNodeTypes"); /** * Determines if this node type implements {@link Canonicalizable}. @@ -172,6 +171,7 @@ @SuppressWarnings("try") public NodeClass(Class clazz, NodeClass superNodeClass, FieldsScanner.CalcOffset calcOffset, int[] presetIterableIds, int presetIterableId) { super(clazz); + DebugContext debug = DebugContext.forCurrentThread(); this.superNodeClass = superNodeClass; assert NODE_CLASS.isAssignableFrom(clazz); @@ -183,18 +183,18 @@ this.isSimplifiable = Simplifiable.class.isAssignableFrom(clazz); - NodeFieldsScanner fs = new NodeFieldsScanner(calcOffset, superNodeClass); - try (DebugCloseable t = Init_FieldScanning.start()) { + NodeFieldsScanner fs = new NodeFieldsScanner(calcOffset, superNodeClass, debug); + try (DebugCloseable t = Init_FieldScanning.start(debug)) { fs.scan(clazz, clazz.getSuperclass(), false); } - try (DebugCloseable t1 = Init_Edges.start()) { + try (DebugCloseable t1 = Init_Edges.start(debug)) { successors = new SuccessorEdges(fs.directSuccessors, fs.successors); successorIteration = computeIterationMask(successors.type(), successors.getDirectCount(), successors.getOffsets()); inputs = new InputEdges(fs.directInputs, fs.inputs); inputsIteration = computeIterationMask(inputs.type(), inputs.getDirectCount(), inputs.getOffsets()); } - try (DebugCloseable t1 = Init_Data.start()) { + try (DebugCloseable t1 = Init_Data.start(debug)) { data = new Fields(fs.data); } @@ -208,7 +208,7 @@ canGVN = Node.ValueNumberable.class.isAssignableFrom(clazz); startGVNNumber = clazz.getName().hashCode(); - NodeInfo info = getAnnotationTimed(clazz, NodeInfo.class); + NodeInfo info = getAnnotationTimed(clazz, NodeInfo.class, debug); assert info != null : "Missing NodeInfo annotation on " + clazz; if (!info.nameTemplate().isEmpty()) { this.nameTemplate = info.nameTemplate(); @@ -218,7 +218,7 @@ this.nameTemplate = ""; } - try (DebugCloseable t1 = Init_AllowedUsages.start()) { + try (DebugCloseable t1 = Init_AllowedUsages.start(debug)) { allowedUsageTypes = superNodeClass == null ? EnumSet.noneOf(InputType.class) : superNodeClass.allowedUsageTypes.clone(); allowedUsageTypes.addAll(Arrays.asList(info.allowedUsageTypes())); } @@ -227,8 +227,8 @@ this.iterableIds = presetIterableIds; this.iterableId = presetIterableId; } else if (IterableNodeType.class.isAssignableFrom(clazz)) { - ITERABLE_NODE_TYPES.increment(); - try (DebugCloseable t1 = Init_IterableIds.start()) { + ITERABLE_NODE_TYPES.increment(debug); + try (DebugCloseable t1 = Init_IterableIds.start(debug)) { this.iterableId = nextIterableId.getAndIncrement(); NodeClass snc = superNodeClass; @@ -243,10 +243,9 @@ this.iterableId = Node.NOT_ITERABLE; this.iterableIds = null; } - nodeIterableCount = Debug.counter("NodeIterable_%s", clazz); assert verifyIterableIds(); - try (Debug.Scope scope = Debug.scope("NodeCosts")) { + try (DebugContext.Scope scope = debug.scope("NodeCosts")) { /* * Note: We do not check for the existence of the node cost annotations during * construction as not every node needs to have them set. However if costs are queried, @@ -271,9 +270,8 @@ size = s; } assert size != null; - Debug.log("Node cost for node of type __| %s |_, cycles:%s,size:%s", clazz, cycles, size); + debug.log("Node cost for node of type __| %s |_, cycles:%s,size:%s", clazz, cycles, size); } - } private final NodeCycles cycles; @@ -357,8 +355,7 @@ return new Fields[]{data, inputs, successors}; } - public int[] iterableIds() { - nodeIterableCount.increment(); + int[] iterableIds() { return iterableIds; } @@ -451,9 +448,11 @@ public final ArrayList successors = new ArrayList<>(); int directInputs; int directSuccessors; + final DebugContext debug; - protected NodeFieldsScanner(FieldsScanner.CalcOffset calc, NodeClass superNodeClass) { + protected NodeFieldsScanner(FieldsScanner.CalcOffset calc, NodeClass superNodeClass, DebugContext debug) { super(calc); + this.debug = debug; if (superNodeClass != null) { translateInto(superNodeClass.inputs, inputs); translateInto(superNodeClass.successors, successors); @@ -466,10 +465,10 @@ @SuppressWarnings("try") @Override protected void scanField(Field field, long offset) { - Input inputAnnotation = getAnnotationTimed(field, Node.Input.class); - OptionalInput optionalInputAnnotation = getAnnotationTimed(field, Node.OptionalInput.class); - Successor successorAnnotation = getAnnotationTimed(field, Successor.class); - try (DebugCloseable s = Init_FieldScanningInner.start()) { + Input inputAnnotation = getAnnotationTimed(field, Node.Input.class, debug); + OptionalInput optionalInputAnnotation = getAnnotationTimed(field, Node.OptionalInput.class, debug); + Successor successorAnnotation = getAnnotationTimed(field, Successor.class, debug); + try (DebugCloseable s = Init_FieldScanningInner.start(debug)) { Class type = field.getType(); int modifiers = field.getModifiers(); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeWorkList.java 2017-07-07 09:29:59.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeWorkList.java 2017-07-07 09:29:59.000000000 -0700 @@ -27,7 +27,7 @@ import java.util.NoSuchElementException; import java.util.Queue; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; public abstract class NodeWorkList implements Iterable { @@ -75,6 +75,7 @@ private static final int EXPLICIT_BITMAP_THRESHOLD = 10; protected NodeBitMap inQueue; + private final DebugContext debug; private int iterationLimit; private Node firstNoChange; private Node lastPull; @@ -82,6 +83,7 @@ public IterativeNodeWorkList(Graph graph, boolean fill, int iterationLimitPerNode) { super(graph, fill); + debug = graph.getDebug(); assert iterationLimitPerNode > 0; long limit = (long) iterationLimitPerNode * graph.getNodeCount(); iterationLimit = (int) Long.min(Integer.MAX_VALUE, limit); @@ -94,7 +96,7 @@ public boolean hasNext() { dropDeleted(); if (iterationLimit <= 0) { - Debug.log(Debug.INFO_LEVEL, "Exceeded iteration limit in IterativeNodeWorkList"); + debug.log(DebugContext.INFO_LEVEL, "Exceeded iteration limit in IterativeNodeWorkList"); return false; } return !worklist.isEmpty(); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java 2017-07-07 09:30:00.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java 2017-07-07 09:30:00.000000000 -0700 @@ -226,7 +226,7 @@ HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null); DataBuilder dataBuilder = new HotSpotDataBuilder(getCodeCache().getTarget()); - CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, dataBuilder, frameContext, lir.getOptions(), compilationResult); + CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, dataBuilder, frameContext, lir.getOptions(), lir.getDebug(), compilationResult); crb.setTotalFrameSize(frameMap.totalFrameSize()); crb.setMaxInterpreterFrameSize(gen.getMaxInterpreterFrameSize()); StackSlot deoptimizationRescueSlot = gen.getDeoptimizationRescueSlot(); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java 2017-07-07 09:30:00.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java 2017-07-07 09:30:00.000000000 -0700 @@ -30,6 +30,7 @@ import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode; +import org.graalvm.compiler.asm.aarch64.AArch64Assembler.PrefetchMode; import org.graalvm.compiler.asm.aarch64.AArch64Assembler.ConditionFlag; import org.graalvm.compiler.core.aarch64.AArch64ArithmeticLIRGenerator; import org.graalvm.compiler.core.aarch64.AArch64LIRGenerator; @@ -250,7 +251,7 @@ @Override public void emitPrefetchAllocate(Value address) { - append(new AArch64PrefetchOp(asAddressValue(address), config.allocatePrefetchInstr)); + append(new AArch64PrefetchOp(asAddressValue(address), PrefetchMode.PSTL1KEEP)); } @Override --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLoweringProvider.java 2017-07-07 09:30:01.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLoweringProvider.java 2017-07-07 09:30:00.000000000 -0700 @@ -24,6 +24,7 @@ package org.graalvm.compiler.hotspot.aarch64; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; @@ -53,10 +54,10 @@ } @Override - public void initialize(OptionValues options, HotSpotProviders providers, GraalHotSpotVMConfig config) { - integerArithmeticSnippets = new AArch64IntegerArithmeticSnippets(options, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget()); - floatArithmeticSnippets = new AArch64FloatArithmeticSnippets(options, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget()); - super.initialize(options, providers, config); + public void initialize(OptionValues options, Iterable factories, HotSpotProviders providers, GraalHotSpotVMConfig config) { + integerArithmeticSnippets = new AArch64IntegerArithmeticSnippets(options, factories, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget()); + floatArithmeticSnippets = new AArch64FloatArithmeticSnippets(options, factories, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget()); + super.initialize(options, factories, providers, config); } @Override --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotNodeLIRBuilder.java 2017-07-07 09:30:01.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotNodeLIRBuilder.java 2017-07-07 09:30:01.000000000 -0700 @@ -22,19 +22,18 @@ */ package org.graalvm.compiler.hotspot.aarch64; -import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER; import static jdk.vm.ci.aarch64.AArch64.lr; import static jdk.vm.ci.code.ValueUtil.isStackSlot; import static jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig.fp; import static jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig.inlineCacheRegister; import static jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig.metaspaceMethodRegister; +import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER; import org.graalvm.compiler.core.aarch64.AArch64NodeLIRBuilder; import org.graalvm.compiler.core.aarch64.AArch64NodeMatchRules; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.gen.DebugInfoBuilder; -import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.hotspot.HotSpotDebugInfoBuilder; import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; import org.graalvm.compiler.hotspot.HotSpotLockStack; @@ -171,7 +170,7 @@ @Override public void visitFullInfopointNode(FullInfopointNode i) { if (i.getState() != null && i.getState().bci == BytecodeFrame.AFTER_BCI) { - Debug.log("Ignoring InfopointNode for AFTER_BCI"); + i.getDebug().log("Ignoring InfopointNode for AFTER_BCI"); } else { super.visitFullInfopointNode(i); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java 2017-07-07 09:30:01.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java 2017-07-07 09:30:01.000000000 -0700 @@ -35,8 +35,8 @@ import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.type.ObjectStamp; import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.nodes.GraalHotSpotVMConfigNode; @@ -55,7 +55,7 @@ public class AMD64HotSpotAddressLowering extends AMD64AddressLowering { - private static final DebugCounter counterFoldedUncompressDuringAddressLowering = Debug.counter("FoldedUncompressDuringAddressLowering"); + private static final CounterKey counterFoldedUncompressDuringAddressLowering = DebugContext.counter("FoldedUncompressDuringAddressLowering"); private final long heapBase; private final Register heapBaseRegister; @@ -93,25 +93,25 @@ } @Override - protected boolean improve(AMD64AddressNode addr) { + protected boolean improve(DebugContext debug, AMD64AddressNode addr) { boolean result = false; - while (super.improve(addr)) { + while (super.improve(debug, addr)) { result = true; } if (addr.getScale() == Scale.Times1) { if (addr.getIndex() instanceof CompressionNode) { if (improveUncompression(addr, (CompressionNode) addr.getIndex(), addr.getBase())) { - counterFoldedUncompressDuringAddressLowering.increment(); + counterFoldedUncompressDuringAddressLowering.increment(debug); return true; } } if (addr.getBase() instanceof CompressionNode) { if (improveUncompression(addr, (CompressionNode) addr.getBase(), addr.getIndex())) { - counterFoldedUncompressDuringAddressLowering.increment(); + counterFoldedUncompressDuringAddressLowering.increment(debug); return true; } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java 2017-07-07 09:30:02.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java 2017-07-07 09:30:02.000000000 -0700 @@ -22,13 +22,13 @@ */ package org.graalvm.compiler.hotspot.amd64; -import static org.graalvm.compiler.core.common.GraalOptions.CanOmitFrame; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; -import static org.graalvm.compiler.core.common.GraalOptions.ZapStackOnMethodEntry; import static jdk.vm.ci.amd64.AMD64.r10; import static jdk.vm.ci.amd64.AMD64.rax; import static jdk.vm.ci.amd64.AMD64.rsp; import static jdk.vm.ci.code.ValueUtil.asRegister; +import static org.graalvm.compiler.core.common.GraalOptions.CanOmitFrame; +import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; +import static org.graalvm.compiler.core.common.GraalOptions.ZapStackOnMethodEntry; import org.graalvm.compiler.asm.Assembler; import org.graalvm.compiler.asm.Label; @@ -37,10 +37,11 @@ import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.amd64.AMD64NodeMatchRules; -import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.CompilationIdentifier; +import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; import org.graalvm.compiler.core.target.Backend; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotDataBuilder; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; @@ -209,13 +210,14 @@ LIR lir = gen.getLIR(); assert gen.getDeoptimizationRescueSlot() == null || frameMap.frameNeedsAllocating() : "method that can deoptimize must have a frame"; OptionValues options = lir.getOptions(); + DebugContext debug = lir.getDebug(); boolean omitFrame = CanOmitFrame.getValue(options) && !frameMap.frameNeedsAllocating() && !lir.hasArgInCallerFrame() && !gen.hasForeignCall(); Stub stub = gen.getStub(); Assembler masm = createAssembler(frameMap); HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null, omitFrame); DataBuilder dataBuilder = new HotSpotDataBuilder(getCodeCache().getTarget()); - CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, dataBuilder, frameContext, options, compilationResult); + CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, dataBuilder, frameContext, options, debug, compilationResult); crb.setTotalFrameSize(frameMap.totalFrameSize()); crb.setMaxInterpreterFrameSize(gen.getMaxInterpreterFrameSize()); StackSlot deoptimizationRescueSlot = gen.getDeoptimizationRescueSlot(); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java 2017-07-07 09:30:02.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java 2017-07-07 09:30:02.000000000 -0700 @@ -41,7 +41,7 @@ import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.common.spi.LIRKindTool; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotBackend; @@ -555,7 +555,7 @@ LIR lir = getResult().getLIR(); ArrayList instructions = lir.getLIRforBlock(lir.getControlFlowGraph().getStartBlock()); instructions.add(1, op); - Debug.dump(Debug.INFO_LEVEL, lir, "created rescue dummy op"); + lir.getDebug().dump(DebugContext.INFO_LEVEL, lir, "created rescue dummy op"); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java 2017-07-07 09:30:03.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java 2017-07-07 09:30:02.000000000 -0700 @@ -33,6 +33,7 @@ import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; @@ -63,11 +64,11 @@ } @Override - public void initialize(OptionValues options, HotSpotProviders providers, GraalHotSpotVMConfig config) { - convertSnippets = new AMD64ConvertSnippets.Templates(options, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget()); + public void initialize(OptionValues options, Iterable factories, HotSpotProviders providers, GraalHotSpotVMConfig config) { + convertSnippets = new AMD64ConvertSnippets.Templates(options, factories, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget()); profileSnippets = ProfileNode.Options.ProbabilisticProfiling.getValue(options) - ? new ProbabilisticProfileSnippets.Templates(options, providers, providers.getCodeCache().getTarget()) : null; - super.initialize(options, providers, config); + ? new ProbabilisticProfileSnippets.Templates(options, factories, providers, providers.getCodeCache().getTarget()) : null; + super.initialize(options, factories, providers, config); } @Override --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java 2017-07-07 09:30:03.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java 2017-07-07 09:30:03.000000000 -0700 @@ -22,16 +22,15 @@ */ package org.graalvm.compiler.hotspot.amd64; -import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER; import static jdk.vm.ci.amd64.AMD64.rbp; import static jdk.vm.ci.code.ValueUtil.isStackSlot; +import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER; import org.graalvm.compiler.core.amd64.AMD64NodeLIRBuilder; import org.graalvm.compiler.core.amd64.AMD64NodeMatchRules; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.gen.DebugInfoBuilder; -import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.hotspot.HotSpotDebugInfoBuilder; import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; import org.graalvm.compiler.hotspot.HotSpotLockStack; @@ -177,7 +176,7 @@ @Override public void visitFullInfopointNode(FullInfopointNode i) { if (i.getState() != null && i.getState().bci == BytecodeFrame.AFTER_BCI) { - Debug.log("Ignoring InfopointNode for AFTER_BCI"); + i.getDebug().log("Ignoring InfopointNode for AFTER_BCI"); } else { super.visitFullInfopointNode(i); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackend.java 2017-07-07 09:30:03.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackend.java 2017-07-07 09:30:03.000000000 -0700 @@ -59,8 +59,8 @@ import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; import org.graalvm.compiler.core.sparc.SPARCNodeMatchRules; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotDataBuilder; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; @@ -117,7 +117,7 @@ } private static class SizeEstimateStatistics { - private static final ConcurrentHashMap counters = new ConcurrentHashMap<>(); + private static final ConcurrentHashMap counters = new ConcurrentHashMap<>(); private final String suffix; SizeEstimateStatistics(String suffix) { @@ -125,10 +125,10 @@ this.suffix = suffix; } - public void add(Class c, int count) { + public void add(Class c, int count, DebugContext debug) { String name = SizeEstimateStatistics.class.getSimpleName() + "_" + c.getSimpleName() + "." + suffix; - DebugCounter m = counters.computeIfAbsent(name, (n) -> Debug.counter(n)); - m.add(count); + CounterKey m = counters.computeIfAbsent(name, (n) -> DebugContext.counter(n)); + m.add(debug, count); } } @@ -239,7 +239,9 @@ HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null); DataBuilder dataBuilder = new HotSpotDataBuilder(getCodeCache().getTarget()); OptionValues options = lir.getOptions(); - CompilationResultBuilder crb = factory.createBuilder(getProviders().getCodeCache(), getProviders().getForeignCalls(), frameMap, masm, dataBuilder, frameContext, options, compilationResult); + DebugContext debug = lir.getDebug(); + CompilationResultBuilder crb = factory.createBuilder(getProviders().getCodeCache(), getProviders().getForeignCalls(), frameMap, masm, dataBuilder, frameContext, options, debug, + compilationResult); crb.setTotalFrameSize(frameMap.totalFrameSize()); crb.setMaxInterpreterFrameSize(gen.getMaxInterpreterFrameSize()); StackSlot deoptimizationRescueSlot = gen.getDeoptimizationRescueSlot(); @@ -253,7 +255,7 @@ EconomicMap calleeSaveInfo = gen.getCalleeSaveInfo(); updateStub(stub, destroyedCallerRegisters, calleeSaveInfo, frameMap); } - assert registerSizePredictionValidator(crb); + assert registerSizePredictionValidator(crb, debug); return crb; } @@ -261,14 +263,19 @@ * Registers a verifier which checks if the LIRInstructions estimate of constants size is * greater or equal to the actual one. */ - private static boolean registerSizePredictionValidator(final CompilationResultBuilder crb) { + private static boolean registerSizePredictionValidator(final CompilationResultBuilder crb, DebugContext debug) { /** * Used to hold state between beforeOp and afterOp */ class ValidationState { LIRInstruction op; + final DebugContext debug; int constantSizeBefore; + ValidationState(DebugContext debug) { + this.debug = debug; + } + public void before(LIRInstruction before) { assert op == null : "LIRInstruction " + op + " no after call received"; op = before; @@ -283,8 +290,8 @@ org.graalvm.compiler.lir.sparc.SPARCLIRInstructionMixin.SizeEstimate size = ((SPARCLIRInstructionMixin) op).estimateSize(); assert size != null : "No size prediction available for op: " + op; Class c = op.getClass(); - CONSTANT_ESTIMATED_STATS.add(c, size.constantSize); - CONSTANT_ACTUAL_STATS.add(c, actual); + CONSTANT_ESTIMATED_STATS.add(c, size.constantSize, debug); + CONSTANT_ACTUAL_STATS.add(c, actual, debug); assert size.constantSize >= actual : "Op " + op + " exceeded estimated constant size; predicted: " + size.constantSize + " actual: " + actual; } else { assert actual == 0 : "Op " + op + " emitted to DataSection without any estimate."; @@ -293,7 +300,7 @@ constantSizeBefore = 0; } } - final ValidationState state = new ValidationState(); + final ValidationState state = new ValidationState(debug); crb.setOpCallback(op -> state.before(op), op -> state.after(op)); return true; } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java 2017-07-07 09:30:04.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java 2017-07-07 09:30:04.000000000 -0700 @@ -22,16 +22,15 @@ */ package org.graalvm.compiler.hotspot.sparc; -import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER; import static jdk.vm.ci.sparc.SPARC.g5; import static jdk.vm.ci.sparc.SPARC.o7; +import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.gen.DebugInfoBuilder; import org.graalvm.compiler.core.sparc.SPARCNodeLIRBuilder; import org.graalvm.compiler.core.sparc.SPARCNodeMatchRules; -import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.hotspot.HotSpotDebugInfoBuilder; import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; import org.graalvm.compiler.hotspot.HotSpotLockStack; @@ -150,7 +149,7 @@ @Override public void visitFullInfopointNode(FullInfopointNode i) { if (i.getState() != null && i.getState().bci == BytecodeFrame.AFTER_BCI) { - Debug.log("Ignoring InfopointNode for AFTER_BCI"); + i.getDebug().log("Ignoring InfopointNode for AFTER_BCI"); } else { super.visitFullInfopointNode(i); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ClassSubstitutionsTests.java 2017-07-07 09:30:04.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ClassSubstitutionsTests.java 2017-07-07 09:30:04.000000000 -0700 @@ -23,16 +23,14 @@ package org.graalvm.compiler.hotspot.test; -import org.junit.Test; - import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.junit.Test; public class ClassSubstitutionsTests extends GraalCompilerTest { @@ -44,14 +42,15 @@ @SuppressWarnings("try") protected StructuredGraph test(final String snippet) { - try (Scope s = Debug.scope("ClassSubstitutionsTest", getMetaAccess().lookupJavaMethod(getMethod(snippet)))) { - StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); + DebugContext debug = getDebugContext(); + try (DebugContext.Scope s = debug.scope("ClassSubstitutionsTest", getMetaAccess().lookupJavaMethod(getMethod(snippet)))) { + StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES, debug); compile(graph.method(), graph); assertNotInGraph(graph, Invoke.class); - Debug.dump(Debug.BASIC_LEVEL, graph, snippet); + debug.dump(DebugContext.BASIC_LEVEL, graph, snippet); return graph; } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java 2017-07-07 09:30:05.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java 2017-07-07 09:30:04.000000000 -0700 @@ -27,6 +27,7 @@ import static org.graalvm.compiler.core.GraalCompilerOptions.PrintBailout; import static org.graalvm.compiler.core.GraalCompilerOptions.PrintStackTraceOnException; import static org.graalvm.compiler.core.test.ReflectionOptionDescriptors.extractEntries; +import static org.graalvm.compiler.debug.MemUseTrackerKey.getCurrentThreadAllocatedBytes; import static org.graalvm.compiler.hotspot.test.CompileTheWorld.Options.DESCRIPTORS; import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier; @@ -68,14 +69,11 @@ import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.bytecode.Bytecodes; import org.graalvm.compiler.core.CompilerThreadFactory; -import org.graalvm.compiler.core.CompilerThreadFactory.DebugConfigAccess; import org.graalvm.compiler.core.test.ReflectionOptionDescriptors; -import org.graalvm.compiler.debug.DebugEnvironment; -import org.graalvm.compiler.debug.GraalDebugConfig; +import org.graalvm.compiler.debug.DebugOptions; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.MethodFilter; import org.graalvm.compiler.debug.TTY; -import org.graalvm.compiler.debug.internal.MemUseTrackerImpl; import org.graalvm.compiler.hotspot.CompilationTask; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotGraalCompiler; @@ -219,7 +217,7 @@ PrintStackTraceOnException.putIfAbsent(compilationOptionsCopy, true); // By default only report statistics for the CTW threads themselves - GraalDebugConfig.Options.DebugValueThreadFilter.putIfAbsent(compilationOptionsCopy, "^CompileTheWorld"); + DebugOptions.MetricsThreadFilter.putIfAbsent(compilationOptionsCopy, "^CompileTheWorld"); this.compilationOptions = compilationOptionsCopy; } @@ -511,13 +509,7 @@ OptionValues savedOptions = currentOptions; currentOptions = new OptionValues(compilationOptions); - threadPool = new ThreadPoolExecutor(threadCount, threadCount, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), - new CompilerThreadFactory("CompileTheWorld", new DebugConfigAccess() { - @Override - public GraalDebugConfig getDebugConfig() { - return DebugEnvironment.ensureInitialized(currentOptions, compiler.getGraalRuntime().getHostProviders().getSnippetReflection()); - } - })); + threadPool = new ThreadPoolExecutor(threadCount, threadCount, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), new CompilerThreadFactory("CompileTheWorld")); try { for (int i = 0; i < entries.length; i++) { @@ -703,7 +695,7 @@ private void compileMethod(HotSpotResolvedJavaMethod method, int counter) { try { long start = System.currentTimeMillis(); - long allocatedAtStart = MemUseTrackerImpl.getCurrentThreadAllocatedBytes(); + long allocatedAtStart = getCurrentThreadAllocatedBytes(); int entryBCI = JVMCICompiler.INVOCATION_ENTRY_BCI; HotSpotCompilationRequest request = new HotSpotCompilationRequest(method, entryBCI, 0L); // For more stable CTW execution, disable use of profiling information @@ -718,7 +710,7 @@ installedCode.invalidate(); } - memoryUsed.getAndAdd(MemUseTrackerImpl.getCurrentThreadAllocatedBytes() - allocatedAtStart); + memoryUsed.getAndAdd(getCurrentThreadAllocatedBytes() - allocatedAtStart); compileTime.getAndAdd(System.currentTimeMillis() - start); compiledMethodsCounter.incrementAndGet(); } catch (Throwable t) { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ConstantPoolSubstitutionsTests.java 2017-07-07 09:30:05.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ConstantPoolSubstitutionsTests.java 2017-07-07 09:30:05.000000000 -0700 @@ -28,8 +28,7 @@ import java.lang.reflect.Method; import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.StructuredGraph; @@ -52,14 +51,15 @@ @SuppressWarnings("try") protected StructuredGraph test(final String snippet) { ResolvedJavaMethod method = getMetaAccess().lookupJavaMethod(getMethod(snippet)); - try (Scope s = Debug.scope("ConstantPoolSubstitutionsTests", method)) { + DebugContext debug = getDebugContext(); + try (DebugContext.Scope s = debug.scope("ConstantPoolSubstitutionsTests", method)) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); compile(graph.method(), graph); assertNotInGraph(graph, Invoke.class); - Debug.dump(Debug.BASIC_LEVEL, graph, snippet); + debug.dump(DebugContext.BASIC_LEVEL, graph, snippet); return graph; } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRLockTest.java 2017-07-07 09:30:05.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRLockTest.java 2017-07-07 09:30:05.000000000 -0700 @@ -32,7 +32,7 @@ import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.core.phases.HighTier; -import org.graalvm.compiler.debug.DebugEnvironment; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.hotspot.phases.OnStackReplacementPhase; @@ -40,7 +40,6 @@ import org.graalvm.compiler.options.OptionValues; import org.graalvm.util.EconomicMap; import org.junit.Assert; -import org.junit.BeforeClass; import org.junit.Test; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -149,11 +148,6 @@ System.gc(); } - @BeforeClass - public static void init() { - DebugEnvironment.ensureInitialized(getInitialOptions()); - } - // @Test @SuppressWarnings("try") public void testLockOSROuterImmediateDeoptAfter() { @@ -313,7 +307,8 @@ EconomicMap, Object> overrides = osrLockNoDeopt(); overrides.put(HighTier.Options.Inline, false); OptionValues options = new OptionValues(getInitialOptions(), overrides); - compile(options, leaf, -1); + DebugContext debug = getDebugContext(options); + compile(debug, leaf, -1); testOSR(options, "testRecursiveLockingRoot"); }); } @@ -327,7 +322,8 @@ EconomicMap, Object> overrides = osrLockNoDeopt(); overrides.put(HighTier.Options.Inline, false); OptionValues options = new OptionValues(getInitialOptions(), overrides); - compile(options, root, -1); + DebugContext debug = getDebugContext(options); + compile(debug, root, -1); testOSR(options, "testRecursiveLeafOSR"); // force a safepoint and hope the inflated locks are deflated System.gc(); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTestBase.java 2017-07-07 09:30:06.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTestBase.java 2017-07-07 09:30:06.000000000 -0700 @@ -31,12 +31,14 @@ import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode; import org.graalvm.compiler.core.target.Backend; import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.hotspot.CompilationTask; import org.graalvm.compiler.hotspot.HotSpotGraalCompiler; import org.graalvm.compiler.java.BciBlockMapping; import org.graalvm.compiler.java.BciBlockMapping.BciBlock; +import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.options.OptionValues; import org.junit.Assert; @@ -68,13 +70,13 @@ checkResult(result); } - protected static void compile(OptionValues options, ResolvedJavaMethod method, int bci) { + protected static void compile(DebugContext debug, ResolvedJavaMethod method, int bci) { HotSpotJVMCIRuntimeProvider runtime = HotSpotJVMCIRuntime.runtime(); long jvmciEnv = 0L; HotSpotCompilationRequest request = new HotSpotCompilationRequest((HotSpotResolvedJavaMethod) method, bci, jvmciEnv); HotSpotGraalCompiler compiler = (HotSpotGraalCompiler) runtime.getCompiler(); - CompilationTask task = new CompilationTask(runtime, compiler, request, true, true, options); - HotSpotCompilationRequestResult result = task.runCompilation(); + CompilationTask task = new CompilationTask(runtime, compiler, request, true, true, debug.getOptions()); + HotSpotCompilationRequestResult result = task.runCompilation(debug); if (result.getFailure() != null) { throw new GraalError(result.getFailureMessage()); } @@ -84,10 +86,11 @@ * Returns the target BCI of the first bytecode backedge. This is where HotSpot triggers * on-stack-replacement in case the backedge counter overflows. */ - private static int getBackedgeBCI(ResolvedJavaMethod method) { + private static int getBackedgeBCI(DebugContext debug, ResolvedJavaMethod method) { Bytecode code = new ResolvedJavaMethodBytecode(method); BytecodeStream stream = new BytecodeStream(code.getCode()); - BciBlockMapping bciBlockMapping = BciBlockMapping.create(stream, code, getInitialOptions()); + OptionValues options = debug.getOptions(); + BciBlockMapping bciBlockMapping = BciBlockMapping.create(stream, code, options, debug); for (BciBlock block : bciBlockMapping.getBlocks()) { if (block.startBci != -1) { @@ -117,12 +120,11 @@ private void compileOSR(OptionValues options, ResolvedJavaMethod method) { // ensure eager resolving - parseEager(method, AllowAssumptions.YES, options); - int bci = getBackedgeBCI(method); + StructuredGraph graph = parseEager(method, AllowAssumptions.YES, options); + DebugContext debug = graph.getDebug(); + int bci = getBackedgeBCI(debug, method); assert bci != -1; - // ensure eager resolving - parseEager(method, AllowAssumptions.YES, options); - compile(options, method, bci); + compile(debug, method, bci); } protected enum ReturnValue { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotCryptoSubstitutionTest.java 2017-07-07 09:30:06.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotCryptoSubstitutionTest.java 2017-07-07 09:30:06.000000000 -0700 @@ -37,6 +37,7 @@ import org.junit.Test; import org.graalvm.compiler.code.CompilationResult; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.hotspot.meta.HotSpotGraphBuilderPlugins; import jdk.vm.ci.code.InstalledCode; @@ -48,8 +49,8 @@ public class HotSpotCryptoSubstitutionTest extends HotSpotGraalCompilerTest { @Override - protected InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult) { - return getBackend().createDefaultInstalledCode(method, compResult); + protected InstalledCode addMethod(DebugContext debug, ResolvedJavaMethod method, CompilationResult compResult) { + return getBackend().createDefaultInstalledCode(debug, method, compResult); } SecretKey aesKey; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalCompilerTest.java 2017-07-07 09:30:07.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalCompilerTest.java 2017-07-07 09:30:06.000000000 -0700 @@ -30,6 +30,7 @@ import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.runtime.RuntimeProvider; import jdk.vm.ci.code.InstalledCode; @@ -54,7 +55,8 @@ HotSpotGraalRuntimeProvider rt = (HotSpotGraalRuntimeProvider) Graal.getRequiredCapability(RuntimeProvider.class); HotSpotProviders providers = rt.getHostBackend().getProviders(); CompilationIdentifier compilationId = runtime().getHostBackend().getCompilationIdentifier(method); - StructuredGraph graph = compiler.getIntrinsicGraph(method, providers, compilationId, getInitialOptions()); + OptionValues options = getInitialOptions(); + StructuredGraph graph = compiler.getIntrinsicGraph(method, providers, compilationId, options, getDebugContext(options)); if (graph != null) { return getCode(method, graph, true, true, graph.getOptions()); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalMBeanTest.java 2017-07-07 09:30:07.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalMBeanTest.java 2017-07-07 09:30:07.000000000 -0700 @@ -41,7 +41,7 @@ import javax.management.ObjectInstance; import javax.management.ObjectName; -import org.graalvm.compiler.debug.GraalDebugConfig; +import org.graalvm.compiler.debug.DebugOptions; import org.graalvm.compiler.hotspot.HotSpotGraalMBean; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.test.GraalTest; @@ -227,14 +227,14 @@ ResolvedJavaMethod method = metaAccess.lookupJavaMethod(Arrays.class.getMethod("asList", Object[].class)); final OptionValues forMethod = realBean.optionsFor(unsetDump, method); assertNotSame(unsetDump, forMethod); - Object nothing = unsetDump.getMap().get(GraalDebugConfig.Options.Dump); + Object nothing = unsetDump.getMap().get(DebugOptions.Dump); assertEquals("Empty string", "", nothing); - Object specialValue = forMethod.getMap().get(GraalDebugConfig.Options.Dump); + Object specialValue = forMethod.getMap().get(DebugOptions.Dump); assertEquals(":3", specialValue); OptionValues normalMethod = realBean.optionsFor(unsetDump, null); - Object noSpecialValue = normalMethod.getMap().get(GraalDebugConfig.Options.Dump); + Object noSpecialValue = normalMethod.getMap().get(DebugOptions.Dump); assertEquals("Empty string", "", noSpecialValue); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotMonitorValueTest.java 2017-07-07 09:30:07.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotMonitorValueTest.java 2017-07-07 09:30:07.000000000 -0700 @@ -34,6 +34,7 @@ import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import jdk.vm.ci.code.BytecodeFrame; @@ -46,7 +47,7 @@ public class HotSpotMonitorValueTest extends GraalCompilerTest { @Override - protected InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult) { + protected InstalledCode addMethod(DebugContext debug, ResolvedJavaMethod method, CompilationResult compResult) { for (Infopoint i : compResult.getInfopoints()) { if (i instanceof Call) { Call call = (Call) i; @@ -75,7 +76,7 @@ } assertDeepEquals(lock3.getOwner(), lock4.getOwner()); assertThat(lock1.getOwner(), not(lock2.getOwner())); - return super.addMethod(method, compResult); + return super.addMethod(debug, method, compResult); } } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotNodeSubstitutionsTest.java 2017-07-07 09:30:08.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotNodeSubstitutionsTest.java 2017-07-07 09:30:08.000000000 -0700 @@ -24,11 +24,13 @@ import org.junit.Test; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.test.MethodSubstitutionTest; /** @@ -38,7 +40,9 @@ @Test public void test() { - StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions(), AllowAssumptions.YES).build(); + OptionValues options = getInitialOptions(); + DebugContext debug = getDebugContext(options); + StructuredGraph graph = new StructuredGraph.Builder(options, debug, AllowAssumptions.YES).build(); test("getNodeClass", ConstantNode.forInt(42, graph)); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/InstalledCodeExecuteHelperTest.java 2017-07-07 09:30:08.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/InstalledCodeExecuteHelperTest.java 2017-07-07 09:30:08.000000000 -0700 @@ -24,13 +24,13 @@ import static java.lang.reflect.Modifier.isStatic; -import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.nodes.StructuredGraph.Builder; +import org.graalvm.compiler.phases.PhaseSuite; +import org.graalvm.compiler.phases.tiers.HighTierContext; import org.junit.Assert; import org.junit.Test; @@ -76,9 +76,10 @@ } @Override - protected StructuredGraph parseEager(ResolvedJavaMethod m, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId, OptionValues options) { - StructuredGraph graph = super.parseEager(m, allowAssumptions, compilationId, options); + protected StructuredGraph parse(Builder builder, PhaseSuite graphBuilderSuite) { + StructuredGraph graph = super.parse(builder, graphBuilderSuite); if (argsToBind != null) { + ResolvedJavaMethod m = graph.method(); Object receiver = isStatic(m.getModifiers()) ? null : this; Object[] args = argsWithReceiver(receiver, argsToBind); JavaType[] parameterTypes = m.toParameterTypes(); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/JVMCIInfopointErrorTest.java 2017-07-07 09:30:09.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/JVMCIInfopointErrorTest.java 2017-07-07 09:30:08.000000000 -0700 @@ -29,14 +29,13 @@ import java.util.function.Consumer; -import org.junit.Test; - import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugConfigScope; +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DebugContext.Scope; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.hotspot.HotSpotCompiledCodeBuilder; import org.graalvm.compiler.lir.FullInfopointOp; @@ -51,6 +50,7 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; +import org.junit.Test; import jdk.vm.ci.code.BytecodeFrame; import jdk.vm.ci.code.CodeCacheProvider; @@ -134,9 +134,13 @@ } private void test(TestSpec spec) { + test(getDebugContext(), spec); + } + + private void test(DebugContext debug, TestSpec spec) { ResolvedJavaMethod method = getResolvedJavaMethod("testMethod"); - StructuredGraph graph = parseForCompile(method); + StructuredGraph graph = parseForCompile(method, debug); TestNode test = graph.add(new TestNode(spec)); graph.addAfterFixed(graph.start(), test); @@ -266,12 +270,13 @@ @SuppressWarnings("try") @Test(expected = Error.class) public void testUnknownJavaValue() { - try (DebugConfigScope s = Debug.setConfig(Debug.silentConfig())) { + DebugContext debug = DebugContext.create(getInitialOptions(), DebugHandlersFactory.LOADER); + try (Scope s = debug.disable()) { /* * Expected: either AssertionError or GraalError, depending on whether the unit test run * is with assertions enabled or disabled. */ - test((tool, state, safepoint) -> { + test(debug, (tool, state, safepoint) -> { LIRFrameState newState = modifyTopFrame(state, new JavaValue[]{new UnknownJavaValue()}, new JavaKind[]{JavaKind.Int}, 1, 0, 0); safepoint.accept(newState); }); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/MemoryUsageBenchmark.java 2017-07-07 09:30:09.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/MemoryUsageBenchmark.java 2017-07-07 09:30:09.000000000 -0700 @@ -22,11 +22,10 @@ */ package org.graalvm.compiler.hotspot.test; -import static org.graalvm.compiler.debug.internal.MemUseTrackerImpl.getCurrentThreadAllocatedBytes; +import static org.graalvm.compiler.debug.MemUseTrackerKey.getCurrentThreadAllocatedBytes; import org.graalvm.compiler.api.test.Graal; import org.graalvm.compiler.core.test.AllocSpy; -import org.graalvm.compiler.debug.DebugEnvironment; import org.graalvm.compiler.hotspot.CompilationTask; import org.graalvm.compiler.hotspot.HotSpotGraalCompiler; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; @@ -121,8 +120,6 @@ // may include processing command line options used by the latter. Graal.getRuntime(); - // Ensure a debug configuration for this thread is initialized - DebugEnvironment.ensureInitialized(getInitialOptions()); new MemoryUsageBenchmark().run(); } @@ -156,7 +153,9 @@ try (AllocSpy as = AllocSpy.open(methodName)) { HotSpotJVMCIRuntimeProvider runtime = HotSpotJVMCIRuntime.runtime(); HotSpotCompilationRequest request = new HotSpotCompilationRequest(method, JVMCICompiler.INVOCATION_ENTRY_BCI, jvmciEnv); - CompilationTask task = new CompilationTask(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), request, true, false, getInitialOptions()); + HotSpotGraalCompiler compiler = (HotSpotGraalCompiler) runtime.getCompiler(); + OptionValues options = getInitialOptions(); + CompilationTask task = new CompilationTask(runtime, compiler, request, true, false, options); task.runCompilation(); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/OptionsInFileTest.java 2017-07-07 09:30:09.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/OptionsInFileTest.java 2017-07-07 09:30:09.000000000 -0700 @@ -22,9 +22,9 @@ */ package org.graalvm.compiler.hotspot.test; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Dump; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.MethodFilter; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.PrintGraph; +import static org.graalvm.compiler.debug.DebugOptions.Dump; +import static org.graalvm.compiler.debug.DebugOptions.MethodFilter; +import static org.graalvm.compiler.debug.DebugOptions.PrintGraph; import static org.graalvm.compiler.test.SubprocessUtil.getVMCommandLine; import static org.graalvm.compiler.test.SubprocessUtil.withoutDebuggerArguments; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/RetryableCompilationTest.java 2017-07-07 09:30:10.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/RetryableCompilationTest.java 2017-07-07 09:30:10.000000000 -0700 @@ -111,7 +111,7 @@ } } if (bgv == 0) { - Assert.fail(String.format("Expected at least one .bgv file in %s: %s", diagnosticOutputZip, entries)); + Assert.fail(String.format("Expected at least one .bgv file in %s: %s%n%s", diagnosticOutputZip, entries, proc)); } if (cfg == 0) { Assert.fail(String.format("Expected at least one .cfg file in %s: %s", diagnosticOutputZip, entries)); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/TestIntrinsicCompiles.java 2017-07-07 09:30:10.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/TestIntrinsicCompiles.java 2017-07-07 09:30:10.000000000 -0700 @@ -23,11 +23,11 @@ package org.graalvm.compiler.hotspot.test; import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; - import java.util.List; import org.graalvm.compiler.api.test.Graal; import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.hotspot.HotSpotGraalCompiler; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; @@ -36,6 +36,7 @@ import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Binding; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin; import org.graalvm.compiler.runtime.RuntimeProvider; import org.graalvm.util.EconomicMap; @@ -63,13 +64,15 @@ EconomicMap> bindings = invocationPlugins.getBindings(true); HotSpotVMConfigStore store = rt.getVMConfig().getStore(); List intrinsics = store.getIntrinsics(); + OptionValues options = getInitialOptions(); + DebugContext debug = getDebugContext(options); for (VMIntrinsicMethod intrinsic : intrinsics) { InvocationPlugin plugin = CheckGraalIntrinsics.findPlugin(bindings, intrinsic); if (plugin != null) { if (plugin instanceof MethodSubstitutionPlugin) { ResolvedJavaMethod method = CheckGraalIntrinsics.resolveIntrinsic(getMetaAccess(), intrinsic); if (!method.isNative()) { - StructuredGraph graph = compiler.getIntrinsicGraph(method, providers, INVALID_COMPILATION_ID, getInitialOptions()); + StructuredGraph graph = compiler.getIntrinsicGraph(method, providers, INVALID_COMPILATION_ID, options, debug); getCode(method, graph); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierAdditionTest.java 2017-07-07 09:30:11.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierAdditionTest.java 2017-07-07 09:30:10.000000000 -0700 @@ -27,11 +27,7 @@ import java.lang.ref.WeakReference; -import org.junit.Assert; -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.nodes.G1PostWriteBarrier; import org.graalvm.compiler.hotspot.nodes.G1PreWriteBarrier; @@ -53,6 +49,8 @@ import org.graalvm.compiler.phases.common.inlining.policy.InlineEverythingPolicy; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.tiers.MidTierContext; +import org.junit.Assert; +import org.junit.Test; import jdk.vm.ci.hotspot.HotSpotInstalledCode; import jdk.vm.ci.meta.JavaConstant; @@ -256,8 +254,9 @@ @SuppressWarnings("try") private void testHelper(final String snippetName, final int expectedBarriers) throws Exception, SecurityException { ResolvedJavaMethod snippet = getResolvedJavaMethod(snippetName); - try (Scope s = Debug.scope("WriteBarrierAdditionTest", snippet)) { - StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); + DebugContext debug = getDebugContext(); + try (DebugContext.Scope s = debug.scope("WriteBarrierAdditionTest", snippet)) { + StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO, debug); HighTierContext highContext = getDefaultHighTierContext(); MidTierContext midContext = new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, graph.getProfilingInfo()); new InliningPhase(new InlineEverythingPolicy(), new CanonicalizerPhase()).apply(graph, highContext); @@ -266,7 +265,7 @@ new GuardLoweringPhase().apply(graph, midContext); new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext); new WriteBarrierAdditionPhase(config).apply(graph); - Debug.dump(Debug.BASIC_LEVEL, graph, "After Write Barrier Addition"); + debug.dump(DebugContext.BASIC_LEVEL, graph, "After Write Barrier Addition"); int barriers = 0; if (config.useG1GC) { @@ -305,7 +304,7 @@ } } } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierVerificationTest.java 2017-07-07 09:30:11.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierVerificationTest.java 2017-07-07 09:30:11.000000000 -0700 @@ -23,14 +23,11 @@ package org.graalvm.compiler.hotspot.test; import java.util.List; -import org.junit.Assert; -import org.junit.Test; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; -import org.graalvm.compiler.debug.DebugConfig; -import org.graalvm.compiler.debug.DebugConfigScope; + +import org.graalvm.compiler.debug.DebugCloseable; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DebugContext.Scope; import org.graalvm.compiler.debug.DebugDumpScope; -import org.graalvm.compiler.debug.internal.DebugScope; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.nodes.G1ArrayRangePostWriteBarrier; import org.graalvm.compiler.hotspot.nodes.G1ArrayRangePreWriteBarrier; @@ -64,6 +61,8 @@ import org.graalvm.compiler.phases.tiers.MidTierContext; import org.graalvm.util.EconomicMap; import org.graalvm.word.LocationIdentity; +import org.junit.Assert; +import org.junit.Test; import jdk.vm.ci.meta.ResolvedJavaField; @@ -647,8 +646,9 @@ @SuppressWarnings("try") private void testPredicate(final String snippet, final GraphPredicate expectedBarriers, final int... removedBarrierIndices) { - try (Scope d = Debug.scope("WriteBarrierVerificationTest", new DebugDumpScope(snippet))) { - final StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); + DebugContext debug = getDebugContext(); + try (DebugCloseable d = debug.disableIntercept(); DebugContext.Scope s = debug.scope("WriteBarrierVerificationTest", new DebugDumpScope(snippet))) { + final StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES, debug); HighTierContext highTierContext = getDefaultHighTierContext(); new InliningPhase(new CanonicalizerPhase()).apply(graph, highTierContext); @@ -725,10 +725,7 @@ } }; - DebugConfig debugConfig = DebugScope.getConfig(); - DebugConfig fixedConfig = debugConfig == null ? null - : Debug.fixedConfig(debugConfig.getOptions(), 0, 0, false, false, false, false, false, debugConfig.dumpHandlers(), debugConfig.verifyHandlers(), debugConfig.output()); - try (DebugConfigScope s = Debug.setConfig(fixedConfig)) { + try (Scope disabled = debug.disable()) { ReentrantNodeIterator.apply(closure, graph.start(), false); new WriteBarrierVerificationPhase(config).apply(graph); } catch (AssertionError error) { @@ -740,7 +737,7 @@ throw error; } } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java 2017-07-07 09:30:11.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java 2017-07-07 09:30:11.000000000 -0700 @@ -34,19 +34,21 @@ import java.util.List; +import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.code.CompilationResult; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.core.common.CompilationIdentifier; +import org.graalvm.compiler.debug.CounterKey; import org.graalvm.compiler.debug.DebugCloseable; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugDumpScope; -import org.graalvm.compiler.debug.DebugTimer; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.Management; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.debug.TimeSource; +import org.graalvm.compiler.debug.TimerKey; import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.printer.GraalDebugHandlersFactory; import org.graalvm.util.EconomicMap; import jdk.vm.ci.code.BailoutException; @@ -63,7 +65,7 @@ public class CompilationTask { - private static final DebugCounter BAILOUTS = Debug.counter("Bailouts"); + private static final CounterKey BAILOUTS = DebugContext.counter("Bailouts"); private static final EventProvider eventProvider; @@ -99,7 +101,7 @@ CompilationResult result; RetryableCompilation(EventProvider.CompilationEvent compilationEvent) { - super(compiler.getGraalRuntime(), options); + super(compiler.getGraalRuntime()); this.compilationEvent = compilationEvent; } @@ -110,7 +112,7 @@ @SuppressWarnings("try") @Override - protected HotSpotCompilationRequestResult run(Throwable retryCause) { + protected HotSpotCompilationRequestResult run(DebugContext debug, Throwable retryCause) { HotSpotResolvedJavaMethod method = getMethod(); int entryBCI = getEntryBCI(); final boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI; @@ -133,15 +135,15 @@ allocatedBytesBefore = 0L; } - try (Scope s = Debug.scope("Compiling", new DebugDumpScope(getIdString(), true))) { + try (DebugContext.Scope s = debug.scope("Compiling", new DebugDumpScope(getIdString(), true))) { // Begin the compilation event. compilationEvent.begin(); - result = compiler.compile(method, entryBCI, useProfilingInfo, compilationId, options); + result = compiler.compile(method, entryBCI, useProfilingInfo, compilationId, options, debug); } catch (Throwable e) { if (retryCause != null) { log("Exception during retry", e); } - throw Debug.handle(e); + throw debug.handle(e); } finally { // End the compilation event. compilationEvent.end(); @@ -166,8 +168,8 @@ } if (result != null) { - try (DebugCloseable b = CodeInstallationTime.start()) { - installMethod(result); + try (DebugCloseable b = CodeInstallationTime.start(debug)) { + installMethod(debug, result); } } stats.finish(method, installedCode); @@ -219,10 +221,14 @@ return getRequest().getMethod(); } + CompilationIdentifier getCompilationIdentifier() { + return compilationId; + } + /** - * Returns the compilation id of this task. + * Returns the HostSpot id of this compilation. * - * @return compile id + * @return HotSpot compile id */ public int getId() { return getRequest().getId(); @@ -251,46 +257,44 @@ /** * Time spent in compilation. */ - private static final DebugTimer CompilationTime = Debug.timer("CompilationTime"); + private static final TimerKey CompilationTime = DebugContext.timer("CompilationTime").doc("Time spent in compilation and code installation."); /** * Counts the number of compiled {@linkplain CompilationResult#getBytecodeSize() bytecodes}. */ - private static final DebugCounter CompiledBytecodes = Debug.counter("CompiledBytecodes"); + private static final CounterKey CompiledBytecodes = DebugContext.counter("CompiledBytecodes"); /** * Counts the number of compiled {@linkplain CompilationResult#getBytecodeSize() bytecodes} for * which {@linkplain CompilationResult#getTargetCode()} code was installed. */ - private static final DebugCounter CompiledAndInstalledBytecodes = Debug.counter("CompiledAndInstalledBytecodes"); + private static final CounterKey CompiledAndInstalledBytecodes = DebugContext.counter("CompiledAndInstalledBytecodes"); /** * Counts the number of installed {@linkplain CompilationResult#getTargetCodeSize()} bytes. */ - private static final DebugCounter InstalledCodeSize = Debug.counter("InstalledCodeSize"); + private static final CounterKey InstalledCodeSize = DebugContext.counter("InstalledCodeSize"); /** * Time spent in code installation. */ - public static final DebugTimer CodeInstallationTime = Debug.timer("CodeInstallation"); + public static final TimerKey CodeInstallationTime = DebugContext.timer("CodeInstallation"); - @SuppressWarnings("try") public HotSpotCompilationRequestResult runCompilation() { + SnippetReflectionProvider snippetReflection = compiler.getGraalRuntime().getHostProviders().getSnippetReflection(); + try (DebugContext debug = DebugContext.create(options, new GraalDebugHandlersFactory(snippetReflection))) { + return runCompilation(debug); + } + } + + @SuppressWarnings("try") + public HotSpotCompilationRequestResult runCompilation(DebugContext debug) { HotSpotGraalRuntimeProvider graalRuntime = compiler.getGraalRuntime(); GraalHotSpotVMConfig config = graalRuntime.getVMConfig(); int entryBCI = getEntryBCI(); boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI; HotSpotResolvedJavaMethod method = getMethod(); - // register the compilation id in the method metrics - if (Debug.isMethodMeterEnabled()) { - if (getEntryBCI() != JVMCICompiler.INVOCATION_ENTRY_BCI) { - Debug.methodMetrics(method).addToMetric(getId(), "CompilationIdOSR"); - } else { - Debug.methodMetrics(method).addToMetric(getId(), "CompilationId"); - } - } - // Log a compilation event. EventProvider.CompilationEvent compilationEvent = eventProvider.newCompilationEvent(); @@ -304,10 +308,10 @@ } RetryableCompilation compilation = new RetryableCompilation(compilationEvent); - try (DebugCloseable a = CompilationTime.start()) { - return compilation.execute(); + try (DebugCloseable a = CompilationTime.start(debug)) { + return compilation.runWithRetry(debug); } catch (BailoutException bailout) { - BAILOUTS.increment(); + BAILOUTS.increment(debug); if (ExitVMOnBailout.getValue(options)) { TTY.out.println(method.format("Bailout in %H.%n(%p)")); bailout.printStackTrace(TTY.out); @@ -350,11 +354,11 @@ if (compilation.result != null) { compiledBytecodes = compilation.result.getBytecodeSize(); - CompiledBytecodes.add(compiledBytecodes); + CompiledBytecodes.add(debug, compiledBytecodes); if (installedCode != null) { codeSize = installedCode.getSize(); - CompiledAndInstalledBytecodes.add(compiledBytecodes); - InstalledCodeSize.add(codeSize); + CompiledAndInstalledBytecodes.add(debug, compiledBytecodes); + InstalledCodeSize.add(debug, codeSize); } } @@ -411,13 +415,17 @@ } @SuppressWarnings("try") - private void installMethod(final CompilationResult compResult) { + private void installMethod(DebugContext debug, final CompilationResult compResult) { final CodeCacheProvider codeCache = jvmciRuntime.getHostJVMCIBackend().getCodeCache(); HotSpotBackend backend = compiler.getGraalRuntime().getHostBackend(); installedCode = null; Object[] context = {new DebugDumpScope(getIdString(), true), codeCache, getMethod(), compResult}; - installedCode = (HotSpotInstalledCode) backend.createInstalledCode(getRequest().getMethod(), getRequest(), compResult, - getRequest().getMethod().getSpeculationLog(), null, installAsDefault, context); + try (DebugContext.Scope s = debug.scope("CodeInstall", context)) { + installedCode = (HotSpotInstalledCode) backend.createInstalledCode(debug, getRequest().getMethod(), getRequest(), compResult, + getRequest().getMethod().getSpeculationLog(), null, installAsDefault, context); + } catch (Throwable e) { + throw debug.handle(e); + } } @Override --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotDebugInfoBuilder.java 2017-07-07 09:30:12.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotDebugInfoBuilder.java 2017-07-07 09:30:12.000000000 -0700 @@ -57,7 +57,7 @@ private HotSpotCodeCacheProvider codeCacheProvider; public HotSpotDebugInfoBuilder(NodeValueMap nodeValueMap, HotSpotLockStack lockStack, HotSpotLIRGenerator gen) { - super(nodeValueMap); + super(nodeValueMap, gen.getResult().getLIR().getDebug()); this.lockStack = lockStack; this.codeCacheProvider = gen.getProviders().getCodeCache(); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java 2017-07-07 09:30:12.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java 2017-07-07 09:30:12.000000000 -0700 @@ -27,8 +27,10 @@ import java.io.ByteArrayOutputStream; import java.io.PrintStream; +import java.util.Collections; import java.util.Formattable; import java.util.Formatter; +import java.util.List; import org.graalvm.compiler.api.runtime.GraalJVMCICompiler; import org.graalvm.compiler.bytecode.Bytecode; @@ -36,12 +38,10 @@ import org.graalvm.compiler.core.GraalCompiler; import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.common.util.CompilationAlarm; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugConfigScope; -import org.graalvm.compiler.debug.DebugEnvironment; -import org.graalvm.compiler.debug.GraalDebugConfig; -import org.graalvm.compiler.debug.TopLevelDebugConfig; -import org.graalvm.compiler.debug.internal.method.MethodMetricsRootScopeInfo; +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DebugContext.Activation; +import org.graalvm.compiler.debug.DebugOptions; import org.graalvm.compiler.hotspot.CompilationCounters.Options; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.phases.OnStackReplacementPhase; @@ -60,6 +60,7 @@ import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.tiers.Suites; +import org.graalvm.compiler.printer.GraalDebugHandlersFactory; import jdk.vm.ci.code.CompilationRequest; import jdk.vm.ci.code.CompilationRequestResult; @@ -80,13 +81,21 @@ private final HotSpotGraalRuntimeProvider graalRuntime; private final CompilationCounters compilationCounters; private final BootstrapWatchDog bootstrapWatchDog; + private List factories; HotSpotGraalCompiler(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalRuntimeProvider graalRuntime, OptionValues options) { this.jvmciRuntime = jvmciRuntime; this.graalRuntime = graalRuntime; // It is sufficient to have one compilation counter object per Graal compiler object. this.compilationCounters = Options.CompilationCountLimit.getValue(options) > 0 ? new CompilationCounters(options) : null; - this.bootstrapWatchDog = graalRuntime.isBootstrapping() && !GraalDebugConfig.Options.BootstrapInitializeOnly.getValue(options) ? BootstrapWatchDog.maybeCreate(graalRuntime) : null; + this.bootstrapWatchDog = graalRuntime.isBootstrapping() && !DebugOptions.BootstrapInitializeOnly.getValue(options) ? BootstrapWatchDog.maybeCreate(graalRuntime) : null; + } + + public List getDebugHandlersFactories() { + if (factories == null) { + factories = Collections.singletonList(new GraalDebugHandlersFactory(graalRuntime.getHostProviders().getSnippetReflection())); + } + return factories; } @Override @@ -104,11 +113,13 @@ if (graalRuntime.isShutdown()) { return HotSpotCompilationRequestResult.failure(String.format("Shutdown entered"), false); } - OptionValues options = graalRuntime.getOptions(request.getMethod()); + + ResolvedJavaMethod method = request.getMethod(); + OptionValues options = graalRuntime.getOptions(method); if (graalRuntime.isBootstrapping()) { - if (GraalDebugConfig.Options.BootstrapInitializeOnly.getValue(options)) { - return HotSpotCompilationRequestResult.failure(String.format("Skip compilation because %s is enabled", GraalDebugConfig.Options.BootstrapInitializeOnly.getName()), true); + if (DebugOptions.BootstrapInitializeOnly.getValue(options)) { + return HotSpotCompilationRequestResult.failure(String.format("Skip compilation because %s is enabled", DebugOptions.BootstrapInitializeOnly.getName()), true); } if (bootstrapWatchDog != null) { if (bootstrapWatchDog.hitCriticalCompilationRateOrTimeout()) { @@ -117,7 +128,6 @@ } } } - ResolvedJavaMethod method = request.getMethod(); HotSpotCompilationRequest hsRequest = (HotSpotCompilationRequest) request; try (CompilationWatchDog w1 = CompilationWatchDog.watch(method, hsRequest.getId(), options); BootstrapWatchDog.Watch w2 = bootstrapWatchDog == null ? null : bootstrapWatchDog.watch(request); @@ -125,31 +135,29 @@ if (compilationCounters != null) { compilationCounters.countCompilation(method); } - // Ensure a debug configuration for this thread is initialized - DebugEnvironment.ensureInitialized(options, graalRuntime.getHostProviders().getSnippetReflection()); CompilationTask task = new CompilationTask(jvmciRuntime, this, hsRequest, true, installAsDefault, options); - CompilationRequestResult r; - try (DebugConfigScope dcs = Debug.setConfig(new TopLevelDebugConfig()); - Debug.Scope s = Debug.methodMetricsScope("HotSpotGraalCompiler", MethodMetricsRootScopeInfo.create(method), true, method)) { - r = task.runCompilation(); + CompilationRequestResult r = null; + try (DebugContext debug = graalRuntime.openDebugContext(options, task.getCompilationIdentifier(), method, getDebugHandlersFactories()); + Activation a = debug.activate()) { + r = task.runCompilation(debug); } assert r != null; return r; } } - public CompilationResult compile(ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, CompilationIdentifier compilationId, OptionValues options) { + public CompilationResult compile(ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, CompilationIdentifier compilationId, OptionValues options, DebugContext debug) { HotSpotBackend backend = graalRuntime.getHostBackend(); HotSpotProviders providers = backend.getProviders(); final boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI; - StructuredGraph graph = method.isNative() || isOSR ? null : getIntrinsicGraph(method, providers, compilationId, options); + StructuredGraph graph = method.isNative() || isOSR ? null : getIntrinsicGraph(method, providers, compilationId, options, debug); if (graph == null) { SpeculationLog speculationLog = method.getSpeculationLog(); if (speculationLog != null) { speculationLog.collectFailedSpeculations(); } - graph = new StructuredGraph.Builder(options, AllowAssumptions.ifTrue(OptAssumptions.getValue(options))).method(method).entryBCI(entryBCI).speculationLog( + graph = new StructuredGraph.Builder(options, debug, AllowAssumptions.ifTrue(OptAssumptions.getValue(options))).method(method).entryBCI(entryBCI).speculationLog( speculationLog).useProfilingInfo(useProfilingInfo).compilationId(compilationId).build(); } @@ -186,17 +194,18 @@ * @param method * @param compilationId * @param options + * @param debug * @return an intrinsic graph that can be compiled and installed for {@code method} or null */ @SuppressWarnings("try") - public StructuredGraph getIntrinsicGraph(ResolvedJavaMethod method, HotSpotProviders providers, CompilationIdentifier compilationId, OptionValues options) { + public StructuredGraph getIntrinsicGraph(ResolvedJavaMethod method, HotSpotProviders providers, CompilationIdentifier compilationId, OptionValues options, DebugContext debug) { Replacements replacements = providers.getReplacements(); Bytecode subst = replacements.getSubstitutionBytecode(method); if (subst != null) { ResolvedJavaMethod substMethod = subst.getMethod(); assert !substMethod.equals(method); - StructuredGraph graph = new StructuredGraph.Builder(options, AllowAssumptions.YES).method(substMethod).compilationId(compilationId).build(); - try (Debug.Scope scope = Debug.scope("GetIntrinsicGraph", graph)) { + StructuredGraph graph = new StructuredGraph.Builder(options, debug, AllowAssumptions.YES).method(substMethod).compilationId(compilationId).build(); + try (DebugContext.Scope scope = debug.scope("GetIntrinsicGraph", graph)) { Plugins plugins = new Plugins(providers.getGraphBuilderPlugins()); GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(plugins); IntrinsicContext initialReplacementContext = new IntrinsicContext(method, substMethod, subst.getOrigin(), ROOT_COMPILATION); @@ -205,7 +214,7 @@ assert !graph.isFrozen(); return graph; } catch (Throwable e) { - Debug.handle(e); + debug.handle(e); } } return null; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalMBean.java 2017-07-07 09:30:13.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalMBean.java 2017-07-07 09:30:13.000000000 -0700 @@ -54,7 +54,8 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; import jdk.vm.ci.runtime.JVMCI; -import org.graalvm.compiler.debug.GraalDebugConfig; + +import org.graalvm.compiler.debug.DebugOptions; import org.graalvm.compiler.options.OptionDescriptor; import org.graalvm.compiler.options.OptionDescriptors; import org.graalvm.compiler.options.OptionKey; @@ -165,9 +166,9 @@ for (Dump request : methodDumps) { final String clazzName = method.getDeclaringClass().getName(); if (method.getName().equals(request.method) && clazzName.equals(request.clazz)) { - current = new OptionValues(current, GraalDebugConfig.Options.Dump, request.filter, - GraalDebugConfig.Options.PrintGraphHost, request.host, - GraalDebugConfig.Options.PrintBinaryGraphPort, request.port); + current = new OptionValues(current, DebugOptions.Dump, request.filter, + DebugOptions.PrintGraphHost, request.host, + DebugOptions.PrintBinaryGraphPort, request.port); break; } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java 2017-07-07 09:30:13.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java 2017-07-07 09:30:13.000000000 -0700 @@ -27,12 +27,7 @@ import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.core.common.GraalOptions.HotSpotPrintInlining; -import static org.graalvm.compiler.debug.GraalDebugConfig.areScopedGlobalMetricsEnabled; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.DebugValueSummary; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Dump; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Log; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.MethodFilter; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Verify; +import static org.graalvm.compiler.debug.DebugContext.DEFAULT_LOG_STREAM; import java.io.File; import java.io.FileOutputStream; @@ -54,14 +49,15 @@ import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.api.runtime.GraalRuntime; +import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.target.Backend; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugEnvironment; +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DebugContext.Description; +import org.graalvm.compiler.debug.GlobalMetrics; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.TTY; -import org.graalvm.compiler.debug.internal.DebugValuesPrinter; -import org.graalvm.compiler.debug.internal.method.MethodMetricsPrinter; import org.graalvm.compiler.hotspot.CompilationStatistics.Options; import org.graalvm.compiler.hotspot.CompilerConfigurationFactory.BackendMap; import org.graalvm.compiler.hotspot.debug.BenchmarkCounters; @@ -104,7 +100,7 @@ } private final HotSpotBackend hostBackend; - private DebugValuesPrinter debugValuesPrinter; + private final GlobalMetrics metricValues = new GlobalMetrics(); private final List snippetCounterGroups; private final EconomicMap, HotSpotBackend> backends = EconomicMap.create(Equivalence.IDENTITY); @@ -163,56 +159,6 @@ } } - if (Log.getValue(options) == null && !areScopedGlobalMetricsEnabled(options) && Dump.getValue(options) == null && Verify.getValue(options) == null) { - if (MethodFilter.getValue(options) != null && !Debug.isEnabled()) { - TTY.println("WARNING: Ignoring MethodFilter option since Log, Meter, Time, TrackMemUse, Dump and Verify options are all null"); - } - } - - if (Debug.isEnabled()) { - DebugEnvironment.ensureInitialized(options, hostBackend.getProviders().getSnippetReflection()); - - String summary = DebugValueSummary.getValue(options); - if (summary != null) { - switch (summary) { - case "Name": - case "Partial": - case "Complete": - case "Thread": - break; - default: - throw new GraalError("Unsupported value for DebugSummaryValue: %s", summary); - } - } - } - - if (Debug.areUnconditionalCountersEnabled() || Debug.areUnconditionalTimersEnabled() || Debug.areUnconditionalMethodMetricsEnabled() || - (Debug.isEnabled() && areScopedGlobalMetricsEnabled(options)) || (Debug.isEnabled() && Debug.isMethodFilteringEnabled())) { - // This must be created here to avoid loading the DebugValuesPrinter class - // during shutdown() which in turn can cause a deadlock - int mmPrinterType = 0; - mmPrinterType |= MethodMetricsPrinter.Options.MethodMeterPrintAscii.getValue(options) ? 1 : 0; - mmPrinterType |= MethodMetricsPrinter.Options.MethodMeterFile.getValue(options) != null ? 2 : 0; - switch (mmPrinterType) { - case 0: - debugValuesPrinter = new DebugValuesPrinter(); - break; - case 1: - debugValuesPrinter = new DebugValuesPrinter(new MethodMetricsPrinter.MethodMetricsASCIIPrinter(TTY.out)); - break; - case 2: - debugValuesPrinter = new DebugValuesPrinter(new MethodMetricsPrinter.MethodMetricsCSVFilePrinter()); - break; - case 3: - debugValuesPrinter = new DebugValuesPrinter( - new MethodMetricsPrinter.MethodMetricsCompositePrinter(new MethodMetricsPrinter.MethodMetricsCSVFilePrinter(), - new MethodMetricsPrinter.MethodMetricsASCIIPrinter(TTY.out))); - break; - default: - break; - } - } - // Complete initialization of backends try (InitTimer st = timer(hostBackend.getTarget().arch.getName(), ".completeInitialization")) { hostBackend.completeInitialization(jvmciRuntime, options); @@ -262,6 +208,12 @@ } @Override + public DebugContext openDebugContext(OptionValues compilationOptions, CompilationIdentifier compilationId, Object compilable, Iterable factories) { + Description description = new Description(compilable, compilationId.toString(CompilationIdentifier.Verbosity.ID)); + return DebugContext.create(compilationOptions, description, metricValues, DEFAULT_LOG_STREAM, factories); + } + + @Override public OptionValues getOptions() { return mBean.optionsFor(options, null); } @@ -330,9 +282,8 @@ void shutdown() { shutdown = true; - if (debugValuesPrinter != null) { - debugValuesPrinter.printDebugValues(options); - } + metricValues.print(options); + phaseTransition("final"); if (snippetCounterGroups != null) { @@ -345,10 +296,8 @@ archiveAndDeleteOutputDirectory(); } - void clearMeters() { - if (debugValuesPrinter != null) { - debugValuesPrinter.clearDebugValues(); - } + void clearMetrics() { + metricValues.clear(); } private final boolean bootstrapJVMCI; @@ -449,15 +398,13 @@ }); TTY.println("Graal diagnostic output saved in %s", zip); } catch (IOException e) { - TTY.printf("IO error archiving %s:%n", dir); - e.printStackTrace(TTY.out); + TTY.printf("IO error archiving %s:%n%s%n", dir, e); } for (Path p : toDelete) { try { Files.delete(p); } catch (IOException e) { - TTY.printf("IO error deleting %s:%n", p); - e.printStackTrace(TTY.out); + TTY.printf("IO error deleting %s:%n%s%n", p, e); } } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntimeProvider.java 2017-07-07 09:30:14.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntimeProvider.java 2017-07-07 09:30:14.000000000 -0700 @@ -23,6 +23,9 @@ package org.graalvm.compiler.hotspot; import org.graalvm.compiler.api.runtime.GraalRuntime; +import org.graalvm.compiler.core.common.CompilationIdentifier; +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.SnippetCounter.Group; @@ -55,19 +58,27 @@ GraalHotSpotVMConfig getVMConfig(); /** + * Opens a debug context for compiling {@code compilable}. The {@link DebugContext#close()} + * method should be called on the returned object once the compilation is finished. + * + * @param compilationOptions the options used to configure the compilation debug context + * @param compilationId a system wide unique compilation id + * @param compilable the input to the compilation + */ + DebugContext openDebugContext(OptionValues compilationOptions, CompilationIdentifier compilationId, Object compilable, Iterable factories); + + /** * Gets the option values associated with this runtime. */ OptionValues getOptions(); /** - * Gets the option values associated with this runtime that are applicable for given method. + * Gets the option values associated with this runtime that are applicable for a given method. * * @param forMethod the method we are seeking for options for - * @return the options - by default same as {@link #getOptions()} + * @return the options applicable for compiling {@code method} */ - default OptionValues getOptions(ResolvedJavaMethod forMethod) { - return getOptions(); - } + OptionValues getOptions(ResolvedJavaMethod forMethod); /** * Determines if the VM is currently bootstrapping the JVMCI compiler. --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalVMEventListener.java 2017-07-07 09:30:14.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalVMEventListener.java 2017-07-07 09:30:14.000000000 -0700 @@ -22,17 +22,18 @@ */ package org.graalvm.compiler.hotspot; +import java.util.ArrayList; +import java.util.List; + +import org.graalvm.compiler.code.CompilationResult; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DebugOptions; +import org.graalvm.compiler.serviceprovider.GraalServices; + import jdk.vm.ci.code.CompiledCode; import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; import jdk.vm.ci.hotspot.HotSpotVMEventListener; -import org.graalvm.compiler.code.CompilationResult; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.GraalDebugConfig; -import org.graalvm.compiler.serviceprovider.GraalServices; - -import java.util.ArrayList; -import java.util.List; public class HotSpotGraalVMEventListener implements HotSpotVMEventListener { @@ -54,13 +55,14 @@ @Override public void notifyInstall(HotSpotCodeCacheProvider codeCache, InstalledCode installedCode, CompiledCode compiledCode) { - if (Debug.isDumpEnabled(Debug.BASIC_LEVEL)) { - CompilationResult compResult = Debug.contextLookup(CompilationResult.class); + DebugContext debug = DebugContext.forCurrentThread(); + if (debug.isDumpEnabled(DebugContext.BASIC_LEVEL)) { + CompilationResult compResult = debug.contextLookup(CompilationResult.class); assert compResult != null : "can't dump installed code properly without CompilationResult"; - Debug.dump(Debug.BASIC_LEVEL, installedCode, "After code installation"); + debug.dump(DebugContext.BASIC_LEVEL, installedCode, "After code installation"); } - if (Debug.isLogEnabled()) { - Debug.log("%s", codeCache.disassemble(installedCode)); + if (debug.isLogEnabled()) { + debug.log("%s", codeCache.disassemble(installedCode)); } for (HotSpotCodeCacheListener listener : listeners) { listener.notifyInstall(codeCache, installedCode, compiledCode); @@ -70,8 +72,8 @@ @Override public void notifyBootstrapFinished() { runtime.notifyBootstrapFinished(); - if (GraalDebugConfig.Options.ClearMetricsAfterBootstrap.getValue(runtime.getOptions())) { - runtime.clearMeters(); + if (DebugOptions.ClearMetricsAfterBootstrap.getValue(runtime.getOptions())) { + runtime.clearMetrics(); } } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotHostBackend.java 2017-07-07 09:30:16.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotHostBackend.java 2017-07-07 09:30:14.000000000 -0700 @@ -26,8 +26,11 @@ import static jdk.vm.ci.code.CodeUtil.getCallingConvention; import static jdk.vm.ci.common.InitTimer.timer; +import java.util.Collections; + import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider; import org.graalvm.compiler.hotspot.meta.HotSpotLoweringProvider; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; @@ -36,6 +39,7 @@ import org.graalvm.compiler.lir.framemap.ReferenceMapBuilder; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.printer.GraalDebugHandlersFactory; import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.common.InitTimer; @@ -77,7 +81,8 @@ foreignCalls.initialize(providers, options); } try (InitTimer st = timer("lowerer.initialize")) { - lowerer.initialize(options, providers, config); + Iterable factories = Collections.singletonList(new GraalDebugHandlersFactory(providers.getSnippetReflection())); + lowerer.initialize(options, factories, providers, config); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java 2017-07-07 09:30:16.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java 2017-07-07 09:30:16.000000000 -0700 @@ -27,6 +27,7 @@ import org.graalvm.compiler.hotspot.word.HotSpotOperation; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.util.Providers; +import org.graalvm.compiler.printer.GraalDebugHandlersFactory; import org.graalvm.compiler.replacements.ReplacementsImpl; import jdk.vm.ci.code.TargetDescription; @@ -39,7 +40,7 @@ public class HotSpotReplacementsImpl extends ReplacementsImpl { public HotSpotReplacementsImpl(OptionValues options, Providers providers, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider, TargetDescription target) { - super(options, providers, snippetReflection, bytecodeProvider, target); + super(options, new GraalDebugHandlersFactory(snippetReflection), providers, snippetReflection, bytecodeProvider, target); } @Override --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotRetryableCompilation.java 2017-07-07 09:30:16.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotRetryableCompilation.java 2017-07-07 09:30:16.000000000 -0700 @@ -22,31 +22,23 @@ */ package org.graalvm.compiler.hotspot; -import static org.graalvm.compiler.debug.Debug.VERBOSE_LEVEL; -import static org.graalvm.compiler.debug.DelegatingDebugConfig.Feature.DUMP_METHOD; -import static org.graalvm.compiler.debug.DelegatingDebugConfig.Level.DUMP; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Dump; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.DumpPath; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.ForceDebugEnable; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.PrintCFGFileName; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.PrintGraphFileName; +import static org.graalvm.compiler.debug.DebugContext.VERBOSE_LEVEL; +import static org.graalvm.compiler.debug.DebugOptions.Dump; +import static org.graalvm.compiler.debug.DebugOptions.DumpPath; +import static org.graalvm.compiler.debug.DebugOptions.MethodFilter; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.PrintStream; -import java.nio.file.InvalidPathException; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Collection; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugDumpHandler; +import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugRetryableTask; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.compiler.printer.GraalDebugConfigCustomizer; +import org.graalvm.compiler.printer.GraalDebugHandlersFactory; import jdk.vm.ci.code.BailoutException; @@ -56,12 +48,10 @@ */ public abstract class HotSpotRetryableCompilation extends DebugRetryableTask { - protected final OptionValues originalOptions; protected final HotSpotGraalRuntimeProvider runtime; - public HotSpotRetryableCompilation(HotSpotGraalRuntimeProvider runtime, OptionValues options) { + public HotSpotRetryableCompilation(HotSpotGraalRuntimeProvider runtime) { this.runtime = runtime; - this.originalOptions = options; } /** @@ -70,65 +60,42 @@ @Override public abstract String toString(); - private static String sanitizedFileName(String name) { - StringBuilder buf = new StringBuilder(name.length()); - for (int i = 0; i < name.length(); i++) { - char c = name.charAt(i); - try { - Paths.get(String.valueOf(c)); - } catch (InvalidPathException e) { - buf.append('_'); - } - buf.append(c); - } - return buf.toString(); - } - @Override - protected boolean onRetry(Throwable t) { + protected DebugContext getRetryContext(DebugContext initialDebug, Throwable t) { if (t instanceof BailoutException) { - return false; - } - - if (!Debug.isEnabled()) { - TTY.printf("Error while compiling %s due to %s.%nRe-run with -D%s%s=true to capture graph dumps upon a compilation failure.%n", this, - t, HotSpotGraalOptionValues.GRAAL_OPTION_PROPERTY_PREFIX, ForceDebugEnable.getName()); - return false; + return null; } - if (Dump.hasBeenSet(originalOptions)) { + OptionValues initialOptions = initialDebug.getOptions(); + if (Dump.hasBeenSet(initialOptions)) { // If dumping is explicitly enabled, Graal is being debugged // so don't interfere with what the user is expecting to see. - return false; + return null; } String outputDirectory = runtime.getOutputDirectory(); if (outputDirectory == null) { - return false; + return null; } - String dumpName = sanitizedFileName(toString()); + String dumpName = GraalDebugHandlersFactory.sanitizedFileName(toString()); File dumpPath = new File(outputDirectory, dumpName); dumpPath.mkdirs(); if (!dumpPath.exists()) { TTY.println("Warning: could not create dump directory " + dumpPath); - return false; + return null; } TTY.println("Retrying compilation of " + this + " due to " + t); retryLogPath = new File(dumpPath, "retry.log").getPath(); log("Exception causing retry", t); - retryDumpHandlers = new ArrayList<>(); - retryOptions = new OptionValues(originalOptions, - PrintCFGFileName, dumpName, - PrintGraphFileName, dumpName, + OptionValues retryOptions = new OptionValues(initialOptions, + Dump, ":" + VERBOSE_LEVEL, + MethodFilter, null, DumpPath, dumpPath.getPath()); - override(DUMP, VERBOSE_LEVEL).enable(DUMP_METHOD); - new GraalDebugConfigCustomizer().customize(this); - return true; + SnippetReflectionProvider snippetReflection = runtime.getHostProviders().getSnippetReflection(); + return DebugContext.create(retryOptions, new GraalDebugHandlersFactory(snippetReflection)); } - private Collection retryDumpHandlers; - private OptionValues retryOptions; private String retryLogPath; /** @@ -153,14 +120,4 @@ } } } - - @Override - public Collection dumpHandlers() { - return retryDumpHandlers; - } - - @Override - public OptionValues getOptions() { - return retryOptions; - } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java 2017-07-07 09:30:17.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java 2017-07-07 09:30:17.000000000 -0700 @@ -38,11 +38,11 @@ class JVMCIVersionCheck { private static final int JVMCI8_MIN_MAJOR_VERSION = 0; - private static final int JVMCI8_MIN_MINOR_VERSION = 26; + private static final int JVMCI8_MIN_MINOR_VERSION = 29; // MAX_VALUE indicates that no current EA version is compatible with Graal. // Note: Keep README.md in sync with the EA version support checked here. - private static final int JVMCI9_MIN_EA_BUILD = 174; + private static final int JVMCI9_MIN_EA_BUILD = 176; private static void failVersionCheck(boolean exit, String reason, Object... args) { Formatter errorMessage = new Formatter().format(reason, args); @@ -112,7 +112,7 @@ "Cannot read JVMCI version from java.vm.version property: %s.%n", vmVersion); } else { if (vmVersion.contains("SNAPSHOT")) { - // The snapshot of http://hg.openjdk.java.net/jdk9/hs tip is expected to work + // The snapshot of http://hg.openjdk.java.net/jdk9/dev tip is expected to work return; } if (vmVersion.contains("internal")) { @@ -120,9 +120,8 @@ return; } // http://openjdk.java.net/jeps/223 - // Only support EA builds until GA is available - if (vmVersion.startsWith("9-ea+")) { - int start = "9-ea+".length(); + if (vmVersion.startsWith("9+")) { + int start = "9+".length(); int end = start; end = start; while (end < vmVersion.length() && Character.isDigit(vmVersion.charAt(end))) { @@ -145,9 +144,10 @@ failVersionCheck(exitOnFailure, "The VM is an insufficiently recent EA JDK9 build for Graal: %d < %d.%n", build, JVMCI9_MIN_EA_BUILD); } return; + } else { + // Graal will be compatible with all JDK versions as of 9 GA + // until a JVMCI API change is made in a 9u or later release. } - failVersionCheck(exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal.%n" + - "Cannot read JDK9 EA build number from java.vm.version property: %s.%n", vmVersion); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/PrintStreamOptionKey.java 2017-07-07 09:30:17.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/PrintStreamOptionKey.java 2017-07-07 09:30:17.000000000 -0700 @@ -65,6 +65,9 @@ } } + if (name.contains("%t")) { + name = name.replaceAll("%t", String.valueOf(System.currentTimeMillis())); + } return name; } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/debug/BenchmarkCounters.java 2017-07-07 09:30:17.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/debug/BenchmarkCounters.java 2017-07-07 09:30:17.000000000 -0700 @@ -22,11 +22,10 @@ */ package org.graalvm.compiler.hotspot.debug; -import java.io.FileNotFoundException; +import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; -import java.nio.file.Path; import java.util.Iterator; import java.util.Locale; import java.util.Map; @@ -39,7 +38,6 @@ import org.graalvm.compiler.core.common.SuppressFBWarnings; import org.graalvm.compiler.debug.CSVUtil; -import org.graalvm.compiler.debug.GraalDebugConfig; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; @@ -49,7 +47,6 @@ import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.compiler.options.UniquePathUtilities; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; @@ -105,9 +102,9 @@ public static final OptionKey BenchmarkDynamicCounters = new OptionKey<>(null); @Option(help = "Use grouping separators for number printing", type = OptionType.Debug) public static final OptionKey DynamicCountersPrintGroupSeparator = new OptionKey<>(true); - @Option(help = "Print in human readable format", type = OptionType.Debug) - public static final OptionKey DynamicCountersHumanReadable = new OptionKey<>(true); - @Option(help = "Benchmark counters log file (default is stdout)", type = OptionType.Debug) + @Option(help = "File to which benchmark counters are dumped. A CSV format is used if the file ends with .csv " + + "otherwise a more human readable format is used. The fields in the CSV format are: " + + "category, group, name, value", type = OptionType.Debug) public static final OptionKey BenchmarkCountersFile = new OptionKey<>(null); @Option(help = "Dump dynamic counters", type = OptionType.Debug) public static final OptionKey BenchmarkCountersDumpDynamic = new OptionKey<>(true); @@ -170,112 +167,153 @@ private static synchronized void dump(OptionValues options, PrintStream out, double seconds, long[] counters, int maxRows) { if (!counterMap.isEmpty()) { - if (Options.DynamicCountersHumanReadable.getValue(options)) { - 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 (Options.BenchmarkCountersDumpStatic.getValue(options)) { - dumpCounters(options, out, seconds, counters, true, group, maxRows); - } - if (Options.BenchmarkCountersDumpDynamic.getValue(options)) { - dumpCounters(options, out, seconds, counters, false, group, maxRows); + try (Dumper dumper = Dumper.getDumper(options, out, counterMap.size(), seconds, maxRows)) { + TreeSet set = new TreeSet<>(); + counterMap.forEach((nameGroup, counter) -> set.add(counter.group)); + for (String group : set) { + if (group != null) { + if (Options.BenchmarkCountersDumpStatic.getValue(options)) { + dumper.dumpCounters(true, group, collectStaticCounters(), counterMap.entrySet(), options); + } + if (Options.BenchmarkCountersDumpDynamic.getValue(options)) { + dumper.dumpCounters(false, group, collectDynamicCounters(counters), counterMap.entrySet(), options); + } } } } - if (Options.DynamicCountersHumanReadable.getValue(options)) { - out.println("============================"); - } clear(counters); } } + private static synchronized long[] collectDynamicCounters(long[] counters) { + long[] array = counters.clone(); + for (int i = 0; i < array.length; i++) { + array[i] -= delta[i]; + } + return array; + } + + private static synchronized long[] collectStaticCounters() { + long[] array = new long[counterMap.size()]; + for (Counter counter : counterMap.values()) { + array[counter.index] = counter.staticCounters.get(); + } + return array; + } + private static synchronized void clear(long[] counters) { delta = counters; } - private static synchronized void dumpCounters(OptionValues options, PrintStream out, double seconds, long[] counters, boolean staticCounter, String group, int maxRows) { + private static boolean shouldDumpComputerReadable(OptionValues options) { + String dumpFile = Options.BenchmarkCountersFile.getValue(options); + return dumpFile != null && (dumpFile.endsWith(".csv") || dumpFile.endsWith(".CSV")); + } + + private abstract static class Dumper implements AutoCloseable { + public static Dumper getDumper(OptionValues options, PrintStream out, int counterSize, double second, int maxRows) { + Dumper dumper = shouldDumpComputerReadable(options) ? new ComputerReadableDumper(out) : new HumanReadableDumper(out, second, maxRows); + dumper.start(counterSize); + return dumper; + } + + protected final PrintStream out; - // collect the numbers - long[] array; - if (staticCounter) { - array = new long[counterMap.size()]; - for (Counter counter : counterMap.values()) { - array[counter.index] = counter.staticCounters.get(); - } - } else { - array = counters.clone(); - for (int i = 0; i < array.length; i++) { - array[i] -= delta[i]; - } - } - Set> counterEntrySet = counterMap.entrySet(); - if (Options.DynamicCountersHumanReadable.getValue(options)) { - dumpHumanReadable(options, out, seconds, staticCounter, group, maxRows, array, counterEntrySet); - } else { - dumpComputerReadable(out, staticCounter, group, array, counterEntrySet); + private Dumper(PrintStream out) { + this.out = out; } + + protected abstract void start(int size); + + public abstract void dumpCounters(boolean staticCounter, String group, long[] array, Set> counterEntrySet, OptionValues options); + + @Override + public abstract void close(); + } private static String getName(String nameGroup, String group) { return nameGroup.substring(0, nameGroup.length() - group.length() - 1); } - private static void dumpHumanReadable(OptionValues options, PrintStream out, double seconds, boolean staticCounter, String group, int maxRows, long[] array, - Set> counterEntrySet) { - // sort the counters by putting them into a sorted map - TreeMap sorted = new TreeMap<>(); - long sum = 0; - for (Map.Entry entry : counterEntrySet) { - Counter counter = entry.getValue(); - int index = counter.index; - if (counter.group.equals(group)) { - sum += array[index]; - sorted.put(array[index] * array.length + index, getName(entry.getKey(), group)); - } + private static long percentage(long counter, long sum) { + return (counter * 200 + 1) / sum / 2; + } + + private static class HumanReadableDumper extends Dumper { + private final double seconds; + private final int maxRows; + + HumanReadableDumper(PrintStream out, double seconds, int maxRows) { + super(out); + this.seconds = seconds; + this.maxRows = maxRows; + } + + @Override + public void start(int size) { + out.println("====== dynamic counters (" + size + " in total) ======"); + } + + @Override + public void close() { + out.println("============================"); } - if (sum > 0) { - long cutoff = sorted.size() < 10 ? 1 : Math.max(1, sum / 100); - int cnt = sorted.size(); - - // remove everything below cutoff and keep at most maxRows - Iterator> iter = sorted.entrySet().iterator(); - while (iter.hasNext()) { - Map.Entry entry = iter.next(); - long counter = entry.getKey() / array.length; - if (counter < cutoff || cnt > maxRows) { - iter.remove(); + @Override + public void dumpCounters(boolean staticCounter, String group, long[] array, Set> counterEntrySet, OptionValues options) { + // sort the counters by putting them into a sorted map + TreeMap sorted = new TreeMap<>(); + long sum = 0; + for (Map.Entry entry : counterEntrySet) { + Counter counter = entry.getValue(); + int index = counter.index; + if (counter.group.equals(group)) { + sum += array[index]; + sorted.put(array[index] * array.length + index, getName(entry.getKey(), group)); } - cnt--; } - String numFmt = Options.DynamicCountersPrintGroupSeparator.getValue(options) ? "%,19d" : "%19d"; - if (staticCounter) { - out.println("=========== " + group + " (static counters):"); - for (Map.Entry entry : sorted.entrySet()) { + if (sum > 0) { + long cutoff = sorted.size() < 10 ? 1 : Math.max(1, sum / 100); + int cnt = sorted.size(); + + // remove everything below cutoff and keep at most maxRows + Iterator> iter = sorted.entrySet().iterator(); + while (iter.hasNext()) { + Map.Entry entry = iter.next(); long counter = entry.getKey() / array.length; - out.format(Locale.US, numFmt + " %3d%% %s\n", counter, percentage(counter, sum), entry.getValue()); - } - 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, numFmt + "/s %3d%% %s\n", (long) (counter / seconds), percentage(counter, sum), entry.getValue()); + if (counter < cutoff || cnt > maxRows) { + iter.remove(); } - out.format(Locale.US, numFmt + "/s total\n", (long) (sum / seconds)); - } else { - out.println("=========== " + group + " (dynamic counters):"); + cnt--; + } + + String numFmt = Options.DynamicCountersPrintGroupSeparator.getValue(options) ? "%,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, numFmt + " %3d%% %s\n", counter, percentage(counter, sum), entry.getValue()); } 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, numFmt + "/s %3d%% %s\n", (long) (counter / seconds), percentage(counter, sum), entry.getValue()); + } + 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, numFmt + " %3d%% %s\n", counter, percentage(counter, sum), entry.getValue()); + } + out.format(Locale.US, numFmt + " total\n", sum); + } } } } @@ -283,21 +321,35 @@ private static final String CSV_FMT = CSVUtil.buildFormatString("%s", "%s", "%s", "%d"); - private static void dumpComputerReadable(PrintStream out, boolean staticCounter, String group, long[] array, Set> counterEntrySet) { - String category = staticCounter ? "static counters" : "dynamic counters"; - for (Map.Entry entry : counterEntrySet) { - Counter counter = entry.getValue(); - if (counter.group.equals(group)) { - String name = getName(entry.getKey(), group); - int index = counter.index; - long value = array[index]; - CSVUtil.Escape.println(out, CSV_FMT, category, group, name, value); - } + private static class ComputerReadableDumper extends Dumper { + + ComputerReadableDumper(PrintStream out) { + super(out); } - } - private static long percentage(long counter, long sum) { - return (counter * 200 + 1) / sum / 2; + @Override + public void start(int size) { + // do nothing + } + + @Override + public void close() { + // do nothing + } + + @Override + public void dumpCounters(boolean staticCounter, String group, long[] array, Set> counterEntrySet, OptionValues options) { + String category = staticCounter ? "static counters" : "dynamic counters"; + for (Map.Entry entry : counterEntrySet) { + Counter counter = entry.getValue(); + if (counter.group.equals(group)) { + String name = getName(entry.getKey(), group); + int index = counter.index; + long value = array[index]; + CSVUtil.Escape.println(out, CSV_FMT, category, group, name, value); + } + } + } } private abstract static class CallbackOutputStream extends OutputStream { @@ -440,10 +492,11 @@ private static PrintStream getPrintStream(OptionValues options) { if (Options.BenchmarkCountersFile.getValue(options) != null) { try { - Path path = UniquePathUtilities.getPathGlobal(options, Options.BenchmarkCountersFile, GraalDebugConfig.Options.DumpPath, "csv"); - TTY.println("Writing benchmark counters to '%s'", path); - return new PrintStream(path.toFile()); - } catch (FileNotFoundException e) { + + File file = new File(Options.BenchmarkCountersFile.getValue(options)); + TTY.println("Writing benchmark counters to '%s'", file.getAbsolutePath()); + return new PrintStream(file); + } catch (IOException e) { TTY.out().println(e.getMessage()); TTY.out().println("Fallback to default"); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/lir/HotSpotZapRegistersPhase.java 2017-07-07 09:30:18.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/lir/HotSpotZapRegistersPhase.java 2017-07-07 09:30:18.000000000 -0700 @@ -27,7 +27,7 @@ import java.util.ArrayList; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.hotspot.HotSpotLIRGenerationResult; import org.graalvm.compiler.hotspot.stubs.Stub; @@ -82,7 +82,8 @@ @SuppressWarnings("try") private static void processBlock(DiagnosticLIRGeneratorTool diagnosticLirGenTool, HotSpotLIRGenerationResult res, LIR lir, LIRInsertionBuffer buffer, AbstractBlockBase block, boolean zapRegisters, boolean zapStack) { - try (Indent indent = Debug.logAndIndent("Process block %s", block)) { + DebugContext debug = lir.getDebug(); + try (Indent indent = debug.logAndIndent("Process block %s", block)) { ArrayList instructions = lir.getLIRforBlock(block); buffer.init(instructions); for (int index = 0; index < instructions.size(); index++) { @@ -100,7 +101,7 @@ SaveRegistersOp old = res.getCalleeSaveInfo().put(state, zap); assert old == null : "Already another SaveRegisterOp registered! " + old; buffer.append(index + 1, (LIRInstruction) zap); - Debug.log("Insert ZapRegister after %s", inst); + debug.log("Insert ZapRegister after %s", inst); } } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java 2017-07-07 09:30:18.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java 2017-07-07 09:30:18.000000000 -0700 @@ -49,6 +49,7 @@ import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.StampPair; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeInputList; @@ -199,25 +200,25 @@ } @Override - public void initialize(OptionValues options, HotSpotProviders providers, GraalHotSpotVMConfig config) { - super.initialize(options, runtime, providers, providers.getSnippetReflection()); + public void initialize(OptionValues options, Iterable factories, HotSpotProviders providers, GraalHotSpotVMConfig config) { + super.initialize(options, factories, runtime, providers, providers.getSnippetReflection()); assert target == providers.getCodeCache().getTarget(); - instanceofSnippets = new InstanceOfSnippets.Templates(options, runtime, providers, target); - newObjectSnippets = new NewObjectSnippets.Templates(options, runtime, providers, target, config); - monitorSnippets = new MonitorSnippets.Templates(options, runtime, providers, target, config.useFastLocking); - writeBarrierSnippets = new WriteBarrierSnippets.Templates(options, runtime, providers, target, config.useCompressedOops ? config.getOopEncoding() : null); - exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(options, providers, target); - unsafeLoadSnippets = new UnsafeLoadSnippets.Templates(options, providers, target); - assertionSnippets = new AssertionSnippets.Templates(options, providers, target); - arraycopySnippets = new ArrayCopySnippets.Templates(options, runtime, providers, target); - stringToBytesSnippets = new StringToBytesSnippets.Templates(options, providers, target); - hashCodeSnippets = new HashCodeSnippets.Templates(options, providers, target); + instanceofSnippets = new InstanceOfSnippets.Templates(options, factories, runtime, providers, target); + newObjectSnippets = new NewObjectSnippets.Templates(options, factories, runtime, providers, target, config); + monitorSnippets = new MonitorSnippets.Templates(options, factories, runtime, providers, target, config.useFastLocking); + writeBarrierSnippets = new WriteBarrierSnippets.Templates(options, factories, runtime, providers, target, config.useCompressedOops ? config.getOopEncoding() : null); + exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(options, factories, providers, target); + unsafeLoadSnippets = new UnsafeLoadSnippets.Templates(options, factories, providers, target); + assertionSnippets = new AssertionSnippets.Templates(options, factories, providers, target); + arraycopySnippets = new ArrayCopySnippets.Templates(options, factories, runtime, providers, target); + stringToBytesSnippets = new StringToBytesSnippets.Templates(options, factories, providers, target); + hashCodeSnippets = new HashCodeSnippets.Templates(options, factories, providers, target); if (GeneratePIC.getValue(options)) { - resolveConstantSnippets = new ResolveConstantSnippets.Templates(options, providers, target); - profileSnippets = new ProfileSnippets.Templates(options, providers, target); + resolveConstantSnippets = new ResolveConstantSnippets.Templates(options, factories, providers, target); + profileSnippets = new ProfileSnippets.Templates(options, factories, providers, target); } - providers.getReplacements().registerSnippetTemplateCache(new UnsafeArrayCopySnippets.Templates(options, providers, target)); + providers.getReplacements().registerSnippetTemplateCache(new UnsafeArrayCopySnippets.Templates(options, factories, providers, target)); } public MonitorSnippets.Templates getMonitorSnippets() { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotAOTProfilingPlugin.java 2017-07-07 09:30:19.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotAOTProfilingPlugin.java 2017-07-07 09:30:19.000000000 -0700 @@ -22,7 +22,6 @@ */ package org.graalvm.compiler.hotspot.meta; -import org.graalvm.compiler.hotspot.FingerprintUtil; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.options.OptionKey; @@ -50,7 +49,7 @@ @Override public boolean shouldProfile(GraphBuilderContext builder, ResolvedJavaMethod method) { - return super.shouldProfile(builder, method) && FingerprintUtil.getFingerprint(((HotSpotResolvedObjectType) method.getDeclaringClass())) != 0; + return super.shouldProfile(builder, method) && ((HotSpotResolvedObjectType) method.getDeclaringClass()).getFingerprint() != 0; } @Override --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java 2017-07-07 09:30:19.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java 2017-07-07 09:30:19.000000000 -0700 @@ -146,8 +146,8 @@ * cannot be re-executed. * @param killedLocations the memory locations killed by the foreign call */ - public void linkForeignCall(OptionValues options, HotSpotProviders providers, ForeignCallDescriptor descriptor, long address, boolean prependThread, Transition transition, - boolean reexecutable, LocationIdentity... killedLocations) { + public void linkForeignCall(OptionValues options, HotSpotProviders providers, ForeignCallDescriptor descriptor, long address, boolean prependThread, Transition transition, boolean reexecutable, + LocationIdentity... killedLocations) { ForeignCallStub stub = new ForeignCallStub(options, jvmciRuntime, providers, address, descriptor, prependThread, transition, reexecutable, killedLocations); HotSpotForeignCallLinkage linkage = stub.getLinkage(); HotSpotForeignCallLinkage targetLinkage = stub.getTargetLinkage(); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java 2017-07-07 09:30:20.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java 2017-07-07 09:30:19.000000000 -0700 @@ -42,7 +42,6 @@ import org.graalvm.compiler.bytecode.BytecodeProvider; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.hotspot.FingerprintUtil; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.nodes.CurrentJavaThreadNode; import org.graalvm.compiler.hotspot.replacements.AESCryptSubstitutions; @@ -148,7 +147,7 @@ return false; } // check if the holder has a valid fingerprint - if (FingerprintUtil.getFingerprint((HotSpotResolvedObjectType) method.getDeclaringClass()) == 0) { + if (((HotSpotResolvedObjectType) method.getDeclaringClass()).getFingerprint() == 0) { // Deopt otherwise b.append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); return true; @@ -163,7 +162,7 @@ if (clazz.equals(String.class)) { return false; } - if (Class.class.isAssignableFrom(clazz) && FingerprintUtil.getFingerprint((HotSpotResolvedObjectType) type) != 0) { + if (Class.class.isAssignableFrom(clazz) && ((HotSpotResolvedObjectType) type).getFingerprint() != 0) { return false; } b.append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotLoweringProvider.java 2017-07-07 09:30:20.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotLoweringProvider.java 2017-07-07 09:30:20.000000000 -0700 @@ -22,6 +22,7 @@ */ package org.graalvm.compiler.hotspot.meta; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.nodes.spi.LoweringProvider; import org.graalvm.compiler.options.OptionValues; @@ -31,5 +32,5 @@ */ public interface HotSpotLoweringProvider extends LoweringProvider { - void initialize(OptionValues options, HotSpotProviders providers, GraalHotSpotVMConfig config); + void initialize(OptionValues options, Iterable factories, HotSpotProviders providers, GraalHotSpotVMConfig config); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java 2017-07-07 09:30:20.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java 2017-07-07 09:30:20.000000000 -0700 @@ -133,7 +133,7 @@ protected void run(StructuredGraph graph, HighTierContext context) { EncodedGraph encodedGraph = GraphEncoder.encodeSingleGraph(graph, runtime.getTarget().arch); - StructuredGraph targetGraph = new StructuredGraph.Builder(graph.getOptions(), AllowAssumptions.YES).method(graph.method()).build(); + StructuredGraph targetGraph = new StructuredGraph.Builder(graph.getOptions(), graph.getDebug(), AllowAssumptions.YES).method(graph.method()).build(); SimplifyingGraphDecoder graphDecoder = new SimplifyingGraphDecoder(runtime.getTarget().arch, targetGraph, context.getMetaAccess(), context.getConstantReflection(), context.getConstantFieldProvider(), context.getStampProvider(), !ImmutableCode.getValue(graph.getOptions())); graphDecoder.decode(encodedGraph); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java 2017-07-07 09:30:21.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java 2017-07-07 09:30:21.000000000 -0700 @@ -27,8 +27,8 @@ import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.core.common.cfg.Loop; import org.graalvm.compiler.core.common.type.Stamp; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.iterators.NodeIterable; @@ -80,7 +80,7 @@ // @formatter:on } - private static final DebugCounter OsrWithLocksCount = Debug.counter("OSRWithLocks"); + private static final CounterKey OsrWithLocksCount = DebugContext.counter("OSRWithLocks"); private static boolean supportOSRWithLocks(OptionValues options) { return Options.SupportOSRWithLocks.getValue(options); @@ -88,13 +88,14 @@ @Override protected void run(StructuredGraph graph) { + DebugContext debug = graph.getDebug(); if (graph.getEntryBCI() == JVMCICompiler.INVOCATION_ENTRY_BCI) { // This happens during inlining in a OSR method, because the same phase plan will be // used. assert graph.getNodes(EntryMarkerNode.TYPE).isEmpty(); return; } - Debug.dump(Debug.DETAILED_LEVEL, graph, "OnStackReplacement initial at bci %d", graph.getEntryBCI()); + debug.dump(DebugContext.DETAILED_LEVEL, graph, "OnStackReplacement initial at bci %d", graph.getEntryBCI()); EntryMarkerNode osr; int maxIterations = -1; @@ -144,7 +145,7 @@ proxy.replaceAndDelete(proxy.value()); } GraphUtil.removeFixedWithUnusedInputs(osr); - Debug.dump(Debug.DETAILED_LEVEL, graph, "OnStackReplacement loop peeling result"); + debug.dump(DebugContext.DETAILED_LEVEL, graph, "OnStackReplacement loop peeling result"); } while (true); FrameState osrState = osr.stateAfter(); @@ -157,7 +158,7 @@ graph.setStart(osrStart); osrStart.setStateAfter(osrState); - Debug.dump(Debug.DETAILED_LEVEL, graph, "OnStackReplacement after setting OSR start"); + debug.dump(DebugContext.DETAILED_LEVEL, graph, "OnStackReplacement after setting OSR start"); final int localsSize = osrState.localsSize(); final int locksSize = osrState.locksSize(); @@ -188,13 +189,13 @@ } osr.replaceAtUsages(InputType.Guard, osrStart); - Debug.dump(Debug.DETAILED_LEVEL, graph, "OnStackReplacement after replacing entry proxies"); + debug.dump(DebugContext.DETAILED_LEVEL, graph, "OnStackReplacement after replacing entry proxies"); GraphUtil.killCFG(start); - Debug.dump(Debug.DETAILED_LEVEL, graph, "OnStackReplacement result"); + debug.dump(DebugContext.DETAILED_LEVEL, graph, "OnStackReplacement result"); new DeadCodeEliminationPhase(Required).apply(graph); if (currentOSRWithLocks) { - OsrWithLocksCount.increment(); + OsrWithLocksCount.increment(debug); for (int i = osrState.monitorIdCount() - 1; i >= 0; --i) { MonitorIdNode id = osrState.monitorIdAt(i); ValueNode lockedObject = osrState.lockAt(i); @@ -210,7 +211,7 @@ osrMonitorEnter.setNext(oldNext); osrStart.setNext(osrMonitorEnter); } - Debug.dump(Debug.DETAILED_LEVEL, graph, "After inserting OSR monitor enters"); + debug.dump(DebugContext.DETAILED_LEVEL, graph, "After inserting OSR monitor enters"); /* * Ensure balanced monitorenter - monitorexit * @@ -226,7 +227,7 @@ } } } - Debug.dump(Debug.DETAILED_LEVEL, graph, "OnStackReplacement result"); + debug.dump(DebugContext.DETAILED_LEVEL, graph, "OnStackReplacement result"); new DeadCodeEliminationPhase(Required).apply(graph); /* * There must not be any parameter nodes left after OSR compilation. --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/AOTInliningPolicy.java 2017-07-07 09:30:21.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/AOTInliningPolicy.java 2017-07-07 09:30:21.000000000 -0700 @@ -27,7 +27,6 @@ import java.util.Map; -import org.graalvm.compiler.hotspot.FingerprintUtil; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.spi.Replacements; import org.graalvm.compiler.options.Option; @@ -67,7 +66,7 @@ for (int i = 0; i < info.numberOfMethods(); ++i) { HotSpotResolvedObjectType t = (HotSpotResolvedObjectType) info.methodAt(i).getDeclaringClass(); - if (FingerprintUtil.getFingerprint(t) == 0) { + if (t.getFingerprint() == 0) { return false; } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java 2017-07-07 09:30:22.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java 2017-07-07 09:30:21.000000000 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -29,14 +29,6 @@ import java.util.HashSet; import java.util.List; -import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; -import jdk.vm.ci.hotspot.HotSpotObjectConstant; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaType; -import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; -import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.ConstantReflectionProvider; -import jdk.vm.ci.meta.ResolvedJavaType; - import org.graalvm.compiler.core.common.cfg.BlockMap; import org.graalvm.compiler.core.common.type.ObjectStamp; import org.graalvm.compiler.core.common.type.Stamp; @@ -44,7 +36,6 @@ import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeMap; -import org.graalvm.compiler.hotspot.FingerprintUtil; import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction; import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode; import org.graalvm.compiler.hotspot.nodes.aot.LoadConstantIndirectlyFixedNode; @@ -52,18 +43,37 @@ import org.graalvm.compiler.hotspot.nodes.aot.LoadMethodCountersNode; import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode; import org.graalvm.compiler.hotspot.nodes.aot.ResolveMethodAndLoadCountersNode; +import org.graalvm.compiler.nodes.AbstractBeginNode; +import org.graalvm.compiler.nodes.AbstractMergeNode; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.FixedWithNextNode; +import org.graalvm.compiler.nodes.FrameState; +import org.graalvm.compiler.nodes.LoopBeginNode; +import org.graalvm.compiler.nodes.LoopExitNode; +import org.graalvm.compiler.nodes.StateSplit; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.cfg.Block; import org.graalvm.compiler.phases.BasePhase; +import org.graalvm.compiler.phases.graph.ReentrantNodeIterator; +import org.graalvm.compiler.phases.graph.ReentrantNodeIterator.NodeIteratorClosure; import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy; import org.graalvm.compiler.phases.tiers.PhaseContext; import org.graalvm.util.EconomicMap; +import jdk.vm.ci.code.BytecodeFrame; +import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; +import jdk.vm.ci.hotspot.HotSpotObjectConstant; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaType; +import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; +import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.ConstantReflectionProvider; +import jdk.vm.ci.meta.ResolvedJavaType; + public class ReplaceConstantNodesPhase extends BasePhase { private static final HashSet> builtIns = new HashSet<>(); @@ -115,63 +125,175 @@ if (type.getElementalType().isPrimitive()) { return false; } - return FingerprintUtil.getFingerprint((HotSpotResolvedObjectType) (type.getElementalType())) == 0; + return ((HotSpotResolvedObjectType) (type.getElementalType())).getFingerprint() == 0; } - return FingerprintUtil.getFingerprint((HotSpotResolvedObjectType) type) == 0; + return ((HotSpotResolvedObjectType) type).getFingerprint() == 0; } /** - * Replace {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} with indirection. + * Insert the replacement node into the graph. We may need to insert it into a place different + * than the original {@link FloatingNode} since we need to make sure that replacement will have + * a valid state assigned. * * @param graph - * @param node {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} that needs - * resolution. + * @param stateMapper + * @param node + * @param replacement */ - private void handleHotSpotMetaspaceConstant(StructuredGraph graph, ConstantNode node) { - HotSpotMetaspaceConstant metaspaceConstant = (HotSpotMetaspaceConstant) node.asConstant(); - HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) metaspaceConstant.asResolvedJavaType(); + private static void insertReplacement(StructuredGraph graph, FrameStateMapperClosure stateMapper, FloatingNode node, FixedWithNextNode replacement) { + FixedWithNextNode insertionPoint = findInsertionPoint(graph, stateMapper, node); + graph.addAfterFixed(insertionPoint, replacement); + stateMapper.addState(replacement, stateMapper.getState(insertionPoint)); + } - if (type != null) { - if (verifyFingerprints && checkForBadFingerprint(type)) { - throw new GraalError("Type with bad fingerprint: " + type); - } - assert !metaspaceConstant.isCompressed() : "No support for replacing compressed metaspace constants"; - tryToReplaceWithExisting(graph, node); - if (anyUsagesNeedReplacement(node)) { - replaceWithResolution(graph, node); - } - } else { - throw new GraalError("Unsupported metaspace constant type: " + type); - } + /** + * Find a good place to insert a stateful fixed node that is above the given node. A good + * insertion point should have a valid FrameState reaching it. + * + * @param graph + * @param stateMapper + * @param node start search from this node up + * @return an insertion point + */ + private static FixedWithNextNode findInsertionPoint(StructuredGraph graph, FrameStateMapperClosure stateMapper, FloatingNode node) { + FixedWithNextNode fixed = findFixedBeforeFloating(graph, node); + FixedWithNextNode result = findFixedWithValidState(graph, stateMapper, fixed); + return result; } /** - * Find the lowest dominating {@link FixedWithNextNode} before given node. + * Find the first {@link FixedWithNextNode} that is currently scheduled before the given + * floating node. * * @param graph - * @param node - * @return the last {@link FixedWithNextNode} that is scheduled before node. + * @param node start search from this node up + * @return the first {@link FixedWithNextNode} */ - private static FixedWithNextNode findFixedWithNextBefore(StructuredGraph graph, Node node) { + private static FixedWithNextNode findFixedBeforeFloating(StructuredGraph graph, FloatingNode node) { ScheduleResult schedule = graph.getLastSchedule(); NodeMap nodeToBlock = schedule.getNodeToBlockMap(); - BlockMap> blockToNodes = schedule.getBlockToNodesMap(); - Block block = nodeToBlock.get(node); + BlockMap> blockToNodes = schedule.getBlockToNodesMap(); FixedWithNextNode result = null; for (Node n : blockToNodes.get(block)) { - if (n instanceof FixedWithNextNode) { - result = (FixedWithNextNode) n; - } if (n.equals(node)) { break; } + if (n instanceof FixedWithNextNode) { + result = (FixedWithNextNode) n; + } } assert result != null; return result; } /** + * Find first dominating {@link FixedWithNextNode} that has a valid state reaching it starting + * from the given node. + * + * @param graph + * @param stateMapper + * @param node + * @return {@link FixedWithNextNode} that we can use as an insertion point + */ + private static FixedWithNextNode findFixedWithValidState(StructuredGraph graph, FrameStateMapperClosure stateMapper, FixedWithNextNode node) { + ScheduleResult schedule = graph.getLastSchedule(); + NodeMap nodeToBlock = schedule.getNodeToBlockMap(); + Block block = nodeToBlock.get(node); + + Node n = node; + do { + if (isFixedWithValidState(stateMapper, n)) { + return (FixedWithNextNode) n; + } + while (n != block.getBeginNode()) { + n = n.predecessor(); + if (isFixedWithValidState(stateMapper, n)) { + return (FixedWithNextNode) n; + } + } + block = block.getDominator(); + if (block != null) { + n = block.getEndNode(); + } + } while (block != null); + + return graph.start(); + } + + private static boolean isFixedWithValidState(FrameStateMapperClosure stateMapper, Node n) { + if (n instanceof FixedWithNextNode) { + FixedWithNextNode fixed = (FixedWithNextNode) n; + assert stateMapper.getState(fixed) != null; + if (!BytecodeFrame.isPlaceholderBci(stateMapper.getState(fixed).bci)) { + return true; + } + } + return false; + } + + /** + * Compute frame states for all fixed nodes in the graph. + */ + private static class FrameStateMapperClosure extends NodeIteratorClosure { + private NodeMap reachingStates; + + @Override + protected FrameState processNode(FixedNode node, FrameState previousState) { + FrameState currentState = previousState; + if (node instanceof StateSplit) { + StateSplit stateSplit = (StateSplit) node; + FrameState stateAfter = stateSplit.stateAfter(); + if (stateAfter != null) { + currentState = stateAfter; + } + } + reachingStates.put(node, currentState); + return currentState; + } + + @Override + protected FrameState merge(AbstractMergeNode merge, List states) { + FrameState singleFrameState = singleFrameState(states); + FrameState currentState = singleFrameState == null ? merge.stateAfter() : singleFrameState; + reachingStates.put(merge, currentState); + return currentState; + } + + @Override + protected FrameState afterSplit(AbstractBeginNode node, FrameState oldState) { + return oldState; + } + + @Override + protected EconomicMap processLoop(LoopBeginNode loop, FrameState initialState) { + return ReentrantNodeIterator.processLoop(this, loop, initialState).exitStates; + } + + private static FrameState singleFrameState(List states) { + FrameState singleState = states.get(0); + for (int i = 1; i < states.size(); ++i) { + if (states.get(i) != singleState) { + return null; + } + } + return singleState; + } + + FrameStateMapperClosure(StructuredGraph graph) { + reachingStates = new NodeMap<>(graph); + } + + public FrameState getState(Node n) { + return reachingStates.get(n); + } + + public void addState(Node n, FrameState s) { + reachingStates.setAndGrow(n, s); + } + } + + /** * Try to find dominating node doing the resolution that can be reused. * * @param graph @@ -223,10 +345,11 @@ * {@link ResolveConstantNode}. * * @param graph + * @param stateMapper * @param node {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} that needs * resolution. */ - private static void replaceWithResolution(StructuredGraph graph, ConstantNode node) { + private static void replaceWithResolution(StructuredGraph graph, FrameStateMapperClosure stateMapper, ConstantNode node) { HotSpotMetaspaceConstant metaspaceConstant = (HotSpotMetaspaceConstant) node.asConstant(); HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) metaspaceConstant.asResolvedJavaType(); ResolvedJavaType topMethodHolder = graph.method().getDeclaringClass(); @@ -249,27 +372,54 @@ } else { fixedReplacement = graph.add(new ResolveConstantNode(node)); } - graph.addAfterFixed(findFixedWithNextBefore(graph, node), fixedReplacement); + insertReplacement(graph, stateMapper, node, fixedReplacement); replacement = fixedReplacement; } node.replaceAtUsages(replacement, n -> !isReplacementNode(n)); } /** + * Replace {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} with indirection. + * + * @param graph + * @param stateMapper + * @param node {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} that needs + * resolution. + */ + private void handleHotSpotMetaspaceConstant(StructuredGraph graph, FrameStateMapperClosure stateMapper, ConstantNode node) { + HotSpotMetaspaceConstant metaspaceConstant = (HotSpotMetaspaceConstant) node.asConstant(); + HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) metaspaceConstant.asResolvedJavaType(); + + if (type != null) { + if (verifyFingerprints && checkForBadFingerprint(type)) { + throw new GraalError("Type with bad fingerprint: " + type); + } + assert !metaspaceConstant.isCompressed() : "No support for replacing compressed metaspace constants"; + tryToReplaceWithExisting(graph, node); + if (anyUsagesNeedReplacement(node)) { + replaceWithResolution(graph, stateMapper, node); + } + } else { + throw new GraalError("Unsupported metaspace constant type: " + type); + } + } + + /** * Replace an object constant with an indirect load {@link ResolveConstantNode}. Currently we * support only strings. * * @param graph + * @param stateMapper * @param node {@link ConstantNode} containing a {@link HotSpotObjectConstant} that needs * resolution. */ - private static void handleHotSpotObjectConstant(StructuredGraph graph, ConstantNode node) { + private static void handleHotSpotObjectConstant(StructuredGraph graph, FrameStateMapperClosure stateMapper, ConstantNode node) { HotSpotObjectConstant constant = (HotSpotObjectConstant) node.asJavaConstant(); HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) constant.getType(); if (type.mirror().equals(String.class)) { assert !constant.isCompressed() : "No support for replacing compressed oop constants"; FixedWithNextNode replacement = graph.add(new ResolveConstantNode(node)); - graph.addAfterFixed(findFixedWithNextBefore(graph, node), replacement); + insertReplacement(graph, stateMapper, node, replacement); node.replaceAtUsages(replacement, n -> !(n instanceof ResolveConstantNode)); } else { throw new GraalError("Unsupported object constant type: " + type); @@ -281,16 +431,17 @@ * {@link ResolveMethodAndLoadCountersNode}, expose a klass constant of the holder. * * @param graph + * @param stateMapper * @param node * @param context */ - private static void handleLoadMethodCounters(StructuredGraph graph, LoadMethodCountersNode node, PhaseContext context) { + private static void handleLoadMethodCounters(StructuredGraph graph, FrameStateMapperClosure stateMapper, LoadMethodCountersNode node, PhaseContext context) { ResolvedJavaType type = node.getMethod().getDeclaringClass(); Stamp hubStamp = context.getStampProvider().createHubStamp((ObjectStamp) StampFactory.objectNonNull()); ConstantReflectionProvider constantReflection = context.getConstantReflection(); ConstantNode klassHint = ConstantNode.forConstant(hubStamp, constantReflection.asObjectHub(type), context.getMetaAccess(), graph); FixedWithNextNode replacement = graph.add(new ResolveMethodAndLoadCountersNode(node.getMethod(), klassHint)); - graph.addAfterFixed(findFixedWithNextBefore(graph, node), replacement); + insertReplacement(graph, stateMapper, node, replacement); node.replaceAtUsages(replacement, n -> !(n instanceof ResolveMethodAndLoadCountersNode)); } @@ -299,13 +450,15 @@ * klass constants. * * @param graph + * @param stateMapper * @param context */ - private static void replaceLoadMethodCounters(StructuredGraph graph, PhaseContext context) { + private static void replaceLoadMethodCounters(StructuredGraph graph, FrameStateMapperClosure stateMapper, PhaseContext context) { new SchedulePhase(SchedulingStrategy.LATEST_OUT_OF_LOOPS, true).apply(graph, false); + for (LoadMethodCountersNode node : getLoadMethodCountersNodes(graph)) { if (anyUsagesNeedReplacement(node)) { - handleLoadMethodCounters(graph, node, context); + handleLoadMethodCounters(graph, stateMapper, node, context); } } } @@ -314,29 +467,33 @@ * Replace object and klass constants with resolution nodes or reuse preceding initializations. * * @param graph + * @param stateMapper */ - private void replaceKlassesAndObjects(StructuredGraph graph) { + private void replaceKlassesAndObjects(StructuredGraph graph, FrameStateMapperClosure stateMapper) { new SchedulePhase(SchedulingStrategy.LATEST_OUT_OF_LOOPS, true).apply(graph, false); for (ConstantNode node : getConstantNodes(graph)) { Constant constant = node.asConstant(); if (constant instanceof HotSpotMetaspaceConstant && anyUsagesNeedReplacement(node)) { - handleHotSpotMetaspaceConstant(graph, node); + handleHotSpotMetaspaceConstant(graph, stateMapper, node); } else if (constant instanceof HotSpotObjectConstant && anyUsagesNeedReplacement(node)) { - handleHotSpotObjectConstant(graph, node); + handleHotSpotObjectConstant(graph, stateMapper, node); } } } @Override protected void run(StructuredGraph graph, PhaseContext context) { + FrameStateMapperClosure stateMapper = new FrameStateMapperClosure(graph); + ReentrantNodeIterator.apply(stateMapper, graph.start(), null); + // Replace LoadMethodCountersNode with ResolveMethodAndLoadCountersNode, expose klass // constants. - replaceLoadMethodCounters(graph, context); + replaceLoadMethodCounters(graph, stateMapper, context); // Replace object and klass constants (including the ones added in the previous pass) with // resolution nodes. - replaceKlassesAndObjects(graph); + replaceKlassesAndObjects(graph, stateMapper); } @Override --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/AssertionSnippets.java 2017-07-07 09:30:22.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/AssertionSnippets.java 2017-07-07 09:30:22.000000000 -0700 @@ -28,6 +28,7 @@ import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.graph.Node.ConstantNodeParameter; import org.graalvm.compiler.graph.Node.NodeIntrinsic; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; @@ -75,8 +76,8 @@ private final SnippetInfo assertion = snippet(AssertionSnippets.class, "assertion"); private final SnippetInfo stubAssertion = snippet(AssertionSnippets.class, "stubAssertion"); - public Templates(OptionValues options, HotSpotProviders providers, TargetDescription target) { - super(options, providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, Iterable factories, HotSpotProviders providers, TargetDescription target) { + super(options, factories, providers, providers.getSnippetReflection(), target); } public void lower(AssertionNode assertionNode, LoweringTool tool) { @@ -85,7 +86,7 @@ args.add("condition", assertionNode.condition()); args.addConst("message", "failed runtime assertion in snippet/stub: " + assertionNode.message() + " (" + graph.method() + ")"); - template(args).instantiate(providers.getMetaAccess(), assertionNode, DEFAULT_REPLACER, args); + template(assertionNode.getDebug(), args).instantiate(providers.getMetaAccess(), assertionNode, DEFAULT_REPLACER, args); } } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HashCodeSnippets.java 2017-07-07 09:30:22.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HashCodeSnippets.java 2017-07-07 09:30:22.000000000 -0700 @@ -36,6 +36,7 @@ import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability; import org.graalvm.compiler.api.replacements.Snippet; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.spi.LoweringTool; @@ -78,15 +79,15 @@ private final SnippetInfo identityHashCodeSnippet = snippet(HashCodeSnippets.class, "identityHashCodeSnippet", HotSpotReplacementsUtil.MARK_WORD_LOCATION); - public Templates(OptionValues options, HotSpotProviders providers, TargetDescription target) { - super(options, providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, Iterable factories, HotSpotProviders providers, TargetDescription target) { + super(options, factories, providers, providers.getSnippetReflection(), target); } public void lower(IdentityHashCodeNode node, LoweringTool tool) { StructuredGraph graph = node.graph(); Arguments args = new Arguments(identityHashCodeSnippet, graph.getGuardsStage(), tool.getLoweringStage()); args.add("thisObj", node.object); - SnippetTemplate template = template(args); + SnippetTemplate template = template(node.getDebug(), args); template.instantiate(providers.getMetaAccess(), node, SnippetTemplate.DEFAULT_REPLACER, args); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/InstanceOfSnippets.java 2017-07-07 09:30:23.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/InstanceOfSnippets.java 2017-07-07 09:30:23.000000000 -0700 @@ -44,6 +44,7 @@ import org.graalvm.compiler.api.replacements.Snippet.VarargsParameter; import org.graalvm.compiler.core.common.type.ObjectStamp; import org.graalvm.compiler.core.common.type.StampFactory; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp; @@ -259,8 +260,8 @@ private final Counters counters; - public Templates(OptionValues options, SnippetCounter.Group.Factory factory, HotSpotProviders providers, TargetDescription target) { - super(options, providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, Iterable factories, SnippetCounter.Group.Factory factory, HotSpotProviders providers, TargetDescription target) { + super(options, factories, providers, providers.getSnippetReflection(), target); this.counters = new Counters(factory); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/LoadExceptionObjectSnippets.java 2017-07-07 09:30:23.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/LoadExceptionObjectSnippets.java 2017-07-07 09:30:23.000000000 -0700 @@ -36,6 +36,7 @@ import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; import org.graalvm.compiler.hotspot.word.HotSpotWordTypes; @@ -82,8 +83,8 @@ private final SnippetInfo loadException = snippet(LoadExceptionObjectSnippets.class, "loadException", EXCEPTION_OOP_LOCATION, EXCEPTION_PC_LOCATION); private final HotSpotWordTypes wordTypes; - public Templates(OptionValues options, HotSpotProviders providers, TargetDescription target) { - super(options, providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, Iterable factories, HotSpotProviders providers, TargetDescription target) { + super(options, factories, providers, providers.getSnippetReflection(), target); this.wordTypes = providers.getWordTypes(); } @@ -100,7 +101,7 @@ } else { Arguments args = new Arguments(loadException, loadExceptionObject.graph().getGuardsStage(), tool.getLoweringStage()); args.addConst("threadRegister", registers.getThreadRegister()); - template(args).instantiate(providers.getMetaAccess(), loadExceptionObject, DEFAULT_REPLACER, args); + template(loadExceptionObject.getDebug(), args).instantiate(providers.getMetaAccess(), loadExceptionObject, DEFAULT_REPLACER, args); } } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java 2017-07-07 09:30:24.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java 2017-07-07 09:30:24.000000000 -0700 @@ -80,6 +80,7 @@ import org.graalvm.compiler.core.common.type.ObjectStamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.StampPair; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.graph.Node.ConstantNodeParameter; import org.graalvm.compiler.graph.Node.NodeIntrinsic; import org.graalvm.compiler.graph.iterators.NodeIterable; @@ -723,8 +724,9 @@ private final boolean useFastLocking; public final Counters counters; - public Templates(OptionValues options, SnippetCounter.Group.Factory factory, HotSpotProviders providers, TargetDescription target, boolean useFastLocking) { - super(options, providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, Iterable factories, SnippetCounter.Group.Factory factory, HotSpotProviders providers, TargetDescription target, + boolean useFastLocking) { + super(options, factories, providers, providers.getSnippetReflection(), target); this.useFastLocking = useFastLocking; this.counters = new Counters(factory); @@ -756,7 +758,7 @@ args.addConst("counters", counters); } - template(args).instantiate(providers.getMetaAccess(), monitorenterNode, DEFAULT_REPLACER, args); + template(graph.getDebug(), args).instantiate(providers.getMetaAccess(), monitorenterNode, DEFAULT_REPLACER, args); } public void lower(MonitorExitNode monitorexitNode, HotSpotRegistersProvider registers, LoweringTool tool) { @@ -775,7 +777,7 @@ args.addConst("options", graph.getOptions()); args.addConst("counters", counters); - template(args).instantiate(providers.getMetaAccess(), monitorexitNode, DEFAULT_REPLACER, args); + template(graph.getDebug(), args).instantiate(providers.getMetaAccess(), monitorexitNode, DEFAULT_REPLACER, args); } public static boolean isTracingEnabledForType(ValueNode object) { @@ -843,7 +845,7 @@ Arguments args = new Arguments(checkCounter, graph.getGuardsStage(), tool.getLoweringStage()); args.addConst("errMsg", msg); - inlineeGraph = template(args).copySpecializedGraph(); + inlineeGraph = template(graph.getDebug(), args).copySpecializedGraph(graph.getDebug()); InliningUtil.inline(invoke, inlineeGraph, false, null); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java 2017-07-07 09:30:24.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java 2017-07-07 09:30:24.000000000 -0700 @@ -74,7 +74,7 @@ import org.graalvm.compiler.api.replacements.Snippet.VarargsParameter; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node.ConstantNodeParameter; import org.graalvm.compiler.graph.Node.NodeIntrinsic; @@ -591,8 +591,9 @@ private final GraalHotSpotVMConfig config; private final Counters counters; - public Templates(OptionValues options, SnippetCounter.Group.Factory factory, HotSpotProviders providers, TargetDescription target, GraalHotSpotVMConfig config) { - super(options, providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, Iterable factories, SnippetCounter.Group.Factory factory, HotSpotProviders providers, TargetDescription target, + GraalHotSpotVMConfig config) { + super(options, factories, providers, providers.getSnippetReflection(), target); this.config = config; counters = new Counters(factory); } @@ -620,8 +621,8 @@ args.addConst("options", localOptions); args.addConst("counters", counters); - SnippetTemplate template = template(args); - Debug.log("Lowering allocateInstance in %s: node=%s, template=%s, arguments=%s", graph, newInstanceNode, template, args); + SnippetTemplate template = template(graph.getDebug(), args); + graph.getDebug().log("Lowering allocateInstance in %s: node=%s, template=%s, arguments=%s", graph, newInstanceNode, template, args); template.instantiate(providers.getMetaAccess(), newInstanceNode, DEFAULT_REPLACER, args); } @@ -663,8 +664,8 @@ args.addConst("typeContext", ProfileAllocations.getValue(localOptions) ? arrayType.toJavaName(false) : ""); args.addConst("options", localOptions); args.addConst("counters", counters); - SnippetTemplate template = template(args); - Debug.log("Lowering allocateArray in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, args); + SnippetTemplate template = template(graph.getDebug(), args); + graph.getDebug().log("Lowering allocateArray in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, args); template.instantiate(providers.getMetaAccess(), newArrayNode, DEFAULT_REPLACER, args); } @@ -680,7 +681,7 @@ args.addConst("options", localOptions); args.addConst("counters", counters); - SnippetTemplate template = template(args); + SnippetTemplate template = template(newInstanceNode.getDebug(), args); template.instantiate(providers.getMetaAccess(), newInstanceNode, DEFAULT_REPLACER, args); } @@ -709,7 +710,7 @@ args.add("prototypeMarkWord", lookupArrayClass(tool, JavaKind.Object).prototypeMarkWord()); args.addConst("options", localOptions); args.addConst("counters", counters); - SnippetTemplate template = template(args); + SnippetTemplate template = template(graph.getDebug(), args); template.instantiate(providers.getMetaAccess(), newArrayNode, DEFAULT_REPLACER, args); } @@ -733,7 +734,7 @@ args.add("hub", hub); args.addConst("rank", rank); args.addVarargs("dimensions", int.class, StampFactory.forKind(JavaKind.Int), dims); - template(args).instantiate(providers.getMetaAccess(), newmultiarrayNode, DEFAULT_REPLACER, args); + template(newmultiarrayNode.getDebug(), args).instantiate(providers.getMetaAccess(), newmultiarrayNode, DEFAULT_REPLACER, args); } private static int instanceSize(HotSpotResolvedObjectType type) { @@ -747,7 +748,7 @@ Arguments args = new Arguments(verifyHeap, verifyHeapNode.graph().getGuardsStage(), tool.getLoweringStage()); args.addConst("threadRegister", registers.getThreadRegister()); - SnippetTemplate template = template(args); + SnippetTemplate template = template(verifyHeapNode.getDebug(), args); template.instantiate(providers.getMetaAccess(), verifyHeapNode, DEFAULT_REPLACER, args); } else { GraphUtil.removeFixedWithUnusedInputs(verifyHeapNode); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ObjectCloneNode.java 2017-07-07 09:30:25.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ObjectCloneNode.java 2017-07-07 09:30:24.000000000 -0700 @@ -27,8 +27,7 @@ import org.graalvm.compiler.core.common.type.AbstractPointerStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampPair; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind; @@ -84,22 +83,23 @@ final ResolvedJavaMethod snippetMethod = tool.getMetaAccess().lookupJavaMethod(method); final Replacements replacements = tool.getReplacements(); StructuredGraph snippetGraph = null; - try (Scope s = Debug.scope("ArrayCloneSnippet", snippetMethod)) { + DebugContext debug = getDebug(); + try (DebugContext.Scope s = debug.scope("ArrayCloneSnippet", snippetMethod)) { snippetGraph = replacements.getSnippet(snippetMethod, null); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } assert snippetGraph != null : "ObjectCloneSnippets should be installed"; assert getConcreteType(stamp()) != null; - return lowerReplacement((StructuredGraph) snippetGraph.copy(), tool); + return lowerReplacement((StructuredGraph) snippetGraph.copy(getDebug()), tool); } assert false : "unhandled array type " + type.getComponentType().getJavaKind(); } else { Assumptions assumptions = graph().getAssumptions(); type = getConcreteType(getObject().stamp()); if (type != null) { - StructuredGraph newGraph = new StructuredGraph.Builder(graph().getOptions(), AllowAssumptions.ifNonNull(assumptions)).build(); + StructuredGraph newGraph = new StructuredGraph.Builder(graph().getOptions(), graph().getDebug(), AllowAssumptions.ifNonNull(assumptions)).build(); ParameterNode param = newGraph.addWithoutUnique(new ParameterNode(0, StampPair.createSingle(getObject().stamp()))); NewInstanceNode newInstance = newGraph.add(new NewInstanceNode(type, true)); newGraph.addAfterFixed(newGraph.start(), newInstance); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/StringToBytesSnippets.java 2017-07-07 09:30:25.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/StringToBytesSnippets.java 2017-07-07 09:30:25.000000000 -0700 @@ -28,6 +28,7 @@ import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.nodes.NamedLocationIdentity; import org.graalvm.compiler.nodes.debug.StringToBytesNode; @@ -74,15 +75,15 @@ private final SnippetInfo create; - public Templates(OptionValues options, HotSpotProviders providers, TargetDescription target) { - super(options, providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, Iterable factories, HotSpotProviders providers, TargetDescription target) { + super(options, factories, providers, providers.getSnippetReflection(), target); create = snippet(StringToBytesSnippets.class, "transform", NamedLocationIdentity.getArrayLocation(JavaKind.Byte)); } public void lower(StringToBytesNode stringToBytesNode, LoweringTool tool) { Arguments args = new Arguments(create, stringToBytesNode.graph().getGuardsStage(), tool.getLoweringStage()); args.addConst("compilationTimeString", stringToBytesNode.getValue()); - SnippetTemplate template = template(args); + SnippetTemplate template = template(stringToBytesNode.getDebug(), args); template.instantiate(providers.getMetaAccess(), stringToBytesNode, DEFAULT_REPLACER, args); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/UnsafeLoadSnippets.java 2017-07-07 09:30:25.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/UnsafeLoadSnippets.java 2017-07-07 09:30:25.000000000 -0700 @@ -26,6 +26,7 @@ import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER; import org.graalvm.compiler.api.replacements.Snippet; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.nodes.extended.FixedValueAnchorNode; import org.graalvm.compiler.nodes.extended.RawLoadNode; @@ -56,15 +57,15 @@ private final SnippetInfo unsafeLoad = snippet(UnsafeLoadSnippets.class, "lowerUnsafeLoad"); - public Templates(OptionValues options, HotSpotProviders providers, TargetDescription target) { - super(options, providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, Iterable factories, HotSpotProviders providers, TargetDescription target) { + super(options, factories, providers, providers.getSnippetReflection(), target); } public void lower(RawLoadNode load, LoweringTool tool) { Arguments args = new Arguments(unsafeLoad, load.graph().getGuardsStage(), tool.getLoweringStage()); args.add("object", load.object()); args.add("offset", load.offset()); - template(args).instantiate(providers.getMetaAccess(), load, DEFAULT_REPLACER, args); + template(load.getDebug(), args).instantiate(providers.getMetaAccess(), load, DEFAULT_REPLACER, args); } } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java 2017-07-07 09:30:26.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java 2017-07-07 09:30:26.000000000 -0700 @@ -49,6 +49,7 @@ import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.graph.Node.ConstantNodeParameter; import org.graalvm.compiler.graph.Node.NodeIntrinsic; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; @@ -406,8 +407,9 @@ private final CompressEncoding oopEncoding; private final Counters counters; - public Templates(OptionValues options, SnippetCounter.Group.Factory factory, HotSpotProviders providers, TargetDescription target, CompressEncoding oopEncoding) { - super(options, providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, Iterable factories, SnippetCounter.Group.Factory factory, HotSpotProviders providers, TargetDescription target, + CompressEncoding oopEncoding) { + super(options, factories, providers, providers.getSnippetReflection(), target); this.oopEncoding = oopEncoding; this.counters = new Counters(factory); } @@ -423,7 +425,7 @@ args.add("object", address.getBase()); } args.addConst("counters", counters); - template(args).instantiate(providers.getMetaAccess(), writeBarrier, DEFAULT_REPLACER, args); + template(writeBarrier.getDebug(), args).instantiate(providers.getMetaAccess(), writeBarrier, DEFAULT_REPLACER, args); } public void lower(SerialArrayRangeWriteBarrier arrayRangeWriteBarrier, LoweringTool tool) { @@ -431,7 +433,7 @@ args.add("object", arrayRangeWriteBarrier.getObject()); args.add("startIndex", arrayRangeWriteBarrier.getStartIndex()); args.add("length", arrayRangeWriteBarrier.getLength()); - template(args).instantiate(providers.getMetaAccess(), arrayRangeWriteBarrier, DEFAULT_REPLACER, args); + template(arrayRangeWriteBarrier.getDebug(), args).instantiate(providers.getMetaAccess(), arrayRangeWriteBarrier, DEFAULT_REPLACER, args); } public void lower(G1PreWriteBarrier writeBarrierPre, HotSpotRegistersProvider registers, LoweringTool tool) { @@ -456,7 +458,7 @@ args.addConst("threadRegister", registers.getThreadRegister()); args.addConst("trace", traceBarrier(writeBarrierPre.graph())); args.addConst("counters", counters); - template(args).instantiate(providers.getMetaAccess(), writeBarrierPre, DEFAULT_REPLACER, args); + template(writeBarrierPre.getDebug(), args).instantiate(providers.getMetaAccess(), writeBarrierPre, DEFAULT_REPLACER, args); } public void lower(G1ReferentFieldReadBarrier readBarrier, HotSpotRegistersProvider registers, LoweringTool tool) { @@ -481,7 +483,7 @@ args.addConst("threadRegister", registers.getThreadRegister()); args.addConst("trace", traceBarrier(readBarrier.graph())); args.addConst("counters", counters); - template(args).instantiate(providers.getMetaAccess(), readBarrier, DEFAULT_REPLACER, args); + template(readBarrier.getDebug(), args).instantiate(providers.getMetaAccess(), readBarrier, DEFAULT_REPLACER, args); } public void lower(G1PostWriteBarrier writeBarrierPost, HotSpotRegistersProvider registers, LoweringTool tool) { @@ -511,7 +513,7 @@ args.addConst("threadRegister", registers.getThreadRegister()); args.addConst("trace", traceBarrier(writeBarrierPost.graph())); args.addConst("counters", counters); - template(args).instantiate(providers.getMetaAccess(), writeBarrierPost, DEFAULT_REPLACER, args); + template(graph.getDebug(), args).instantiate(providers.getMetaAccess(), writeBarrierPost, DEFAULT_REPLACER, args); } public void lower(G1ArrayRangePreWriteBarrier arrayRangeWriteBarrier, HotSpotRegistersProvider registers, LoweringTool tool) { @@ -520,7 +522,7 @@ args.add("startIndex", arrayRangeWriteBarrier.getStartIndex()); args.add("length", arrayRangeWriteBarrier.getLength()); args.addConst("threadRegister", registers.getThreadRegister()); - template(args).instantiate(providers.getMetaAccess(), arrayRangeWriteBarrier, DEFAULT_REPLACER, args); + template(arrayRangeWriteBarrier.getDebug(), args).instantiate(providers.getMetaAccess(), arrayRangeWriteBarrier, DEFAULT_REPLACER, args); } public void lower(G1ArrayRangePostWriteBarrier arrayRangeWriteBarrier, HotSpotRegistersProvider registers, LoweringTool tool) { @@ -529,7 +531,7 @@ args.add("startIndex", arrayRangeWriteBarrier.getStartIndex()); args.add("length", arrayRangeWriteBarrier.getLength()); args.addConst("threadRegister", registers.getThreadRegister()); - template(args).instantiate(providers.getMetaAccess(), arrayRangeWriteBarrier, DEFAULT_REPLACER, args); + template(arrayRangeWriteBarrier.getDebug(), args).instantiate(providers.getMetaAccess(), arrayRangeWriteBarrier, DEFAULT_REPLACER, args); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/aot/ResolveConstantSnippets.java 2017-07-07 09:30:26.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/aot/ResolveConstantSnippets.java 2017-07-07 09:30:26.000000000 -0700 @@ -27,6 +27,7 @@ import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER; import org.graalvm.compiler.api.replacements.Snippet; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; @@ -114,8 +115,8 @@ private final SnippetInfo initializeKlass = snippet(ResolveConstantSnippets.class, "initializeKlass"); private final SnippetInfo pureInitializeKlass = snippet(ResolveConstantSnippets.class, "pureInitializeKlass"); - public Templates(OptionValues options, HotSpotProviders providers, TargetDescription target) { - super(options, providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, Iterable factories, HotSpotProviders providers, TargetDescription target) { + super(options, factories, providers, providers.getSnippetReflection(), target); } public void lower(ResolveConstantNode resolveConstantNode, LoweringTool tool) { @@ -148,7 +149,7 @@ Arguments args = new Arguments(snippet, graph.getGuardsStage(), tool.getLoweringStage()); args.add("constant", value); - SnippetTemplate template = template(args); + SnippetTemplate template = template(graph.getDebug(), args); template.instantiate(providers.getMetaAccess(), resolveConstantNode, DEFAULT_REPLACER, args); assert resolveConstantNode.hasNoUsages(); @@ -168,7 +169,7 @@ Arguments args = new Arguments(initializeKlass, graph.getGuardsStage(), tool.getLoweringStage()); args.add("constant", value); - SnippetTemplate template = template(args); + SnippetTemplate template = template(graph.getDebug(), args); template.instantiate(providers.getMetaAccess(), initializeKlassNode, DEFAULT_REPLACER, args); assert initializeKlassNode.hasNoUsages(); if (!initializeKlassNode.isDeleted()) { @@ -186,7 +187,7 @@ Arguments args = new Arguments(resolveMethodAndLoadCounters, graph.getGuardsStage(), tool.getLoweringStage()); args.add("method", method); args.add("klassHint", resolveMethodAndLoadCountersNode.getHub()); - SnippetTemplate template = template(args); + SnippetTemplate template = template(graph.getDebug(), args); template.instantiate(providers.getMetaAccess(), resolveMethodAndLoadCountersNode, DEFAULT_REPLACER, args); assert resolveMethodAndLoadCountersNode.hasNoUsages(); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java 2017-07-07 09:30:27.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java 2017-07-07 09:30:27.000000000 -0700 @@ -43,6 +43,7 @@ import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; @@ -411,8 +412,8 @@ public static class Templates extends SnippetTemplate.AbstractTemplates { - public Templates(OptionValues options, SnippetCounter.Group.Factory factory, HotSpotProviders providers, TargetDescription target) { - super(options, providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, Iterable factories, SnippetCounter.Group.Factory factory, HotSpotProviders providers, TargetDescription target) { + super(options, factories, providers, providers.getSnippetReflection(), target); this.counters = new Counters(factory); } @@ -617,7 +618,7 @@ args.add("destPos", arraycopy.getDestinationPosition()); args.addConst("length", arraycopy.getUnrollLength()); args.addConst("elementKind", arraycopy.getElementKind()); - template(args).instantiate(providers.getMetaAccess(), arraycopy, SnippetTemplate.DEFAULT_REPLACER, args); + template(graph.getDebug(), args).instantiate(providers.getMetaAccess(), arraycopy, SnippetTemplate.DEFAULT_REPLACER, args); } /** @@ -629,7 +630,7 @@ */ private void instantiate(Arguments args, BasicArrayCopyNode arraycopy) { StructuredGraph graph = arraycopy.graph(); - SnippetTemplate template = template(args); + SnippetTemplate template = template(graph.getDebug(), args); UnmodifiableEconomicMap replacements = template.instantiate(providers.getMetaAccess(), arraycopy, SnippetTemplate.DEFAULT_REPLACER, args, false); for (Node originalNode : replacements.getKeys()) { if (originalNode instanceof Invoke) { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/UnsafeArrayCopySnippets.java 2017-07-07 09:30:28.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/UnsafeArrayCopySnippets.java 2017-07-07 09:30:27.000000000 -0700 @@ -22,6 +22,7 @@ */ package org.graalvm.compiler.hotspot.replacements.arraycopy; +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayBaseOffset; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayIndexScale; @@ -31,32 +32,33 @@ import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.layoutHelperLog2ElementSizeShift; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.runtime; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.wordSize; -import static org.graalvm.compiler.nodes.NamedLocationIdentity.any; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.NOT_FREQUENT_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability; import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER; -import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale; +import static org.graalvm.word.LocationIdentity.any; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.core.common.NumUtil; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.phases.WriteBarrierAdditionPhase; import org.graalvm.compiler.nodes.NamedLocationIdentity; -import org.graalvm.compiler.nodes.extended.UnsafeCopyNode; import org.graalvm.compiler.nodes.extended.RawLoadNode; import org.graalvm.compiler.nodes.extended.RawStoreNode; +import org.graalvm.compiler.nodes.extended.UnsafeCopyNode; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.SnippetTemplate; import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; +import org.graalvm.compiler.replacements.Snippets; import org.graalvm.compiler.word.ObjectAccess; import org.graalvm.word.LocationIdentity; import org.graalvm.word.Unsigned; import org.graalvm.word.WordFactory; -import org.graalvm.compiler.replacements.Snippets; + import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.meta.JavaKind; @@ -284,8 +286,8 @@ private final SnippetInfo[] arraycopySnippets; private final SnippetInfo genericPrimitiveSnippet; - public Templates(OptionValues options, HotSpotProviders providers, TargetDescription target) { - super(options, providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, Iterable factories, HotSpotProviders providers, TargetDescription target) { + super(options, factories, providers, providers.getSnippetReflection(), target); arraycopySnippets = new SnippetInfo[JavaKind.values().length]; arraycopySnippets[JavaKind.Boolean.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyBoolean"); @@ -315,7 +317,7 @@ Arguments args = new Arguments(snippet, node.graph().getGuardsStage(), tool.getLoweringStage()); node.addSnippetArguments(args); - SnippetTemplate template = template(args); + SnippetTemplate template = template(node.getDebug(), args); template.instantiate(providers.getMetaAccess(), node, DEFAULT_REPLACER, args); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProbabilisticProfileSnippets.java 2017-07-07 09:30:28.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProbabilisticProfileSnippets.java 2017-07-07 09:30:28.000000000 -0700 @@ -31,6 +31,7 @@ import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node.ConstantNodeParameter; import org.graalvm.compiler.graph.Node.NodeIntrinsic; @@ -114,8 +115,8 @@ private final SnippetInfo profileBackedgeWithProbability = snippet(ProbabilisticProfileSnippets.class, "profileBackedgeWithProbability"); private final SnippetInfo profileConditionalBackedgeWithProbability = snippet(ProbabilisticProfileSnippets.class, "profileConditionalBackedgeWithProbability"); - public Templates(OptionValues options, HotSpotProviders providers, TargetDescription target) { - super(options, providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, Iterable factories, HotSpotProviders providers, TargetDescription target) { + super(options, factories, providers, providers.getSnippetReflection(), target); } public void lower(ProfileNode profileNode, LoweringTool tool) { @@ -141,7 +142,7 @@ args.add("bci", bci); args.add("targetBci", targetBci); - SnippetTemplate template = template(args); + SnippetTemplate template = template(graph.getDebug(), args); template.instantiate(providers.getMetaAccess(), profileNode, DEFAULT_REPLACER, args); } else if (profileNode instanceof ProfileInvokeNode) { ProfileInvokeNode profileInvokeNode = (ProfileInvokeNode) profileNode; @@ -151,7 +152,7 @@ args.add("random", profileInvokeNode.getRandom()); args.addConst("freqLog", profileInvokeNode.getNotificationFreqLog()); args.addConst("probLog", profileInvokeNode.getProbabilityLog()); - SnippetTemplate template = template(args); + SnippetTemplate template = template(graph.getDebug(), args); template.instantiate(providers.getMetaAccess(), profileNode, DEFAULT_REPLACER, args); } else { throw new GraalError("Unsupported profile node type: " + profileNode); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProfileSnippets.java 2017-07-07 09:30:29.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProfileSnippets.java 2017-07-07 09:30:29.000000000 -0700 @@ -31,6 +31,7 @@ import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node.ConstantNodeParameter; import org.graalvm.compiler.graph.Node.NodeIntrinsic; @@ -96,8 +97,8 @@ private final SnippetInfo profileBackedge = snippet(ProfileSnippets.class, "profileBackedge"); private final SnippetInfo profileConditionalBackedge = snippet(ProfileSnippets.class, "profileConditionalBackedge"); - public Templates(OptionValues options, HotSpotProviders providers, TargetDescription target) { - super(options, providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, Iterable factories, HotSpotProviders providers, TargetDescription target) { + super(options, factories, providers, providers.getSnippetReflection(), target); } public void lower(ProfileNode profileNode, LoweringTool tool) { @@ -119,7 +120,7 @@ args.add("bci", bci); args.add("targetBci", targetBci); - SnippetTemplate template = template(args); + SnippetTemplate template = template(graph.getDebug(), args); template.instantiate(providers.getMetaAccess(), profileNode, DEFAULT_REPLACER, args); } else if (profileNode instanceof ProfileInvokeNode) { ProfileInvokeNode profileInvokeNode = (ProfileInvokeNode) profileNode; @@ -127,7 +128,7 @@ Arguments args = new Arguments(profileMethodEntry, graph.getGuardsStage(), tool.getLoweringStage()); args.add("counters", counters); args.addConst("freqLog", profileInvokeNode.getNotificationFreqLog()); - SnippetTemplate template = template(args); + SnippetTemplate template = template(graph.getDebug(), args); template.instantiate(providers.getMetaAccess(), profileNode, DEFAULT_REPLACER, args); } else { throw new GraalError("Unsupported profile node type: " + profileNode); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/CreateExceptionStub.java 2017-07-07 09:30:29.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/CreateExceptionStub.java 2017-07-07 09:30:29.000000000 -0700 @@ -22,20 +22,20 @@ */ package org.graalvm.compiler.hotspot.stubs; +import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.NativeCall; import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.DESTROYS_REGISTERS; import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.SAFEPOINT; import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl.REEXECUTABLE; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.clearPendingException; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord; import static org.graalvm.word.LocationIdentity.any; -import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.NativeCall; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.graph.Node.ConstantNodeParameter; import org.graalvm.compiler.graph.Node.NodeIntrinsic; -import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; +import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.nodes.StubForeignCallNode; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallStub.java 2017-07-07 09:30:30.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallStub.java 2017-07-07 09:30:30.000000000 -0700 @@ -22,11 +22,11 @@ */ package org.graalvm.compiler.hotspot.stubs; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.DESTROYS_REGISTERS; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS; import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.JavaCall; import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.JavaCallee; import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.NativeCall; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.DESTROYS_REGISTERS; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS; import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.common.LIRKind; @@ -34,7 +34,7 @@ import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.StampPair; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.JavaMethodContext; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition; @@ -104,7 +104,8 @@ */ public ForeignCallStub(OptionValues options, HotSpotJVMCIRuntimeProvider runtime, HotSpotProviders providers, long address, ForeignCallDescriptor descriptor, boolean prependThread, Transition transition, - boolean reexecutable, LocationIdentity... killedLocations) { + boolean reexecutable, + LocationIdentity... killedLocations) { super(options, providers, HotSpotForeignCallLinkageImpl.create(providers.getMetaAccess(), providers.getCodeCache(), providers.getWordTypes(), providers.getForeignCalls(), descriptor, 0L, PRESERVES_REGISTERS, JavaCall, JavaCallee, transition, reexecutable, killedLocations)); this.jvmciRuntime = runtime; @@ -223,12 +224,11 @@ * %r15 on AMD64) and is only prepended if {@link #prependThread} is true. */ @Override - protected StructuredGraph getGraph(CompilationIdentifier compilationId) { + protected StructuredGraph getGraph(DebugContext debug, CompilationIdentifier compilationId) { WordTypes wordTypes = providers.getWordTypes(); Class[] args = linkage.getDescriptor().getArgumentTypes(); boolean isObjectResult = !LIRKind.isValue(linkage.getOutgoingCallingConvention().getReturn()); - - StructuredGraph graph = new StructuredGraph.Builder(options).name(toString()).compilationId(compilationId).build(); + StructuredGraph graph = new StructuredGraph.Builder(options, debug).name(toString()).compilationId(compilationId).build(); graph.disableUnsafeAccessTracking(); GraphKit kit = new GraphKit(graph, providers, wordTypes, providers.getGraphBuilderPlugins()); @@ -243,13 +243,13 @@ } kit.append(new ReturnNode(linkage.getDescriptor().getResultType() == void.class ? null : result)); - Debug.dump(Debug.VERBOSE_LEVEL, graph, "Initial stub graph"); + debug.dump(DebugContext.VERBOSE_LEVEL, graph, "Initial stub graph"); kit.inlineInvokes(); new RemoveValueProxyPhase().apply(graph); - Debug.dump(Debug.VERBOSE_LEVEL, graph, "Stub graph before compilation"); + debug.dump(DebugContext.VERBOSE_LEVEL, graph, "Stub graph before compilation"); return graph; } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/SnippetStub.java 2017-07-07 09:30:31.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/SnippetStub.java 2017-07-07 09:30:31.000000000 -0700 @@ -33,8 +33,7 @@ import org.graalvm.compiler.bytecode.BytecodeProvider; import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; @@ -96,7 +95,7 @@ @Override @SuppressWarnings("try") - protected StructuredGraph getGraph(CompilationIdentifier compilationId) { + protected StructuredGraph getGraph(DebugContext debug, CompilationIdentifier compilationId) { Plugins defaultPlugins = providers.getGraphBuilderPlugins(); MetaAccessProvider metaAccess = providers.getMetaAccess(); SnippetReflectionProvider snippetReflection = providers.getSnippetReflection(); @@ -107,8 +106,8 @@ // Stubs cannot have optimistic assumptions since they have // to be valid for the entire run of the VM. - final StructuredGraph graph = new StructuredGraph.Builder(options).method(method).compilationId(compilationId).build(); - try (Scope outer = Debug.scope("SnippetStub", graph)) { + final StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(method).compilationId(compilationId).build(); + try (DebugContext.Scope outer = debug.scope("SnippetStub", graph)) { graph.disableUnsafeAccessTracking(); IntrinsicContext initialIntrinsicContext = new IntrinsicContext(method, method, getReplacementsBytecodeProvider(), INLINE_AFTER_PARSING); @@ -132,7 +131,7 @@ canonicalizer.apply(graph, context); new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } return graph; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java 2017-07-07 09:30:31.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java 2017-07-07 09:30:31.000000000 -0700 @@ -22,22 +22,23 @@ */ package org.graalvm.compiler.hotspot.stubs; +import static java.util.Collections.singletonList; import static org.graalvm.compiler.core.GraalCompiler.emitBackEnd; import static org.graalvm.compiler.core.GraalCompiler.emitFrontEnd; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.DebugStubsAndSnippets; +import static org.graalvm.compiler.debug.DebugContext.DEFAULT_LOG_STREAM; +import static org.graalvm.compiler.debug.DebugOptions.DebugStubsAndSnippets; import static org.graalvm.compiler.hotspot.HotSpotHostBackend.UNCOMMON_TRAP_HANDLER; import static org.graalvm.util.CollectionsUtil.allMatch; import java.util.ListIterator; +import java.util.concurrent.atomic.AtomicInteger; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.target.Backend; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; -import org.graalvm.compiler.debug.DebugConfig; -import org.graalvm.compiler.debug.internal.DebugScope; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DebugContext.Description; import org.graalvm.compiler.hotspot.HotSpotCompiledCodeBuilder; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; @@ -52,6 +53,7 @@ import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.tiers.Suites; +import org.graalvm.compiler.printer.GraalDebugHandlersFactory; import org.graalvm.util.EconomicSet; import jdk.vm.ci.code.CodeCacheProvider; @@ -155,7 +157,7 @@ * * @param compilationId unique compilation id for the stub */ - protected abstract StructuredGraph getGraph(CompilationIdentifier compilationId); + protected abstract StructuredGraph getGraph(DebugContext debug, CompilationIdentifier compilationId); @Override public String toString() { @@ -172,39 +174,50 @@ */ protected abstract Object debugScopeContext(); + private static final AtomicInteger nextStubId = new AtomicInteger(); + + private DebugContext openDebugContext(DebugContext outer) { + if (DebugStubsAndSnippets.getValue(options)) { + Description description = new Description(linkage, "Stub_" + nextStubId.incrementAndGet()); + return DebugContext.create(options, description, outer.getGlobalMetrics(), DEFAULT_LOG_STREAM, singletonList(new GraalDebugHandlersFactory(providers.getSnippetReflection()))); + } + return DebugContext.DISABLED; + } + /** * Gets the code for this stub, compiling it first if necessary. */ @SuppressWarnings("try") public synchronized InstalledCode getCode(final Backend backend) { if (code == null) { - DebugConfig config = DebugStubsAndSnippets.getValue(options) ? DebugScope.getConfig() : Debug.silentConfig(); - try (Scope d = Debug.sandbox("CompilingStub", config, providers.getCodeCache(), debugScopeContext())) { - CodeCacheProvider codeCache = providers.getCodeCache(); - - CompilationResult compResult = buildCompilationResult(backend); - try (Scope s = Debug.scope("CodeInstall", compResult)) { - assert destroyedCallerRegisters != null; - // Add a GeneratePIC check here later, we don't want to install - // code if we don't have a corresponding VM global symbol. - HotSpotCompiledCode compiledCode = HotSpotCompiledCodeBuilder.createCompiledCode(codeCache, null, null, compResult); - code = codeCache.installCode(null, compiledCode, null, null, false); + try (DebugContext debug = openDebugContext(DebugContext.forCurrentThread())) { + try (DebugContext.Scope d = debug.scope("CompilingStub", providers.getCodeCache(), debugScopeContext())) { + CodeCacheProvider codeCache = providers.getCodeCache(); + CompilationResult compResult = buildCompilationResult(debug, backend); + try (DebugContext.Scope s = debug.scope("CodeInstall", compResult); + DebugContext.Activation a = debug.activate()) { + assert destroyedCallerRegisters != null; + // Add a GeneratePIC check here later, we don't want to install + // code if we don't have a corresponding VM global symbol. + HotSpotCompiledCode compiledCode = HotSpotCompiledCodeBuilder.createCompiledCode(codeCache, null, null, compResult); + code = codeCache.installCode(null, compiledCode, null, null, false); + } catch (Throwable e) { + throw debug.handle(e); + } } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } - } catch (Throwable e) { - throw Debug.handle(e); + assert code != null : "error installing stub " + this; } - assert code != null : "error installing stub " + this; } return code; } @SuppressWarnings("try") - private CompilationResult buildCompilationResult(final Backend backend) { + private CompilationResult buildCompilationResult(DebugContext debug, final Backend backend) { CompilationResult compResult = new CompilationResult(toString(), GeneratePIC.getValue(options)); - final StructuredGraph graph = getGraph(getStubCompilationId()); + final StructuredGraph graph = getGraph(debug, getStubCompilationId()); // Stubs cannot be recompiled so they cannot be compiled with assumptions assert graph.getAssumptions() == null; @@ -215,14 +228,14 @@ graph.replaceFixed(graph.start(), newStart); } - try (Scope s0 = Debug.scope("StubCompilation", graph, providers.getCodeCache())) { + try (DebugContext.Scope s0 = debug.scope("StubCompilation", graph, providers.getCodeCache())) { Suites suites = createSuites(); emitFrontEnd(providers, backend, graph, providers.getSuites().getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL, DefaultProfilingInfo.get(TriState.UNKNOWN), suites); LIRSuites lirSuites = createLIRSuites(); emitBackEnd(graph, Stub.this, getInstalledCodeOwner(), backend, compResult, CompilationResultBuilderFactory.Default, getRegisterConfig(), lirSuites); assert checkStubInvariants(compResult); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } return compResult; } @@ -231,11 +244,11 @@ * Gets a {@link CompilationResult} that can be used for code generation. Required for AOT. */ @SuppressWarnings("try") - public CompilationResult getCompilationResult(final Backend backend) { - try (Scope d = Debug.sandbox("CompilingStub", DebugScope.getConfig(), providers.getCodeCache(), debugScopeContext())) { - return buildCompilationResult(backend); + public CompilationResult getCompilationResult(DebugContext debug, final Backend backend) { + try (DebugContext.Scope d = debug.scope("CompilingStub", providers.getCodeCache(), debugScopeContext())) { + return buildCompilationResult(debug, backend); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java 2017-07-07 09:30:32.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java 2017-07-07 09:30:32.000000000 -0700 @@ -93,7 +93,7 @@ import org.graalvm.compiler.bytecode.BytecodeTableSwitch; import org.graalvm.compiler.bytecode.Bytecodes; import org.graalvm.compiler.core.common.PermanentBailoutException; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.options.OptionValues; import org.graalvm.util.EconomicMap; import org.graalvm.util.Equivalence; @@ -437,12 +437,14 @@ private static final int LOOP_HEADER_INITIAL_CAPACITY = 4; private int blocksNotYetAssignedId; + private final DebugContext debug; /** * Creates a new BlockMap instance from {@code code}. */ - private BciBlockMapping(Bytecode code) { + private BciBlockMapping(Bytecode code, DebugContext debug) { this.code = code; + this.debug = debug; this.exceptionHandlers = code.getExceptionHandlers(); } @@ -464,7 +466,7 @@ } createJsrAlternatives(blockMap, blockMap[0]); } - if (Debug.isLogEnabled()) { + if (debug.isLogEnabled()) { this.log(blockMap, "Before BlockOrder"); } computeBlockOrder(blockMap); @@ -473,7 +475,7 @@ assert verify(); startBlock = blockMap[0]; - if (Debug.isLogEnabled()) { + if (debug.isLogEnabled()) { this.log(blockMap, "Before LivenessAnalysis"); } } @@ -703,7 +705,7 @@ block.addSuccessor(block.getRetSuccessor()); assert block.getRetSuccessor() != block.getJsrSuccessor(); } - Debug.log("JSR alternatives block %s sux %s jsrSux %s retSux %s jsrScope %s", block, block.getSuccessors(), block.getJsrSuccessor(), block.getRetSuccessor(), block.getJsrScope()); + debug.log("JSR alternatives block %s sux %s jsrSux %s retSux %s jsrScope %s", block, block.getSuccessors(), block.getJsrSuccessor(), block.getRetSuccessor(), block.getJsrScope()); if (block.getJsrSuccessor() != null || !scope.isEmpty()) { for (int i = 0; i < block.getSuccessorCount(); i++) { @@ -870,9 +872,9 @@ } public void log(BciBlock[] blockMap, String name) { - if (Debug.isLogEnabled()) { + if (debug.isLogEnabled()) { String n = System.lineSeparator(); - StringBuilder sb = new StringBuilder(Debug.currentScope()).append("BlockMap ").append(name).append(" :"); + StringBuilder sb = new StringBuilder(debug.getCurrentScopeName()).append("BlockMap ").append(name).append(" :"); sb.append(n); Iterable it; if (blocks == null) { @@ -905,7 +907,7 @@ } sb.append(n); } - Debug.log("%s", sb); + debug.log("%s", sb); } } @@ -946,7 +948,7 @@ assert block.loops == 0; block.loops = 1L << nextLoop; - Debug.log("makeLoopHeader(%s) -> %x", block, block.loops); + debug.log("makeLoopHeader(%s) -> %x", block, block.loops); if (loopHeaders == null) { loopHeaders = new BciBlock[LOOP_HEADER_INITIAL_CAPACITY]; } else if (nextLoop >= loopHeaders.length) { @@ -992,7 +994,7 @@ } block.loops = loops; - Debug.log("computeBlockOrder(%s) -> %x", block, block.loops); + debug.log("computeBlockOrder(%s) -> %x", block, block.loops); if (block.isLoopHeader) { loops &= ~(1L << block.loopId); @@ -1024,7 +1026,7 @@ if (block.loops != loops) { loopChanges = true; block.loops = loops; - Debug.log("fixLoopBits0(%s) -> %x", block, block.loops); + debug.log("fixLoopBits0(%s) -> %x", block, block.loops); } if (block.isLoopHeader) { @@ -1034,11 +1036,11 @@ return loops; } - public static BciBlockMapping create(BytecodeStream stream, Bytecode code, OptionValues options) { - BciBlockMapping map = new BciBlockMapping(code); + public static BciBlockMapping create(BytecodeStream stream, Bytecode code, OptionValues options, DebugContext debug) { + BciBlockMapping map = new BciBlockMapping(code, debug); map.build(stream, options); - if (Debug.isDumpEnabled(Debug.INFO_LEVEL)) { - Debug.dump(Debug.INFO_LEVEL, map, code.getMethod().format("After block building %f %R %H.%n(%P)")); + if (debug.isDumpEnabled(DebugContext.INFO_LEVEL)) { + debug.dump(DebugContext.INFO_LEVEL, map, code.getMethod().format("After block building %f %R %H.%n(%P)")); } return map; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java 2017-07-07 09:30:32.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java 2017-07-07 09:30:32.000000000 -0700 @@ -27,6 +27,8 @@ import static java.lang.reflect.Modifier.SYNCHRONIZED; import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateRecompile; import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateReprofile; +import static jdk.vm.ci.meta.DeoptimizationAction.None; +import static jdk.vm.ci.meta.DeoptimizationReason.ClassCastException; import static jdk.vm.ci.meta.DeoptimizationReason.JavaSubroutineMismatch; import static jdk.vm.ci.meta.DeoptimizationReason.NullCheckException; import static jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint; @@ -286,10 +288,9 @@ import org.graalvm.compiler.core.common.type.TypeReference; import org.graalvm.compiler.core.common.util.Util; import org.graalvm.compiler.debug.Assertions; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.CounterKey; import org.graalvm.compiler.debug.DebugCloseable; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.debug.TTY; @@ -452,9 +453,9 @@ /** * Meters the number of actual bytecodes parsed. */ - public static final DebugCounter BytecodesParsed = Debug.counter("BytecodesParsed"); + public static final CounterKey BytecodesParsed = DebugContext.counter("BytecodesParsed"); - protected static final DebugCounter EXPLICIT_EXCEPTIONS = Debug.counter("ExplicitExceptions"); + protected static final CounterKey EXPLICIT_EXCEPTIONS = DebugContext.counter("ExplicitExceptions"); /** * A scoped object for tasks to be performed after parsing an intrinsic such as processing @@ -629,6 +630,7 @@ private final GraphBuilderPhase.Instance graphBuilderInstance; protected final StructuredGraph graph; protected final OptionValues options; + protected final DebugContext debug; private BciBlockMapping blockMap; private LocalLiveness liveness; @@ -663,6 +665,7 @@ this.graphBuilderInstance = graphBuilderInstance; this.graph = graph; this.options = graph.getOptions(); + this.debug = graph.getDebug(); this.graphBuilderConfig = graphBuilderInstance.graphBuilderConfig; this.optimisticOpts = graphBuilderInstance.optimisticOpts; this.metaAccess = graphBuilderInstance.metaAccess; @@ -716,7 +719,7 @@ TTY.println(Util.indent(profilingInfo.toString(method, CodeUtil.NEW_LINE), " ")); } - try (Indent indent = Debug.logAndIndent("build graph for %s", method)) { + try (Indent indent = debug.logAndIndent("build graph for %s", method)) { if (bytecodeProvider.shouldRecordMethodDependencies()) { assert getParent() != null || method.equals(graph.method()); // Record method dependency in the graph @@ -724,7 +727,7 @@ } // compute the block map, setup exception handlers and get the entrypoint(s) - BciBlockMapping newMapping = BciBlockMapping.create(stream, code, options); + BciBlockMapping newMapping = BciBlockMapping.create(stream, code, options, graph.getDebug()); this.blockMap = newMapping; this.firstInstructionArray = new FixedWithNextNode[blockMap.getBlockCount()]; this.entryStateArray = new FrameStateBuilder[blockMap.getBlockCount()]; @@ -738,11 +741,11 @@ */ assert computeKindVerification(startFrameState); - try (Scope s = Debug.scope("LivenessAnalysis")) { + try (DebugContext.Scope s = debug.scope("LivenessAnalysis")) { int maxLocals = method.getMaxLocals(); - liveness = LocalLiveness.compute(stream, blockMap.getBlocks(), maxLocals, blockMap.getLoopCount()); + liveness = LocalLiveness.compute(debug, stream, blockMap.getBlocks(), maxLocals, blockMap.getLoopCount()); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } lastInstr = startInstruction; @@ -1005,7 +1008,7 @@ private AbstractBeginNode handleException(ValueNode exceptionObject, int bci) { assert bci == BytecodeFrame.BEFORE_BCI || bci == bci() : "invalid bci"; - Debug.log("Creating exception dispatch edges at %d, exception object=%s, exception seen=%s", bci, exceptionObject, (profilingInfo == null ? "" : profilingInfo.getExceptionSeen(bci))); + debug.log("Creating exception dispatch edges at %d, exception object=%s, exception seen=%s", bci, exceptionObject, (profilingInfo == null ? "" : profilingInfo.getExceptionSeen(bci))); FrameStateBuilder dispatchState = frameState.copy(); dispatchState.clearStack(); @@ -1244,7 +1247,7 @@ exception.setStateAfter(createFrameState(bci(), exception)); exception.setNext(handleException(exception, bci())); - EXPLICIT_EXCEPTIONS.increment(); + EXPLICIT_EXCEPTIONS.increment(debug); return nonNullReceiver; } @@ -1452,6 +1455,10 @@ args[0] = emitExplicitExceptions(args[0]); } + if (initialInvokeKind == InvokeKind.Special && !targetMethod.isConstructor()) { + emitCheckForInvokeSuperSpecial(args); + } + InlineInfo inlineInfo = null; try { currentInvoke = new CurrentInvoke(args, invokeKind, returnType); @@ -1535,6 +1542,30 @@ return invoke; } + /** + * Checks that the class of the receiver of an {@link Bytecodes#INVOKESPECIAL} in a method + * declared in an interface (i.e., a default method) is assignable to the interface. If not, + * then deoptimize so that the interpreter can throw an {@link IllegalAccessError}. + * + * This is a check not performed by the verifier and so must be performed at runtime. + * + * @param args arguments to an {@link Bytecodes#INVOKESPECIAL} implementing a direct call to a + * method in a super class + */ + protected void emitCheckForInvokeSuperSpecial(ValueNode[] args) { + ResolvedJavaType callingClass = method.getDeclaringClass(); + if (callingClass.getHostClass() != null) { + callingClass = callingClass.getHostClass(); + } + if (callingClass.isInterface()) { + ValueNode receiver = args[0]; + TypeReference checkedType = TypeReference.createTrusted(graph.getAssumptions(), callingClass); + LogicNode condition = genUnique(createInstanceOf(checkedType, receiver, null)); + FixedGuardNode fixedGuard = append(new FixedGuardNode(condition, ClassCastException, None, false)); + args[0] = append(PiNode.create(receiver, StampFactory.object(checkedType, true), fixedGuard)); + } + } + protected JavaTypeProfile getProfileForInvoke(InvokeKind invokeKind) { if (invokeKind.isIndirect() && profilingInfo != null && this.optimisticOpts.useTypeCheckHints(getOptions())) { return profilingInfo.getTypeProfile(bci()); @@ -2095,9 +2126,6 @@ StackTraceElement where = code.asStackTraceElement(bci()); String s = format("%s%s (%s:%d) %s", nSpaces(getDepth()), method.isConstructor() ? method.format("%h.%n") : method.getName(), where.getFileName(), where.getLineNumber(), format(format, args)); - if (s.equals("decrypt (CipherBlockChainingSubstitutions.java:117) inlining call to CipherBlockChainingSubstitutions.decrypt(Object, byte[], int, int, byte[], int)")) { - System.console(); - } TTY.println(s); } @@ -2421,7 +2449,7 @@ firstLoopExit = loopExit; } lastLoopExit = loopExit; - Debug.log("Target %s Exits %s, scanning framestates...", targetBlock, loop); + debug.log("Target %s Exits %s, scanning framestates...", targetBlock, loop); newState.clearNonLiveLocals(targetBlock, liveness, true); newState.insertLoopProxies(loopExit, getEntryState(loop)); loopExit.setStateAfter(newState.create(bci, loopExit)); @@ -2487,7 +2515,7 @@ setEntryState(block, currentEntryState); currentEntryState.clearNonLiveLocals(block, liveness, true); - Debug.log("createTarget %s: first visit, result: %s", block, targetNode); + debug.log("createTarget %s: first visit, result: %s", block, targetNode); return result; } @@ -2508,7 +2536,7 @@ FixedNode result = target.fixed; getEntryState(block).merge(loopBegin, target.state); - Debug.log("createTarget %s: merging backward branch to loop header %s, result: %s", block, loopBegin, result); + debug.log("createTarget %s: merging backward branch to loop header %s, result: %s", block, loopBegin, result); return result; } assert currentBlock == null || currentBlock.getId() < block.getId() : "must not be backward branch"; @@ -2549,7 +2577,7 @@ getEntryState(block).merge(mergeNode, target.state); mergeNode.addForwardEnd(newEnd); - Debug.log("createTarget %s: merging state, result: %s", block, result); + debug.log("createTarget %s: merging state, result: %s", block, result); return result; } @@ -2580,10 +2608,10 @@ // Ignore blocks that have no predecessors by the time their bytecodes are parsed FixedWithNextNode firstInstruction = getFirstInstruction(block); if (firstInstruction == null) { - Debug.log("Ignoring block %s", block); + debug.log("Ignoring block %s", block); return; } - try (Indent indent = Debug.logAndIndent("Parsing block %s firstInstruction: %s loopHeader: %b", block, firstInstruction, block.isLoopHeader)) { + try (Indent indent = debug.logAndIndent("Parsing block %s firstInstruction: %s loopHeader: %b", block, firstInstruction, block.isLoopHeader)) { lastInstr = firstInstruction; frameState = getEntryState(block); @@ -2729,7 +2757,7 @@ */ setEntryState(block, frameState.copy()); - Debug.log(" created loop header %s", loopBegin); + debug.log(" created loop header %s", loopBegin); } else if (lastInstr instanceof MergeNode) { /* * All inputs of non-loop phi nodes are known by now. We can infer the stamp for the @@ -2738,7 +2766,7 @@ frameState.inferPhiStamps((AbstractMergeNode) lastInstr); } assert lastInstr.next() == null : "instructions already appended at block " + block; - Debug.log(" frameState: %s", frameState); + debug.log(" frameState: %s", frameState); lastInstr = finishInstruction(lastInstr, frameState); @@ -2746,7 +2774,7 @@ stream.setBCI(block.startBci); int bci = block.startBci; - BytecodesParsed.add(block.endBci - bci); + BytecodesParsed.add(debug, block.endBci - bci); /* Reset line number for new block */ if (graphBuilderConfig.insertFullInfopoints()) { @@ -2807,7 +2835,7 @@ } private DebugCloseable openNodeContext() { - if ((graphBuilderConfig.trackNodeSourcePosition() || Debug.isDumpEnabledForMethod()) && !parsingIntrinsic()) { + if ((graphBuilderConfig.trackNodeSourcePosition() || debug.isDumpEnabledForMethod()) && !parsingIntrinsic()) { return graph.withNodeSourcePosition(createBytecodePosition()); } return null; @@ -2870,7 +2898,7 @@ } private boolean traceState() { - if (Debug.isEnabled() && TraceBytecodeParserLevel.getValue(options) >= TRACELEVEL_STATE && Debug.isLogEnabled()) { + if (debug.isLogEnabled() && TraceBytecodeParserLevel.getValue(options) >= TRACELEVEL_STATE) { frameState.traceState(); } return true; @@ -3920,7 +3948,7 @@ if (prob != null) { assert prob.length == numberOfCases; } else { - Debug.log("Missing probability (switch) in %s at bci %d", method, bci); + debug.log("Missing probability (switch) in %s at bci %d", method, bci); prob = new double[numberOfCases]; for (int i = 0; i < numberOfCases; i++) { prob[i] = 1.0d / numberOfCases; @@ -4006,7 +4034,7 @@ double probability = profilingInfo.getBranchTakenProbability(bci()); if (probability < 0) { assert probability == -1 : "invalid probability"; - Debug.log("missing probability in %s at bci %d", code, bci()); + debug.log("missing probability in %s at bci %d", code, bci()); probability = 0.5; } @@ -4279,7 +4307,7 @@ } protected boolean traceInstruction(int bci, int opcode, boolean blockStart) { - if (Debug.isEnabled() && TraceBytecodeParserLevel.getValue(options) >= TRACELEVEL_INSTRUCTIONS && Debug.isLogEnabled()) { + if (debug.isLogEnabled() && TraceBytecodeParserLevel.getValue(options) >= TRACELEVEL_INSTRUCTIONS) { traceInstructionHelper(bci, opcode, blockStart); } return true; @@ -4300,7 +4328,7 @@ if (!currentBlock.getJsrScope().isEmpty()) { sb.append(' ').append(currentBlock.getJsrScope()); } - Debug.log("%s", sb); + debug.log("%s", sb); } @Override --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java 2017-07-07 09:30:33.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java 2017-07-07 09:30:33.000000000 -0700 @@ -46,7 +46,7 @@ import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.StampPair; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.NodeSourcePosition; import org.graalvm.compiler.java.BciBlockMapping.BciBlock; import org.graalvm.compiler.nodeinfo.Verbosity; @@ -503,48 +503,50 @@ } public void insertLoopProxies(LoopExitNode loopExit, FrameStateBuilder loopEntryState) { + DebugContext debug = graph.getDebug(); for (int i = 0; i < localsSize(); i++) { ValueNode value = locals[i]; if (value != null && value != TWO_SLOT_MARKER && (!loopEntryState.contains(value) || loopExit.loopBegin().isPhiAtMerge(value))) { - Debug.log(" inserting proxy for %s", value); + debug.log(" inserting proxy for %s", value); locals[i] = ProxyNode.forValue(value, loopExit, graph); } } for (int i = 0; i < stackSize(); i++) { ValueNode value = stack[i]; if (value != null && value != TWO_SLOT_MARKER && (!loopEntryState.contains(value) || loopExit.loopBegin().isPhiAtMerge(value))) { - Debug.log(" inserting proxy for %s", value); + debug.log(" inserting proxy for %s", value); stack[i] = ProxyNode.forValue(value, loopExit, graph); } } for (int i = 0; i < lockedObjects.length; i++) { ValueNode value = lockedObjects[i]; if (value != null && (!loopEntryState.contains(value) || loopExit.loopBegin().isPhiAtMerge(value))) { - Debug.log(" inserting proxy for %s", value); + debug.log(" inserting proxy for %s", value); lockedObjects[i] = ProxyNode.forValue(value, loopExit, graph); } } } public void insertProxies(Function proxyFunction) { + DebugContext debug = graph.getDebug(); for (int i = 0; i < localsSize(); i++) { ValueNode value = locals[i]; if (value != null && value != TWO_SLOT_MARKER) { - Debug.log(" inserting proxy for %s", value); + debug.log(" inserting proxy for %s", value); locals[i] = proxyFunction.apply(value); } } for (int i = 0; i < stackSize(); i++) { ValueNode value = stack[i]; if (value != null && value != TWO_SLOT_MARKER) { - Debug.log(" inserting proxy for %s", value); + debug.log(" inserting proxy for %s", value); stack[i] = proxyFunction.apply(value); } } for (int i = 0; i < lockedObjects.length; i++) { ValueNode value = lockedObjects[i]; if (value != null) { - Debug.log(" inserting proxy for %s", value); + debug.log(" inserting proxy for %s", value); lockedObjects[i] = proxyFunction.apply(value); } } @@ -996,14 +998,15 @@ } public void traceState() { - Debug.log("| state [nr locals = %d, stack depth = %d, method = %s]", localsSize(), stackSize(), getMethod()); + DebugContext debug = graph.getDebug(); + debug.log("| state [nr locals = %d, stack depth = %d, method = %s]", localsSize(), stackSize(), getMethod()); for (int i = 0; i < localsSize(); ++i) { ValueNode value = locals[i]; - Debug.log("| local[%d] = %-8s : %s", i, value == null ? "bogus" : value == TWO_SLOT_MARKER ? "second" : value.getStackKind().getJavaName(), value); + debug.log("| local[%d] = %-8s : %s", i, value == null ? "bogus" : value == TWO_SLOT_MARKER ? "second" : value.getStackKind().getJavaName(), value); } for (int i = 0; i < stackSize(); ++i) { ValueNode value = stack[i]; - Debug.log("| stack[%d] = %-8s : %s", i, value == null ? "bogus" : value == TWO_SLOT_MARKER ? "second" : value.getStackKind().getJavaName(), value); + debug.log("| stack[%d] = %-8s : %s", i, value == null ? "bogus" : value == TWO_SLOT_MARKER ? "second" : value.getStackKind().getJavaName(), value); } } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/LocalLiveness.java 2017-07-07 09:30:33.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/LocalLiveness.java 2017-07-07 09:30:33.000000000 -0700 @@ -76,7 +76,7 @@ import static org.graalvm.compiler.bytecode.Bytecodes.RET; import org.graalvm.compiler.bytecode.BytecodeStream; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.java.BciBlockMapping.BciBlock; /** @@ -86,9 +86,9 @@ public abstract class LocalLiveness { protected final BciBlock[] blocks; - public static LocalLiveness compute(BytecodeStream stream, BciBlock[] blocks, int maxLocals, int loopCount) { + public static LocalLiveness compute(DebugContext debug, BytecodeStream stream, BciBlock[] blocks, int maxLocals, int loopCount) { LocalLiveness liveness = maxLocals <= 64 ? new SmallLocalLiveness(blocks, maxLocals, loopCount) : new LargeLocalLiveness(blocks, maxLocals, loopCount); - liveness.computeLiveness(stream); + liveness.computeLiveness(debug, stream); return liveness; } @@ -96,7 +96,7 @@ this.blocks = blocks; } - void computeLiveness(BytecodeStream stream) { + void computeLiveness(DebugContext debug, BytecodeStream stream) { for (BciBlock block : blocks) { computeLocalLiveness(stream, block); } @@ -104,18 +104,18 @@ boolean changed; int iteration = 0; do { - assert traceIteration(iteration); + assert traceIteration(debug, iteration); changed = false; for (int i = blocks.length - 1; i >= 0; i--) { BciBlock block = blocks[i]; int blockID = block.getId(); - assert traceStart(block, blockID); + assert traceStart(debug, block, blockID); boolean blockChanged = (iteration == 0); if (block.getSuccessorCount() > 0) { int oldCardinality = liveOutCardinality(blockID); for (BciBlock sux : block.getSuccessors()) { - assert traceSuccessor(sux); + assert traceSuccessor(debug, sux); propagateLiveness(blockID, sux.getId()); } blockChanged |= (oldCardinality != liveOutCardinality(blockID)); @@ -123,7 +123,7 @@ if (blockChanged) { updateLiveness(blockID); - assert traceEnd(block, blockID); + assert traceEnd(debug, block, blockID); } changed |= blockChanged; } @@ -131,29 +131,29 @@ } while (changed); } - private static boolean traceIteration(int iteration) { - Debug.log("Iteration %d", iteration); + private static boolean traceIteration(DebugContext debug, int iteration) { + debug.log("Iteration %d", iteration); return true; } - private boolean traceEnd(BciBlock block, int blockID) { - if (Debug.isLogEnabled()) { - Debug.logv(" end B%d [%d, %d] in: %s out: %s gen: %s kill: %s", block.getId(), block.startBci, block.endBci, debugLiveIn(blockID), debugLiveOut(blockID), debugLiveGen(blockID), + private boolean traceEnd(DebugContext debug, BciBlock block, int blockID) { + if (debug.isLogEnabled()) { + debug.logv(" end B%d [%d, %d] in: %s out: %s gen: %s kill: %s", block.getId(), block.startBci, block.endBci, debugLiveIn(blockID), debugLiveOut(blockID), debugLiveGen(blockID), debugLiveKill(blockID)); } return true; } - private boolean traceSuccessor(BciBlock sux) { - if (Debug.isLogEnabled()) { - Debug.log(" Successor B%d: %s", sux.getId(), debugLiveIn(sux.getId())); + private boolean traceSuccessor(DebugContext debug, BciBlock sux) { + if (debug.isLogEnabled()) { + debug.log(" Successor B%d: %s", sux.getId(), debugLiveIn(sux.getId())); } return true; } - private boolean traceStart(BciBlock block, int blockID) { - if (Debug.isLogEnabled()) { - Debug.logv(" start B%d [%d, %d] in: %s out: %s gen: %s kill: %s", block.getId(), block.startBci, block.endBci, debugLiveIn(blockID), debugLiveOut(blockID), debugLiveGen(blockID), + private boolean traceStart(DebugContext debug, BciBlock block, int blockID) { + if (debug.isLogEnabled()) { + debug.logv(" start B%d [%d, %d] in: %s out: %s gen: %s kill: %s", block.getId(), block.startBci, block.endBci, debugLiveIn(blockID), debugLiveOut(blockID), debugLiveGen(blockID), debugLiveKill(blockID)); } return true; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/JTTTest.java 2017-07-07 09:30:34.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/JTTTest.java 2017-07-07 09:30:34.000000000 -0700 @@ -23,16 +23,18 @@ package org.graalvm.compiler.jtt; import static java.lang.reflect.Modifier.isStatic; + import java.util.Collections; import java.util.Set; -import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.nodes.StructuredGraph.Builder; import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.phases.PhaseSuite; +import org.graalvm.compiler.phases.tiers.HighTierContext; import org.junit.Assert; import jdk.vm.ci.code.InstalledCode; @@ -64,9 +66,10 @@ } @Override - protected StructuredGraph parseEager(ResolvedJavaMethod m, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId, OptionValues options) { - StructuredGraph graph = super.parseEager(m, allowAssumptions, compilationId, options); + protected StructuredGraph parse(Builder builder, PhaseSuite graphBuilderSuite) { + StructuredGraph graph = super.parse(builder, graphBuilderSuite); if (argsToBind != null) { + ResolvedJavaMethod m = graph.method(); Object receiver = isStatic(m.getModifiers()) ? null : this; Object[] args = argsWithReceiver(receiver, argsToBind); JavaType[] parameterTypes = m.toParameterTypes(); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait03.java 2017-07-07 09:30:34.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait03.java 2017-07-07 09:30:34.000000000 -0700 @@ -25,7 +25,7 @@ package org.graalvm.compiler.jtt.threads; import org.graalvm.compiler.core.common.CancellationBailoutException; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.jtt.JTTTest; import org.graalvm.compiler.nodes.Cancellable; import org.junit.Rule; @@ -125,7 +125,8 @@ } catch (CancellationBailoutException e) { String message = String.format("Compilation cancelled after " + COMPILATION_TIMEOUT_MS + " ms"); // For diagnosing expectedly long compilations (GR-3853) - Debug.forceDump(lastCompiledGraph, message); + DebugContext debug = getDebugContext(); + debug.forceDump(lastCompiledGraph, message); throw new AssertionError(message, e); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64PrefetchOp.java 2017-07-07 09:30:35.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64PrefetchOp.java 2017-07-07 09:30:34.000000000 -0700 @@ -25,6 +25,7 @@ import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.COMPOSITE; +import org.graalvm.compiler.asm.aarch64.AArch64Assembler.PrefetchMode; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; @@ -32,18 +33,18 @@ public final class AArch64PrefetchOp extends AArch64LIRInstruction { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AArch64PrefetchOp.class); - @SuppressWarnings("unused") private final int instr; // AllocatePrefetchInstr + private final PrefetchMode mode; // AllocatePrefetchInstr @Alive({COMPOSITE}) protected AArch64AddressValue address; - public AArch64PrefetchOp(AArch64AddressValue address, int instr) { + public AArch64PrefetchOp(AArch64AddressValue address, PrefetchMode mode) { super(TYPE); this.address = address; - this.instr = instr; + this.mode = mode; } @Override public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { - // TODO implement prefetch - masm.nop(); + // instr gets ignored! + masm.prfm(address.toAddress(), mode); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/phases/StackMoveOptimizationPhase.java 2017-07-07 09:30:35.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/phases/StackMoveOptimizationPhase.java 2017-07-07 09:30:35.000000000 -0700 @@ -29,8 +29,8 @@ import java.util.List; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.RedundantMoveElimination; @@ -62,14 +62,15 @@ // @formatter:on } - private static final DebugCounter eliminatedBackup = Debug.counter("StackMoveOptimizer[EliminatedScratchBackupRestore]"); + private static final CounterKey eliminatedBackup = DebugContext.counter("StackMoveOptimizer[EliminatedScratchBackupRestore]"); @Override protected void run(TargetDescription target, LIRGenerationResult lirGenRes, PostAllocationOptimizationContext context) { LIR lir = lirGenRes.getLIR(); + DebugContext debug = lir.getDebug(); for (AbstractBlockBase block : lir.getControlFlowGraph().getBlocks()) { ArrayList instructions = lir.getLIRforBlock(block); - new Closure().process(instructions); + new Closure().process(debug, instructions); } } @@ -83,7 +84,7 @@ private AllocatableValue slot; private boolean removed = false; - public void process(List instructions) { + public void process(DebugContext debug, List instructions) { for (int i = 0; i < instructions.size(); i++) { LIRInstruction inst = instructions.get(i); @@ -92,7 +93,7 @@ if (reg != null && !reg.equals(move.getScratchRegister())) { // end of trace & start of new - replaceStackMoves(instructions); + replaceStackMoves(debug, instructions); } // lazy initialize @@ -114,7 +115,7 @@ } else if (begin != NONE) { // end of trace - replaceStackMoves(instructions); + replaceStackMoves(debug, instructions); } } // remove instructions @@ -124,7 +125,7 @@ } - private void replaceStackMoves(List instructions) { + private void replaceStackMoves(DebugContext debug, List instructions) { int size = dst.size(); if (size > 1) { AMD64MultiStackMove multiMove = new AMD64MultiStackMove(dst.toArray(new AllocatableValue[size]), src.toArray(new AllocatableValue[size]), reg, slot); @@ -134,7 +135,7 @@ Collections.fill(instructions.subList(begin + 1, begin + size), null); // removed removed = true; - eliminatedBackup.add(size - 1); + eliminatedBackup.add(debug, size - 1); } // reset dst.clear(); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/SPARCBranchBailoutTest.java 2017-07-07 09:30:35.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/SPARCBranchBailoutTest.java 2017-07-07 09:30:35.000000000 -0700 @@ -24,13 +24,15 @@ import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.core.common.PermanentBailoutException; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugConfigScope; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DebugContext.Scope; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.junit.Assert; import org.junit.Assume; import org.junit.Test; @@ -82,9 +84,11 @@ public void testBailoutOnBranchOverflow() throws Throwable { Assume.assumeTrue(getBackend().getTarget().arch instanceof SPARC); ResolvedJavaMethod m = getResolvedJavaMethod("testBranch"); + DebugContext debug = getDebugContext(); try { - try (DebugConfigScope s = Debug.setConfig(Debug.silentConfig())) { - compile(m, null); + try (Scope s = debug.disable()) { + StructuredGraph graph = parseEager(m, AllowAssumptions.YES, debug); + compile(m, graph); } } catch (GraalError e) { Assert.assertEquals(PermanentBailoutException.class, e.getCause().getClass()); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/CompositeValue.java 2017-07-07 09:30:36.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/CompositeValue.java 2017-07-07 09:30:36.000000000 -0700 @@ -28,8 +28,6 @@ import java.lang.annotation.Target; import java.util.EnumSet; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; import org.graalvm.compiler.lir.LIRInstruction.OperandFlag; import org.graalvm.compiler.lir.LIRInstruction.OperandMode; @@ -50,11 +48,8 @@ OperandFlag[] value() default OperandFlag.REG; } - private static final DebugCounter COMPOSITE_VALUE_COUNT = Debug.counter("CompositeValues"); - public CompositeValue(ValueKind kind) { super(kind); - COMPOSITE_VALUE_COUNT.increment(); assert CompositeValueClass.get(getClass()) != null; } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ControlFlowOptimizer.java 2017-07-07 09:30:36.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ControlFlowOptimizer.java 2017-07-07 09:30:36.000000000 -0700 @@ -27,8 +27,8 @@ import java.util.ArrayList; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.lir.gen.LIRGenerationResult; import org.graalvm.compiler.lir.phases.PostAllocationOptimizationPhase; @@ -56,7 +56,7 @@ this.lir = lir; } - private static final DebugCounter BLOCKS_DELETED = Debug.counter("BlocksDeleted"); + private static final CounterKey BLOCKS_DELETED = DebugContext.counter("BlocksDeleted"); /** * Checks whether a block can be deleted. Only blocks with exactly one successor and an @@ -105,7 +105,7 @@ alignBlock(other); } - BLOCKS_DELETED.increment(); + BLOCKS_DELETED.increment(lir.getDebug()); blocks[i] = null; } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIR.java 2017-07-07 09:30:37.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIR.java 2017-07-07 09:30:37.000000000 -0700 @@ -29,6 +29,7 @@ import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; import org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph; import org.graalvm.compiler.core.common.cfg.BlockMap; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.lir.StandardOp.BlockEndOp; import org.graalvm.compiler.lir.StandardOp.LabelOp; import org.graalvm.compiler.lir.gen.LIRGenerator; @@ -62,15 +63,18 @@ private final OptionValues options; + private final DebugContext debug; + /** * Creates a new LIR instance for the specified compilation. */ - public LIR(AbstractControlFlowGraph cfg, AbstractBlockBase[] linearScanOrder, AbstractBlockBase[] codeEmittingOrder, OptionValues options) { + public LIR(AbstractControlFlowGraph cfg, AbstractBlockBase[] linearScanOrder, AbstractBlockBase[] codeEmittingOrder, OptionValues options, DebugContext debug) { this.cfg = cfg; this.codeEmittingOrder = codeEmittingOrder; this.linearScanOrder = linearScanOrder; this.lirInstructions = new BlockMap<>(cfg); this.options = options; + this.debug = debug; } public AbstractControlFlowGraph getControlFlowGraph() { @@ -81,6 +85,10 @@ return options; } + public DebugContext getDebug() { + return debug; + } + /** * Determines if any instruction in the LIR has debug info associated with it. */ --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRInstruction.java 2017-07-07 09:30:37.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRInstruction.java 2017-07-07 09:30:37.000000000 -0700 @@ -22,6 +22,7 @@ */ package org.graalvm.compiler.lir; +import static jdk.vm.ci.code.ValueUtil.isStackSlot; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.COMPOSITE; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.CONST; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT; @@ -34,7 +35,6 @@ import static org.graalvm.compiler.lir.LIRInstruction.OperandMode.DEF; import static org.graalvm.compiler.lir.LIRInstruction.OperandMode.TEMP; import static org.graalvm.compiler.lir.LIRValueUtil.isVirtualStackSlot; -import static jdk.vm.ci.code.ValueUtil.isStackSlot; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -44,8 +44,6 @@ import java.util.EnumMap; import java.util.EnumSet; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; import org.graalvm.compiler.graph.NodeSourcePosition; import org.graalvm.compiler.lir.StandardOp.LoadConstantOp; import org.graalvm.compiler.lir.StandardOp.MoveOp; @@ -204,13 +202,10 @@ */ private NodeSourcePosition position; - private static final DebugCounter LIR_NODE_COUNT = Debug.counter("LIRNodes"); - /** * Constructs a new LIR instruction. */ public LIRInstruction(LIRInstructionClass c) { - LIR_NODE_COUNT.increment(); instructionClass = c; assert c.getClazz() == this.getClass(); id = -1; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/RedundantMoveElimination.java 2017-07-07 09:30:37.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/RedundantMoveElimination.java 2017-07-07 09:30:37.000000000 -0700 @@ -32,8 +32,8 @@ import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.LIRInstruction.OperandFlag; import org.graalvm.compiler.lir.LIRInstruction.OperandMode; @@ -42,8 +42,8 @@ import org.graalvm.compiler.lir.framemap.FrameMap; import org.graalvm.compiler.lir.gen.LIRGenerationResult; import org.graalvm.compiler.lir.phases.PostAllocationOptimizationPhase; -import org.graalvm.util.Equivalence; import org.graalvm.util.EconomicMap; +import org.graalvm.util.Equivalence; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.RegisterArray; @@ -57,7 +57,7 @@ */ public final class RedundantMoveElimination extends PostAllocationOptimizationPhase { - private static final DebugCounter deletedMoves = Debug.counter("RedundantMovesEliminated"); + private static final CounterKey deletedMoves = DebugContext.counter("RedundantMovesEliminated"); @Override protected void run(TargetDescription target, LIRGenerationResult lirGenRes, PostAllocationOptimizationContext context) { @@ -136,8 +136,8 @@ */ @SuppressWarnings("try") private void doOptimize(LIR lir) { - - try (Indent indent = Debug.logAndIndent("eliminate redundant moves")) { + DebugContext debug = lir.getDebug(); + try (Indent indent = debug.logAndIndent("eliminate redundant moves")) { callerSaveRegs = frameMap.getRegisterConfig().getCallerSaveRegisters(); @@ -168,7 +168,7 @@ private static final int COMPLEXITY_LIMIT = 30000; private void initBlockData(LIR lir) { - + DebugContext debug = lir.getDebug(); AbstractBlockBase[] blocks = lir.linearScanOrder(); numRegs = 0; @@ -203,7 +203,7 @@ * Now we know the number of locations to optimize, so we can allocate the block states. */ int numLocations = numRegs + stackIndices.size(); - Debug.log("num locations = %d (regs = %d, stack = %d)", numLocations, numRegs, stackIndices.size()); + debug.log("num locations = %d (regs = %d, stack = %d)", numLocations, numRegs, stackIndices.size()); for (AbstractBlockBase block : blocks) { BlockData data = new BlockData(numLocations); blockData.put(block, data); @@ -222,7 +222,8 @@ @SuppressWarnings("try") private boolean solveDataFlow(LIR lir) { - try (Indent indent = Debug.logAndIndent("solve data flow")) { + DebugContext debug = lir.getDebug(); + try (Indent indent = debug.logAndIndent("solve data flow")) { AbstractBlockBase[] blocks = lir.linearScanOrder(); @@ -236,7 +237,7 @@ boolean changed; do { changed = false; - try (Indent indent2 = Debug.logAndIndent("new iteration")) { + try (Indent indent2 = debug.logAndIndent("new iteration")) { for (AbstractBlockBase block : blocks) { @@ -262,7 +263,7 @@ * control flow in case of an exception. So we assume a save default * for exception handler blocks. */ - Debug.log("kill all values at entry of block %d", block.getId()); + debug.log("kill all values at entry of block %d", block.getId()); clearValues(data.entryState, valueNum); } else { /* @@ -278,7 +279,7 @@ valueNum += data.entryState.length; if (newState || firstRound) { - try (Indent indent3 = Debug.logAndIndent("update block %d", block.getId())) { + try (Indent indent3 = debug.logAndIndent("update block %d", block.getId())) { /* * Derive the exit state from the entry state by iterating @@ -289,7 +290,7 @@ ArrayList instructions = lir.getLIRforBlock(block); for (LIRInstruction op : instructions) { - valueNum = updateState(iterState, op, valueNum); + valueNum = updateState(debug, iterState, op, valueNum); } changed = true; } @@ -322,14 +323,15 @@ */ @SuppressWarnings("try") private void eliminateMoves(LIR lir) { + DebugContext debug = lir.getDebug(); - try (Indent indent = Debug.logAndIndent("eliminate moves")) { + try (Indent indent = debug.logAndIndent("eliminate moves")) { AbstractBlockBase[] blocks = lir.linearScanOrder(); for (AbstractBlockBase block : blocks) { - try (Indent indent2 = Debug.logAndIndent("eliminate moves in block %d", block.getId())) { + try (Indent indent2 = debug.logAndIndent("eliminate moves in block %d", block.getId())) { ArrayList instructions = lir.getLIRforBlock(block); BlockData data = blockData.get(block); @@ -351,16 +353,14 @@ int destIdx = getStateIdx(moveOp.getResult()); if (sourceIdx >= 0 && destIdx >= 0 && iterState[sourceIdx] == iterState[destIdx]) { assert iterState[sourceIdx] != INIT_VALUE; - Debug.log("delete move %s", op); + debug.log("delete move %s", op); instructions.set(idx, null); hasDead = true; - if (deletedMoves.isEnabled()) { - deletedMoves.increment(); - } + deletedMoves.increment(debug); } } // It doesn't harm if updateState is also called for a deleted move - valueNum = updateState(iterState, op, valueNum); + valueNum = updateState(debug, iterState, op, valueNum); } if (hasDead) { instructions.removeAll(Collections.singleton(null)); @@ -374,9 +374,9 @@ * Updates the state for one instruction. */ @SuppressWarnings("try") - private int updateState(final int[] state, LIRInstruction op, int initValueNum) { + private int updateState(DebugContext debug, final int[] state, LIRInstruction op, int initValueNum) { - try (Indent indent = Debug.logAndIndent("update state for op %s, initial value num = %d", op, initValueNum)) { + try (Indent indent = debug.logAndIndent("update state for op %s, initial value num = %d", op, initValueNum)) { if (isEligibleMove(op)) { /* * Handle the special case of a move instruction @@ -387,7 +387,7 @@ if (sourceIdx >= 0 && destIdx >= 0) { assert isObjectValue(state[sourceIdx]) || LIRKind.isValue(moveOp.getInput()) : "move op moves object but input is not defined as object " + moveOp; state[destIdx] = state[sourceIdx]; - Debug.log("move value %d from %d to %d", state[sourceIdx], sourceIdx, destIdx); + debug.log("move value %d from %d to %d", state[sourceIdx], sourceIdx, destIdx); return initValueNum; } } @@ -395,7 +395,7 @@ int valueNum = initValueNum; if (op.destroysCallerSavedRegisters()) { - Debug.log("kill all caller save regs"); + debug.log("kill all caller save regs"); for (Register reg : callerSaveRegs) { if (reg.number < numRegs) { @@ -424,7 +424,7 @@ * Assign a unique number to the output or temp location. */ state[stateIdx] = encodeValueNum(opValueNum++, !LIRKind.isValue(operand)); - Debug.log("set def %d for register %s(%d): %d", opValueNum, operand, stateIdx, state[stateIdx]); + debug.log("set def %d for register %s(%d): %d", opValueNum, operand, stateIdx, state[stateIdx]); } } } @@ -447,7 +447,7 @@ * all values which are referenced in the state (or all values which are not), * but for simplicity we kill all values. */ - Debug.log("kill all object values"); + debug.log("kill all object values"); clearValuesOfKindObject(state, valueNum); valueNum += state.length; } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/IntervalWalker.java 2017-07-07 09:30:38.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/IntervalWalker.java 2017-07-07 09:30:38.000000000 -0700 @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.lir.alloc.lsra; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.alloc.lsra.Interval.RegisterBinding; import org.graalvm.compiler.lir.alloc.lsra.Interval.RegisterBindingLists; @@ -233,7 +233,8 @@ walkTo(State.Active, opId); walkTo(State.Inactive, opId); - try (Indent indent = Debug.logAndIndent("walk to op %d", opId)) { + DebugContext debug = allocator.getDebug(); + try (Indent indent = debug.logAndIndent("walk to op %d", opId)) { currentInterval.state = State.Active; if (activateCurrent(currentInterval)) { activeLists.addToListSortedByCurrentFromPositions(currentBinding, currentInterval); @@ -257,8 +258,9 @@ private void intervalMoved(Interval interval, State from, State to) { // intervalMoved() is called whenever an interval moves from one interval list to another. // In the implementation of this method it is prohibited to move the interval to any list. - if (Debug.isLogEnabled()) { - Debug.log("interval moved from %s to %s: %s", from, to, interval.logString(allocator)); + DebugContext debug = allocator.getDebug(); + if (debug.isLogEnabled()) { + debug.log("interval moved from %s to %s: %s", from, to, interval.logString(allocator)); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScan.java 2017-07-07 09:30:38.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScan.java 2017-07-07 09:30:38.000000000 -0700 @@ -40,8 +40,7 @@ import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; import org.graalvm.compiler.core.common.cfg.BlockMap; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.LIR; @@ -128,6 +127,7 @@ private final MoveFactory moveFactory; private final BlockMap blockData; + protected final DebugContext debug; /** * List of blocks in linear-scan order. This is only correct as long as the CFG does not change. @@ -191,6 +191,7 @@ boolean neverSpillConstants) { this.ir = res.getLIR(); this.res = res; + this.debug = ir.getDebug(); this.moveFactory = spillMoveFactory; this.frameMapBuilder = res.getFrameMapBuilder(); this.sortedBlocks = sortedBlocks; @@ -220,6 +221,10 @@ return ir.getOptions(); } + public DebugContext getDebug() { + return debug; + } + public int getFirstLirInstructionId(AbstractBlockBase block) { int result = ir.getLIRforBlock(block).get(0).id(); assert result >= 0; @@ -642,8 +647,8 @@ Interval result = interval.getSplitChildAtOpId(opId, mode, this); if (result != null) { - if (Debug.isLogEnabled()) { - Debug.log("Split child at pos %d of interval %s is %s", opId, interval, result); + if (debug.isLogEnabled()) { + debug.log("Split child at pos %d of interval %s is %s", opId, interval, result); } return result; } @@ -679,11 +684,11 @@ /* * This is the point to enable debug logging for the whole register allocation. */ - try (Indent indent = Debug.logAndIndent("LinearScan allocate")) { + try (Indent indent = debug.logAndIndent("LinearScan allocate")) { createLifetimeAnalysisPhase().apply(target, lirGenRes, context); - try (Scope s = Debug.scope("AfterLifetimeAnalysis", (Object) intervals)) { + try (DebugContext.Scope s = debug.scope("AfterLifetimeAnalysis", (Object) intervals)) { sortIntervalsBeforeAllocation(); createRegisterAllocationPhase().apply(target, lirGenRes, context); @@ -706,7 +711,7 @@ verifyIntervals(); } } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } } @@ -740,23 +745,23 @@ @SuppressWarnings("try") public void printIntervals(String label) { - if (Debug.isLogEnabled()) { - try (Indent indent = Debug.logAndIndent("intervals %s", label)) { + if (debug.isLogEnabled()) { + try (Indent indent = debug.logAndIndent("intervals %s", label)) { for (Interval interval : intervals) { if (interval != null) { - Debug.log("%s", interval.logString(this)); + debug.log("%s", interval.logString(this)); } } - try (Indent indent2 = Debug.logAndIndent("Basic Blocks")) { + try (Indent indent2 = debug.logAndIndent("Basic Blocks")) { for (int i = 0; i < blockCount(); i++) { AbstractBlockBase block = blockAt(i); - Debug.log("B%d [%d, %d, %s] ", block.getId(), getFirstLirInstructionId(block), getLastLirInstructionId(block), block.getLoop()); + debug.log("B%d [%d, %d, %s] ", block.getId(), getFirstLirInstructionId(block), getLastLirInstructionId(block), block.getLoop()); } } } } - Debug.dump(Debug.VERBOSE_LEVEL, new LinearScanIntervalDumper(Arrays.copyOf(intervals, intervalsSize)), label); + debug.dump(DebugContext.VERBOSE_LEVEL, new LinearScanIntervalDumper(Arrays.copyOf(intervals, intervalsSize)), label); } boolean verify() { @@ -765,7 +770,7 @@ verifyRegisters(); - Debug.log("no errors found"); + debug.log("no errors found"); return true; } @@ -773,7 +778,7 @@ @SuppressWarnings("try") private void verifyRegisters() { // Enable this logging to get output for the verification process. - try (Indent indent = Debug.logAndIndent("verifying register allocation")) { + try (Indent indent = debug.logAndIndent("verifying register allocation")) { RegisterVerifier verifier = new RegisterVerifier(this); verifier.verify(blockAt(0)); } @@ -781,7 +786,7 @@ @SuppressWarnings("try") protected void verifyIntervals() { - try (Indent indent = Debug.logAndIndent("verifying intervals")) { + try (Indent indent = debug.logAndIndent("verifying intervals")) { int len = intervalsSize; for (int i = 0; i < len; i++) { @@ -793,33 +798,33 @@ i1.checkSplitChildren(); if (i1.operandNumber != i) { - Debug.log("Interval %d is on position %d in list", i1.operandNumber, i); - Debug.log(i1.logString(this)); + debug.log("Interval %d is on position %d in list", i1.operandNumber, i); + debug.log(i1.logString(this)); throw new GraalError(""); } if (isVariable(i1.operand) && i1.kind().equals(LIRKind.Illegal)) { - Debug.log("Interval %d has no type assigned", i1.operandNumber); - Debug.log(i1.logString(this)); + debug.log("Interval %d has no type assigned", i1.operandNumber); + debug.log(i1.logString(this)); throw new GraalError(""); } if (i1.location() == null) { - Debug.log("Interval %d has no register assigned", i1.operandNumber); - Debug.log(i1.logString(this)); + debug.log("Interval %d has no register assigned", i1.operandNumber); + debug.log(i1.logString(this)); throw new GraalError(""); } if (i1.first().isEndMarker()) { - Debug.log("Interval %d has no Range", i1.operandNumber); - Debug.log(i1.logString(this)); + debug.log("Interval %d has no Range", i1.operandNumber); + debug.log(i1.logString(this)); throw new GraalError(""); } for (Range r = i1.first(); !r.isEndMarker(); r = r.next) { if (r.from >= r.to) { - Debug.log("Interval %d has zero length range", i1.operandNumber); - Debug.log(i1.logString(this)); + debug.log("Interval %d has zero length range", i1.operandNumber); + debug.log(i1.logString(this)); throw new GraalError(""); } } @@ -866,7 +871,7 @@ @SuppressWarnings("try") void verifyNoOopsInFixedIntervals() { - try (Indent indent = Debug.logAndIndent("verifying that no oops are in fixed intervals *")) { + try (Indent indent = debug.logAndIndent("verifying that no oops are in fixed intervals *")) { CheckConsumer checkConsumer = new CheckConsumer(); Interval fixedIntervals; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanAllocationPhase.java 2017-07-07 09:30:39.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanAllocationPhase.java 2017-07-07 09:30:39.000000000 -0700 @@ -22,8 +22,7 @@ */ package org.graalvm.compiler.lir.alloc.lsra; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.lir.gen.LIRGenerationResult; import static org.graalvm.compiler.lir.phases.AllocationPhase.AllocationContext; import org.graalvm.compiler.lir.phases.LIRPhase; @@ -47,13 +46,16 @@ @SuppressWarnings("try") public final void apply(TargetDescription target, LIRGenerationResult lirGenRes, AllocationContext context, boolean dumpLIR) { - try (Scope s = Debug.scope(getName(), this)) { + DebugContext debug = lirGenRes.getLIR().getDebug(); + try (DebugContext.Scope s = debug.scope(getName(), this)) { run(target, lirGenRes, context); - if (dumpLIR && Debug.isDumpEnabled(Debug.VERBOSE_LEVEL)) { - Debug.dump(Debug.VERBOSE_LEVEL, lirGenRes.getLIR(), "After %s", getName()); + if (dumpLIR) { + if (debug.isDumpEnabled(DebugContext.VERBOSE_LEVEL)) { + debug.dump(DebugContext.VERBOSE_LEVEL, lirGenRes.getLIR(), "After %s", getName()); + } } } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanAssignLocationsPhase.java 2017-07-07 09:30:39.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanAssignLocationsPhase.java 2017-07-07 09:30:39.000000000 -0700 @@ -33,7 +33,7 @@ import java.util.EnumSet; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.ConstantValue; import org.graalvm.compiler.lir.InstructionValueProcedure; @@ -230,9 +230,10 @@ @SuppressWarnings("try") private void assignLocations() { - try (Indent indent = Debug.logAndIndent("assign locations")) { + DebugContext debug = allocator.getDebug(); + try (Indent indent = debug.logAndIndent("assign locations")) { for (AbstractBlockBase block : allocator.sortedBlocks()) { - try (Indent indent2 = Debug.logAndIndent("assign locations in block B%d", block.getId())) { + try (Indent indent2 = debug.logAndIndent("assign locations in block B%d", block.getId())) { assignLocations(allocator.getLIR().getLIRforBlock(block)); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanEliminateSpillMovePhase.java 2017-07-07 09:30:39.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanEliminateSpillMovePhase.java 2017-07-07 09:30:39.000000000 -0700 @@ -31,7 +31,7 @@ import java.util.ArrayList; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.LIRInsertionBuffer; import org.graalvm.compiler.lir.LIRInstruction; @@ -90,7 +90,8 @@ // called once before assignment of register numbers @SuppressWarnings("try") void eliminateSpillMoves(LIRGenerationResult res) { - try (Indent indent = Debug.logAndIndent("Eliminating unnecessary spill moves")) { + DebugContext debug = allocator.getDebug(); + try (Indent indent = debug.logAndIndent("Eliminating unnecessary spill moves")) { /* * collect all intervals that must be stored after their definition. The list is sorted @@ -99,12 +100,12 @@ Interval interval; interval = allocator.createUnhandledLists(mustStoreAtDefinition, null).getLeft(); if (DetailedAsserts.getValue(allocator.getOptions())) { - checkIntervals(interval); + checkIntervals(debug, interval); } LIRInsertionBuffer insertionBuffer = new LIRInsertionBuffer(); for (AbstractBlockBase block : allocator.sortedBlocks()) { - try (Indent indent1 = Debug.logAndIndent("Handle %s", block)) { + try (Indent indent1 = debug.logAndIndent("Handle %s", block)) { ArrayList instructions = allocator.getLIR().getLIRforBlock(block); int numInst = instructions.size(); @@ -125,14 +126,14 @@ * Move target is a stack slot that is always correct, so eliminate * instruction. */ - if (Debug.isLogEnabled()) { + if (debug.isLogEnabled()) { if (ValueMoveOp.isValueMoveOp(op)) { ValueMoveOp vmove = ValueMoveOp.asValueMoveOp(op); - Debug.log("eliminating move from interval %d (%s) to %d (%s) in block %s", allocator.operandNumber(vmove.getInput()), vmove.getInput(), + debug.log("eliminating move from interval %d (%s) to %d (%s) in block %s", allocator.operandNumber(vmove.getInput()), vmove.getInput(), allocator.operandNumber(vmove.getResult()), vmove.getResult(), block); } else { LoadConstantOp load = LoadConstantOp.asLoadConstantOp(op); - Debug.log("eliminating constant load from %s to %d (%s) in block %s", load.getConstant(), allocator.operandNumber(load.getResult()), load.getResult(), block); + debug.log("eliminating constant load from %s to %d (%s) in block %s", load.getConstant(), allocator.operandNumber(load.getResult()), load.getResult(), block); } } @@ -170,8 +171,8 @@ insertionBuffer.append(j + 1, move); move.setComment(res, "LSRAEliminateSpillMove: store at definition"); - if (Debug.isLogEnabled()) { - Debug.log("inserting move after definition of interval %d to stack slot %s at opId %d", interval.operandNumber, interval.spillSlot(), opId); + if (debug.isLogEnabled()) { + debug.log("inserting move after definition of interval %d to stack slot %s at opId %d", interval.operandNumber, interval.spillSlot(), opId); } } } @@ -206,7 +207,7 @@ return false; } - private static void checkIntervals(Interval interval) { + private static void checkIntervals(DebugContext debug, Interval interval) { Interval prev = null; Interval temp = interval; while (!temp.isEndMarker()) { @@ -220,8 +221,8 @@ assert temp.spillDefinitionPos() >= temp.from() : "invalid order"; assert temp.spillDefinitionPos() <= temp.from() + 2 : "only intervals defined once at their start-pos can be optimized"; - if (Debug.isLogEnabled()) { - Debug.log("interval %d (from %d to %d) must be stored at %d", temp.operandNumber, temp.from(), temp.to(), temp.spillDefinitionPos()); + if (debug.isLogEnabled()) { + debug.log("interval %d (from %d to %d) must be stored at %d", temp.operandNumber, temp.from(), temp.to(), temp.spillDefinitionPos()); } prev = temp; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java 2017-07-07 09:30:40.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java 2017-07-07 09:30:40.000000000 -0700 @@ -41,8 +41,7 @@ import org.graalvm.compiler.core.common.alloc.ComputeBlockOrder; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; import org.graalvm.compiler.core.common.util.BitMap2D; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.InstructionValueConsumer; @@ -73,18 +72,20 @@ public class LinearScanLifetimeAnalysisPhase extends LinearScanAllocationPhase { protected final LinearScan allocator; + protected final DebugContext debug; /** * @param linearScan */ protected LinearScanLifetimeAnalysisPhase(LinearScan linearScan) { allocator = linearScan; + debug = allocator.getDebug(); } @Override protected void run(TargetDescription target, LIRGenerationResult lirGenRes, AllocationContext context) { numberInstructions(); - Debug.dump(Debug.VERBOSE_LEVEL, lirGenRes.getLIR(), "Before register allocation"); + debug.dump(DebugContext.VERBOSE_LEVEL, lirGenRes.getLIR(), "Before register allocation"); computeLocalLiveSets(); computeGlobalLiveSets(); buildIntervals(DetailedAsserts.getValue(allocator.getOptions())); @@ -160,7 +161,7 @@ // iterate all blocks for (final AbstractBlockBase block : allocator.sortedBlocks()) { - try (Indent indent = Debug.logAndIndent("compute local live sets for block %s", block)) { + try (Indent indent = debug.logAndIndent("compute local live sets for block %s", block)) { final BitSet liveGen = new BitSet(liveSize); final BitSet liveKill = new BitSet(liveSize); @@ -173,8 +174,8 @@ int operandNum = allocator.operandNumber(operand); if (!liveKill.get(operandNum)) { liveGen.set(operandNum); - if (Debug.isLogEnabled()) { - Debug.log("liveGen for operand %d(%s)", operandNum, operand); + if (debug.isLogEnabled()) { + debug.log("liveGen for operand %d(%s)", operandNum, operand); } } if (block.getLoop() != null) { @@ -191,8 +192,8 @@ int operandNum = allocator.operandNumber(operand); if (!liveKill.get(operandNum)) { liveGen.set(operandNum); - if (Debug.isLogEnabled()) { - Debug.log("liveGen in state for operand %d(%s)", operandNum, operand); + if (debug.isLogEnabled()) { + debug.log("liveGen in state for operand %d(%s)", operandNum, operand); } } } @@ -201,8 +202,8 @@ if (isVariable(operand)) { int varNum = allocator.operandNumber(operand); liveKill.set(varNum); - if (Debug.isLogEnabled()) { - Debug.log("liveKill for operand %d(%s)", varNum, operand); + if (debug.isLogEnabled()) { + debug.log("liveKill for operand %d(%s)", varNum, operand); } if (block.getLoop() != null) { intervalInLoop.setBit(varNum, block.getLoop().getIndex()); @@ -223,7 +224,7 @@ for (int j = 0; j < numInst; j++) { final LIRInstruction op = instructions.get(j); - try (Indent indent2 = Debug.logAndIndent("handle op %d: %s", op.id(), op)) { + try (Indent indent2 = debug.logAndIndent("handle op %d: %s", op.id(), op)) { op.visitEachInput(useConsumer); op.visitEachAlive(useConsumer); /* @@ -242,9 +243,9 @@ blockSets.liveIn = new BitSet(liveSize); blockSets.liveOut = new BitSet(liveSize); - if (Debug.isLogEnabled()) { - Debug.log("liveGen B%d %s", block.getId(), blockSets.liveGen); - Debug.log("liveKill B%d %s", block.getId(), blockSets.liveKill); + if (debug.isLogEnabled()) { + debug.log("liveGen B%d %s", block.getId(), blockSets.liveGen); + debug.log("liveKill B%d %s", block.getId(), blockSets.liveKill); } } @@ -282,7 +283,7 @@ */ @SuppressWarnings("try") protected void computeGlobalLiveSets() { - try (Indent indent = Debug.logAndIndent("compute global live sets")) { + try (Indent indent = debug.logAndIndent("compute global live sets")) { int numBlocks = allocator.blockCount(); boolean changeOccurred; boolean changeOccurredInBlock; @@ -296,7 +297,7 @@ do { changeOccurred = false; - try (Indent indent2 = Debug.logAndIndent("new iteration %d", iterationCount)) { + try (Indent indent2 = debug.logAndIndent("new iteration %d", iterationCount)) { // iterate all blocks in reverse order for (int i = numBlocks - 1; i >= 0; i--) { @@ -346,8 +347,8 @@ liveIn.andNot(blockSets.liveKill); liveIn.or(blockSets.liveGen); - if (Debug.isLogEnabled()) { - Debug.log("block %d: livein = %s, liveout = %s", block.getId(), liveIn, blockSets.liveOut); + if (debug.isLogEnabled()) { + debug.log("block %d: livein = %s, liveout = %s", block.getId(), liveIn, blockSets.liveOut); } } } @@ -381,18 +382,18 @@ @SuppressWarnings("try") protected void reportFailure(int numBlocks) { - try (Scope s = Debug.forceLog()) { - try (Indent indent = Debug.logAndIndent("report failure")) { + try (DebugContext.Scope s = debug.forceLog()) { + try (Indent indent = debug.logAndIndent("report failure")) { BitSet startBlockLiveIn = allocator.getBlockData(allocator.getLIR().getControlFlowGraph().getStartBlock()).liveIn; - try (Indent indent2 = Debug.logAndIndent("Error: liveIn set of first block must be empty (when this fails, variables are used before they are defined):")) { + try (Indent indent2 = debug.logAndIndent("Error: liveIn set of first block must be empty (when this fails, variables are used before they are defined):")) { for (int operandNum = startBlockLiveIn.nextSetBit(0); operandNum >= 0; operandNum = startBlockLiveIn.nextSetBit(operandNum + 1)) { Interval interval = allocator.intervalFor(operandNum); if (interval != null) { Value operand = interval.operand; - Debug.log("var %d; operand=%s; node=%s", operandNum, operand, getSourceForOperandFromDebugContext(operand)); + debug.log("var %d; operand=%s; node=%s", operandNum, operand, getSourceForOperandFromDebugContext(debug, operand)); } else { - Debug.log("var %d; missing operand", operandNum); + debug.log("var %d; missing operand", operandNum); } } } @@ -404,20 +405,20 @@ Object valueForOperandFromDebugContext = null; if (interval != null) { operand = interval.operand; - valueForOperandFromDebugContext = getSourceForOperandFromDebugContext(operand); + valueForOperandFromDebugContext = getSourceForOperandFromDebugContext(debug, operand); } - try (Indent indent2 = Debug.logAndIndent("---- Detailed information for var %d; operand=%s; node=%s ----", operandNum, operand, valueForOperandFromDebugContext)) { + try (Indent indent2 = debug.logAndIndent("---- Detailed information for var %d; operand=%s; node=%s ----", operandNum, operand, valueForOperandFromDebugContext)) { ArrayDeque> definedIn = new ArrayDeque<>(); EconomicSet> usedIn = EconomicSet.create(Equivalence.IDENTITY); for (AbstractBlockBase block : allocator.sortedBlocks()) { if (allocator.getBlockData(block).liveGen.get(operandNum)) { usedIn.add(block); - try (Indent indent3 = Debug.logAndIndent("used in block B%d", block.getId())) { + try (Indent indent3 = debug.logAndIndent("used in block B%d", block.getId())) { for (LIRInstruction ins : allocator.getLIR().getLIRforBlock(block)) { - try (Indent indent4 = Debug.logAndIndent("%d: %s", ins.id(), ins)) { + try (Indent indent4 = debug.logAndIndent("%d: %s", ins.id(), ins)) { ins.forEachState((liveStateOperand, mode, flags) -> { - Debug.log("operand=%s", liveStateOperand); + debug.log("operand=%s", liveStateOperand); return liveStateOperand; }); } @@ -426,9 +427,9 @@ } if (allocator.getBlockData(block).liveKill.get(operandNum)) { definedIn.add(block); - try (Indent indent3 = Debug.logAndIndent("defined in block B%d", block.getId())) { + try (Indent indent3 = debug.logAndIndent("defined in block B%d", block.getId())) { for (LIRInstruction ins : allocator.getLIR().getLIRforBlock(block)) { - Debug.log("%d: %s", ins.id(), ins); + debug.log("%d: %s", ins.id(), ins); } } } @@ -451,16 +452,16 @@ } } } - try (Indent indent3 = Debug.logAndIndent("**** offending usages are in: ")) { + try (Indent indent3 = debug.logAndIndent("**** offending usages are in: ")) { for (AbstractBlockBase block : usedIn) { - Debug.log("B%d", block.getId()); + debug.log("B%d", block.getId()); } } } } } } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } @@ -493,8 +494,8 @@ // Register use position at even instruction id. interval.addUsePos(to & ~1, registerPriority, detailedAsserts); - if (Debug.isLogEnabled()) { - Debug.log("add use: %s, from %d to %d (%s)", interval, from, to, registerPriority.name()); + if (debug.isLogEnabled()) { + debug.log("add use: %s, from %d to %d (%s)", interval, from, to, registerPriority.name()); } } @@ -512,8 +513,8 @@ interval.addUsePos(tempPos, registerPriority, detailedAsserts); interval.addMaterializationValue(null); - if (Debug.isLogEnabled()) { - Debug.log("add temp: %s tempPos %d (%s)", interval, tempPos, RegisterPriority.MustHaveRegister.name()); + if (debug.isLogEnabled()) { + debug.log("add temp: %s tempPos %d (%s)", interval, tempPos, RegisterPriority.MustHaveRegister.name()); } } @@ -543,8 +544,8 @@ */ interval.addRange(defPos, defPos + 1); interval.addUsePos(defPos, registerPriority, detailedAsserts); - if (Debug.isLogEnabled()) { - Debug.log("Warning: def of operand %s at %d occurs without use", operand, defPos); + if (debug.isLogEnabled()) { + debug.log("Warning: def of operand %s at %d occurs without use", operand, defPos); } } @@ -555,8 +556,8 @@ } interval.addMaterializationValue(getMaterializedValue(op, operand, interval)); - if (Debug.isLogEnabled()) { - Debug.log("add def: %s defPos %d (%s)", interval, defPos, registerPriority.name()); + if (debug.isLogEnabled()) { + debug.log("add def: %s defPos %d (%s)", interval, defPos, registerPriority.name()); } } @@ -574,8 +575,8 @@ assert allocator.blockForId(op.id()).getPredecessorCount() == 0 : "move from stack must be in first block"; assert isVariable(move.getResult()) : "result of move must be a variable"; - if (Debug.isLogEnabled()) { - Debug.log("found move from stack slot %s to %s", slot, move.getResult()); + if (debug.isLogEnabled()) { + debug.log("found move from stack slot %s to %s", slot, move.getResult()); } } @@ -600,8 +601,8 @@ } else { from.setLocationHint(to); } - if (Debug.isLogEnabled()) { - Debug.log("operation at opId %d: added hint from interval %d to %d", op.id(), from.operandNumber, to.operandNumber); + if (debug.isLogEnabled()) { + debug.log("operation at opId %d: added hint from interval %d to %d", op.id(), from.operandNumber, to.operandNumber); } return registerHint; @@ -685,7 +686,7 @@ @SuppressWarnings("try") protected void buildIntervals(boolean detailedAsserts) { - try (Indent indent = Debug.logAndIndent("build intervals")) { + try (Indent indent = debug.logAndIndent("build intervals")) { InstructionValueConsumer outputConsumer = (op, operand, mode, flags) -> { if (LinearScan.isVariableOrRegister(operand)) { addDef((AllocatableValue) operand, op, registerPriorityOfOutputOperand(op), operand.getValueKind(), detailedAsserts); @@ -735,7 +736,7 @@ for (int i = allocator.blockCount() - 1; i >= 0; i--) { AbstractBlockBase block = allocator.blockAt(i); - try (Indent indent2 = Debug.logAndIndent("handle block %d", block.getId())) { + try (Indent indent2 = debug.logAndIndent("handle block %d", block.getId())) { ArrayList instructions = allocator.getLIR().getLIRforBlock(block); final int blockFrom = allocator.getFirstLirInstructionId(block); @@ -749,8 +750,8 @@ for (int operandNum = live.nextSetBit(0); operandNum >= 0; operandNum = live.nextSetBit(operandNum + 1)) { assert live.get(operandNum) : "should not stop here otherwise"; AllocatableValue operand = allocator.intervalFor(operandNum).operand; - if (Debug.isLogEnabled()) { - Debug.log("live in %d: %s", operandNum, operand); + if (debug.isLogEnabled()) { + debug.log("live in %d: %s", operandNum, operand); } addUse(operand, blockFrom, blockTo + 2, RegisterPriority.None, LIRKind.Illegal, detailedAsserts); @@ -773,7 +774,7 @@ final LIRInstruction op = instructions.get(j); final int opId = op.id(); - try (Indent indent3 = Debug.logAndIndent("handle inst %d: %s", opId, op)) { + try (Indent indent3 = debug.logAndIndent("handle inst %d: %s", opId, op)) { // add a temp range for each register if operation destroys // caller-save registers @@ -783,8 +784,8 @@ addTemp(r.asValue(), opId, RegisterPriority.None, LIRKind.Illegal, detailedAsserts); } } - if (Debug.isLogEnabled()) { - Debug.log("operation destroys all caller-save registers"); + if (debug.isLogEnabled()) { + debug.log("operation destroys all caller-save registers"); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanOptimizeSpillPositionPhase.java 2017-07-07 09:30:41.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanOptimizeSpillPositionPhase.java 2017-07-07 09:30:40.000000000 -0700 @@ -29,8 +29,8 @@ import java.util.Iterator; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.LIRInsertionBuffer; import org.graalvm.compiler.lir.LIRInstruction; @@ -44,13 +44,15 @@ public final class LinearScanOptimizeSpillPositionPhase extends LinearScanAllocationPhase { - private static final DebugCounter betterSpillPos = Debug.counter("BetterSpillPosition"); - private static final DebugCounter betterSpillPosWithLowerProbability = Debug.counter("BetterSpillPositionWithLowerProbability"); + private static final CounterKey betterSpillPos = DebugContext.counter("BetterSpillPosition"); + private static final CounterKey betterSpillPosWithLowerProbability = DebugContext.counter("BetterSpillPositionWithLowerProbability"); private final LinearScan allocator; + private DebugContext debug; LinearScanOptimizeSpillPositionPhase(LinearScan allocator) { this.allocator = allocator; + this.debug = allocator.getDebug(); } @Override @@ -61,7 +63,7 @@ @SuppressWarnings("try") private void optimizeSpillPosition(LIRGenerationResult res) { - try (Indent indent0 = Debug.logAndIndent("OptimizeSpillPositions")) { + try (Indent indent0 = debug.logAndIndent("OptimizeSpillPositions")) { LIRInsertionBuffer[] insertionBuffers = new LIRInsertionBuffer[allocator.getLIR().linearScanOrder().length]; for (Interval interval : allocator.intervals()) { optimizeInterval(insertionBuffers, interval, res); @@ -83,7 +85,7 @@ AbstractBlockBase defBlock = allocator.blockForId(interval.spillDefinitionPos()); AbstractBlockBase spillBlock = null; Interval firstSpillChild = null; - try (Indent indent = Debug.logAndIndent("interval %s (%s)", interval, defBlock)) { + try (Indent indent = debug.logAndIndent("interval %s (%s)", interval, defBlock)) { for (Interval splitChild : interval.getSplitChildren()) { if (isStackSlotValue(splitChild.location())) { if (firstSpillChild == null || splitChild.from() < firstSpillChild.from()) { @@ -94,7 +96,7 @@ // iterate all blocks where the interval has use positions for (AbstractBlockBase splitBlock : blocksForInterval(splitChild)) { if (dominates(defBlock, splitBlock)) { - Debug.log("Split interval %s, block %s", splitChild, splitBlock); + debug.log("Split interval %s, block %s", splitChild, splitBlock); if (spillBlock == null) { spillBlock = splitBlock; } else { @@ -106,17 +108,17 @@ } } if (spillBlock == null) { - Debug.log("not spill interval found"); + debug.log("not spill interval found"); // no spill interval interval.setSpillState(SpillState.StoreAtDefinition); return; } - Debug.log(Debug.VERBOSE_LEVEL, "Spill block candidate (initial): %s", spillBlock); + debug.log(DebugContext.VERBOSE_LEVEL, "Spill block candidate (initial): %s", spillBlock); // move out of loops if (defBlock.getLoopDepth() < spillBlock.getLoopDepth()) { spillBlock = moveSpillOutOfLoop(defBlock, spillBlock); } - Debug.log(Debug.VERBOSE_LEVEL, "Spill block candidate (after loop optimizaton): %s", spillBlock); + debug.log(DebugContext.VERBOSE_LEVEL, "Spill block candidate (after loop optimizaton): %s", spillBlock); /* * The spill block is the begin of the first split child (aka the value is on the @@ -129,25 +131,25 @@ assert firstSpillChild != null; if (!defBlock.equals(spillBlock) && spillBlock.equals(allocator.blockForId(firstSpillChild.from()))) { AbstractBlockBase dom = spillBlock.getDominator(); - if (Debug.isLogEnabled()) { - Debug.log("Spill block (%s) is the beginning of a spill child -> use dominator (%s)", spillBlock, dom); + if (debug.isLogEnabled()) { + debug.log("Spill block (%s) is the beginning of a spill child -> use dominator (%s)", spillBlock, dom); } spillBlock = dom; } if (defBlock.equals(spillBlock)) { - Debug.log(Debug.VERBOSE_LEVEL, "Definition is the best choice: %s", defBlock); + debug.log(DebugContext.VERBOSE_LEVEL, "Definition is the best choice: %s", defBlock); // definition is the best choice interval.setSpillState(SpillState.StoreAtDefinition); return; } assert dominates(defBlock, spillBlock); - betterSpillPos.increment(); - if (Debug.isLogEnabled()) { - Debug.log("Better spill position found (Block %s)", spillBlock); + betterSpillPos.increment(debug); + if (debug.isLogEnabled()) { + debug.log("Better spill position found (Block %s)", spillBlock); } if (defBlock.probability() <= spillBlock.probability()) { - Debug.log(Debug.VERBOSE_LEVEL, "Definition has lower probability %s (%f) is lower than spill block %s (%f)", defBlock, defBlock.probability(), spillBlock, + debug.log(DebugContext.VERBOSE_LEVEL, "Definition has lower probability %s (%f) is lower than spill block %s (%f)", defBlock, defBlock.probability(), spillBlock, spillBlock.probability()); // better spill block has the same probability -> do nothing interval.setSpillState(SpillState.StoreAtDefinition); @@ -166,14 +168,14 @@ AllocatableValue toLocation = LinearScan.canonicalSpillOpr(interval); LIRInstruction move = allocator.getSpillMoveFactory().createMove(toLocation, fromLocation); move.setComment(res, "LSRAOptimizeSpillPos: optimize spill pos"); - Debug.log(Debug.VERBOSE_LEVEL, "Insert spill move %s", move); + debug.log(DebugContext.VERBOSE_LEVEL, "Insert spill move %s", move); move.setId(LinearScan.DOMINATOR_SPILL_MOVE_ID); /* * We can use the insertion buffer directly because we always insert at position 1. */ insertionBuffer.append(1, move); - betterSpillPosWithLowerProbability.increment(); + betterSpillPosWithLowerProbability.increment(debug); interval.setSpillDefinitionPos(spillOpId); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanRegisterAllocationPhase.java 2017-07-07 09:30:41.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanRegisterAllocationPhase.java 2017-07-07 09:30:41.000000000 -0700 @@ -22,7 +22,6 @@ */ package org.graalvm.compiler.lir.alloc.lsra; -import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.gen.LIRGenerationResult; import org.graalvm.compiler.lir.phases.AllocationPhase.AllocationContext; @@ -47,7 +46,7 @@ @SuppressWarnings("try") void allocateRegisters() { - try (Indent indent = Debug.logAndIndent("allocate registers")) { + try (Indent indent = allocator.getDebug().logAndIndent("allocate registers")) { Interval precoloredIntervals; Interval notPrecoloredIntervals; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanResolveDataFlowPhase.java 2017-07-07 09:30:42.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanResolveDataFlowPhase.java 2017-07-07 09:30:42.000000000 -0700 @@ -26,7 +26,7 @@ import java.util.BitSet; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.StandardOp; @@ -81,9 +81,10 @@ } void resolveFindInsertPos(AbstractBlockBase fromBlock, AbstractBlockBase toBlock, MoveResolver moveResolver) { + DebugContext debug = allocator.getDebug(); if (fromBlock.getSuccessorCount() <= 1) { - if (Debug.isLogEnabled()) { - Debug.log("inserting moves at end of fromBlock B%d", fromBlock.getId()); + if (debug.isLogEnabled()) { + debug.log("inserting moves at end of fromBlock B%d", fromBlock.getId()); } ArrayList instructions = allocator.getLIR().getLIRforBlock(fromBlock); @@ -96,8 +97,8 @@ } } else { - if (Debug.isLogEnabled()) { - Debug.log("inserting moves at beginning of toBlock B%d", toBlock.getId()); + if (debug.isLogEnabled()) { + debug.log("inserting moves at beginning of toBlock B%d", toBlock.getId()); } if (allocator.detailedAsserts) { @@ -123,7 +124,7 @@ */ @SuppressWarnings("try") protected void resolveDataFlow() { - try (Indent indent = Debug.logAndIndent("resolve data flow")) { + try (Indent indent = allocator.getDebug().logAndIndent("resolve data flow")) { MoveResolver moveResolver = allocator.createMoveResolver(); BitSet blockCompleted = new BitSet(allocator.blockCount()); @@ -151,8 +152,9 @@ // prevent optimization of two consecutive blocks if (!blockCompleted.get(pred.getLinearScanNumber()) && !blockCompleted.get(sux.getLinearScanNumber())) { - if (Debug.isLogEnabled()) { - Debug.log(" optimizing empty block B%d (pred: B%d, sux: B%d)", block.getId(), pred.getId(), sux.getId()); + DebugContext debug = allocator.getDebug(); + if (debug.isLogEnabled()) { + debug.log(" optimizing empty block B%d (pred: B%d, sux: B%d)", block.getId(), pred.getId(), sux.getId()); } blockCompleted.set(block.getLinearScanNumber()); @@ -186,8 +188,9 @@ * blocks). */ if (!alreadyResolved.get(toBlock.getLinearScanNumber())) { - if (Debug.isLogEnabled()) { - Debug.log("processing edge between B%d and B%d", fromBlock.getId(), toBlock.getId()); + DebugContext debug = allocator.getDebug(); + if (debug.isLogEnabled()) { + debug.log("processing edge between B%d and B%d", fromBlock.getId(), toBlock.getId()); } alreadyResolved.set(toBlock.getLinearScanNumber()); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanWalker.java 2017-07-07 09:30:42.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanWalker.java 2017-07-07 09:30:42.000000000 -0700 @@ -36,7 +36,7 @@ import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig.AllocatableRegisters; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; import org.graalvm.compiler.core.common.util.Util; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.LIRInstruction; @@ -323,11 +323,12 @@ } int findOptimalSplitPos(Interval interval, int minSplitPos, int maxSplitPos, boolean doLoopOptimization) { + DebugContext debug = allocator.getDebug(); int optimalSplitPos = -1; if (minSplitPos == maxSplitPos) { // trivial case, no optimization of split position possible - if (Debug.isLogEnabled()) { - Debug.log("min-pos and max-pos are equal, no optimization possible"); + if (debug.isLogEnabled()) { + debug.log("min-pos and max-pos are equal, no optimization possible"); } optimalSplitPos = minSplitPos; @@ -350,8 +351,8 @@ assert minBlock.getLinearScanNumber() <= maxBlock.getLinearScanNumber() : "invalid order"; if (minBlock == maxBlock) { // split position cannot be moved to block boundary : so split as late as possible - if (Debug.isLogEnabled()) { - Debug.log("cannot move split pos to block boundary because minPos and maxPos are in same block"); + if (debug.isLogEnabled()) { + debug.log("cannot move split pos to block boundary because minPos and maxPos are in same block"); } optimalSplitPos = maxSplitPos; @@ -362,15 +363,15 @@ // as mustHaveRegister) with a hole before each definition. When the register is // needed // for the second definition : an earlier reloading is unnecessary. - if (Debug.isLogEnabled()) { - Debug.log("interval has hole just before maxSplitPos, so splitting at maxSplitPos"); + if (debug.isLogEnabled()) { + debug.log("interval has hole just before maxSplitPos, so splitting at maxSplitPos"); } optimalSplitPos = maxSplitPos; } else { // seach optimal block boundary between minSplitPos and maxSplitPos - if (Debug.isLogEnabled()) { - Debug.log("moving split pos to optimal block boundary between block B%d and B%d", minBlock.getId(), maxBlock.getId()); + if (debug.isLogEnabled()) { + debug.log("moving split pos to optimal block boundary between block B%d and B%d", minBlock.getId(), maxBlock.getId()); } if (doLoopOptimization) { @@ -378,8 +379,8 @@ // max-position : // then split before this loop int loopEndPos = interval.nextUsageExact(RegisterPriority.LiveAtLoopEnd, allocator.getLastLirInstructionId(minBlock) + 2); - if (Debug.isLogEnabled()) { - Debug.log("loop optimization: loop end found at pos %d", loopEndPos); + if (debug.isLogEnabled()) { + debug.log("loop optimization: loop end found at pos %d", loopEndPos); } assert loopEndPos > minSplitPos : "invalid order"; @@ -393,8 +394,8 @@ // of the interval (normally, only mustHaveRegister causes a reloading) AbstractBlockBase loopBlock = allocator.blockForId(loopEndPos); - if (Debug.isLogEnabled()) { - Debug.log("interval is used in loop that ends in block B%d, so trying to move maxBlock back from B%d to B%d", loopBlock.getId(), maxBlock.getId(), loopBlock.getId()); + if (debug.isLogEnabled()) { + debug.log("interval is used in loop that ends in block B%d, so trying to move maxBlock back from B%d to B%d", loopBlock.getId(), maxBlock.getId(), loopBlock.getId()); } assert loopBlock != minBlock : "loopBlock and minBlock must be different because block boundary is needed between"; @@ -402,12 +403,12 @@ optimalSplitPos = findOptimalSplitPos(minBlock, loopBlock, maxSpillPos); if (optimalSplitPos == maxSpillPos) { optimalSplitPos = -1; - if (Debug.isLogEnabled()) { - Debug.log("loop optimization not necessary"); + if (debug.isLogEnabled()) { + debug.log("loop optimization not necessary"); } } else { - if (Debug.isLogEnabled()) { - Debug.log("loop optimization successful"); + if (debug.isLogEnabled()) { + debug.log("loop optimization successful"); } } } @@ -420,8 +421,8 @@ } } } - if (Debug.isLogEnabled()) { - Debug.log("optimal split position: %d", optimalSplitPos); + if (debug.isLogEnabled()) { + debug.log("optimal split position: %d", optimalSplitPos); } return optimalSplitPos; @@ -433,8 +434,8 @@ // 2) the right part is sorted into to the unhandled-list @SuppressWarnings("try") void splitBeforeUsage(Interval interval, int minSplitPos, int maxSplitPos) { - - try (Indent indent = Debug.logAndIndent("splitting interval %s between %d and %d", interval, minSplitPos, maxSplitPos)) { + DebugContext debug = allocator.getDebug(); + try (Indent indent = debug.logAndIndent("splitting interval %s between %d and %d", interval, minSplitPos, maxSplitPos)) { assert interval.from() < minSplitPos : "cannot split at start of interval"; assert currentPosition < minSplitPos : "cannot split before current position"; @@ -450,8 +451,8 @@ if (optimalSplitPos == interval.to() && interval.nextUsage(RegisterPriority.MustHaveRegister, minSplitPos) == Integer.MAX_VALUE) { // the split position would be just before the end of the interval // . no split at all necessary - if (Debug.isLogEnabled()) { - Debug.log("no split necessary because optimal split position is at end of interval"); + if (debug.isLogEnabled()) { + debug.log("no split necessary because optimal split position is at end of interval"); } return; } @@ -465,8 +466,8 @@ optimalSplitPos = (optimalSplitPos - 1) | 1; } - if (Debug.isLogEnabled()) { - Debug.log("splitting at position %d", optimalSplitPos); + if (debug.isLogEnabled()) { + debug.log("splitting at position %d", optimalSplitPos); } assert allocator.isBlockBegin(optimalSplitPos) || ((optimalSplitPos & 1) == 1) : "split pos must be odd when not on block boundary"; @@ -479,9 +480,9 @@ assert splitPart.from() >= currentPosition : "cannot append new interval before current walk position"; unhandledLists.addToListSortedByStartAndUsePositions(RegisterBinding.Any, splitPart); - if (Debug.isLogEnabled()) { - Debug.log("left interval %s: %s", moveNecessary ? " " : "", interval.logString(allocator)); - Debug.log("right interval %s: %s", moveNecessary ? "(move)" : "", splitPart.logString(allocator)); + if (debug.isLogEnabled()) { + debug.log("left interval %s: %s", moveNecessary ? " " : "", interval.logString(allocator)); + debug.log("right interval %s: %s", moveNecessary ? "(move)" : "", splitPart.logString(allocator)); } } } @@ -492,6 +493,7 @@ // 2) the right part is always on the stack and therefore ignored in further processing @SuppressWarnings("try") void splitForSpilling(Interval interval) { + DebugContext debug = allocator.getDebug(); // calculate allowed range of splitting position int maxSplitPos = currentPosition; int previousUsage = interval.previousUsage(RegisterPriority.ShouldHaveRegister, maxSplitPos); @@ -505,7 +507,7 @@ } int minSplitPos = Math.max(previousUsage + 1, interval.from()); - try (Indent indent = Debug.logAndIndent("splitting and spilling interval %s between %d and %d", interval, minSplitPos, maxSplitPos)) { + try (Indent indent = debug.logAndIndent("splitting and spilling interval %s between %d and %d", interval, minSplitPos, maxSplitPos)) { assert interval.state == State.Active : "why spill interval that is not active?"; assert interval.from() <= minSplitPos : "cannot split before start of interval"; @@ -516,7 +518,7 @@ if (minSplitPos == interval.from()) { // the whole interval is never used, so spill it entirely to memory - try (Indent indent2 = Debug.logAndIndent("spilling entire interval because split pos is at beginning of interval (use positions: %d)", interval.usePosList().size())) { + try (Indent indent2 = debug.logAndIndent("spilling entire interval because split pos is at beginning of interval (use positions: %d)", interval.usePosList().size())) { assert interval.firstUsage(RegisterPriority.MustHaveRegister) > currentPosition : String.format("interval %s must not have use position before currentPosition %d", interval, currentPosition); @@ -535,8 +537,8 @@ if (isRegister(parent.location())) { if (parent.firstUsage(RegisterPriority.ShouldHaveRegister) == Integer.MAX_VALUE) { // parent is never used, so kick it out of its assigned register - if (Debug.isLogEnabled()) { - Debug.log("kicking out interval %d out of its register because it is never used", parent.operandNumber); + if (debug.isLogEnabled()) { + debug.log("kicking out interval %d out of its register because it is never used", parent.operandNumber); } allocator.assignSpillSlot(parent); handleSpillSlot(parent); @@ -562,7 +564,7 @@ optimalSplitPos = (optimalSplitPos - 1) | 1; } - try (Indent indent2 = Debug.logAndIndent("splitting at position %d", optimalSplitPos)) { + try (Indent indent2 = debug.logAndIndent("splitting at position %d", optimalSplitPos)) { assert allocator.isBlockBegin(optimalSplitPos) || ((optimalSplitPos & 1) == 1) : "split pos must be odd when not on block boundary"; assert !allocator.isBlockBegin(optimalSplitPos) || ((optimalSplitPos & 1) == 0) : "split pos must be even on block boundary"; @@ -572,8 +574,8 @@ changeSpillState(spilledPart, optimalSplitPos); if (!allocator.isBlockBegin(optimalSplitPos)) { - if (Debug.isLogEnabled()) { - Debug.log("inserting move from interval %d to %d", interval.operandNumber, spilledPart.operandNumber); + if (debug.isLogEnabled()) { + debug.log("inserting move from interval %d to %d", interval.operandNumber, spilledPart.operandNumber); } insertMove(optimalSplitPos, interval, spilledPart); } @@ -582,9 +584,9 @@ assert spilledPart.currentSplitChild() == interval : "overwriting wrong currentSplitChild"; spilledPart.makeCurrentSplitChild(); - if (Debug.isLogEnabled()) { - Debug.log("left interval: %s", interval.logString(allocator)); - Debug.log("spilled interval : %s", spilledPart.logString(allocator)); + if (debug.isLogEnabled()) { + debug.log("left interval: %s", interval.logString(allocator)); + debug.log("spilled interval : %s", spilledPart.logString(allocator)); } } } @@ -697,7 +699,8 @@ @SuppressWarnings("try") boolean allocFreeRegister(Interval interval) { - try (Indent indent = Debug.logAndIndent("trying to find free register for %s", interval)) { + DebugContext debug = allocator.getDebug(); + try (Indent indent = debug.logAndIndent("trying to find free register for %s", interval)) { initUseLists(true); freeExcludeActiveFixed(); @@ -711,12 +714,12 @@ // (either as a fixed register or a normal allocated register in the past) // only intervals overlapping with cur are processed, non-overlapping invervals can be // ignored safely - if (Debug.isLogEnabled()) { + if (debug.isLogEnabled()) { // Enable this logging to see all register states - try (Indent indent2 = Debug.logAndIndent("state of registers:")) { + try (Indent indent2 = debug.logAndIndent("state of registers:")) { for (Register register : availableRegs) { int i = register.number; - Debug.log("reg %d: usePos: %d", register.number, usePos[i]); + debug.log("reg %d: usePos: %d", register.number, usePos[i]); } } } @@ -725,8 +728,8 @@ Interval locationHint = interval.locationHint(true); if (locationHint != null && locationHint.location() != null && isRegister(locationHint.location())) { hint = asRegister(locationHint.location()); - if (Debug.isLogEnabled()) { - Debug.log("hint register %d from interval %s", hint.number, locationHint); + if (debug.isLogEnabled()) { + debug.log("hint register %d from interval %s", hint.number, locationHint); } } assert interval.location() == null : "register already assigned to interval"; @@ -768,8 +771,8 @@ splitPos = usePos[reg.number]; interval.assignLocation(reg.asValue(interval.kind())); - if (Debug.isLogEnabled()) { - Debug.log("selected register %d", reg.number); + if (debug.isLogEnabled()) { + debug.log("selected register %d", reg.number); } assert splitPos > 0 : "invalid splitPos"; @@ -795,7 +798,8 @@ // Split an Interval and spill it to memory so that cur can be placed in a register @SuppressWarnings("try") void allocLockedRegister(Interval interval) { - try (Indent indent = Debug.logAndIndent("alloc locked register: need to split and spill to get register for %s", interval)) { + DebugContext debug = allocator.getDebug(); + try (Indent indent = debug.logAndIndent("alloc locked register: need to split and spill to get register for %s", interval)) { // the register must be free at least until this position int firstUsage = interval.firstUsage(RegisterPriority.MustHaveRegister); @@ -821,7 +825,7 @@ spillBlockInactiveFixed(interval); spillCollectActiveAny(registerPriority); spillCollectInactiveAny(interval); - if (Debug.isLogEnabled()) { + if (debug.isLogEnabled()) { printRegisterState(); } @@ -841,8 +845,8 @@ int regUsePos = (reg == null ? 0 : usePos[reg.number]); if (regUsePos <= firstShouldHaveUsage) { - if (Debug.isLogEnabled()) { - Debug.log("able to spill current interval. firstUsage(register): %d, usePos: %d", firstUsage, regUsePos); + if (debug.isLogEnabled()) { + debug.log("able to spill current interval. firstUsage(register): %d, usePos: %d", firstUsage, regUsePos); } if (firstUsage <= interval.from() + 1) { @@ -852,7 +856,7 @@ * to spill an active interval that has a usage but do not require a * register. */ - Debug.log("retry with register priority must have register"); + debug.log("retry with register priority must have register"); continue; } String description = generateOutOfRegErrorMsg(interval, firstUsage, availableRegs); @@ -861,7 +865,7 @@ * errors */ allocator.assignSpillSlot(interval); - Debug.dump(Debug.INFO_LEVEL, allocator.getLIR(), description); + debug.dump(DebugContext.INFO_LEVEL, allocator.getLIR(), description); allocator.printIntervals(description); throw new OutOfRegistersException("LinearScan: no register found", description); } @@ -876,8 +880,8 @@ int splitPos = blockPos[reg.number]; - if (Debug.isLogEnabled()) { - Debug.log("decided to use register %d", reg.number); + if (debug.isLogEnabled()) { + debug.log("decided to use register %d", reg.number); } assert splitPos > 0 : "invalid splitPos"; assert needSplit || splitPos > interval.from() : "splitting interval at from"; @@ -901,12 +905,13 @@ @SuppressWarnings("try") void printRegisterState() { - try (Indent indent2 = Debug.logAndIndent("state of registers:")) { + DebugContext debug = allocator.getDebug(); + try (Indent indent2 = debug.logAndIndent("state of registers:")) { for (Register reg : availableRegs) { int i = reg.number; - try (Indent indent3 = Debug.logAndIndent("reg %d: usePos: %d, blockPos: %d, intervals: ", i, usePos[i], blockPos[i])) { + try (Indent indent3 = debug.logAndIndent("reg %d: usePos: %d, blockPos: %d, intervals: ", i, usePos[i], blockPos[i])) { for (int j = 0; j < spillIntervals[i].size(); j++) { - Debug.log("%s ", spillIntervals[i].get(j)); + debug.log("%s ", spillIntervals[i].get(j)); } } } @@ -925,8 +930,9 @@ if (isOdd(pos)) { // the current instruction is a call that blocks all registers if (pos < allocator.maxOpId() && allocator.hasCall(pos + 1) && interval.to() > pos + 1) { - if (Debug.isLogEnabled()) { - Debug.log("free register cannot be available because all registers blocked by following call"); + DebugContext debug = allocator.getDebug(); + if (debug.isLogEnabled()) { + debug.log("free register cannot be available because all registers blocked by following call"); } // safety check that there is really no register available @@ -1019,16 +1025,16 @@ @SuppressWarnings("try") protected boolean activateCurrent(Interval interval) { boolean result = true; - - try (Indent indent = Debug.logAndIndent("activating interval %s, splitParent: %d", interval, interval.splitParent().operandNumber)) { + DebugContext debug = allocator.getDebug(); + try (Indent indent = debug.logAndIndent("activating interval %s, splitParent: %d", interval, interval.splitParent().operandNumber)) { final Value operand = interval.operand; if (interval.location() != null && isStackSlotValue(interval.location())) { // activating an interval that has a stack slot assigned . split it at first use // position // used for method parameters - if (Debug.isLogEnabled()) { - Debug.log("interval has spill slot assigned (method parameter) . split it before first use"); + if (debug.isLogEnabled()) { + debug.log("interval has spill slot assigned (method parameter) . split it before first use"); } splitStackInterval(interval); result = false; @@ -1037,8 +1043,8 @@ if (interval.location() == null) { // interval has not assigned register . normal allocation // (this is the normal case for most intervals) - if (Debug.isLogEnabled()) { - Debug.log("normal allocation of register"); + if (debug.isLogEnabled()) { + debug.log("normal allocation of register"); } // assign same spill slot to non-intersecting intervals @@ -1063,8 +1069,8 @@ assert interval.isSplitChild(); assert interval.currentSplitChild() != null; assert !interval.currentSplitChild().operand.equals(operand) : "cannot insert move between same interval"; - if (Debug.isLogEnabled()) { - Debug.log("Inserting move from interval %d to %d because insertMoveWhenActivated is set", interval.currentSplitChild().operandNumber, interval.operandNumber); + if (debug.isLogEnabled()) { + debug.log("Inserting move from interval %d to %d because insertMoveWhenActivated is set", interval.currentSplitChild().operandNumber, interval.operandNumber); } insertMove(interval.from(), interval.currentSplitChild(), interval); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/MoveResolver.java 2017-07-07 09:30:43.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/MoveResolver.java 2017-07-07 09:30:43.000000000 -0700 @@ -29,8 +29,8 @@ import java.util.ArrayList; import org.graalvm.compiler.core.common.LIRKind; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.LIRInsertionBuffer; @@ -39,7 +39,6 @@ import org.graalvm.compiler.lir.gen.LIRGenerationResult; import org.graalvm.util.Equivalence; import org.graalvm.util.EconomicSet; - import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.Value; @@ -48,7 +47,7 @@ */ public class MoveResolver { - private static final DebugCounter cycleBreakingSlotsAllocated = Debug.counter("LSRA[cycleBreakingSlotsAllocated]"); + private static final CounterKey cycleBreakingSlotsAllocated = DebugContext.counter("LSRA[cycleBreakingSlotsAllocated]"); private final LinearScan allocator; @@ -207,7 +206,7 @@ assert areMultipleReadsAllowed() || valueBlocked(location) == 0 : "location already marked as used: " + location; int direction = 1; setValueBlocked(location, direction); - Debug.log("block %s", location); + allocator.getDebug().log("block %s", location); } } @@ -217,7 +216,7 @@ if (mightBeBlocked(location)) { assert valueBlocked(location) > 0 : "location already marked as unused: " + location; setValueBlocked(location, -1); - Debug.log("unblock %s", location); + allocator.getDebug().log("unblock %s", location); } } @@ -276,8 +275,9 @@ LIRInstruction move = createMove(fromInterval.operand, toInterval.operand, fromInterval.location(), toInterval.location()); insertionBuffer.append(insertIdx, move); - if (Debug.isLogEnabled()) { - Debug.log("insert move from %s to %s at %d", fromInterval, toInterval, insertIdx); + DebugContext debug = allocator.getDebug(); + if (debug.isLogEnabled()) { + debug.log("insert move from %s to %s at %d", fromInterval, toInterval, insertIdx); } return move; } @@ -299,17 +299,19 @@ LIRInstruction move = getAllocator().getSpillMoveFactory().createLoad(toOpr, fromOpr); insertionBuffer.append(insertIdx, move); - if (Debug.isLogEnabled()) { - Debug.log("insert move from value %s to %s at %d", fromOpr, toInterval, insertIdx); + DebugContext debug = allocator.getDebug(); + if (debug.isLogEnabled()) { + debug.log("insert move from value %s to %s at %d", fromOpr, toInterval, insertIdx); } return move; } @SuppressWarnings("try") private void resolveMappings() { - try (Indent indent = Debug.logAndIndent("resolveMapping")) { + DebugContext debug = allocator.getDebug(); + try (Indent indent = debug.logAndIndent("resolveMapping")) { assert verifyBeforeResolve(); - if (Debug.isLogEnabled()) { + if (debug.isLogEnabled()) { printMapping(); } @@ -389,7 +391,7 @@ if (spillSlot == null) { spillSlot = getAllocator().getFrameMapBuilder().allocateSpillSlot(fromInterval.kind()); fromInterval.setSpillSlot(spillSlot); - cycleBreakingSlotsAllocated.increment(); + cycleBreakingSlotsAllocated.increment(allocator.getDebug()); } spillInterval(spillCandidate, fromInterval, spillSlot); } @@ -406,8 +408,9 @@ spillInterval.assignLocation(spillSlot); - if (Debug.isLogEnabled()) { - Debug.log("created new Interval for spilling: %s", spillInterval); + DebugContext debug = allocator.getDebug(); + if (debug.isLogEnabled()) { + debug.log("created new Interval for spilling: %s", spillInterval); } blockRegisters(spillInterval); @@ -420,7 +423,8 @@ @SuppressWarnings("try") private void printMapping() { - try (Indent indent = Debug.logAndIndent("Mapping")) { + DebugContext debug = allocator.getDebug(); + try (Indent indent = debug.logAndIndent("Mapping")) { for (int i = mappingFrom.size() - 1; i >= 0; i--) { Interval fromInterval = mappingFrom.get(i); Interval toInterval = mappingTo.get(i); @@ -431,7 +435,7 @@ } else { from = fromInterval.location().toString(); } - Debug.log("move %s <- %s", from, to); + debug.log("move %s <- %s", from, to); } } } @@ -460,10 +464,10 @@ } public void addMapping(Interval fromInterval, Interval toInterval) { - + DebugContext debug = allocator.getDebug(); if (isIllegal(toInterval.location()) && toInterval.canMaterialize()) { - if (Debug.isLogEnabled()) { - Debug.log("no store to rematerializable interval %s needed", toInterval); + if (debug.isLogEnabled()) { + debug.log("no store to rematerializable interval %s needed", toInterval); } return; } @@ -473,8 +477,8 @@ addMapping(rematValue, toInterval); return; } - if (Debug.isLogEnabled()) { - Debug.log("add move mapping from %s to %s", fromInterval, toInterval); + if (debug.isLogEnabled()) { + debug.log("add move mapping from %s to %s", fromInterval, toInterval); } assert !fromInterval.operand.equals(toInterval.operand) : "from and to interval equal: " + fromInterval; @@ -486,8 +490,9 @@ } public void addMapping(Constant fromOpr, Interval toInterval) { - if (Debug.isLogEnabled()) { - Debug.log("add move mapping from %s to %s", fromOpr, toInterval); + DebugContext debug = allocator.getDebug(); + if (debug.isLogEnabled()) { + debug.log("add move mapping from %s to %s", fromOpr, toInterval); } mappingFrom.add(null); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/OptimizingLinearScanWalker.java 2017-07-07 09:30:43.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/OptimizingLinearScanWalker.java 2017-07-07 09:30:43.000000000 -0700 @@ -22,21 +22,20 @@ */ package org.graalvm.compiler.lir.alloc.lsra; -import static org.graalvm.compiler.lir.LIRValueUtil.isStackSlotValue; import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.code.ValueUtil.isRegister; +import static org.graalvm.compiler.lir.LIRValueUtil.isStackSlotValue; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.alloc.lsra.Interval.RegisterBinding; import org.graalvm.compiler.lir.alloc.lsra.Interval.RegisterBindingLists; import org.graalvm.compiler.lir.alloc.lsra.Interval.RegisterPriority; import org.graalvm.compiler.lir.alloc.lsra.Interval.State; import org.graalvm.compiler.options.Option; -import org.graalvm.compiler.options.OptionType; import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionType; import jdk.vm.ci.code.Register; import jdk.vm.ci.meta.AllocatableValue; @@ -65,23 +64,24 @@ return; } assert isStackSlotValue(interval.location()) : "interval not assigned to a stack slot " + interval; - try (Scope s1 = Debug.scope("LSRAOptimization")) { - Debug.log("adding stack to unhandled list %s", interval); + DebugContext debug = allocator.getDebug(); + try (DebugContext.Scope s1 = debug.scope("LSRAOptimization")) { + debug.log("adding stack to unhandled list %s", interval); unhandledLists.addToListSortedByStartAndUsePositions(RegisterBinding.Stack, interval); } } @SuppressWarnings("unused") - private static void printRegisterBindingList(RegisterBindingLists list, RegisterBinding binding) { + private static void printRegisterBindingList(DebugContext debug, RegisterBindingLists list, RegisterBinding binding) { for (Interval interval = list.get(binding); !interval.isEndMarker(); interval = interval.next) { - Debug.log("%s", interval); + debug.log("%s", interval); } } @SuppressWarnings("try") @Override void walk() { - try (Scope s = Debug.scope("OptimizingLinearScanWalker")) { + try (DebugContext.Scope s = allocator.getDebug().scope("OptimizingLinearScanWalker")) { for (AbstractBlockBase block : allocator.sortedBlocks()) { optimizeBlock(block); } @@ -93,27 +93,28 @@ private void optimizeBlock(AbstractBlockBase block) { if (block.getPredecessorCount() == 1) { int nextBlock = allocator.getFirstLirInstructionId(block); - try (Scope s1 = Debug.scope("LSRAOptimization")) { - Debug.log("next block: %s (%d)", block, nextBlock); + DebugContext debug = allocator.getDebug(); + try (DebugContext.Scope s1 = debug.scope("LSRAOptimization")) { + debug.log("next block: %s (%d)", block, nextBlock); } - try (Indent indent0 = Debug.indent()) { + try (Indent indent0 = debug.indent()) { walkTo(nextBlock); - try (Scope s1 = Debug.scope("LSRAOptimization")) { + try (DebugContext.Scope s1 = debug.scope("LSRAOptimization")) { boolean changed = true; // we need to do this because the active lists might change loop: while (changed) { changed = false; - try (Indent indent1 = Debug.logAndIndent("Active intervals: (block %s [%d])", block, nextBlock)) { + try (Indent indent1 = debug.logAndIndent("Active intervals: (block %s [%d])", block, nextBlock)) { for (Interval active = activeLists.get(RegisterBinding.Any); !active.isEndMarker(); active = active.next) { - Debug.log("active (any): %s", active); + debug.log("active (any): %s", active); if (optimize(nextBlock, block, active, RegisterBinding.Any)) { changed = true; break loop; } } for (Interval active = activeLists.get(RegisterBinding.Stack); !active.isEndMarker(); active = active.next) { - Debug.log("active (stack): %s", active); + debug.log("active (stack): %s", active); if (optimize(nextBlock, block, active, RegisterBinding.Stack)) { changed = true; break loop; @@ -171,9 +172,10 @@ assert isStackSlotValue(currentLocation) || isRegister(currentLocation) : "current location not a register or stack slot " + currentLocation; - try (Indent indent = Debug.logAndIndent("location differs: %s vs. %s", predecessorLocation, currentLocation)) { + DebugContext debug = allocator.getDebug(); + try (Indent indent = debug.logAndIndent("location differs: %s vs. %s", predecessorLocation, currentLocation)) { // split current interval at current position - Debug.log("splitting at position %d", currentPos); + debug.log("splitting at position %d", currentPos); assert allocator.isBlockBegin(currentPos) && ((currentPos & 1) == 0) : "split pos must be even when on block boundary"; @@ -186,9 +188,9 @@ assert splitPart.currentSplitChild() == currentInterval : "overwriting wrong currentSplitChild"; splitPart.makeCurrentSplitChild(); - if (Debug.isLogEnabled()) { - Debug.log("left interval : %s", currentInterval.logString(allocator)); - Debug.log("right interval : %s", splitPart.logString(allocator)); + if (debug.isLogEnabled()) { + debug.log("left interval : %s", currentInterval.logString(allocator)); + debug.log("right interval : %s", splitPart.logString(allocator)); } if (Options.LSRAOptSplitOnly.getValue(allocator.getOptions())) { @@ -199,7 +201,7 @@ splitRegisterInterval(splitPart, asRegister(predecessorLocation)); } else { assert isStackSlotValue(predecessorLocation); - Debug.log("assigning interval %s to %s", splitPart, predecessorLocation); + debug.log("assigning interval %s to %s", splitPart, predecessorLocation); splitPart.assignLocation(predecessorLocation); // activate interval activeLists.addToListSortedByCurrentFromPositions(RegisterBinding.Stack, splitPart); @@ -224,13 +226,14 @@ spillCollectActiveAny(RegisterPriority.LiveAtLoopEnd); spillCollectInactiveAny(interval); - if (Debug.isLogEnabled()) { - try (Indent indent2 = Debug.logAndIndent("state of registers:")) { + DebugContext debug = allocator.getDebug(); + if (debug.isLogEnabled()) { + try (Indent indent2 = debug.logAndIndent("state of registers:")) { for (Register register : availableRegs) { int i = register.number; - try (Indent indent3 = Debug.logAndIndent("reg %d: usePos: %d, blockPos: %d, intervals: ", i, usePos[i], blockPos[i])) { + try (Indent indent3 = debug.logAndIndent("reg %d: usePos: %d, blockPos: %d, intervals: ", i, usePos[i], blockPos[i])) { for (int j = 0; j < spillIntervals[i].size(); j++) { - Debug.log("%d ", spillIntervals[i].get(j).operandNumber); + debug.log("%d ", spillIntervals[i].get(j).operandNumber); } } } @@ -245,7 +248,7 @@ assert splitPos > 0 : "invalid splitPos"; assert needSplit || splitPos > interval.from() : "splitting interval at from"; - Debug.log("assigning interval %s to %s", interval, reg); + debug.log("assigning interval %s to %s", interval, reg); interval.assignLocation(reg.asValue(interval.kind())); if (needSplit) { // register not available for full interval : so split it --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/RegisterVerifier.java 2017-07-07 09:30:44.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/RegisterVerifier.java 2017-07-07 09:30:44.000000000 -0700 @@ -30,8 +30,7 @@ import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; import org.graalvm.compiler.core.common.cfg.BlockMap; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.InstructionValueConsumer; @@ -84,7 +83,8 @@ @SuppressWarnings("try") void verify(AbstractBlockBase start) { - try (Scope s = Debug.scope("RegisterVerifier")) { + DebugContext debug = allocator.getDebug(); + try (DebugContext.Scope s = debug.scope("RegisterVerifier")) { // setup input registers (method arguments) for first block Interval[] inputState = new Interval[stateSize()]; setStateForBlock(start, inputState); @@ -102,18 +102,19 @@ @SuppressWarnings("try") private void processBlock(AbstractBlockBase block) { - try (Indent indent = Debug.logAndIndent("processBlock B%d", block.getId())) { + DebugContext debug = allocator.getDebug(); + try (Indent indent = debug.logAndIndent("processBlock B%d", block.getId())) { // must copy state because it is modified Interval[] inputState = copy(stateForBlock(block)); - try (Indent indent2 = Debug.logAndIndent("Input-State of intervals:")) { + try (Indent indent2 = debug.logAndIndent("Input-State of intervals:")) { printState(inputState); } // process all operations of the block processOperations(block, inputState); - try (Indent indent2 = Debug.logAndIndent("Output-State of intervals:")) { + try (Indent indent2 = debug.logAndIndent("Output-State of intervals:")) { printState(inputState); } @@ -125,18 +126,20 @@ } protected void printState(Interval[] inputState) { + DebugContext debug = allocator.getDebug(); for (int i = 0; i < stateSize(); i++) { Register reg = allocator.getRegisters().get(i); assert reg.number == i; if (inputState[i] != null) { - Debug.log(" %6s %4d -- %s", reg, inputState[i].operandNumber, inputState[i]); + debug.log(" %6s %4d -- %s", reg, inputState[i].operandNumber, inputState[i]); } else { - Debug.log(" %6s __", reg); + debug.log(" %6s __", reg); } } } private void processSuccessor(AbstractBlockBase block, Interval[] inputState) { + DebugContext debug = allocator.getDebug(); Interval[] savedState = stateForBlock(block); if (savedState != null) { @@ -155,23 +158,23 @@ savedStateCorrect = false; savedState[i] = null; - Debug.log("processSuccessor B%d: invalidating slot %d", block.getId(), i); + debug.log("processSuccessor B%d: invalidating slot %d", block.getId(), i); } } } if (savedStateCorrect) { // already processed block with correct inputState - Debug.log("processSuccessor B%d: previous visit already correct", block.getId()); + debug.log("processSuccessor B%d: previous visit already correct", block.getId()); } else { // must re-visit this block - Debug.log("processSuccessor B%d: must re-visit because input state changed", block.getId()); + debug.log("processSuccessor B%d: must re-visit because input state changed", block.getId()); addToWorkList(block); } } else { // block was not processed before, so set initial inputState - Debug.log("processSuccessor B%d: initial visit", block.getId()); + debug.log("processSuccessor B%d: initial visit", block.getId()); setStateForBlock(block, copy(inputState)); addToWorkList(block); @@ -182,14 +185,14 @@ return inputState.clone(); } - static void statePut(Interval[] inputState, Value location, Interval interval) { + static void statePut(DebugContext debug, Interval[] inputState, Value location, Interval interval) { if (location != null && isRegister(location)) { Register reg = asRegister(location); int regNum = reg.number; if (interval != null) { - Debug.log("%s = %s", reg, interval.operand); + debug.log("%s = %s", reg, interval.operand); } else if (inputState[regNum] != null) { - Debug.log("%s = null", reg); + debug.log("%s = null", reg); } inputState[regNum] = interval; @@ -209,6 +212,7 @@ void processOperations(AbstractBlockBase block, final Interval[] inputState) { ArrayList ops = allocator.getLIR().getLIRforBlock(block); + DebugContext debug = allocator.getDebug(); InstructionValueConsumer useConsumer = new InstructionValueConsumer() { @Override @@ -232,7 +236,7 @@ interval = interval.getSplitChildAtOpId(op.id(), mode, allocator); } - statePut(inputState, interval.location(), interval.splitParent()); + statePut(debug, inputState, interval.location(), interval.splitParent()); } }; @@ -240,8 +244,8 @@ for (int i = 0; i < ops.size(); i++) { final LIRInstruction op = ops.get(i); - if (Debug.isLogEnabled()) { - Debug.log("%s", op.toStringWithIdPrefix()); + if (debug.isLogEnabled()) { + debug.log("%s", op.toStringWithIdPrefix()); } // check if input operands are correct @@ -249,7 +253,7 @@ // invalidate all caller save registers at calls if (op.destroysCallerSavedRegisters()) { for (Register r : allocator.getRegisterAllocationConfig().getRegisterConfig().getCallerSaveRegisters()) { - statePut(inputState, r.asValue(), null); + statePut(debug, inputState, r.asValue(), null); } } op.visitEachAlive(useConsumer); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/ssa/SSALinearScan.java 2017-07-07 09:30:45.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/ssa/SSALinearScan.java 2017-07-07 09:30:45.000000000 -0700 @@ -24,8 +24,7 @@ import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.lir.alloc.lsra.LinearScan; import org.graalvm.compiler.lir.alloc.lsra.LinearScanEliminateSpillMovePhase; import org.graalvm.compiler.lir.alloc.lsra.LinearScanLifetimeAnalysisPhase; @@ -73,7 +72,7 @@ * PHI Ins are needed for the RegisterVerifier, otherwise PHIs where the Out and In value * matches (ie. there is no resolution move) are falsely detected as errors. */ - try (Scope s1 = Debug.scope("Remove Phi In")) { + try (DebugContext.Scope s1 = debug.scope("Remove Phi In")) { for (AbstractBlockBase toBlock : sortedBlocks()) { if (toBlock.getPredecessorCount() > 1) { SSAUtil.removePhiIn(getLIR(), toBlock); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/ssa/SSALinearScanEliminateSpillMovePhase.java 2017-07-07 09:30:45.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/ssa/SSALinearScanEliminateSpillMovePhase.java 2017-07-07 09:30:45.000000000 -0700 @@ -22,11 +22,11 @@ */ package org.graalvm.compiler.lir.alloc.lsra.ssa; -import static org.graalvm.compiler.lir.LIRValueUtil.isStackSlotValue; import static jdk.vm.ci.code.ValueUtil.isRegister; +import static org.graalvm.compiler.lir.LIRValueUtil.isStackSlotValue; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.StandardOp.LabelOp; @@ -82,8 +82,9 @@ if (!block.getSuccessors()[0].equals(intStartBlock)) { return false; } - try (Indent indet = Debug.indent()) { - Debug.log("Is a move (%s) to phi interval %s", move, toInterval); + DebugContext debug = allocator.getDebug(); + try (Indent indent = debug.indent()) { + debug.log("Is a move (%s) to phi interval %s", move, toInterval); } return true; } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/ssa/SSALinearScanLifetimeAnalysisPhase.java 2017-07-07 09:30:46.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/ssa/SSALinearScanLifetimeAnalysisPhase.java 2017-07-07 09:30:46.000000000 -0700 @@ -24,7 +24,7 @@ import java.util.EnumSet; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.LIRInstruction.OperandFlag; import org.graalvm.compiler.lir.LIRInstruction.OperandMode; @@ -58,14 +58,14 @@ if (LinearScan.isVariableOrRegister(registerHint)) { Interval from = allocator.getOrCreateInterval((AllocatableValue) registerHint); - setHint(op, to, from); - setHint(op, from, to); + setHint(debug, op, to, from); + setHint(debug, op, from, to); } }); } } - public static void setHint(final LIRInstruction op, Interval target, Interval source) { + public static void setHint(DebugContext debug, final LIRInstruction op, Interval target, Interval source) { Interval currentHint = target.locationHint(false); if (currentHint == null || currentHint.from() > target.from()) { /* @@ -73,8 +73,8 @@ * interval. */ target.setLocationHint(source); - if (Debug.isLogEnabled()) { - Debug.log("operation at opId %d: added hint from interval %d to %d", op.id(), source.operandNumber, target.operandNumber); + if (debug.isLogEnabled()) { + debug.log("operation at opId %d: added hint from interval %d to %d", op.id(), source.operandNumber, target.operandNumber); } } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/ssa/SSALinearScanResolveDataFlowPhase.java 2017-07-07 09:30:47.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/ssa/SSALinearScanResolveDataFlowPhase.java 2017-07-07 09:30:47.000000000 -0700 @@ -30,8 +30,8 @@ import java.util.ArrayList; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.alloc.lsra.Interval; import org.graalvm.compiler.lir.alloc.lsra.LinearScan; @@ -44,8 +44,8 @@ class SSALinearScanResolveDataFlowPhase extends LinearScanResolveDataFlowPhase { - private static final DebugCounter numPhiResolutionMoves = Debug.counter("SSA LSRA[numPhiResolutionMoves]"); - private static final DebugCounter numStackToStackMoves = Debug.counter("SSA LSRA[numStackToStackMoves]"); + private static final CounterKey numPhiResolutionMoves = DebugContext.counter("SSA LSRA[numPhiResolutionMoves]"); + private static final CounterKey numStackToStackMoves = DebugContext.counter("SSA LSRA[numStackToStackMoves]"); SSALinearScanResolveDataFlowPhase(LinearScan allocator) { super(allocator); @@ -72,17 +72,18 @@ assert !isRegister(phiOut) : "phiOut is a register: " + phiOut; assert !isRegister(phiIn) : "phiIn is a register: " + phiIn; Interval toInterval = allocator.splitChildAtOpId(allocator.intervalFor(phiIn), toBlockFirstInstructionId, LIRInstruction.OperandMode.DEF); + DebugContext debug = allocator.getDebug(); if (isConstantValue(phiOut)) { - numPhiResolutionMoves.increment(); + numPhiResolutionMoves.increment(debug); moveResolver.addMapping(asConstant(phiOut), toInterval); } else { Interval fromInterval = allocator.splitChildAtOpId(allocator.intervalFor(phiOut), phiOutId, LIRInstruction.OperandMode.DEF); if (fromInterval != toInterval && !fromInterval.location().equals(toInterval.location())) { - numPhiResolutionMoves.increment(); + numPhiResolutionMoves.increment(debug); if (!(isStackSlotValue(toInterval.location()) && isStackSlotValue(fromInterval.location()))) { moveResolver.addMapping(fromInterval, toInterval); } else { - numStackToStackMoves.increment(); + numStackToStackMoves.increment(debug); moveResolver.addMapping(fromInterval, toInterval); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/DefaultTraceRegisterAllocationPolicy.java 2017-07-07 09:30:47.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/DefaultTraceRegisterAllocationPolicy.java 2017-07-07 09:30:47.000000000 -0700 @@ -43,6 +43,7 @@ import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.common.JVMCIError; import jdk.vm.ci.meta.AllocatableValue; +import jdk.vm.ci.meta.PlatformKind; /** * Manages the selection of allocation strategies. @@ -52,15 +53,32 @@ public enum TraceRAPolicies { Default, LinearScanOnly, - BottomUpOnly + BottomUpOnly, + AlmostTrivial, + NumVariables, + Ratio, + Loops, + MaxFreq, + FreqBudget, + LoopRatio, + LoopBudget, + LoopMaxFreq } public static class Options { // @formatter:off @Option(help = "Use special allocator for trivial blocks.", type = OptionType.Debug) public static final OptionKey TraceRAtrivialBlockAllocator = new OptionKey<>(true); + @Option(help = "Use BottomUp if there is only one block with at most this number of instructions", type = OptionType.Debug) + public static final OptionKey TraceRAalmostTrivialSize = new OptionKey<>(2); + @Option(help = "Use BottomUp for traces with low number of variables at block boundaries", type = OptionType.Debug) + public static final OptionKey TraceRAnumVariables = new OptionKey<>(null); @Option(help = "Use LSRA / BottomUp ratio", type = OptionType.Debug) public static final OptionKey TraceRAbottomUpRatio = new OptionKey<>(0.0); + @Option(help = "Probability Threshold", type = OptionType.Debug) + public static final OptionKey TraceRAprobalilityThreshold = new OptionKey<>(0.8); + @Option(help = "Sum Probability Budget Threshold", type = OptionType.Debug) + public static final OptionKey TraceRAsumBudget = new OptionKey<>(0.5); @Option(help = "TraceRA allocation policy to use.", type = OptionType.Debug) public static final EnumOptionKey TraceRAPolicy = new EnumOptionKey<>(TraceRAPolicies.Default); // @formatter:on @@ -117,6 +135,216 @@ } } + public static final class BottomUpAlmostTrivialStrategy extends BottomUpStrategy { + + private final int trivialTraceSize; + + public BottomUpAlmostTrivialStrategy(TraceRegisterAllocationPolicy plan) { + // explicitly specify the enclosing instance for the superclass constructor call + super(plan); + trivialTraceSize = Options.TraceRAalmostTrivialSize.getValue(plan.getOptions()); + } + + @Override + public boolean shouldApplyTo(Trace trace) { + if (!super.shouldApplyTo(trace)) { + return false; + } + if (trace.size() != 1) { + return false; + } + return getLIR().getLIRforBlock(trace.getBlocks()[0]).size() <= trivialTraceSize; + } + + } + + public static final class BottomUpNumVariablesStrategy extends BottomUpStrategy { + + private final int numVarLimit; + + public BottomUpNumVariablesStrategy(TraceRegisterAllocationPolicy plan) { + // explicitly specify the enclosing instance for the superclass constructor call + super(plan); + Integer value = Options.TraceRAnumVariables.getValue(plan.getOptions()); + if (value != null) { + numVarLimit = value; + } else { + /* Default to the number of allocatable word registers. */ + PlatformKind wordKind = getTarget().arch.getWordKind(); + int numWordRegisters = getRegisterAllocationConfig().getAllocatableRegisters(wordKind).allocatableRegisters.length; + numVarLimit = numWordRegisters; + } + } + + @Override + public boolean shouldApplyTo(Trace trace) { + if (!super.shouldApplyTo(trace)) { + return false; + } + GlobalLivenessInfo livenessInfo = getGlobalLivenessInfo(); + int maxNumVars = livenessInfo.getBlockIn(trace.getBlocks()[0]).length; + for (AbstractBlockBase block : trace.getBlocks()) { + maxNumVars = Math.max(maxNumVars, livenessInfo.getBlockOut(block).length); + } + return maxNumVars <= numVarLimit; + } + + } + + public static final class BottomUpRatioStrategy extends BottomUpStrategy { + + private final double ratio; + + public BottomUpRatioStrategy(TraceRegisterAllocationPolicy plan) { + // explicitly specify the enclosing instance for the superclass constructor call + super(plan); + ratio = Options.TraceRAbottomUpRatio.getValue(plan.getOptions()); + } + + @Override + public boolean shouldApplyTo(Trace trace) { + if (!super.shouldApplyTo(trace)) { + return false; + } + double numTraces = getTraceBuilderResult().getTraces().size(); + double traceId = trace.getId(); + assert ratio >= 0 && ratio <= 1.0 : "Ratio out of range: " + ratio; + return (traceId / numTraces) >= ratio; + } + + } + + public abstract static class BottomUpLoopStrategyBase extends BottomUpStrategy { + + public BottomUpLoopStrategyBase(TraceRegisterAllocationPolicy plan) { + // explicitly specify the enclosing instance for the superclass constructor call + super(plan); + } + + @Override + public final boolean shouldApplyTo(Trace trace) { + if (!super.shouldApplyTo(trace)) { + return false; + } + if (getLIR().getControlFlowGraph().getLoops().isEmpty()) { + return shouldApplyToNoLoop(trace); + } + for (AbstractBlockBase block : trace.getBlocks()) { + if (block.getLoopDepth() > 0) { + return false; + } + } + return true; + } + + protected abstract boolean shouldApplyToNoLoop(Trace trace); + + } + + public static final class BottomUpLoopStrategy extends BottomUpLoopStrategyBase { + + public BottomUpLoopStrategy(TraceRegisterAllocationPolicy plan) { + // explicitly specify the enclosing instance for the superclass constructor call + super(plan); + } + + @Override + protected boolean shouldApplyToNoLoop(Trace trace) { + // no loops at all -> use LSRA + return false; + } + + } + + public static final class BottomUpDelegatingLoopStrategy extends BottomUpLoopStrategyBase { + + private final BottomUpStrategy delegate; + + public BottomUpDelegatingLoopStrategy(TraceRegisterAllocationPolicy plan, BottomUpStrategy delegate) { + // explicitly specify the enclosing instance for the superclass constructor call + super(plan); + this.delegate = delegate; + } + + @Override + protected boolean shouldApplyToNoLoop(Trace trace) { + return delegate.shouldApplyTo(trace); + } + + } + + public static final class BottomUpMaxFrequencyStrategy extends BottomUpStrategy { + + private final double maxMethodProbability; + private final double probabilityThreshold; + + public BottomUpMaxFrequencyStrategy(TraceRegisterAllocationPolicy plan) { + // explicitly specify the enclosing instance for the superclass constructor call + super(plan); + maxMethodProbability = maxProbability(getLIR().getControlFlowGraph().getBlocks()); + probabilityThreshold = Options.TraceRAprobalilityThreshold.getValue(plan.getOptions()); + } + + private static double maxProbability(AbstractBlockBase[] blocks) { + double max = 0; + for (AbstractBlockBase block : blocks) { + double probability = block.probability(); + if (probability > max) { + max = probability; + } + } + return max; + } + + @Override + public boolean shouldApplyTo(Trace trace) { + if (!super.shouldApplyTo(trace)) { + return false; + } + return maxProbability(trace.getBlocks()) / maxMethodProbability <= probabilityThreshold; + } + + } + + public static final class BottomUpFrequencyBudgetStrategy extends BottomUpStrategy { + + private final double[] cumulativeTraceProbability; + private final double budget; + + public BottomUpFrequencyBudgetStrategy(TraceRegisterAllocationPolicy plan) { + // explicitly specify the enclosing instance for the superclass constructor call + super(plan); + ArrayList traces = getTraceBuilderResult().getTraces(); + this.cumulativeTraceProbability = new double[traces.size()]; + double sumMethodProbability = init(traces, this.cumulativeTraceProbability); + this.budget = sumMethodProbability * Options.TraceRAsumBudget.getValue(plan.getOptions()); + } + + private static double init(ArrayList traces, double[] sumTraces) { + double sumMethod = 0; + for (Trace trace : traces) { + double traceSum = 0; + for (AbstractBlockBase block : trace.getBlocks()) { + traceSum += block.probability(); + } + sumMethod += traceSum; + // store cumulative sum for trace + sumTraces[trace.getId()] = sumMethod; + } + return sumMethod; + } + + @Override + public boolean shouldApplyTo(Trace trace) { + if (!super.shouldApplyTo(trace)) { + return false; + } + double cumTraceProb = cumulativeTraceProbability[trace.getId()]; + return cumTraceProb > budget; + } + + } + public static final class TraceLinearScanStrategy extends AllocationStrategy { public TraceLinearScanStrategy(TraceRegisterAllocationPolicy plan) { @@ -135,6 +363,7 @@ GlobalLivenessInfo livenessInfo, ArrayList strategies) { return new TraceLinearScanPhase(target, lirGenRes, spillMoveFactory, registerAllocationConfig, resultTraces, neverSpillConstant, cachedStackSlots, livenessInfo); } + } public static TraceRegisterAllocationPolicy allocationPolicy(TargetDescription target, LIRGenerationResult lirGenRes, MoveFactory spillMoveFactory, @@ -148,16 +377,42 @@ switch (Options.TraceRAPolicy.getValue(options)) { case Default: case LinearScanOnly: - plan.appendStrategy(new TraceLinearScanStrategy(plan)); break; case BottomUpOnly: plan.appendStrategy(new BottomUpStrategy(plan)); - // Fallback - plan.appendStrategy(new TraceLinearScanStrategy(plan)); + break; + case AlmostTrivial: + plan.appendStrategy(new BottomUpAlmostTrivialStrategy(plan)); + break; + case NumVariables: + plan.appendStrategy(new BottomUpNumVariablesStrategy(plan)); + break; + case Ratio: + plan.appendStrategy(new BottomUpRatioStrategy(plan)); + break; + case Loops: + plan.appendStrategy(new BottomUpLoopStrategy(plan)); + break; + case MaxFreq: + plan.appendStrategy(new BottomUpMaxFrequencyStrategy(plan)); + break; + case FreqBudget: + plan.appendStrategy(new BottomUpFrequencyBudgetStrategy(plan)); + break; + case LoopRatio: + plan.appendStrategy(new BottomUpDelegatingLoopStrategy(plan, new BottomUpRatioStrategy(plan))); + break; + case LoopMaxFreq: + plan.appendStrategy(new BottomUpDelegatingLoopStrategy(plan, new BottomUpMaxFrequencyStrategy(plan))); + break; + case LoopBudget: + plan.appendStrategy(new BottomUpDelegatingLoopStrategy(plan, new BottomUpFrequencyBudgetStrategy(plan))); break; default: throw JVMCIError.shouldNotReachHere(); } + // Fallback + plan.appendStrategy(new TraceLinearScanStrategy(plan)); return plan; } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/GlobalLivenessAnalysisPhase.java 2017-07-07 09:30:48.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/GlobalLivenessAnalysisPhase.java 2017-07-07 09:30:48.000000000 -0700 @@ -31,7 +31,7 @@ import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; import org.graalvm.compiler.core.common.cfg.Loop; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.InstructionValueConsumer; @@ -65,7 +65,7 @@ private final class Analyser { - private static final int LOG_LEVEL = Debug.INFO_LEVEL; + private static final int LOG_LEVEL = DebugContext.INFO_LEVEL; /** * Bit map specifying which operands are live upon entry to this block. These are values @@ -140,9 +140,10 @@ @SuppressWarnings("try") private void computeLiveness() { // iterate all blocks + DebugContext debug = lir.getDebug(); for (int i = blocks.length - 1; i >= 0; i--) { final AbstractBlockBase block = blocks[i]; - try (Indent indent = Debug.logAndIndent(LOG_LEVEL, "compute local live sets for block %s", block)) { + try (Indent indent = debug.logAndIndent(LOG_LEVEL, "compute local live sets for block %s", block)) { final BitSet liveIn = mergeLiveSets(block); setLiveOut(block, (BitSet) liveIn.clone()); @@ -159,8 +160,8 @@ processDef(liveIn, op, operand); } }; - if (Debug.isLogEnabled()) { - Debug.log(LOG_LEVEL, "liveOut B%d %s", block.getId(), getLiveOut(block)); + if (debug.isLogEnabled()) { + debug.log(LOG_LEVEL, "liveOut B%d %s", block.getId(), getLiveOut(block)); } // iterate all instructions of the block @@ -168,7 +169,7 @@ for (int j = instructions.size() - 1; j >= 0; j--) { final LIRInstruction op = instructions.get(j); - try (Indent indent2 = Debug.logAndIndent(LOG_LEVEL, "handle op %d: %s", op.id(), op)) { + try (Indent indent2 = debug.logAndIndent(LOG_LEVEL, "handle op %d: %s", op.id(), op)) { op.visitEachOutput(defConsumer); op.visitEachTemp(defConsumer); op.visitEachState(useConsumer); @@ -182,8 +183,8 @@ handleLoopHeader(block.getLoop(), liveIn); } - if (Debug.isLogEnabled()) { - Debug.log(LOG_LEVEL, "liveIn B%d %s", block.getId(), getLiveIn(block)); + if (debug.isLogEnabled()) { + debug.log(LOG_LEVEL, "liveIn B%d %s", block.getId(), getLiveIn(block)); } } @@ -218,8 +219,9 @@ if (isVariable(operand)) { int operandNum = operandNumber(operand); liveGen.set(operandNum); - if (Debug.isLogEnabled()) { - Debug.log(LOG_LEVEL, "liveGen for operand %d(%s)", operandNum, operand); + DebugContext debug = lir.getDebug(); + if (debug.isLogEnabled()) { + debug.log(LOG_LEVEL, "liveGen for operand %d(%s)", operandNum, operand); } } } @@ -232,8 +234,9 @@ operands[operandNum] = operand; } liveGen.clear(operandNum); - if (Debug.isLogEnabled()) { - Debug.log(LOG_LEVEL, "liveKill for operand %d(%s)", operandNum, operand); + DebugContext debug = lir.getDebug(); + if (debug.isLogEnabled()) { + debug.log(LOG_LEVEL, "liveKill for operand %d(%s)", operandNum, operand); } } } @@ -256,7 +259,7 @@ public void finish() { // iterate all blocks in reverse order for (AbstractBlockBase block : (AbstractBlockBase[]) lir.getControlFlowGraph().getBlocks()) { - try (Indent indent = Debug.logAndIndent(LOG_LEVEL, "Finish Block %s", block)) { + try (Indent indent = lir.getDebug().logAndIndent(LOG_LEVEL, "Finish Block %s", block)) { buildIncoming(block); buildOutgoing(block); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/GlobalLivenessInfo.java 2017-07-07 09:30:49.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/GlobalLivenessInfo.java 2017-07-07 09:30:48.000000000 -0700 @@ -27,8 +27,7 @@ import java.util.EnumSet; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.LIRInstruction.OperandFlag; @@ -156,12 +155,13 @@ */ @SuppressWarnings("try") public boolean verify(LIR lir) { - try (Scope s = Debug.scope("Verify GlobalLivenessInfo", this)) { + DebugContext debug = lir.getDebug(); + try (DebugContext.Scope s = debug.scope("Verify GlobalLivenessInfo", this)) { for (AbstractBlockBase block : lir.getControlFlowGraph().getBlocks()) { assert verifyBlock(block, lir); } } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } return true; } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/TraceAllocationPhase.java 2017-07-07 09:30:49.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/TraceAllocationPhase.java 2017-07-07 09:30:49.000000000 -0700 @@ -25,12 +25,11 @@ import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; import org.graalvm.compiler.core.common.alloc.Trace; import org.graalvm.compiler.core.common.alloc.TraceBuilderResult; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.CounterKey; import org.graalvm.compiler.debug.DebugCloseable; -import org.graalvm.compiler.debug.DebugCounter; -import org.graalvm.compiler.debug.DebugMemUseTracker; -import org.graalvm.compiler.debug.DebugTimer; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.MemUseTrackerKey; +import org.graalvm.compiler.debug.TimerKey; import org.graalvm.compiler.lir.gen.LIRGenerationResult; import org.graalvm.compiler.lir.gen.LIRGeneratorTool.MoveFactory; import org.graalvm.compiler.lir.phases.LIRPhase; @@ -57,23 +56,23 @@ /** * Records time spent within {@link #apply}. */ - private final DebugTimer timer; + private final TimerKey timer; /** * Records memory usage within {@link #apply}. */ - private final DebugMemUseTracker memUseTracker; + private final MemUseTrackerKey memUseTracker; /** * Records the number of traces allocated with this phase. */ - private final DebugCounter allocatedTraces; + private final CounterKey allocatedTraces; public static final class AllocationStatistics { - private final DebugCounter allocatedTraces; + private final CounterKey allocatedTraces; public AllocationStatistics(Class clazz) { - allocatedTraces = Debug.counter("TraceRA[%s]", clazz); + allocatedTraces = DebugContext.counter("TraceRA[%s]", clazz); } } @@ -110,19 +109,24 @@ @SuppressWarnings("try") public final void apply(TargetDescription target, LIRGenerationResult lirGenRes, Trace trace, C context, boolean dumpTrace) { - try (Scope s = Debug.scope(getName(), this)) { - try (DebugCloseable a = timer.start(); DebugCloseable c = memUseTracker.start()) { - if (dumpTrace && Debug.isDumpEnabled(Debug.DETAILED_LEVEL)) { - Debug.dump(Debug.DETAILED_LEVEL, trace, "Before %s (Trace%s: %s)", getName(), trace.getId(), trace); + DebugContext debug = lirGenRes.getLIR().getDebug(); + try (DebugContext.Scope s = debug.scope(getName(), this)) { + try (DebugCloseable a = timer.start(debug); DebugCloseable c = memUseTracker.start(debug)) { + if (dumpTrace) { + if (debug.isDumpEnabled(DebugContext.DETAILED_LEVEL)) { + debug.dump(DebugContext.DETAILED_LEVEL, trace, "Before %s (Trace%s: %s)", getName(), trace.getId(), trace); + } } run(target, lirGenRes, trace, context); - allocatedTraces.increment(); - if (dumpTrace && Debug.isDumpEnabled(Debug.VERBOSE_LEVEL)) { - Debug.dump(Debug.VERBOSE_LEVEL, trace, "After %s (Trace%s: %s)", getName(), trace.getId(), trace); + allocatedTraces.increment(debug); + if (dumpTrace) { + if (debug.isDumpEnabled(DebugContext.VERBOSE_LEVEL)) { + debug.dump(DebugContext.VERBOSE_LEVEL, trace, "After %s (Trace%s: %s)", getName(), trace.getId(), trace); + } } } } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/TraceBuilderPhase.java 2017-07-07 09:30:50.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/TraceBuilderPhase.java 2017-07-07 09:30:50.000000000 -0700 @@ -34,16 +34,16 @@ import org.graalvm.compiler.core.common.alloc.TraceStatisticsPrinter; import org.graalvm.compiler.core.common.alloc.UniDirectionalTraceBuilder; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.gen.LIRGenerationResult; import org.graalvm.compiler.lir.phases.AllocationPhase; import org.graalvm.compiler.options.EnumOptionKey; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.compiler.options.OptionKey; import jdk.vm.ci.code.TargetDescription; @@ -73,15 +73,16 @@ final TraceBuilderResult traceBuilderResult = getTraceBuilderResult(lir, startBlock, linearScanOrder); - if (Debug.isLogEnabled(Debug.BASIC_LEVEL)) { + DebugContext debug = lir.getDebug(); + if (debug.isLogEnabled(DebugContext.BASIC_LEVEL)) { ArrayList traces = traceBuilderResult.getTraces(); for (int i = 0; i < traces.size(); i++) { Trace trace = traces.get(i); - Debug.log(Debug.BASIC_LEVEL, "Trace %5d: %s%s", i, trace, isTrivialTrace(lirGenRes.getLIR(), trace) ? " (trivial)" : ""); + debug.log(DebugContext.BASIC_LEVEL, "Trace %5d: %s%s", i, trace, isTrivialTrace(lirGenRes.getLIR(), trace) ? " (trivial)" : ""); } } - TraceStatisticsPrinter.printTraceStatistics(traceBuilderResult, lirGenRes.getCompilationUnitName()); - Debug.dump(Debug.VERBOSE_LEVEL, traceBuilderResult, "TraceBuilderResult"); + TraceStatisticsPrinter.printTraceStatistics(debug, traceBuilderResult, lirGenRes.getCompilationUnitName()); + debug.dump(DebugContext.VERBOSE_LEVEL, traceBuilderResult, "TraceBuilderResult"); context.contextAdd(traceBuilderResult); } @@ -90,14 +91,15 @@ OptionValues options = lir.getOptions(); TraceBuilder selectedTraceBuilder = Options.TraceBuilding.getValue(options); - Debug.log(Debug.BASIC_LEVEL, "Building Traces using %s", selectedTraceBuilder); + DebugContext debug = lir.getDebug(); + debug.log(DebugContext.BASIC_LEVEL, "Building Traces using %s", selectedTraceBuilder); switch (Options.TraceBuilding.getValue(options)) { case SingleBlock: - return SingleBlockTraceBuilder.computeTraces(startBlock, linearScanOrder, pred); + return SingleBlockTraceBuilder.computeTraces(debug, startBlock, linearScanOrder, pred); case BiDirectional: - return BiDirectionalTraceBuilder.computeTraces(startBlock, linearScanOrder, pred); + return BiDirectionalTraceBuilder.computeTraces(debug, startBlock, linearScanOrder, pred); case UniDirectional: - return UniDirectionalTraceBuilder.computeTraces(startBlock, linearScanOrder, pred); + return UniDirectionalTraceBuilder.computeTraces(debug, startBlock, linearScanOrder, pred); } throw GraalError.shouldNotReachHere("Unknown trace building algorithm: " + Options.TraceBuilding.getValue(options)); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/TraceGlobalMoveResolutionPhase.java 2017-07-07 09:30:50.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/TraceGlobalMoveResolutionPhase.java 2017-07-07 09:30:50.000000000 -0700 @@ -37,7 +37,7 @@ import org.graalvm.compiler.core.common.alloc.Trace; import org.graalvm.compiler.core.common.alloc.TraceBuilderResult; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.LIRInstruction; @@ -67,7 +67,9 @@ } public static void resolve(TargetDescription target, LIRGenerationResult lirGenRes, TraceAllocationContext context) { - Debug.dump(Debug.VERBOSE_LEVEL, lirGenRes.getLIR(), "Before TraceGlobalMoveResultion"); + LIR lir = lirGenRes.getLIR(); + DebugContext debug = lir.getDebug(); + debug.dump(DebugContext.VERBOSE_LEVEL, lir, "Before TraceGlobalMoveResultion"); MoveFactory spillMoveFactory = context.spillMoveFactory; resolveGlobalDataFlow(context.resultTraces, lirGenRes, spillMoveFactory, target.arch, context.livenessInfo, context.registerAllocationConfig); } @@ -79,12 +81,13 @@ /* Resolve trace global data-flow mismatch. */ TraceGlobalMoveResolver moveResolver = new TraceGlobalMoveResolver(lirGenRes, spillMoveFactory, registerAllocationConfig, arch); - try (Indent indent = Debug.logAndIndent("Trace global move resolution")) { + DebugContext debug = lir.getDebug(); + try (Indent indent = debug.logAndIndent("Trace global move resolution")) { for (Trace trace : resultTraces.getTraces()) { for (AbstractBlockBase fromBlock : trace.getBlocks()) { for (AbstractBlockBase toBlock : fromBlock.getSuccessors()) { if (resultTraces.getTraceForBlock(fromBlock) != resultTraces.getTraceForBlock(toBlock)) { - try (Indent indent0 = Debug.logAndIndent("Handle trace edge from %s (Trace%d) to %s (Trace%d)", fromBlock, resultTraces.getTraceForBlock(fromBlock).getId(), toBlock, + try (Indent indent0 = debug.logAndIndent("Handle trace edge from %s (Trace%d) to %s (Trace%d)", fromBlock, resultTraces.getTraceForBlock(fromBlock).getId(), toBlock, resultTraces.getTraceForBlock(toBlock).getId())) { final ArrayList instructions; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/TraceGlobalMoveResolver.java 2017-07-07 09:30:51.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/TraceGlobalMoveResolver.java 2017-07-07 09:30:51.000000000 -0700 @@ -40,10 +40,11 @@ import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.Indent; +import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.LIRInsertionBuffer; import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.VirtualStackSlot; @@ -64,8 +65,8 @@ */ public final class TraceGlobalMoveResolver extends TraceGlobalMoveResolutionPhase.MoveResolver { - private static final DebugCounter cycleBreakingSlotsAllocated = Debug.counter("TraceRA[cycleBreakingSlotsAllocated(global)]"); - private static final DebugCounter cycleBreakingSlotsReused = Debug.counter("TraceRA[cycleBreakingSlotsReused(global)]"); + private static final CounterKey cycleBreakingSlotsAllocated = DebugContext.counter("TraceRA[cycleBreakingSlotsAllocated(global)]"); + private static final CounterKey cycleBreakingSlotsReused = DebugContext.counter("TraceRA[cycleBreakingSlotsReused(global)]"); private int insertIdx; private LIRInsertionBuffer insertionBuffer; // buffer where moves are inserted @@ -82,6 +83,7 @@ private final OptionValues options; private final RegisterAllocationConfig registerAllocationConfig; private final LIRGenerationResult res; + private final DebugContext debug; private void setValueBlocked(Value location, int direction) { assert direction == 1 || direction == -1 : "out of bounds"; @@ -157,8 +159,10 @@ FrameMap frameMap = frameMapBuilderTool.getFrameMap(); this.firstVirtualStackIndex = !frameMap.frameNeedsAllocating() ? 0 : frameMap.currentFrameSize() + 1; - this.options = res.getLIR().getOptions(); this.res = res; + LIR lir = res.getLIR(); + this.options = lir.getOptions(); + this.debug = lir.getDebug(); } private boolean checkEmpty() { @@ -228,7 +232,7 @@ if (mightBeBlocked(location)) { assert areMultipleReadsAllowed() || valueBlocked(location) == 0 : "location already marked as used: " + location; setValueBlocked(location, 1); - Debug.log("block %s", location); + debug.log("block %s", location); } } @@ -237,7 +241,7 @@ if (mightBeBlocked(location)) { assert valueBlocked(location) > 0 : "location already marked as unused: " + location; setValueBlocked(location, -1); - Debug.log("unblock %s", location); + debug.log("unblock %s", location); } } @@ -324,8 +328,8 @@ LIRInstruction move = createMove(fromOperand, toOperand); insertionBuffer.append(insertIdx, move); - if (Debug.isLogEnabled()) { - Debug.log("insert move from %s to %s at %d", fromOperand, toOperand, insertIdx); + if (debug.isLogEnabled()) { + debug.log("insert move from %s to %s at %d", fromOperand, toOperand, insertIdx); } return move; } @@ -343,9 +347,9 @@ @SuppressWarnings("try") private void resolveMappings() { - try (Indent indent = Debug.logAndIndent("resolveMapping")) { + try (Indent indent = debug.logAndIndent("resolveMapping")) { assert verifyBeforeResolve(); - if (Debug.isLogEnabled()) { + if (debug.isLogEnabled()) { printMapping(); } @@ -411,21 +415,21 @@ // create a new spill interval and assign a stack slot to it Value from = mappingFrom.get(spillCandidate); - try (Indent indent = Debug.logAndIndent("BreakCycle: %s", from)) { + try (Indent indent = debug.logAndIndent("BreakCycle: %s", from)) { AllocatableValue spillSlot = null; if (TraceRegisterAllocationPhase.Options.TraceRAreuseStackSlotsForMoveResolutionCycleBreaking.getValue(options) && !isStackSlotValue(from)) { // don't use the stack slot if from is already the stack slot Value fromStack = mappingFromStack.get(spillCandidate); if (fromStack != null) { spillSlot = (AllocatableValue) fromStack; - cycleBreakingSlotsReused.increment(); - Debug.log("reuse slot for spilling: %s", spillSlot); + cycleBreakingSlotsReused.increment(debug); + debug.log("reuse slot for spilling: %s", spillSlot); } } if (spillSlot == null) { spillSlot = frameMapBuilder.allocateSpillSlot(from.getValueKind()); - cycleBreakingSlotsAllocated.increment(); - Debug.log("created new slot for spilling: %s", spillSlot); + cycleBreakingSlotsAllocated.increment(debug); + debug.log("created new slot for spilling: %s", spillSlot); // insert a move from register to stack and update the mapping LIRInstruction move = insertMove(from, spillSlot); move.setComment(res, "TraceGlobalMoveResolver: breakCycle"); @@ -438,9 +442,9 @@ @SuppressWarnings("try") private void printMapping() { - try (Indent indent = Debug.logAndIndent("Mapping")) { + try (Indent indent = debug.logAndIndent("Mapping")) { for (int i = mappingFrom.size() - 1; i >= 0; i--) { - Debug.log("move %s <- %s (%s)", mappingTo.get(i), mappingFrom.get(i), mappingFromStack.get(i)); + debug.log("move %s <- %s (%s)", mappingTo.get(i), mappingFrom.get(i), mappingFromStack.get(i)); } } } @@ -454,8 +458,8 @@ @Override public void addMapping(Value from, AllocatableValue to, Value fromStack) { - if (Debug.isLogEnabled()) { - Debug.log("add move mapping from %s to %s", from, to); + if (debug.isLogEnabled()) { + debug.log("add move mapping from %s to %s", from, to); } assert !from.equals(to) : "from and to interval equal: " + from; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/TraceRegisterAllocationPhase.java 2017-07-07 09:30:52.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/TraceRegisterAllocationPhase.java 2017-07-07 09:30:52.000000000 -0700 @@ -26,9 +26,8 @@ import org.graalvm.compiler.core.common.alloc.Trace; import org.graalvm.compiler.core.common.alloc.TraceBuilderResult; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.alloc.trace.TraceAllocationPhase.TraceAllocationContext; @@ -63,10 +62,10 @@ // @formatter:on } - private static final DebugCounter tracesCounter = Debug.counter("TraceRA[traces]"); + private static final CounterKey tracesCounter = DebugContext.counter("TraceRA[traces]"); - public static final DebugCounter globalStackSlots = Debug.counter("TraceRA[GlobalStackSlots]"); - public static final DebugCounter allocatedStackSlots = Debug.counter("TraceRA[AllocatedStackSlots]"); + public static final CounterKey globalStackSlots = DebugContext.counter("TraceRA[GlobalStackSlots]"); + public static final CounterKey allocatedStackSlots = DebugContext.counter("TraceRA[AllocatedStackSlots]"); @Override @SuppressWarnings("try") @@ -74,6 +73,7 @@ MoveFactory spillMoveFactory = context.spillMoveFactory; RegisterAllocationConfig registerAllocationConfig = context.registerAllocationConfig; LIR lir = lirGenRes.getLIR(); + DebugContext debug = lir.getDebug(); TraceBuilderResult resultTraces = context.contextLookup(TraceBuilderResult.class); GlobalLivenessInfo livenessInfo = context.contextLookup(GlobalLivenessInfo.class); assert livenessInfo != null; @@ -86,16 +86,16 @@ final TraceRegisterAllocationPolicy plan = DefaultTraceRegisterAllocationPolicy.allocationPolicy(target, lirGenRes, spillMoveFactory, registerAllocationConfig, cachedStackSlots, resultTraces, neverSpillConstant, livenessInfo, lir.getOptions()); - try (Scope s0 = Debug.scope("AllocateTraces", resultTraces, livenessInfo)) { + try (DebugContext.Scope s0 = debug.scope("AllocateTraces", resultTraces, livenessInfo)) { for (Trace trace : resultTraces.getTraces()) { - tracesCounter.increment(); + tracesCounter.increment(debug); TraceAllocationPhase allocator = plan.selectStrategy(trace); - try (Indent i = Debug.logAndIndent("Allocating Trace%d: %s (%s)", trace.getId(), trace, allocator); Scope s = Debug.scope("AllocateTrace", trace)) { + try (Indent i = debug.logAndIndent("Allocating Trace%d: %s (%s)", trace.getId(), trace, allocator); DebugContext.Scope s = debug.scope("AllocateTrace", trace)) { allocator.apply(target, lirGenRes, trace, traceContext); } } } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } TraceGlobalMoveResolutionPhase.resolve(target, lirGenRes, traceContext); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/TraceRegisterAllocationPolicy.java 2017-07-07 09:30:52.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/TraceRegisterAllocationPolicy.java 2017-07-07 09:30:52.000000000 -0700 @@ -31,6 +31,7 @@ import org.graalvm.compiler.lir.alloc.trace.TraceAllocationPhase.TraceAllocationContext; import org.graalvm.compiler.lir.gen.LIRGenerationResult; import org.graalvm.compiler.lir.gen.LIRGeneratorTool.MoveFactory; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.common.JVMCIError; @@ -63,8 +64,23 @@ return resultTraces; } + protected final GlobalLivenessInfo getGlobalLivenessInfo() { + return livenessInfo; + } + + protected final RegisterAllocationConfig getRegisterAllocationConfig() { + return registerAllocationConfig; + } + + protected final TargetDescription getTarget() { + return target; + } + /** * Returns {@code true} if the allocation strategy should be used for {@code trace}. + * + * This method must not alter any state of the strategy, nor rely on being called in a + * specific trace order. */ public abstract boolean shouldApplyTo(Trace trace); @@ -99,6 +115,10 @@ this.strategies = new ArrayList<>(3); } + protected OptionValues getOptions() { + return lirGenRes.getLIR().getOptions(); + } + public void appendStrategy(AllocationStrategy strategy) { strategies.add(strategy); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/bu/BottomUpAllocator.java 2017-07-07 09:30:53.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/bu/BottomUpAllocator.java 2017-07-07 09:30:53.000000000 -0700 @@ -42,8 +42,7 @@ import org.graalvm.compiler.core.common.alloc.Trace; import org.graalvm.compiler.core.common.alloc.TraceBuilderResult; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.InstructionValueProcedure; import org.graalvm.compiler.lir.LIR; @@ -102,6 +101,7 @@ private final BitSet allocatedBlocks; private final TraceBuilderResult resultTraces; private final TraceGlobalMoveResolver moveResolver; + private final DebugContext debug; /** * Maps from {@link Variable#index} to a spill stack slot. If @@ -119,6 +119,7 @@ public BottomUpAllocator(TargetDescription target, LIRGenerationResult lirGenRes, MoveFactory spillMoveFactory, RegisterAllocationConfig registerAllocationConfig, AllocatableValue[] cachedStackSlots, TraceBuilderResult resultTraces, boolean neverSpillConstant, GlobalLivenessInfo livenessInfo) { this.target = target; + this.debug = lirGenRes.getLIR().getDebug(); this.lirGenRes = lirGenRes; this.spillMoveFactory = spillMoveFactory; this.registerAllocationConfig = registerAllocationConfig; @@ -160,13 +161,13 @@ int variableIndex = var.index; AllocatableValue cachedStackSlot = stackSlots[variableIndex]; if (cachedStackSlot != null) { - TraceRegisterAllocationPhase.globalStackSlots.increment(); + TraceRegisterAllocationPhase.globalStackSlots.increment(debug); assert cachedStackSlot.getValueKind().equals(var.getValueKind()) : "CachedStackSlot: kind mismatch? " + var.getValueKind() + " vs. " + cachedStackSlot.getValueKind(); return cachedStackSlot; } VirtualStackSlot slot = lirGenRes.getFrameMapBuilder().allocateSpillSlot(var.getValueKind()); stackSlots[variableIndex] = slot; - TraceRegisterAllocationPhase.allocatedStackSlots.increment(); + TraceRegisterAllocationPhase.allocatedStackSlots.increment(debug); return slot; } @@ -205,8 +206,8 @@ private void resolveFindInsertPos(AbstractBlockBase fromBlock, AbstractBlockBase toBlock) { LIR lir = lirGenRes.getLIR(); if (fromBlock.getSuccessorCount() <= 1) { - if (Debug.isLogEnabled()) { - Debug.log("inserting moves at end of fromBlock B%d", fromBlock.getId()); + if (debug.isLogEnabled()) { + debug.log("inserting moves at end of fromBlock B%d", fromBlock.getId()); } ArrayList instructions = lir.getLIRforBlock(fromBlock); @@ -219,8 +220,8 @@ } } else { - if (Debug.isLogEnabled()) { - Debug.log("inserting moves at beginning of toBlock B%d", toBlock.getId()); + if (debug.isLogEnabled()) { + debug.log("inserting moves at beginning of toBlock B%d", toBlock.getId()); } if (DetailedAsserts.getValue(getLIR().getOptions())) { @@ -284,7 +285,7 @@ } private void setLastRegisterUsage(Register reg, int pos) { - Debug.log("Register %s last used %d", reg, pos); + debug.log("Register %s last used %d", reg, pos); lastRegisterUsage[reg.number] = pos; } @@ -293,7 +294,7 @@ } private void setLastRegisterKill(Register reg, int pos) { - Debug.log("Register %s killed %d", reg, pos); + debug.log("Register %s killed %d", reg, pos); lastRegisterKill[reg.number] = pos; } @@ -309,7 +310,7 @@ LIRInstruction move = spillMoveFactory.createMove(dst, src); insertInstructionsBefore.add(move); move.setComment(lirGenRes, "BottomUp: spill move before"); - Debug.log("insert before %s", move); + debug.log("insert before %s", move); } private void insertSpillMoveAfter(AllocatableValue dst, Value src) { @@ -318,9 +319,9 @@ LIRInstruction move = spillMoveFactory.createMove(dst, src); insertInstructionsAfter.add(move); move.setComment(lirGenRes, "BottomUp: spill move after"); - Debug.log("insert after %s", move); + debug.log("insert after %s", move); } else { - Debug.log("Block end op. No from %s to %s necessary.", src, dst); + debug.log("Block end op. No from %s to %s necessary.", src, dst); requireResolution = true; } } @@ -346,7 +347,7 @@ @SuppressWarnings("try") private void allocateTrace(Trace trace) { - try (Scope s = Debug.scope("BottomUpAllocator", trace.getBlocks()); Indent indent = Debug.logAndIndent("%s (Trace%d)", trace, trace.getId())) { + try (DebugContext.Scope s = debug.scope("BottomUpAllocator", trace.getBlocks()); Indent indent = debug.logAndIndent("%s (Trace%d)", trace, trace.getId())) { AbstractBlockBase[] blocks = trace.getBlocks(); int lastBlockIdx = blocks.length - 1; AbstractBlockBase successorBlock = blocks[lastBlockIdx]; @@ -367,7 +368,7 @@ } resolveLoopBackEdge(trace); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } @@ -410,7 +411,7 @@ // insert move from variable move = spillMoveFactory.createMove(dest, asVariable(phiOut)); } - Debug.log("Inserting load %s", move); + debug.log("Inserting load %s", move); move.setComment(lirGenRes, "BottomUp: phi resolution"); phiResolutionMoves.add(move); } @@ -498,7 +499,7 @@ // might be set in insertSpillMoveAfter requireResolution = false; - try (Indent indent = Debug.logAndIndent("handle block %s", block)) { + try (Indent indent = debug.logAndIndent("handle block %s", block)) { currentInstructions = getLIR().getLIRforBlock(block); for (currentInstructionIndex = currentInstructions.size() - 1; currentInstructionIndex >= 0; currentInstructionIndex--) { LIRInstruction inst = currentInstructions.get(currentInstructionIndex); @@ -515,8 +516,8 @@ @SuppressWarnings("try") private void allocateInstruction(LIRInstruction op, AbstractBlockBase block) { assert op != null && op.id() == currentOpId; - try (Indent indent = Debug.logAndIndent("handle inst: %d: %s", op.id(), op)) { - try (Indent indent1 = Debug.logAndIndent("output pos")) { + try (Indent indent = debug.logAndIndent("handle inst: %d: %s", op.id(), op)) { + try (Indent indent1 = debug.logAndIndent("output pos")) { // spill caller saved registers if (op.destroysCallerSavedRegisters()) { spillCallerSavedRegisters(); @@ -540,7 +541,7 @@ processIncoming(block, op); } } - try (Indent indent1 = Debug.logAndIndent("input pos")) { + try (Indent indent1 = debug.logAndIndent("input pos")) { currentOpId++; @@ -592,8 +593,8 @@ setLastRegisterUsage(reg, currentOpId); } } - if (Debug.isLogEnabled()) { - Debug.log("operation destroys all caller-save registers"); + if (debug.isLogEnabled()) { + debug.log("operation destroys all caller-save registers"); } } @@ -670,7 +671,7 @@ setRegisterUsage(freeRegister, var); RegisterValue registerValue = freeRegister.asValue(var.getValueKind()); setCurrentLocation(var, registerValue); - Debug.log("AllocateRegister[%5s] %s for %s", mode, freeRegister, var); + debug.log("AllocateRegister[%5s] %s for %s", mode, freeRegister, var); return registerValue; } @@ -693,13 +694,13 @@ if (mode == OperandMode.ALIVE && killedAtDef(reg)) { AllocatableValue spillSlot = allocateSpillSlot(var); insertSpillMoveBefore(spillSlot, currentLocation); - Debug.log("AllocateStackOrReg[%5s] temporary use %s for %s since current location %s is destroyed at def", mode, spillSlot, var, currentLocation); + debug.log("AllocateStackOrReg[%5s] temporary use %s for %s since current location %s is destroyed at def", mode, spillSlot, var, currentLocation); return spillSlot; } // update register usage setLastRegisterUsage(reg, currentOpId); } - Debug.log(3, "AllocateStackOrReg[%5s] %s already in %s", mode, var, currentLocation); + debug.log(3, "AllocateStackOrReg[%5s] %s already in %s", mode, var, currentLocation); return currentLocation; } // no location available @@ -716,7 +717,7 @@ setRegisterUsage(freeRegister, var); RegisterValue registerValue = freeRegister.asValue(var.getValueKind()); setCurrentLocation(var, registerValue); - Debug.log("AllocateStackOrReg[%5s] %s for %s", mode, freeRegister, var); + debug.log("AllocateStackOrReg[%5s] %s for %s", mode, freeRegister, var); return registerValue; } return value; @@ -739,10 +740,10 @@ return reg; } } - if (Debug.isLogEnabled()) { - try (Indent i = Debug.logAndIndent("All Registers occupied:")) { + if (debug.isLogEnabled()) { + try (Indent i = debug.logAndIndent("All Registers occupied:")) { for (Register reg : availableRegs) { - Debug.log("%6s: last used %4d %s", reg, getLastRegisterUsage(reg), getCurrentValue(reg)); + debug.log("%6s: last used %4d %s", reg, getLastRegisterUsage(reg), getCurrentValue(reg)); } } } @@ -792,9 +793,9 @@ if (val != null && isVariable(val)) { Variable var = asVariable(val); setCurrentLocation(var, null); - Debug.log("Free Registers %s (was %s)", reg, var); + debug.log("Free Registers %s (was %s)", reg, var); } else { - Debug.log("Free Registers %s", reg); + debug.log("Free Registers %s", reg); } } @@ -838,7 +839,7 @@ private void spillVariable(AllocatableValue val, Register reg) { if (val != null && isVariable(val)) { Variable var = asVariable(val); - Debug.log("Spill Variable %s from %s", var, reg); + debug.log("Spill Variable %s from %s", var, reg); // insert reload AllocatableValue spillSlot = allocateSpillSlot(var); setCurrentLocation(var, spillSlot); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/RegisterVerifier.java 2017-07-07 09:30:54.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/RegisterVerifier.java 2017-07-07 09:30:53.000000000 -0700 @@ -32,8 +32,7 @@ import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; import org.graalvm.compiler.core.common.cfg.BlockMap; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.InstructionValueConsumer; @@ -46,8 +45,6 @@ import jdk.vm.ci.code.Register; import jdk.vm.ci.meta.Value; -/** - */ final class RegisterVerifier { TraceLinearScan allocator; @@ -88,7 +85,8 @@ @SuppressWarnings("try") void verify(AbstractBlockBase start) { - try (Scope s = Debug.scope("RegisterVerifier")) { + DebugContext debug = allocator.getDebug(); + try (DebugContext.Scope s = debug.scope("RegisterVerifier")) { // setup input registers (method arguments) for first block TraceInterval[] inputState = new TraceInterval[stateSize()]; setStateForBlock(start, inputState); @@ -106,18 +104,19 @@ @SuppressWarnings("try") private void processBlock(AbstractBlockBase block) { - try (Indent indent = Debug.logAndIndent("processBlock B%d", block.getId())) { + DebugContext debug = allocator.getDebug(); + try (Indent indent = debug.logAndIndent("processBlock B%d", block.getId())) { // must copy state because it is modified TraceInterval[] inputState = copy(stateForBlock(block)); - try (Indent indent2 = Debug.logAndIndent("Input-State of intervals:")) { + try (Indent indent2 = debug.logAndIndent("Input-State of intervals:")) { printState(inputState); } // process all operations of the block processOperations(block, inputState); - try (Indent indent2 = Debug.logAndIndent("Output-State of intervals:")) { + try (Indent indent2 = debug.logAndIndent("Output-State of intervals:")) { printState(inputState); } @@ -129,13 +128,14 @@ } protected void printState(TraceInterval[] inputState) { + DebugContext debug = allocator.getDebug(); for (int i = 0; i < stateSize(); i++) { Register reg = allocator.getRegisters().get(i); assert reg.number == i; if (inputState[i] != null) { - Debug.log(" %6s %4d -- %s", reg, inputState[i].operandNumber, inputState[i]); + debug.log(" %6s %4d -- %s", reg, inputState[i].operandNumber, inputState[i]); } else { - Debug.log(" %6s __", reg); + debug.log(" %6s __", reg); } } } @@ -143,6 +143,7 @@ private void processSuccessor(AbstractBlockBase block, TraceInterval[] inputState) { TraceInterval[] savedState = stateForBlock(block); + DebugContext debug = allocator.getDebug(); if (savedState != null) { // this block was already processed before. // check if new inputState is consistent with savedState @@ -159,23 +160,23 @@ savedStateCorrect = false; savedState[i] = null; - Debug.log("processSuccessor B%d: invalidating slot %d", block.getId(), i); + debug.log("processSuccessor B%d: invalidating slot %d", block.getId(), i); } } } if (savedStateCorrect) { // already processed block with correct inputState - Debug.log("processSuccessor B%d: previous visit already correct", block.getId()); + debug.log("processSuccessor B%d: previous visit already correct", block.getId()); } else { // must re-visit this block - Debug.log("processSuccessor B%d: must re-visit because input state changed", block.getId()); + debug.log("processSuccessor B%d: must re-visit because input state changed", block.getId()); addToWorkList(block); } } else { // block was not processed before, so set initial inputState - Debug.log("processSuccessor B%d: initial visit", block.getId()); + debug.log("processSuccessor B%d: initial visit", block.getId()); setStateForBlock(block, copy(inputState)); addToWorkList(block); @@ -186,14 +187,14 @@ return inputState.clone(); } - static void statePut(TraceInterval[] inputState, Value location, TraceInterval interval) { + static void statePut(DebugContext debug, TraceInterval[] inputState, Value location, TraceInterval interval) { if (location != null && isRegister(location)) { Register reg = asRegister(location); int regNum = reg.number; if (interval != null) { - Debug.log("%s = v%d", reg, interval.operandNumber); + debug.log("%s = v%d", reg, interval.operandNumber); } else if (inputState[regNum] != null) { - Debug.log("%s = null", reg); + debug.log("%s = null", reg); } inputState[regNum] = interval; @@ -213,6 +214,7 @@ void processOperations(AbstractBlockBase block, final TraceInterval[] inputState) { ArrayList ops = allocator.getLIR().getLIRforBlock(block); + DebugContext debug = allocator.getDebug(); InstructionValueConsumer useConsumer = new InstructionValueConsumer() { @Override @@ -236,7 +238,7 @@ interval = interval.getSplitChildAtOpId(op.id(), mode); } - statePut(inputState, interval.location(), interval.splitParent()); + statePut(debug, inputState, interval.location(), interval.splitParent()); } }; @@ -244,8 +246,8 @@ for (int i = 0; i < ops.size(); i++) { final LIRInstruction op = ops.get(i); - if (Debug.isLogEnabled()) { - Debug.log("%s", op.toStringWithIdPrefix()); + if (debug.isLogEnabled()) { + debug.log("%s", op.toStringWithIdPrefix()); } // check if input operands are correct @@ -253,7 +255,7 @@ // invalidate all caller save registers at calls if (op.destroysCallerSavedRegisters()) { for (Register r : allocator.getRegisterAllocationConfig().getRegisterConfig().getCallerSaveRegisters()) { - statePut(inputState, r.asValue(), null); + statePut(debug, inputState, r.asValue(), null); } } op.visitEachAlive(useConsumer); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceLinearScanAllocationPhase.java 2017-07-07 09:30:54.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceLinearScanAllocationPhase.java 2017-07-07 09:30:54.000000000 -0700 @@ -25,7 +25,7 @@ import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; import org.graalvm.compiler.core.common.alloc.Trace; import org.graalvm.compiler.core.common.alloc.TraceBuilderResult; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.lir.alloc.trace.lsra.TraceLinearScanPhase.TraceLinearScan; import org.graalvm.compiler.lir.gen.LIRGenerationResult; import org.graalvm.compiler.lir.gen.LIRGeneratorTool.MoveFactory; @@ -52,8 +52,11 @@ final void apply(TargetDescription target, LIRGenerationResult lirGenRes, Trace trace, MoveFactory spillMoveFactory, RegisterAllocationConfig registerAllocationConfig, TraceBuilderResult traceBuilderResult, TraceLinearScan allocator, boolean dumpLIR) { run(target, lirGenRes, trace, spillMoveFactory, registerAllocationConfig, traceBuilderResult, allocator); - if (dumpLIR && Debug.isDumpEnabled(Debug.DETAILED_LEVEL)) { - Debug.dump(Debug.DETAILED_LEVEL, trace, "After %s (Trace%s)", getName(), trace.getId()); + if (dumpLIR) { + DebugContext debug = lirGenRes.getLIR().getDebug(); + if (debug.isDumpEnabled(DebugContext.DETAILED_LEVEL)) { + debug.dump(DebugContext.DETAILED_LEVEL, trace, "After %s (Trace%s)", getName(), trace.getId()); + } } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceLinearScanAssignLocationsPhase.java 2017-07-07 09:30:55.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceLinearScanAssignLocationsPhase.java 2017-07-07 09:30:55.000000000 -0700 @@ -38,7 +38,7 @@ import org.graalvm.compiler.core.common.alloc.Trace; import org.graalvm.compiler.core.common.alloc.TraceBuilderResult; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.ConstantValue; @@ -165,7 +165,8 @@ @SuppressWarnings("try") private void assignBlock(AbstractBlockBase block) { - try (Indent indent2 = Debug.logAndIndent("assign locations in block B%d", block.getId())) { + DebugContext debug = allocator.getDebug(); + try (Indent indent2 = debug.logAndIndent("assign locations in block B%d", block.getId())) { ArrayList instructions = allocator.getLIR().getLIRforBlock(block); handleBlockBegin(block, instructions); int numInst = instructions.size(); @@ -312,7 +313,7 @@ @SuppressWarnings("try") private void assign() { - try (Indent indent = Debug.logAndIndent("assign locations")) { + try (Indent indent = allocator.getDebug().logAndIndent("assign locations")) { for (AbstractBlockBase block : allocator.sortedBlocks()) { assignBlock(block); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceLinearScanEliminateSpillMovePhase.java 2017-07-07 09:30:55.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceLinearScanEliminateSpillMovePhase.java 2017-07-07 09:30:55.000000000 -0700 @@ -34,7 +34,7 @@ import org.graalvm.compiler.core.common.alloc.Trace; import org.graalvm.compiler.core.common.alloc.TraceBuilderResult; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.LIRInsertionBuffer; import org.graalvm.compiler.lir.LIRInstruction; @@ -75,7 +75,8 @@ // called once before assignment of register numbers @SuppressWarnings("try") private static void eliminateSpillMoves(TraceLinearScan allocator, boolean shouldEliminateSpillMoves, TraceBuilderResult traceBuilderResult, LIRGenerationResult res) { - try (Indent indent = Debug.logAndIndent("Eliminating unnecessary spill moves: Trace%d", traceBuilderResult.getTraceForBlock(allocator.blockAt(0)).getId())) { + DebugContext debug = allocator.getDebug(); + try (Indent indent = debug.logAndIndent("Eliminating unnecessary spill moves: Trace%d", traceBuilderResult.getTraceForBlock(allocator.blockAt(0)).getId())) { allocator.sortIntervalsBySpillPos(); /* @@ -84,19 +85,19 @@ */ TraceInterval interval = allocator.createUnhandledListBySpillPos(spilledIntervals); if (DetailedAsserts.getValue(allocator.getOptions())) { - checkIntervals(interval); + checkIntervals(debug, interval); } - if (Debug.isLogEnabled()) { - try (Indent indent2 = Debug.logAndIndent("Sorted intervals")) { + if (debug.isLogEnabled()) { + try (Indent indent2 = debug.logAndIndent("Sorted intervals")) { for (TraceInterval i = interval; i != null; i = i.next) { - Debug.log("%5d: %s", i.spillDefinitionPos(), i); + debug.log("%5d: %s", i.spillDefinitionPos(), i); } } } LIRInsertionBuffer insertionBuffer = new LIRInsertionBuffer(); for (AbstractBlockBase block : allocator.sortedBlocks()) { - try (Indent indent1 = Debug.logAndIndent("Handle %s", block)) { + try (Indent indent1 = debug.logAndIndent("Handle %s", block)) { ArrayList instructions = allocator.getLIR().getLIRforBlock(block); int numInst = instructions.size(); @@ -105,7 +106,7 @@ for (int j = 0; j < numInst; j++) { LIRInstruction op = instructions.get(j); int opId = op.id(); - try (Indent indent2 = Debug.logAndIndent("%5d %s", opId, op)) { + try (Indent indent2 = debug.logAndIndent("%5d %s", opId, op)) { if (opId == -1) { MoveOp move = MoveOp.asMoveOp(op); @@ -119,13 +120,13 @@ * Move target is a stack slot that is always correct, so * eliminate instruction. */ - if (Debug.isLogEnabled()) { + if (debug.isLogEnabled()) { if (ValueMoveOp.isValueMoveOp(op)) { ValueMoveOp vmove = ValueMoveOp.asValueMoveOp(op); - Debug.log("eliminating move from interval %s to %s in block %s", vmove.getInput(), vmove.getResult(), block); + debug.log("eliminating move from interval %s to %s in block %s", vmove.getInput(), vmove.getResult(), block); } else { LoadConstantOp load = LoadConstantOp.asLoadConstantOp(op); - Debug.log("eliminating constant load from %s to %s in block %s", load.getConstant(), load.getResult(), + debug.log("eliminating constant load from %s to %s in block %s", load.getConstant(), load.getResult(), block); } } @@ -145,7 +146,7 @@ assert interval == TraceInterval.EndMarker || (interval.isSplitParent() && SpillState.IN_MEMORY.contains(interval.spillState())) : "invalid interval"; while (interval != TraceInterval.EndMarker && interval.spillDefinitionPos() == opId) { - Debug.log("handle %s", interval); + debug.log("handle %s", interval); if (!interval.canMaterialize() && interval.spillState() != SpillState.StartInMemory) { AllocatableValue fromLocation = interval.getSplitChildAtOpId(opId, OperandMode.DEF).location(); @@ -168,8 +169,8 @@ insertionBuffer.append(j + 1, move); move.setComment(res, "TraceLSRAEliminateSpillMove: spill def pos"); - if (Debug.isLogEnabled()) { - Debug.log("inserting move after definition of interval %d to stack slot %s at opId %d", interval.operandNumber, interval.spillSlot(), opId); + if (debug.isLogEnabled()) { + debug.log("inserting move after definition of interval %d to stack slot %s at opId %d", interval.operandNumber, interval.spillSlot(), opId); } } } @@ -226,7 +227,7 @@ return curInterval.isSplitParent(); } - private static void checkIntervals(TraceInterval interval) { + private static void checkIntervals(DebugContext debug, TraceInterval interval) { TraceInterval prev = null; TraceInterval temp = interval; while (temp != TraceInterval.EndMarker) { @@ -241,8 +242,8 @@ // assert temp.spillDefinitionPos() <= temp.from() + 2 : // "only intervals defined once at their start-pos can be optimized"; - if (Debug.isLogEnabled()) { - Debug.log("interval %d (from %d to %d) must be stored at %d", temp.operandNumber, temp.from(), temp.to(), temp.spillDefinitionPos()); + if (debug.isLogEnabled()) { + debug.log("interval %d (from %d to %d) must be stored at %d", temp.operandNumber, temp.from(), temp.to(), temp.spillDefinitionPos()); } prev = temp; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceLinearScanLifetimeAnalysisPhase.java 2017-07-07 09:30:56.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceLinearScanLifetimeAnalysisPhase.java 2017-07-07 09:30:56.000000000 -0700 @@ -43,8 +43,7 @@ import org.graalvm.compiler.core.common.alloc.Trace; import org.graalvm.compiler.core.common.alloc.TraceBuilderResult; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.InstructionValueConsumer; @@ -86,11 +85,13 @@ public static final class Analyser { private final TraceLinearScan allocator; + private final DebugContext debug; private final TraceBuilderResult traceBuilderResult; private int numInstructions; public Analyser(TraceLinearScan allocator, TraceBuilderResult traceBuilderResult) { this.allocator = allocator; + this.debug = allocator.getDebug(); this.traceBuilderResult = traceBuilderResult; } @@ -205,8 +206,8 @@ private void addFixedUse(RegisterValue reg, int from, int to) { FixedInterval interval = allocator.getOrCreateFixedInterval(reg); interval.addRange(from, to); - if (Debug.isLogEnabled()) { - Debug.log("add fixed use: %s, at %d", interval, to); + if (debug.isLogEnabled()) { + debug.log("add fixed use: %s, at %d", interval, to); } } @@ -217,8 +218,8 @@ // Register use position at even instruction id. interval.addUsePos(to & ~1, registerPriority, allocator.getOptions()); - if (Debug.isLogEnabled()) { - Debug.log("add use: %s, at %d (%s)", interval, to, registerPriority.name()); + if (debug.isLogEnabled()) { + debug.log("add use: %s, at %d (%s)", interval, to, registerPriority.name()); } } @@ -249,12 +250,12 @@ * Dead value - make vacuous interval also add register priority for dead intervals */ interval.addRange(defPos, defPos + 1); - if (Debug.isLogEnabled()) { - Debug.log("Warning: def of operand %s at %d occurs without use", reg, defPos); + if (debug.isLogEnabled()) { + debug.log("Warning: def of operand %s at %d occurs without use", reg, defPos); } } - if (Debug.isLogEnabled()) { - Debug.log("add fixed def: %s, at %d", interval, defPos); + if (debug.isLogEnabled()) { + debug.log("add fixed def: %s, at %d", interval, defPos); } } @@ -268,8 +269,8 @@ * Dead value - make vacuous interval also add register priority for dead intervals */ interval.addRange(defPos, defPos + 1); - if (Debug.isLogEnabled()) { - Debug.log("Warning: def of operand %s at %d occurs without use", operand, defPos); + if (debug.isLogEnabled()) { + debug.log("Warning: def of operand %s at %d occurs without use", operand, defPos); } } else { /* @@ -290,8 +291,8 @@ } interval.addMaterializationValue(getMaterializedValue(op, operand, interval, allocator.neverSpillConstants(), allocator.getSpillMoveFactory())); - if (Debug.isLogEnabled()) { - Debug.log("add def: %s defPos %d (%s)", interval, defPos, registerPriority.name()); + if (debug.isLogEnabled()) { + debug.log("add def: %s defPos %d (%s)", interval, defPos, registerPriority.name()); } return interval; } @@ -311,8 +312,8 @@ private void addFixedTemp(RegisterValue reg, int tempPos) { FixedInterval interval = allocator.getOrCreateFixedInterval(reg); interval.addRange(tempPos, tempPos + 1); - if (Debug.isLogEnabled()) { - Debug.log("add fixed temp: %s, at %d", interval, tempPos); + if (debug.isLogEnabled()) { + debug.log("add fixed temp: %s, at %d", interval, tempPos); } } @@ -328,8 +329,8 @@ interval.addUsePos(tempPos, registerPriority, allocator.getOptions()); interval.addMaterializationValue(null); - if (Debug.isLogEnabled()) { - Debug.log("add temp: %s tempPos %d (%s)", interval, tempPos, RegisterPriority.MustHaveRegister.name()); + if (debug.isLogEnabled()) { + debug.log("add temp: %s tempPos %d (%s)", interval, tempPos, RegisterPriority.MustHaveRegister.name()); } } @@ -395,7 +396,7 @@ fromValue = (AllocatableValue) targetValue; toValue = (AllocatableValue) registerHint; } - Debug.log("addRegisterHint %s to %s", fromValue, toValue); + debug.log("addRegisterHint %s to %s", fromValue, toValue); final TraceInterval to; final IntervalHint from; if (isRegister(toValue)) { @@ -411,8 +412,8 @@ } to.setLocationHint(from); - if (Debug.isLogEnabled()) { - Debug.log("operation at opId %d: added hint from interval %s to %s", op.id(), from, to); + if (debug.isLogEnabled()) { + debug.log("operation at opId %d: added hint from interval %s to %s", op.id(), from, to); } return registerHint; @@ -469,7 +470,7 @@ @SuppressWarnings("try") private void buildIntervals() { - try (Indent indent = Debug.logAndIndent("build intervals")) { + try (Indent indent = debug.logAndIndent("build intervals")) { // create a list with all caller-save registers (cpu, fpu, xmm) RegisterArray callerSaveRegs = getCallerSavedRegisters(); @@ -480,7 +481,7 @@ for (int blockId = blocks.length - 1; blockId >= 0; blockId--) { final AbstractBlockBase block = blocks[blockId]; - try (Indent indent2 = Debug.logAndIndent("handle block %d", block.getId())) { + try (Indent indent2 = debug.logAndIndent("handle block %d", block.getId())) { handleBlockEnd(block, (instructionIndex - 1) << 1); /* @@ -495,7 +496,7 @@ numberInstruction(block, op, instructionIndex); final int opId = op.id(); - try (Indent indent3 = Debug.logAndIndent("handle inst %d: %s", opId, op)) { + try (Indent indent3 = debug.logAndIndent("handle inst %d: %s", opId, op)) { /* * Add a temp range for each register if operation destroys @@ -507,8 +508,8 @@ addTemp(r.asValue(), opId, RegisterPriority.None); } } - if (Debug.isLogEnabled()) { - Debug.log("operation destroys all caller-save registers"); + if (debug.isLogEnabled()) { + debug.log("operation destroys all caller-save registers"); } } @@ -533,7 +534,7 @@ AbstractBlockBase pred = blockId == 0 ? null : blocks[blockId - 1]; handleBlockBegin(block, pred); } - if (Debug.isDumpEnabled(Debug.VERY_DETAILED_LEVEL)) { + if (debug.isDumpEnabled(DebugContext.VERY_DETAILED_LEVEL)) { allocator.printIntervals("After Block " + block); } } // end of block iteration @@ -615,7 +616,7 @@ @SuppressWarnings("try") private void addInterTraceHints() { - try (Scope s = Debug.scope("InterTraceHints", allocator)) { + try (DebugContext.Scope s = debug.scope("InterTraceHints", allocator)) { GlobalLivenessInfo livenessInfo = allocator.getGlobalLivenessInfo(); // set hints for phi/incoming intervals for (AbstractBlockBase block : sortedBlocks()) { @@ -625,7 +626,7 @@ } } } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } @@ -656,20 +657,20 @@ } if (isVariableOrRegister(fromValue)) { IntervalHint from = getIntervalHint((AllocatableValue) fromValue); - setHint(label, to, from); + setHint(label, to, from, debug); } else if (isStackSlotValue(fromValue)) { - setSpillSlot(label, to, (AllocatableValue) fromValue); + setSpillSlot(label, to, (AllocatableValue) fromValue, debug); } else if (TraceRAshareSpillInformation.getValue(allocator.getLIR().getOptions()) && isShadowedRegisterValue(fromValue)) { ShadowedRegisterValue shadowedRegisterValue = asShadowedRegisterValue(fromValue); IntervalHint from = getIntervalHint(shadowedRegisterValue.getRegister()); - setHint(label, to, from); - setSpillSlot(label, to, shadowedRegisterValue.getStackSlot()); + setHint(label, to, from, debug); + setSpillSlot(label, to, shadowedRegisterValue.getStackSlot(), debug); } else { throw GraalError.shouldNotReachHere(); } } - private static void setHint(final LIRInstruction op, TraceInterval to, IntervalHint from) { + private static void setHint(final LIRInstruction op, TraceInterval to, IntervalHint from, DebugContext debug) { IntervalHint currentHint = to.locationHint(false); if (currentHint == null) { /* @@ -677,21 +678,21 @@ * interval. */ to.setLocationHint(from); - if (Debug.isLogEnabled()) { - Debug.log("operation at opId %d: added hint from interval %s to %s", op.id(), from, to); + if (debug.isLogEnabled()) { + debug.log("operation at opId %d: added hint from interval %s to %s", op.id(), from, to); } } } - private static void setSpillSlot(LIRInstruction op, TraceInterval interval, AllocatableValue spillSlot) { + private static void setSpillSlot(LIRInstruction op, TraceInterval interval, AllocatableValue spillSlot, DebugContext debug) { if (interval.spillSlot() == null) { interval.setSpillSlot(spillSlot); interval.setSpillState(SpillState.StartInMemory); - if (Debug.isLogEnabled()) { - Debug.log("operation at opId %d: added spill slot %s to interval %s", op.id(), spillSlot, interval); + if (debug.isLogEnabled()) { + debug.log("operation at opId %d: added spill slot %s to interval %s", op.id(), spillSlot, interval); } - } else if (Debug.isLogEnabled()) { - Debug.log("operation at opId %d: has already a slot assigned %s", op.id(), interval.spillSlot()); + } else if (debug.isLogEnabled()) { + debug.log("operation at opId %d: has already a slot assigned %s", op.id(), interval.spillSlot()); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceLinearScanPhase.java 2017-07-07 09:30:57.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceLinearScanPhase.java 2017-07-07 09:30:57.000000000 -0700 @@ -39,8 +39,7 @@ import org.graalvm.compiler.core.common.alloc.Trace; import org.graalvm.compiler.core.common.alloc.TraceBuilderResult; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.LIR; @@ -136,6 +135,10 @@ assert livenessInfo != null; } + protected DebugContext getDebug() { + return res.getLIR().getDebug(); + } + public static boolean isVariableOrRegister(Value value) { return isVariable(value) || isRegister(value); } @@ -256,6 +259,10 @@ return getLIR().getOptions(); } + DebugContext getDebug() { + return getLIR().getDebug(); + } + /** * Gets the number of operands. This value will increase by 1 for new variable. */ @@ -326,12 +333,13 @@ * {@linkplain TraceInterval variable}. */ private AllocatableValue allocateSpillSlot(TraceInterval interval) { + DebugContext debug = res.getLIR().getDebug(); int variableIndex = interval.splitParent().operandNumber; OptionValues options = getOptions(); if (TraceRegisterAllocationPhase.Options.TraceRACacheStackSlots.getValue(options)) { AllocatableValue cachedStackSlot = cachedStackSlots[variableIndex]; if (cachedStackSlot != null) { - TraceRegisterAllocationPhase.globalStackSlots.increment(); + TraceRegisterAllocationPhase.globalStackSlots.increment(debug); assert cachedStackSlot.getValueKind().equals(getKind(interval)) : "CachedStackSlot: kind mismatch? " + getKind(interval) + " vs. " + cachedStackSlot.getValueKind(); return cachedStackSlot; } @@ -340,7 +348,7 @@ if (TraceRegisterAllocationPhase.Options.TraceRACacheStackSlots.getValue(options)) { cachedStackSlots[variableIndex] = slot; } - TraceRegisterAllocationPhase.allocatedStackSlots.increment(); + TraceRegisterAllocationPhase.allocatedStackSlots.increment(debug); return slot; } @@ -531,8 +539,8 @@ TraceInterval result = interval.getSplitChildAtOpId(opId, mode); if (result != null) { - if (Debug.isLogEnabled()) { - Debug.log("Split child at pos %d of interval %s is %s", opId, interval, result); + if (getDebug().isLogEnabled()) { + getDebug().log("Split child at pos %d of interval %s is %s", opId, interval, result); } return result; } @@ -570,10 +578,11 @@ /* * This is the point to enable debug logging for the whole register allocation. */ - try (Indent indent = Debug.logAndIndent("LinearScan allocate")) { + DebugContext debug = res.getLIR().getDebug(); + try (Indent indent = debug.logAndIndent("LinearScan allocate")) { TRACE_LINEAR_SCAN_LIFETIME_ANALYSIS_PHASE.apply(target, lirGenRes, trace, spillMoveFactory, registerAllocationConfig, traceBuilderResult, this, false); - try (Scope s = Debug.scope("AfterLifetimeAnalysis", this)) { + try (DebugContext.Scope s = debug.scope("AfterLifetimeAnalysis", this)) { printLir("After instruction numbering"); printIntervals("Before register allocation"); @@ -598,14 +607,14 @@ verifyIntervals(); } } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } } public void printLir(String label) { - if (Debug.isDumpEnabled(Debug.DETAILED_LEVEL)) { - Debug.dump(Debug.DETAILED_LEVEL, sortedBlocks(), "%s (Trace%d)", label, trace.getId()); + if (getDebug().isDumpEnabled(DebugContext.DETAILED_LEVEL)) { + getDebug().dump(DebugContext.DETAILED_LEVEL, sortedBlocks(), "%s (Trace%d)", label, trace.getId()); } } @@ -616,7 +625,7 @@ verifyRegisters(); - Debug.log("no errors found"); + getDebug().log("no errors found"); return true; } @@ -624,7 +633,7 @@ @SuppressWarnings("try") private void verifyRegisters() { // Enable this logging to get output for the verification process. - try (Indent indent = Debug.logAndIndent("verifying register allocation")) { + try (Indent indent = getDebug().logAndIndent("verifying register allocation")) { RegisterVerifier verifier = new RegisterVerifier(this); verifier.verify(blockAt(0)); } @@ -632,7 +641,8 @@ @SuppressWarnings("try") protected void verifyIntervals() { - try (Indent indent = Debug.logAndIndent("verifying intervals")) { + DebugContext debug = getDebug(); + try (Indent indent = debug.logAndIndent("verifying intervals")) { int len = intervalsSize(); for (int i = 0; i < len; i++) { @@ -644,32 +654,32 @@ i1.checkSplitChildren(); if (i1.operandNumber != i) { - Debug.log("Interval %d is on position %d in list", i1.operandNumber, i); - Debug.log(i1.logString()); + debug.log("Interval %d is on position %d in list", i1.operandNumber, i); + debug.log(i1.logString()); throw new GraalError(""); } if (getKind(i1).equals(LIRKind.Illegal)) { - Debug.log("Interval %d has no type assigned", i1.operandNumber); - Debug.log(i1.logString()); + debug.log("Interval %d has no type assigned", i1.operandNumber); + debug.log(i1.logString()); throw new GraalError(""); } if (i1.location() == null) { - Debug.log("Interval %d has no register assigned", i1.operandNumber); - Debug.log(i1.logString()); + debug.log("Interval %d has no register assigned", i1.operandNumber); + debug.log(i1.logString()); throw new GraalError(""); } if (i1.isEmpty()) { - Debug.log("Interval %d has no Range", i1.operandNumber); - Debug.log(i1.logString()); + debug.log("Interval %d has no Range", i1.operandNumber); + debug.log(i1.logString()); throw new GraalError(""); } if (i1.from() >= i1.to()) { - Debug.log("Interval %d has zero length range", i1.operandNumber); - Debug.log(i1.logString()); + debug.log("Interval %d has zero length range", i1.operandNumber); + debug.log(i1.logString()); throw new GraalError(""); } @@ -958,29 +968,30 @@ @SuppressWarnings("try") public void printIntervals(String label) { - if (Debug.isDumpEnabled(Debug.DETAILED_LEVEL)) { - if (Debug.isLogEnabled()) { - try (Indent indent = Debug.logAndIndent("intervals %s", label)) { + DebugContext debug = getDebug(); + if (debug.isDumpEnabled(DebugContext.DETAILED_LEVEL)) { + if (debug.isLogEnabled()) { + try (Indent indent = debug.logAndIndent("intervals %s", label)) { for (FixedInterval interval : fixedIntervals) { if (interval != null) { - Debug.log("%s", interval.logString()); + debug.log("%s", interval.logString()); } } for (TraceInterval interval : intervals) { if (interval != null) { - Debug.log("%s", interval.logString()); + debug.log("%s", interval.logString()); } } - try (Indent indent2 = Debug.logAndIndent("Basic Blocks")) { + try (Indent indent2 = debug.logAndIndent("Basic Blocks")) { for (AbstractBlockBase block : trace.getBlocks()) { - Debug.log("B%d [%d, %d, %s] ", block.getId(), getFirstLirInstructionId(block), getLastLirInstructionId(block), block.getLoop()); + debug.log("B%d [%d, %d, %s] ", block.getId(), getFirstLirInstructionId(block), getLastLirInstructionId(block), block.getLoop()); } } } } - Debug.dump(Debug.DETAILED_LEVEL, this, "%s (Trace%d)", label, trace.getId()); + debug.dump(DebugContext.DETAILED_LEVEL, this, "%s (Trace%d)", label, trace.getId()); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceLinearScanRegisterAllocationPhase.java 2017-07-07 09:30:57.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceLinearScanRegisterAllocationPhase.java 2017-07-07 09:30:57.000000000 -0700 @@ -25,7 +25,7 @@ import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; import org.graalvm.compiler.core.common.alloc.Trace; import org.graalvm.compiler.core.common.alloc.TraceBuilderResult; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.alloc.trace.lsra.TraceLinearScanPhase.TraceLinearScan; import org.graalvm.compiler.lir.gen.LIRGenerationResult; @@ -43,7 +43,8 @@ @SuppressWarnings("try") private static void allocateRegisters(TraceLinearScan allocator) { - try (Indent indent = Debug.logAndIndent("allocate registers")) { + DebugContext debug = allocator.getDebug(); + try (Indent indent = debug.logAndIndent("allocate registers")) { FixedInterval precoloredIntervals = allocator.createFixedUnhandledList(); TraceInterval notPrecoloredIntervals = allocator.createUnhandledListByFrom(TraceLinearScanPhase.IS_VARIABLE_INTERVAL); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceLinearScanResolveDataFlowPhase.java 2017-07-07 09:30:58.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceLinearScanResolveDataFlowPhase.java 2017-07-07 09:30:58.000000000 -0700 @@ -36,8 +36,8 @@ import org.graalvm.compiler.core.common.alloc.Trace; import org.graalvm.compiler.core.common.alloc.TraceBuilderResult; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.LIRInstruction; @@ -69,16 +69,18 @@ private static final class Resolver { private final TraceLinearScan allocator; private final TraceBuilderResult traceBuilderResult; + private final DebugContext debug; private Resolver(TraceLinearScan allocator, TraceBuilderResult traceBuilderResult) { this.allocator = allocator; this.traceBuilderResult = traceBuilderResult; + this.debug = allocator.getDebug(); } private void resolveFindInsertPos(AbstractBlockBase fromBlock, AbstractBlockBase toBlock, TraceLocalMoveResolver moveResolver) { if (fromBlock.getSuccessorCount() <= 1) { - if (Debug.isLogEnabled()) { - Debug.log("inserting moves at end of fromBlock B%d", fromBlock.getId()); + if (debug.isLogEnabled()) { + debug.log("inserting moves at end of fromBlock B%d", fromBlock.getId()); } ArrayList instructions = allocator.getLIR().getLIRforBlock(fromBlock); @@ -91,8 +93,8 @@ } } else { - if (Debug.isLogEnabled()) { - Debug.log("inserting moves at beginning of toBlock B%d", toBlock.getId()); + if (debug.isLogEnabled()) { + debug.log("inserting moves at beginning of toBlock B%d", toBlock.getId()); } if (DetailedAsserts.getValue(allocator.getOptions())) { @@ -123,7 +125,7 @@ // no resolution necessary return; } - try (Indent indent = Debug.logAndIndent("resolve data flow")) { + try (Indent indent = debug.logAndIndent("resolve data flow")) { TraceLocalMoveResolver moveResolver = allocator.createMoveResolver(); AbstractBlockBase toBlock = null; @@ -148,7 +150,7 @@ @SuppressWarnings("try") private void resolveCollectMappings(AbstractBlockBase fromBlock, AbstractBlockBase toBlock, TraceLocalMoveResolver moveResolver) { - try (Indent indent0 = Debug.logAndIndent("Edge %s -> %s", fromBlock, toBlock)) { + try (Indent indent0 = debug.logAndIndent("Edge %s -> %s", fromBlock, toBlock)) { // collect all intervals that have been split between // fromBlock and toBlock int toId = allocator.getFirstLirInstructionId(toBlock); @@ -180,8 +182,8 @@ return currentTrace.getId() == traceBuilderResult.getTraceForBlock(block).getId(); } - private static final DebugCounter numResolutionMoves = Debug.counter("TraceRA[numTraceLSRAResolutionMoves]"); - private static final DebugCounter numStackToStackMoves = Debug.counter("TraceRA[numTraceLSRAStackToStackMoves]"); + private static final CounterKey numResolutionMoves = DebugContext.counter("TraceRA[numTraceLSRAResolutionMoves]"); + private static final CounterKey numStackToStackMoves = DebugContext.counter("TraceRA[numTraceLSRAStackToStackMoves]"); private void addMapping(Value phiFrom, Value phiTo, int fromId, int toId, TraceLocalMoveResolver moveResolver) { assert !isRegister(phiFrom) : "Out is a register: " + phiFrom; @@ -193,7 +195,7 @@ } TraceInterval toParent = allocator.intervalFor(asVariable(phiTo)); if (isConstantValue(phiFrom)) { - numResolutionMoves.increment(); + numResolutionMoves.increment(debug); TraceInterval toInterval = allocator.splitChildAtOpId(toParent, toId, LIRInstruction.OperandMode.DEF); moveResolver.addMapping(asConstant(phiFrom), toInterval); } else { @@ -209,9 +211,9 @@ return; } if (fromInterval != toInterval) { - numResolutionMoves.increment(); - if (numStackToStackMoves.isEnabled() && isStackSlotValue(toInterval.location()) && isStackSlotValue(fromInterval.location())) { - numStackToStackMoves.increment(); + numResolutionMoves.increment(debug); + if (isStackSlotValue(toInterval.location()) && isStackSlotValue(fromInterval.location())) { + numStackToStackMoves.increment(debug); } moveResolver.addMapping(fromInterval, toInterval); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceLinearScanWalker.java 2017-07-07 09:30:59.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceLinearScanWalker.java 2017-07-07 09:30:59.000000000 -0700 @@ -35,7 +35,7 @@ import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig.AllocatableRegisters; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; import org.graalvm.compiler.core.common.util.Util; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.LIRInstruction; @@ -175,6 +175,7 @@ private int maxReg; private final TraceLinearScan allocator; + private final DebugContext debug; /** * Sorted list of intervals, not live before the current position. @@ -222,6 +223,7 @@ TraceLinearScanWalker(TraceLinearScan allocator, FixedInterval unhandledFixedFirst, TraceInterval unhandledAnyFirst) { this.allocator = allocator; + this.debug = allocator.getDebug(); unhandledAnyList = unhandledAnyFirst; activeAnyList = TraceInterval.EndMarker; @@ -466,8 +468,8 @@ @SuppressWarnings({"unused"}) private int findOptimalSplitPos(TraceInterval interval, int minSplitPos, int maxSplitPos, boolean doLoopOptimization) { int optimalSplitPos = findOptimalSplitPos0(minSplitPos, maxSplitPos); - if (Debug.isLogEnabled()) { - Debug.log("optimal split position: %d", optimalSplitPos); + if (debug.isLogEnabled()) { + debug.log("optimal split position: %d", optimalSplitPos); } return optimalSplitPos; } @@ -475,8 +477,8 @@ private int findOptimalSplitPos0(int minSplitPos, int maxSplitPos) { if (minSplitPos == maxSplitPos) { // trivial case, no optimization of split position possible - if (Debug.isLogEnabled()) { - Debug.log("min-pos and max-pos are equal, no optimization possible"); + if (debug.isLogEnabled()) { + debug.log("min-pos and max-pos are equal, no optimization possible"); } return minSplitPos; @@ -499,15 +501,15 @@ assert minBlock.getLinearScanNumber() <= maxBlock.getLinearScanNumber() : "invalid order"; if (minBlock == maxBlock) { // split position cannot be moved to block boundary : so split as late as possible - if (Debug.isLogEnabled()) { - Debug.log("cannot move split pos to block boundary because minPos and maxPos are in same block"); + if (debug.isLogEnabled()) { + debug.log("cannot move split pos to block boundary because minPos and maxPos are in same block"); } return maxSplitPos; } // seach optimal block boundary between minSplitPos and maxSplitPos - if (Debug.isLogEnabled()) { - Debug.log("moving split pos to optimal block boundary between block B%d and B%d", minBlock.getId(), maxBlock.getId()); + if (debug.isLogEnabled()) { + debug.log("moving split pos to optimal block boundary between block B%d and B%d", minBlock.getId(), maxBlock.getId()); } return findOptimalSplitPos(minBlock, maxBlock, maxSplitPos); @@ -520,7 +522,7 @@ @SuppressWarnings("try") private void splitBeforeUsage(TraceInterval interval, int minSplitPos, int maxSplitPos) { - try (Indent indent = Debug.logAndIndent("splitting interval %s between %d and %d", interval, minSplitPos, maxSplitPos)) { + try (Indent indent = debug.logAndIndent("splitting interval %s between %d and %d", interval, minSplitPos, maxSplitPos)) { assert interval.from() < minSplitPos : "cannot split at start of interval"; assert currentPosition < minSplitPos : "cannot split before current position"; @@ -532,8 +534,8 @@ if (optimalSplitPos == interval.to() && interval.nextUsage(RegisterPriority.MustHaveRegister, minSplitPos) == Integer.MAX_VALUE) { // the split position would be just before the end of the interval // . no split at all necessary - if (Debug.isLogEnabled()) { - Debug.log("no split necessary because optimal split position is at end of interval"); + if (debug.isLogEnabled()) { + debug.log("no split necessary because optimal split position is at end of interval"); } return; } @@ -555,8 +557,8 @@ assert optimalSplitPosFinal <= interval.to() : "cannot split after end of interval"; assert optimalSplitPosFinal > interval.from() : "cannot split at start of interval"; - if (Debug.isLogEnabled()) { - Debug.log("splitting at position %d", optimalSplitPosFinal); + if (debug.isLogEnabled()) { + debug.log("splitting at position %d", optimalSplitPosFinal); } assert optimalSplitPosFinal > currentPosition : "Can not split interval " + interval + " at current position: " + currentPosition; @@ -567,8 +569,8 @@ if (optimalSplitPosFinal == interval.to() && interval.nextUsage(RegisterPriority.MustHaveRegister, minSplitPos) == Integer.MAX_VALUE) { // the split position would be just before the end of the interval // . no split at all necessary - if (Debug.isLogEnabled()) { - Debug.log("no split necessary because optimal split position is at end of interval"); + if (debug.isLogEnabled()) { + debug.log("no split necessary because optimal split position is at end of interval"); } return; } @@ -579,9 +581,9 @@ assert splitPart.from() >= currentPosition : "cannot append new interval before current walk position"; unhandledAnyList = TraceLinearScanWalker.addToListSortedByStartAndUsePositions(unhandledAnyList, splitPart); - if (Debug.isLogEnabled()) { - Debug.log("left interval %s: %s", moveNecessary ? " " : "", interval.logString()); - Debug.log("right interval %s: %s", moveNecessary ? "(move)" : "", splitPart.logString()); + if (debug.isLogEnabled()) { + debug.log("left interval %s: %s", moveNecessary ? " " : "", interval.logString()); + debug.log("right interval %s: %s", moveNecessary ? "(move)" : "", splitPart.logString()); } } } @@ -605,7 +607,7 @@ } int minSplitPos = Math.max(previousUsage + 1, interval.from()); - try (Indent indent = Debug.logAndIndent("splitting and spilling interval %s between %d and %d", interval, minSplitPos, maxSplitPos)) { + try (Indent indent = debug.logAndIndent("splitting and spilling interval %s between %d and %d", interval, minSplitPos, maxSplitPos)) { assert interval.from() <= minSplitPos : "cannot split before start of interval"; assert minSplitPos <= maxSplitPos : "invalid order"; @@ -615,7 +617,7 @@ if (minSplitPos == interval.from()) { // the whole interval is never used, so spill it entirely to memory - try (Indent indent2 = Debug.logAndIndent("spilling entire interval because split pos is at beginning of interval (use positions: %d)", interval.numUsePos())) { + try (Indent indent2 = debug.logAndIndent("spilling entire interval because split pos is at beginning of interval (use positions: %d)", interval.numUsePos())) { assert interval.firstUsage(RegisterPriority.MustHaveRegister) > currentPosition : String.format("interval %s must not have use position before currentPosition %d", interval, currentPosition); @@ -634,8 +636,8 @@ if (isRegister(parent.location())) { if (parent.firstUsage(RegisterPriority.ShouldHaveRegister) == Integer.MAX_VALUE) { // parent is never used, so kick it out of its assigned register - if (Debug.isLogEnabled()) { - Debug.log("kicking out interval %d out of its register because it is never used", parent.operandNumber); + if (debug.isLogEnabled()) { + debug.log("kicking out interval %d out of its register because it is never used", parent.operandNumber); } allocator.assignSpillSlot(parent); handleSpillSlot(parent); @@ -661,7 +663,7 @@ optimalSplitPos = (optimalSplitPos - 1) | 1; } - try (Indent indent2 = Debug.logAndIndent("splitting at position %d", optimalSplitPos)) { + try (Indent indent2 = debug.logAndIndent("splitting at position %d", optimalSplitPos)) { assert allocator.isBlockBegin(optimalSplitPos) || ((optimalSplitPos & 1) == 1) : "split pos must be odd when not on block boundary"; assert !allocator.isBlockBegin(optimalSplitPos) || ((optimalSplitPos & 1) == 0) : "split pos must be even on block boundary"; @@ -671,13 +673,13 @@ changeSpillState(spilledPart, optimalSplitPos); if (!allocator.isBlockBegin(optimalSplitPos)) { - if (Debug.isLogEnabled()) { - Debug.log("inserting move from interval %s to %s", interval, spilledPart); + if (debug.isLogEnabled()) { + debug.log("inserting move from interval %s to %s", interval, spilledPart); } insertMove(optimalSplitPos, interval, spilledPart); } else { - if (Debug.isLogEnabled()) { - Debug.log("no need to insert move. done by data-flow resolution"); + if (debug.isLogEnabled()) { + debug.log("no need to insert move. done by data-flow resolution"); } } @@ -685,9 +687,9 @@ assert spilledPart.currentSplitChild() == interval : "overwriting wrong currentSplitChild"; spilledPart.makeCurrentSplitChild(); - if (Debug.isLogEnabled()) { - Debug.log("left interval: %s", interval.logString()); - Debug.log("spilled interval : %s", spilledPart.logString()); + if (debug.isLogEnabled()) { + debug.log("left interval: %s", interval.logString()); + debug.log("spilled interval : %s", spilledPart.logString()); } } } @@ -795,8 +797,8 @@ */ private int findOptimalSpillPos(int minSpillPos, int maxSpillPos) { int optimalSpillPos = findOptimalSpillPos0(minSpillPos, maxSpillPos) & (~1); - if (Debug.isLogEnabled()) { - Debug.log("optimal spill position: %d", optimalSpillPos); + if (debug.isLogEnabled()) { + debug.log("optimal spill position: %d", optimalSpillPos); } return optimalSpillPos; } @@ -804,8 +806,8 @@ private int findOptimalSpillPos0(int minSpillPos, int maxSpillPos) { if (minSpillPos == maxSpillPos) { // trivial case, no optimization of split position possible - if (Debug.isLogEnabled()) { - Debug.log("min-pos and max-pos are equal, no optimization possible"); + if (debug.isLogEnabled()) { + debug.log("min-pos and max-pos are equal, no optimization possible"); } return minSpillPos; @@ -819,15 +821,15 @@ assert minBlock.getLinearScanNumber() <= maxBlock.getLinearScanNumber() : "invalid order"; if (minBlock == maxBlock) { // split position cannot be moved to block boundary : so split as late as possible - if (Debug.isLogEnabled()) { - Debug.log("cannot move split pos to block boundary because minPos and maxPos are in same block"); + if (debug.isLogEnabled()) { + debug.log("cannot move split pos to block boundary because minPos and maxPos are in same block"); } return maxSpillPos; } // search optimal block boundary between minSplitPos and maxSplitPos - if (Debug.isLogEnabled()) { - Debug.log("moving split pos to optimal block boundary between block B%d and B%d", minBlock.getId(), maxBlock.getId()); + if (debug.isLogEnabled()) { + debug.log("moving split pos to optimal block boundary between block B%d and B%d", minBlock.getId(), maxBlock.getId()); } // currently using the same heuristic as for splitting @@ -910,7 +912,7 @@ if (maxSplitPos <= interval.to()) { splitBeforeUsage(interval, minSplitPos, maxSplitPos); } else { - Debug.log("No more usage, no need to split: %s", interval); + debug.log("No more usage, no need to split: %s", interval); } assert interval.nextUsage(RegisterPriority.MustHaveRegister, currentPos) == Integer.MAX_VALUE : "the remaining part is spilled to stack and therefore has no register"; @@ -919,7 +921,7 @@ @SuppressWarnings("try") private boolean allocFreeRegister(TraceInterval interval) { - try (Indent indent = Debug.logAndIndent("trying to find free register for %s", interval)) { + try (Indent indent = debug.logAndIndent("trying to find free register for %s", interval)) { initUseLists(true); freeExcludeActiveFixed(); @@ -931,12 +933,12 @@ // (either as a fixed register or a normal allocated register in the past) // only intervals overlapping with cur are processed, non-overlapping invervals can be // ignored safely - if (Debug.isLogEnabled()) { + if (debug.isLogEnabled()) { // Enable this logging to see all register states - try (Indent indent2 = Debug.logAndIndent("state of registers:")) { + try (Indent indent2 = debug.logAndIndent("state of registers:")) { for (Register register : availableRegs) { int i = register.number; - Debug.log("reg %d (%s): usePos: %d", register.number, register, usePos[i]); + debug.log("reg %d (%s): usePos: %d", register.number, register, usePos[i]); } } } @@ -945,8 +947,8 @@ IntervalHint locationHint = interval.locationHint(true); if (locationHint != null && locationHint.location() != null && isRegister(locationHint.location())) { hint = asRegister(locationHint.location()); - if (Debug.isLogEnabled()) { - Debug.log("hint register %3d (%4s) from interval %s", hint.number, hint, locationHint); + if (debug.isLogEnabled()) { + debug.log("hint register %3d (%4s) from interval %s", hint.number, hint, locationHint); } } assert interval.location() == null : "register already assigned to interval"; @@ -988,8 +990,8 @@ splitPos = usePos[reg.number]; interval.assignLocation(reg.asValue(allocator.getKind(interval))); - if (Debug.isLogEnabled()) { - Debug.log("selected register %d (%s)", reg.number, reg); + if (debug.isLogEnabled()) { + debug.log("selected register %d (%s)", reg.number, reg); } assert splitPos > 0 : "invalid splitPos"; @@ -1015,7 +1017,7 @@ // Split an Interval and spill it to memory so that cur can be placed in a register @SuppressWarnings("try") private void allocLockedRegister(TraceInterval interval) { - try (Indent indent = Debug.logAndIndent("alloc locked register: need to split and spill to get register for %s", interval)) { + try (Indent indent = debug.logAndIndent("alloc locked register: need to split and spill to get register for %s", interval)) { // the register must be free at least until this position int firstUsage = interval.firstUsage(RegisterPriority.MustHaveRegister); @@ -1039,7 +1041,7 @@ // spillBlockUnhandledFixed(cur); spillBlockInactiveFixed(interval); spillCollectActiveAny(registerPriority); - if (Debug.isLogEnabled()) { + if (debug.isLogEnabled()) { printRegisterState(); } @@ -1061,16 +1063,16 @@ } } - if (Debug.isLogEnabled()) { - Debug.log("Register Selected: %s", reg); + if (debug.isLogEnabled()) { + debug.log("Register Selected: %s", reg); } int regUsePos = (reg == null ? 0 : usePos[reg.number]); if (regUsePos <= firstShouldHaveUsage) { /* Check if there is another interval that is already in memory. */ if (reg == null || interval.inMemoryAt(currentPosition) || !isInMemory.get(reg.number)) { - if (Debug.isLogEnabled()) { - Debug.log("able to spill current interval. firstUsage(register): %d, usePos: %d", firstUsage, regUsePos); + if (debug.isLogEnabled()) { + debug.log("able to spill current interval. firstUsage(register): %d, usePos: %d", firstUsage, regUsePos); } if (firstUsage <= interval.from() + 1) { @@ -1080,7 +1082,7 @@ * try to spill an active interval that has a usage but do not * require a register. */ - Debug.log("retry with register priority must have register"); + debug.log("retry with register priority must have register"); continue; } String description = "cannot spill interval (" + interval + ") that is used in first instruction (possible reason: no register found) firstUsage=" + firstUsage + @@ -1090,7 +1092,7 @@ * avoid errors */ allocator.assignSpillSlot(interval); - if (Debug.isDumpEnabled(Debug.INFO_LEVEL)) { + if (debug.isDumpEnabled(DebugContext.INFO_LEVEL)) { dumpLIRAndIntervals(description); } throw new OutOfRegistersException("LinearScan: no register found", description); @@ -1108,8 +1110,8 @@ int splitPos = blockPos[reg.number]; - if (Debug.isLogEnabled()) { - Debug.log("decided to use register %d", reg.number); + if (debug.isLogEnabled()) { + debug.log("decided to use register %d", reg.number); } assert splitPos > 0 : "invalid splitPos"; assert needSplit || splitPos > interval.from() : "splitting interval at from"; @@ -1127,18 +1129,18 @@ } private void dumpLIRAndIntervals(String description) { - Debug.dump(Debug.INFO_LEVEL, allocator.getLIR(), description); + debug.dump(DebugContext.INFO_LEVEL, allocator.getLIR(), description); allocator.printIntervals(description); } @SuppressWarnings("try") private void printRegisterState() { - try (Indent indent2 = Debug.logAndIndent("state of registers:")) { + try (Indent indent2 = debug.logAndIndent("state of registers:")) { for (Register reg : availableRegs) { int i = reg.number; - try (Indent indent3 = Debug.logAndIndent("reg %d: usePos: %d, blockPos: %d, inMemory: %b, intervals: ", i, usePos[i], blockPos[i], isInMemory.get(i))) { + try (Indent indent3 = debug.logAndIndent("reg %d: usePos: %d, blockPos: %d, inMemory: %b, intervals: ", i, usePos[i], blockPos[i], isInMemory.get(i))) { for (int j = 0; j < spillIntervals[i].size(); j++) { - Debug.log("%s", spillIntervals[i].get(j)); + debug.log("%s", spillIntervals[i].get(j)); } } } @@ -1157,8 +1159,8 @@ if (isOdd(pos)) { // the current instruction is a call that blocks all registers if (pos < allocator.maxOpId() && allocator.hasCall(pos + 1) && interval.to() > pos + 1) { - if (Debug.isLogEnabled()) { - Debug.log("free register cannot be available because all registers blocked by following call"); + if (debug.isLogEnabled()) { + debug.log("free register cannot be available because all registers blocked by following call"); } // safety check that there is really no register available @@ -1250,19 +1252,19 @@ // allocate a physical register or memory location to an interval @SuppressWarnings("try") private boolean activateCurrent(TraceInterval interval) { - if (Debug.isLogEnabled()) { + if (debug.isLogEnabled()) { logCurrentStatus(); } boolean result = true; - try (Indent indent = Debug.logAndIndent("activating interval %s, splitParent: %d", interval, interval.splitParent().operandNumber)) { + try (Indent indent = debug.logAndIndent("activating interval %s, splitParent: %d", interval, interval.splitParent().operandNumber)) { if (interval.location() != null && isStackSlotValue(interval.location())) { // activating an interval that has a stack slot assigned . split it at first use // position // used for method parameters - if (Debug.isLogEnabled()) { - Debug.log("interval has spill slot assigned (method parameter) . split it before first use"); + if (debug.isLogEnabled()) { + debug.log("interval has spill slot assigned (method parameter) . split it before first use"); } splitStackInterval(interval); result = false; @@ -1271,8 +1273,8 @@ if (interval.location() == null) { // interval has not assigned register . normal allocation // (this is the normal case for most intervals) - if (Debug.isLogEnabled()) { - Debug.log("normal allocation of register"); + if (debug.isLogEnabled()) { + debug.log("normal allocation of register"); } // assign same spill slot to non-intersecting intervals @@ -1297,8 +1299,8 @@ assert interval.isSplitChild(); assert interval.currentSplitChild() != null; assert interval.currentSplitChild().operandNumber != interval.operandNumber : "cannot insert move between same interval"; - if (Debug.isLogEnabled()) { - Debug.log("Inserting move from interval %d to %d because insertMoveWhenActivated is set", interval.currentSplitChild().operandNumber, interval.operandNumber); + if (debug.isLogEnabled()) { + debug.log("Inserting move from interval %d to %d because insertMoveWhenActivated is set", interval.currentSplitChild().operandNumber, interval.operandNumber); } insertMove(interval.from(), interval.currentSplitChild(), interval); @@ -1317,12 +1319,12 @@ @SuppressWarnings("try") private void logCurrentStatus() { - try (Indent i = Debug.logAndIndent("active:")) { - logList(activeFixedList); - logList(activeAnyList); + try (Indent i = debug.logAndIndent("active:")) { + logList(debug, activeFixedList); + logList(debug, activeAnyList); } - try (Indent i = Debug.logAndIndent("inactive(fixed):")) { - logList(inactiveFixedList); + try (Indent i = debug.logAndIndent("inactive(fixed):")) { + logList(debug, inactiveFixedList); } } @@ -1347,9 +1349,9 @@ FixedInterval prevprev = null; FixedInterval prev = (state == State.Active) ? activeFixedList : inactiveFixedList; FixedInterval next = prev; - if (Debug.isLogEnabled()) { - try (Indent i = Debug.logAndIndent("walkToFixed(%s, %d):", state, from)) { - logList(next); + if (debug.isLogEnabled()) { + try (Indent i = debug.logAndIndent("walkToFixed(%s, %d):", state, from)) { + logList(debug, next); } } while (next.currentFrom() <= from) { @@ -1397,7 +1399,7 @@ prev = cur.next; } } - intervalMoved(cur, state, newState); + intervalMoved(debug, cur, state, newState); } else { prevprev = prev; prev = cur.next; @@ -1416,9 +1418,9 @@ TraceInterval prevprev = null; TraceInterval prev = activeAnyList; TraceInterval next = prev; - if (Debug.isLogEnabled()) { - try (Indent i = Debug.logAndIndent("walkToAny(%d):", from)) { - logList(next); + if (debug.isLogEnabled()) { + try (Indent i = debug.logAndIndent("walkToAny(%d):", from)) { + logList(debug, next); } } while (next.from() <= from) { @@ -1432,7 +1434,7 @@ } else { prevprev.next = next; } - intervalMoved(cur, State.Active, State.Handled); + intervalMoved(debug, cur, State.Active, State.Handled); } else { prevprev = prev; } @@ -1489,10 +1491,10 @@ walkToFixed(State.Inactive, opId); walkToAny(opId); - try (Indent indent = Debug.logAndIndent("walk to op %d", opId)) { + try (Indent indent = debug.logAndIndent("walk to op %d", opId)) { if (activateCurrent(currentInterval)) { activeAnyList = TraceLinearScanWalker.addToListSortedByFromPositions(activeAnyList, currentInterval); - intervalMoved(currentInterval, State.Unhandled, State.Active); + intervalMoved(debug, currentInterval, State.Unhandled, State.Active); } } } @@ -1510,23 +1512,23 @@ } } - private static void logList(FixedInterval i) { + private static void logList(DebugContext debug, FixedInterval i) { for (FixedInterval interval = i; interval != FixedInterval.EndMarker; interval = interval.next) { - Debug.log("%s", interval.logString()); + debug.log("%s", interval.logString()); } } - private static void logList(TraceInterval i) { + private static void logList(DebugContext debug, TraceInterval i) { for (TraceInterval interval = i; interval != TraceInterval.EndMarker; interval = interval.next) { - Debug.log("%s", interval.logString()); + debug.log("%s", interval.logString()); } } - private static void intervalMoved(IntervalHint interval, State from, State to) { + private static void intervalMoved(DebugContext debug, IntervalHint interval, State from, State to) { // intervalMoved() is called whenever an interval moves from one interval list to another. // In the implementation of this method it is prohibited to move the interval to any list. - if (Debug.isLogEnabled()) { - Debug.log("interval moved from %s to %s: %s", from, to, interval.logString()); + if (debug.isLogEnabled()) { + debug.log("interval moved from %s to %s: %s", from, to, interval.logString()); } } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceLocalMoveResolver.java 2017-07-07 09:30:59.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceLocalMoveResolver.java 2017-07-07 09:30:59.000000000 -0700 @@ -37,8 +37,8 @@ import java.util.List; import org.graalvm.compiler.core.common.LIRKind; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.LIRInsertionBuffer; @@ -54,11 +54,9 @@ import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.Value; -/** - */ final class TraceLocalMoveResolver { - private static final DebugCounter cycleBreakingSlotsAllocated = Debug.counter("TraceRA[cycleBreakingSlotsAllocated(local)]"); + private static final CounterKey cycleBreakingSlotsAllocated = DebugContext.counter("TraceRA[cycleBreakingSlotsAllocated(local)]"); private static final int STACK_SLOT_IN_CALLER_FRAME_IDX = -1; private final TraceLinearScan allocator; @@ -74,6 +72,8 @@ private int[] stackBlocked; private final int firstVirtualStackIndex; + private final DebugContext debug; + private int getStackArrayIndex(Value stackSlotValue) { if (isStackSlot(stackSlotValue)) { return getStackArrayIndex(asStackSlot(stackSlotValue)); @@ -168,6 +168,7 @@ protected TraceLocalMoveResolver(TraceLinearScan allocator) { this.allocator = allocator; + this.debug = allocator.getDebug(); this.mappingFrom = new ArrayList<>(8); this.mappingFromOpr = new ArrayList<>(8); this.mappingTo = new ArrayList<>(8); @@ -256,7 +257,7 @@ assert areMultipleReadsAllowed() || valueBlocked(location) == 0 : "location already marked as used: " + location; int direction = 1; setValueBlocked(location, direction); - Debug.log("block %s", location); + debug.log("block %s", location); } } @@ -266,7 +267,7 @@ if (mightBeBlocked(location)) { assert valueBlocked(location) > 0 : "location already marked as unused: " + location; setValueBlocked(location, -1); - Debug.log("unblock %s", location); + debug.log("unblock %s", location); } } @@ -329,8 +330,8 @@ insertionBuffer.append(insertIdx, createMove(allocator.getOperand(fromInterval), allocator.getOperand(toInterval), fromInterval.location(), toInterval.location())); - if (Debug.isLogEnabled()) { - Debug.log("insert move from %s to %s at %d", fromInterval, toInterval, insertIdx); + if (debug.isLogEnabled()) { + debug.log("insert move from %s to %s at %d", fromInterval, toInterval, insertIdx); } } @@ -354,16 +355,16 @@ LIRInstruction move = getAllocator().getSpillMoveFactory().createLoad(toOpr, fromOpr); insertionBuffer.append(insertIdx, move); - if (Debug.isLogEnabled()) { - Debug.log("insert move from value %s to %s at %d", fromOpr, toInterval, insertIdx); + if (debug.isLogEnabled()) { + debug.log("insert move from value %s to %s at %d", fromOpr, toInterval, insertIdx); } } @SuppressWarnings("try") private void resolveMappings() { - try (Indent indent = Debug.logAndIndent("resolveMapping")) { + try (Indent indent = debug.logAndIndent("resolveMapping")) { assert verifyBeforeResolve(); - if (Debug.isLogEnabled()) { + if (debug.isLogEnabled()) { printMapping(); } @@ -438,7 +439,7 @@ if (spillSlot1 == null) { spillSlot1 = getAllocator().getFrameMapBuilder().allocateSpillSlot(allocator.getKind(fromInterval1)); fromInterval1.setSpillSlot(spillSlot1); - cycleBreakingSlotsAllocated.increment(); + cycleBreakingSlotsAllocated.increment(debug); } spillInterval(spillCandidate, fromInterval1, spillSlot1); return; @@ -463,8 +464,8 @@ spillInterval.assignLocation(spillSlot); - if (Debug.isLogEnabled()) { - Debug.log("created new Interval for spilling: %s", spillInterval); + if (debug.isLogEnabled()) { + debug.log("created new Interval for spilling: %s", spillInterval); } blockRegisters(spillInterval); @@ -476,7 +477,7 @@ @SuppressWarnings("try") private void printMapping() { - try (Indent indent = Debug.logAndIndent("Mapping")) { + try (Indent indent = debug.logAndIndent("Mapping")) { for (int i = mappingFrom.size() - 1; i >= 0; i--) { TraceInterval fromInterval = mappingFrom.get(i); TraceInterval toInterval = mappingTo.get(i); @@ -487,7 +488,7 @@ } else { from = fromInterval.location().toString(); } - Debug.log("move %s <- %s", from, to); + debug.log("move %s <- %s", from, to); } } } @@ -520,8 +521,8 @@ public void addMapping(TraceInterval fromInterval, TraceInterval toInterval) { if (isIllegal(toInterval.location()) && toInterval.canMaterialize()) { - if (Debug.isLogEnabled()) { - Debug.log("no store to rematerializable interval %s needed", toInterval); + if (debug.isLogEnabled()) { + debug.log("no store to rematerializable interval %s needed", toInterval); } return; } @@ -531,8 +532,8 @@ addMapping(rematValue, toInterval); return; } - if (Debug.isLogEnabled()) { - Debug.log("add move mapping from %s to %s", fromInterval, toInterval); + if (debug.isLogEnabled()) { + debug.log("add move mapping from %s to %s", fromInterval, toInterval); } assert fromInterval.operandNumber != toInterval.operandNumber : "from and to interval equal: " + fromInterval; @@ -544,8 +545,8 @@ } public void addMapping(Constant fromOpr, TraceInterval toInterval) { - if (Debug.isLogEnabled()) { - Debug.log("add move mapping from %s to %s", fromOpr, toInterval); + if (debug.isLogEnabled()) { + debug.log("add move mapping from %s to %s", fromOpr, toInterval); } mappingFrom.add(null); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java 2017-07-07 09:31:00.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java 2017-07-07 09:31:00.000000000 -0700 @@ -34,16 +34,16 @@ import org.graalvm.compiler.asm.AbstractAddress; import org.graalvm.compiler.asm.Assembler; -import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.code.CompilationResult.CodeAnnotation; import org.graalvm.compiler.code.DataSection.Data; import org.graalvm.compiler.code.DataSection.RawData; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; import org.graalvm.compiler.core.common.type.DataPointerConstant; import org.graalvm.compiler.debug.Assertions; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.NodeSourcePosition; import org.graalvm.compiler.lir.LIR; @@ -145,18 +145,19 @@ private List exceptionInfoList; private final OptionValues options; + private final DebugContext debug; private final EconomicMap dataCache; private Consumer beforeOp; private Consumer afterOp; public CompilationResultBuilder(CodeCacheProvider codeCache, ForeignCallsProvider foreignCalls, FrameMap frameMap, Assembler asm, DataBuilder dataBuilder, FrameContext frameContext, - OptionValues options, CompilationResult compilationResult) { - this(codeCache, foreignCalls, frameMap, asm, dataBuilder, frameContext, options, compilationResult, EconomicMap.create(Equivalence.DEFAULT)); + OptionValues options, DebugContext debug, CompilationResult compilationResult) { + this(codeCache, foreignCalls, frameMap, asm, dataBuilder, frameContext, options, debug, compilationResult, EconomicMap.create(Equivalence.DEFAULT)); } public CompilationResultBuilder(CodeCacheProvider codeCache, ForeignCallsProvider foreignCalls, FrameMap frameMap, Assembler asm, DataBuilder dataBuilder, FrameContext frameContext, - OptionValues options, CompilationResult compilationResult, EconomicMap dataCache) { + OptionValues options, DebugContext debug, CompilationResult compilationResult, EconomicMap dataCache) { this.target = codeCache.getTarget(); this.codeCache = codeCache; this.foreignCalls = foreignCalls; @@ -166,6 +167,7 @@ this.compilationResult = compilationResult; this.frameContext = frameContext; this.options = options; + this.debug = debug; assert frameContext != null; this.dataCache = dataCache; @@ -263,7 +265,7 @@ public void recordInlineDataInCode(Constant data) { assert data != null; int pos = asm.position(); - Debug.log("Inline data in code: pos = %d, data = %s", pos, data); + debug.log("Inline data in code: pos = %d, data = %s", pos, data); if (data instanceof VMConstant) { compilationResult.recordDataPatch(pos, new ConstantReference((VMConstant) data)); } @@ -272,7 +274,7 @@ public void recordInlineDataInCodeWithNote(Constant data, Object note) { assert data != null; int pos = asm.position(); - Debug.log("Inline data in code: pos = %d, data = %s, note = %s", pos, data, note); + debug.log("Inline data in code: pos = %d, data = %s, note = %s", pos, data, note); if (data instanceof VMConstant) { compilationResult.recordDataPatchWithNote(pos, new ConstantReference((VMConstant) data), note); } @@ -292,7 +294,7 @@ public AbstractAddress recordDataReferenceInCode(Constant constant, int alignment) { assert constant != null; - Debug.log("Constant reference in code: pos = %d, data = %s", asm.position(), constant); + debug.log("Constant reference in code: pos = %d, data = %s", asm.position(), constant); Data data = dataCache.get(constant); if (data == null) { data = dataBuilder.createDataItem(constant); @@ -304,8 +306,8 @@ public AbstractAddress recordDataReferenceInCode(byte[] data, int alignment) { assert data != null; - if (Debug.isLogEnabled()) { - Debug.log("Data reference in code: pos = %d, data = %s", asm.position(), Arrays.toString(data)); + if (debug.isLogEnabled()) { + debug.log("Data reference in code: pos = %d, data = %s", asm.position(), Arrays.toString(data)); } return recordDataSectionReference(new RawData(data, alignment)); } @@ -461,7 +463,7 @@ if (block == null) { return; } - boolean emitComment = Debug.isDumpEnabled(Debug.BASIC_LEVEL) || PrintLIRWithAssembly.getValue(getOptions()); + boolean emitComment = debug.isDumpEnabled(DebugContext.BASIC_LEVEL) || PrintLIRWithAssembly.getValue(getOptions()); if (emitComment) { blockComment(String.format("block B%d %s", block.getId(), block.getLoop())); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilderFactory.java 2017-07-07 09:31:01.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilderFactory.java 2017-07-07 09:31:00.000000000 -0700 @@ -25,6 +25,7 @@ import org.graalvm.compiler.asm.Assembler; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.lir.framemap.FrameMap; import org.graalvm.compiler.options.OptionValues; @@ -39,7 +40,7 @@ * Creates a new {@link CompilationResultBuilder}. */ CompilationResultBuilder createBuilder(CodeCacheProvider codeCache, ForeignCallsProvider foreignCalls, FrameMap frameMap, Assembler asm, DataBuilder dataBuilder, FrameContext frameContext, - OptionValues options, CompilationResult compilationResult); + OptionValues options, DebugContext debug, CompilationResult compilationResult); /** * The default factory creates a standard {@link CompilationResultBuilder}. @@ -48,8 +49,8 @@ @Override public CompilationResultBuilder createBuilder(CodeCacheProvider codeCache, ForeignCallsProvider foreignCalls, FrameMap frameMap, Assembler asm, DataBuilder dataBuilder, - FrameContext frameContext, OptionValues options, CompilationResult compilationResult) { - return new CompilationResultBuilder(codeCache, foreignCalls, frameMap, asm, dataBuilder, frameContext, options, compilationResult); + FrameContext frameContext, OptionValues options, DebugContext debug, CompilationResult compilationResult) { + return new CompilationResultBuilder(codeCache, foreignCalls, frameMap, asm, dataBuilder, frameContext, options, debug, compilationResult); } }; } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/ConstantLoadOptimization.java 2017-07-07 09:31:01.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/ConstantLoadOptimization.java 2017-07-07 09:31:01.000000000 -0700 @@ -35,9 +35,8 @@ import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; import org.graalvm.compiler.core.common.cfg.BlockMap; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.InstructionValueConsumer; import org.graalvm.compiler.lir.LIR; @@ -82,12 +81,12 @@ new Optimization(lirGenRes.getLIR(), lirGen).apply(); } - private static final DebugCounter constantsTotal = Debug.counter("ConstantLoadOptimization[total]"); - private static final DebugCounter phiConstantsSkipped = Debug.counter("ConstantLoadOptimization[PhisSkipped]"); - private static final DebugCounter singleUsageConstantsSkipped = Debug.counter("ConstantLoadOptimization[SingleUsageSkipped]"); - private static final DebugCounter usageAtDefinitionSkipped = Debug.counter("ConstantLoadOptimization[UsageAtDefinitionSkipped]"); - private static final DebugCounter materializeAtDefinitionSkipped = Debug.counter("ConstantLoadOptimization[MaterializeAtDefinitionSkipped]"); - private static final DebugCounter constantsOptimized = Debug.counter("ConstantLoadOptimization[optimized]"); + private static final CounterKey constantsTotal = DebugContext.counter("ConstantLoadOptimization[total]"); + private static final CounterKey phiConstantsSkipped = DebugContext.counter("ConstantLoadOptimization[PhisSkipped]"); + private static final CounterKey singleUsageConstantsSkipped = DebugContext.counter("ConstantLoadOptimization[SingleUsageSkipped]"); + private static final CounterKey usageAtDefinitionSkipped = DebugContext.counter("ConstantLoadOptimization[UsageAtDefinitionSkipped]"); + private static final CounterKey materializeAtDefinitionSkipped = DebugContext.counter("ConstantLoadOptimization[MaterializeAtDefinitionSkipped]"); + private static final CounterKey constantsOptimized = DebugContext.counter("ConstantLoadOptimization[optimized]"); private static final class Optimization { private final LIR lir; @@ -97,9 +96,11 @@ private final BitSet defined; private final BlockMap> blockMap; private final BlockMap insertionBuffers; + private final DebugContext debug; private Optimization(LIR lir, LIRGeneratorTool lirGen) { this.lir = lir; + this.debug = lir.getDebug(); this.lirGen = lirGen; this.map = new VariableMap<>(); this.phiConstants = new BitSet(); @@ -110,8 +111,8 @@ @SuppressWarnings("try") private void apply() { - try (Indent indent = Debug.logAndIndent("ConstantLoadOptimization")) { - try (Scope s = Debug.scope("BuildDefUseTree")) { + try (Indent indent = debug.logAndIndent("ConstantLoadOptimization")) { + try (DebugContext.Scope s = debug.scope("BuildDefUseTree")) { // build DefUseTree for (AbstractBlockBase b : lir.getControlFlowGraph().getBlocks()) { this.analyzeBlock(b); @@ -121,17 +122,17 @@ if (t.usageCount() > 1) { return true; } else { - singleUsageConstantsSkipped.increment(); + singleUsageConstantsSkipped.increment(debug); return false; } }); // collect block map map.forEach(tree -> tree.forEach(this::addUsageToBlockMap)); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } - try (Scope s = Debug.scope("BuildConstantTree")) { + try (DebugContext.Scope s = debug.scope("BuildConstantTree")) { // create ConstantTree map.forEach(this::createConstantTree); @@ -142,7 +143,7 @@ assert verifyStates(); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } } @@ -191,7 +192,7 @@ */ @SuppressWarnings("try") private void analyzeBlock(AbstractBlockBase block) { - try (Indent indent = Debug.logAndIndent("Block: %s", block)) { + try (Indent indent = debug.logAndIndent("Block: %s", block)) { InstructionValueConsumer loadConsumer = (instruction, value, mode, flags) -> { if (isVariable(value)) { @@ -201,19 +202,19 @@ if (!defined.get(var.index)) { defined.set(var.index); if (isConstantLoad(instruction)) { - Debug.log("constant load: %s", instruction); + debug.log("constant load: %s", instruction); map.put(var, new DefUseTree(instruction, block)); - constantsTotal.increment(); + constantsTotal.increment(debug); } } else { // Variable is redefined, this only happens for constant loads // introduced by phi resolution -> ignore. DefUseTree removed = map.remove(var); if (removed != null) { - phiConstantsSkipped.increment(); + phiConstantsSkipped.increment(debug); } phiConstants.set(var.index); - Debug.log(Debug.VERBOSE_LEVEL, "Removing phi variable: %s", var); + debug.log(DebugContext.VERBOSE_LEVEL, "Removing phi variable: %s", var); } } else { assert defined.get(var.index) : "phi but not defined? " + var; @@ -228,7 +229,7 @@ DefUseTree tree = map.get(var); if (tree != null) { tree.addUsage(block, instruction, value); - Debug.log("usage of %s : %s", var, instruction); + debug.log("usage of %s : %s", var, instruction); } } } @@ -257,40 +258,40 @@ if (constTree.get(Flags.USAGE, tree.getBlock())) { // usage in the definition block -> no optimization - usageAtDefinitionSkipped.increment(); + usageAtDefinitionSkipped.increment(debug); return; } constTree.markBlocks(); - NodeCost cost = ConstantTreeAnalyzer.analyze(constTree, tree.getBlock()); + NodeCost cost = ConstantTreeAnalyzer.analyze(debug, constTree, tree.getBlock()); int usageCount = cost.getUsages().size(); assert usageCount == tree.usageCount() : "Usage count differs: " + usageCount + " vs. " + tree.usageCount(); - if (Debug.isLogEnabled()) { - try (Indent i = Debug.logAndIndent("Variable: %s, Block: %s, prob.: %f", tree.getVariable(), tree.getBlock(), tree.getBlock().probability())) { - Debug.log("Usages result: %s", cost); + if (debug.isLogEnabled()) { + try (Indent i = debug.logAndIndent("Variable: %s, Block: %s, prob.: %f", tree.getVariable(), tree.getBlock(), tree.getBlock().probability())) { + debug.log("Usages result: %s", cost); } } if (cost.getNumMaterializations() > 1 || cost.getBestCost() < tree.getBlock().probability()) { - try (Scope s = Debug.scope("CLOmodify", constTree); Indent i = Debug.logAndIndent("Replacing %s = %s", tree.getVariable(), tree.getConstant().toValueString())) { + try (DebugContext.Scope s = debug.scope("CLOmodify", constTree); Indent i = debug.logAndIndent("Replacing %s = %s", tree.getVariable(), tree.getConstant().toValueString())) { // mark original load for removal deleteInstruction(tree); - constantsOptimized.increment(); + constantsOptimized.increment(debug); // collect result createLoads(tree, constTree, tree.getBlock()); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } else { // no better solution found - materializeAtDefinitionSkipped.increment(); + materializeAtDefinitionSkipped.increment(debug); } - Debug.dump(Debug.DETAILED_LEVEL, constTree, "ConstantTree for %s", tree.getVariable()); + debug.dump(DebugContext.DETAILED_LEVEL, constTree, "ConstantTree for %s", tree.getVariable()); } private void createLoads(DefUseTree tree, ConstantTree constTree, AbstractBlockBase startBlock) { @@ -322,11 +323,11 @@ LIRInstruction move = lirGen.getSpillMoveFactory().createLoad(variable, constant); // insert instruction getInsertionBuffer(block).append(1, move); - Debug.log("new move (%s) and inserted in block %s", move, block); + debug.log("new move (%s) and inserted in block %s", move, block); // update usages for (UseEntry u : usages) { u.setValue(variable); - Debug.log("patched instruction %s", u.getInstruction()); + debug.log("patched instruction %s", u.getInstruction()); } } @@ -361,7 +362,7 @@ private void deleteInstruction(DefUseTree tree) { AbstractBlockBase block = tree.getBlock(); LIRInstruction instruction = tree.getInstruction(); - Debug.log("deleting instruction %s from block %s", instruction, block); + debug.log("deleting instruction %s from block %s", instruction, block); lir.getLIRforBlock(block).set(instruction.id(), null); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/ConstantTreeAnalyzer.java 2017-07-07 09:31:02.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/ConstantTreeAnalyzer.java 2017-07-07 09:31:02.000000000 -0700 @@ -29,8 +29,7 @@ import java.util.List; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.constopt.ConstantTree.Flags; import org.graalvm.compiler.lir.constopt.ConstantTree.NodeCost; @@ -43,13 +42,13 @@ private final BitSet visited; @SuppressWarnings("try") - public static NodeCost analyze(ConstantTree tree, AbstractBlockBase startBlock) { - try (Scope s = Debug.scope("ConstantTreeAnalyzer")) { + public static NodeCost analyze(DebugContext debug, ConstantTree tree, AbstractBlockBase startBlock) { + try (DebugContext.Scope s = debug.scope("ConstantTreeAnalyzer")) { ConstantTreeAnalyzer analyzer = new ConstantTreeAnalyzer(tree); - analyzer.analyzeBlocks(startBlock); + analyzer.analyzeBlocks(debug, startBlock); return tree.getCost(startBlock); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } @@ -67,33 +66,33 @@ * @param startBlock The start block of the dominator subtree. */ @SuppressWarnings("try") - private void analyzeBlocks(AbstractBlockBase startBlock) { + private void analyzeBlocks(DebugContext debug, AbstractBlockBase startBlock) { Deque> worklist = new ArrayDeque<>(); worklist.offerLast(startBlock); while (!worklist.isEmpty()) { AbstractBlockBase block = worklist.pollLast(); - try (Indent i = Debug.logAndIndent(Debug.VERBOSE_LEVEL, "analyze: %s", block)) { + try (Indent i = debug.logAndIndent(DebugContext.VERBOSE_LEVEL, "analyze: %s", block)) { assert block != null : "worklist is empty!"; assert isMarked(block) : "Block not part of the dominator tree: " + block; if (isLeafBlock(block)) { - Debug.log(Debug.VERBOSE_LEVEL, "leaf block"); + debug.log(DebugContext.VERBOSE_LEVEL, "leaf block"); leafCost(block); continue; } if (!visited.get(block.getId())) { // if not yet visited (and not a leaf block) process all children first! - Debug.log(Debug.VERBOSE_LEVEL, "not marked"); + debug.log(DebugContext.VERBOSE_LEVEL, "not marked"); worklist.offerLast(block); AbstractBlockBase dominated = block.getFirstDominated(); while (dominated != null) { - filteredPush(worklist, dominated); + filteredPush(debug, worklist, dominated); dominated = dominated.getDominatedSibling(); } visited.set(block.getId()); } else { - Debug.log(Debug.VERBOSE_LEVEL, "marked"); + debug.log(DebugContext.VERBOSE_LEVEL, "marked"); // otherwise, process block process(block); } @@ -160,9 +159,9 @@ return probabilityBlock * Math.pow(0.9, numMat - 1) < probabilityChildren; } - private void filteredPush(Deque> worklist, AbstractBlockBase block) { + private void filteredPush(DebugContext debug, Deque> worklist, AbstractBlockBase block) { if (isMarked(block)) { - Debug.log(Debug.VERBOSE_LEVEL, "adding %s to the worklist", block); + debug.log(DebugContext.VERBOSE_LEVEL, "adding %s to the worklist", block); worklist.offerLast(block); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/debug/LIRGenerationDebugContext.java 2017-07-07 09:31:02.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/debug/LIRGenerationDebugContext.java 2017-07-07 09:31:02.000000000 -0700 @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.lir.debug; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.lir.LIR; import jdk.vm.ci.meta.Value; @@ -38,17 +38,17 @@ */ Object getSourceForOperand(Value value); - static LIRGenerationDebugContext getFromDebugContext() { - if (Debug.isEnabled()) { - LIRGenerationDebugContext lirGen = Debug.contextLookup(LIRGenerationDebugContext.class); + static LIRGenerationDebugContext getFromDebugContext(DebugContext debug) { + if (debug.areScopesEnabled()) { + LIRGenerationDebugContext lirGen = debug.contextLookup(LIRGenerationDebugContext.class); assert lirGen != null; return lirGen; } return null; } - static Object getSourceForOperandFromDebugContext(Value value) { - LIRGenerationDebugContext gen = getFromDebugContext(); + static Object getSourceForOperandFromDebugContext(DebugContext debug, Value value) { + LIRGenerationDebugContext gen = getFromDebugContext(debug); if (gen != null) { return gen.getSourceForOperand(value); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/dfa/LocationMarker.java 2017-07-07 09:31:03.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/dfa/LocationMarker.java 2017-07-07 09:31:03.000000000 -0700 @@ -30,7 +30,7 @@ import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; import org.graalvm.compiler.core.common.cfg.BlockMap; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.InstructionStateProcedure; import org.graalvm.compiler.lir.LIR; @@ -102,7 +102,8 @@ @SuppressWarnings("try") private void processBlock(AbstractBlockBase block, UniqueWorkList worklist) { if (updateOutBlock(block)) { - try (Indent indent = Debug.logAndIndent("handle block %s", block)) { + DebugContext debug = lir.getDebug(); + try (Indent indent = debug.logAndIndent("handle block %s", block)) { currentSet = liveOutMap.get(block).copy(); ArrayList instructions = lir.getLIRforBlock(block); for (int i = instructions.size() - 1; i >= 0; i--) { @@ -128,7 +129,8 @@ */ @SuppressWarnings("try") private void processInstructionBottomUp(LIRInstruction op) { - try (Indent indent = Debug.logAndIndent("handle op %d, %s", op.id(), op)) { + DebugContext debug = lir.getDebug(); + try (Indent indent = debug.logAndIndent("handle op %d, %s", op.id(), op)) { // kills op.visitEachTemp(defConsumer); @@ -162,8 +164,9 @@ public void visitValue(Value operand, OperandMode mode, EnumSet flags) { if (shouldProcessValue(operand)) { // no need to insert values and derived reference - if (Debug.isLogEnabled()) { - Debug.log("set operand: %s", operand); + DebugContext debug = lir.getDebug(); + if (debug.isLogEnabled()) { + debug.log("set operand: %s", operand); } currentSet.put(operand); } @@ -174,8 +177,9 @@ @Override public void visitValue(Value operand, OperandMode mode, EnumSet flags) { if (shouldProcessValue(operand)) { - if (Debug.isLogEnabled()) { - Debug.log("clear operand: %s", operand); + DebugContext debug = lir.getDebug(); + if (debug.isLogEnabled()) { + debug.log("clear operand: %s", operand); } currentSet.remove(operand); } else { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/framemap/FrameMapBuilderImpl.java 2017-07-07 09:31:04.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/framemap/FrameMapBuilderImpl.java 2017-07-07 09:31:03.000000000 -0700 @@ -31,7 +31,7 @@ import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.lir.InstructionValueConsumer; import org.graalvm.compiler.lir.LIR; @@ -118,7 +118,8 @@ @Override @SuppressWarnings("try") public FrameMap buildFrameMap(LIRGenerationResult res) { - if (Debug.isEnabled()) { + DebugContext debug = res.getLIR().getDebug(); + if (debug.areScopesEnabled()) { verifyStackSlotAllocation(res); } for (CallingConvention cc : calls) { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGenerationResult.java 2017-07-07 09:31:04.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGenerationResult.java 2017-07-07 09:31:04.000000000 -0700 @@ -24,7 +24,7 @@ import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.common.CompilationIdentifier.Verbosity; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.framemap.FrameMap; @@ -65,7 +65,8 @@ * Adds a comment to a {@link LIRInstruction}. Existing comments are replaced. */ public final void setComment(LIRInstruction op, String comment) { - if (Debug.isDumpEnabled(Debug.BASIC_LEVEL)) { + DebugContext debug = lir.getDebug(); + if (debug.isDumpEnabled(DebugContext.BASIC_LEVEL)) { if (comments == null) { comments = EconomicMap.create(Equivalence.IDENTITY); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGenerator.java 2017-07-07 09:31:05.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGenerator.java 2017-07-07 09:31:04.000000000 -0700 @@ -47,6 +47,7 @@ import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.graph.NodeSourcePosition; import org.graalvm.compiler.lir.ConstantValue; +import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.LIRFrameState; import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.LIRVerifier; @@ -302,12 +303,13 @@ @Override public I append(I op) { + LIR lir = res.getLIR(); if (printIrWithLir) { TTY.println(op.toStringWithIdPrefix()); TTY.println(); } assert LIRVerifier.verify(op); - ArrayList lirForBlock = res.getLIR().getLIRforBlock(getCurrentBlock()); + ArrayList lirForBlock = lir.getLIRforBlock(getCurrentBlock()); op.setPosition(currentPosition); lirForBlock.add(op); return op; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/phases/EconomyAllocationStage.java 2017-07-07 09:31:05.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/phases/EconomyAllocationStage.java 2017-07-07 09:31:05.000000000 -0700 @@ -22,14 +22,26 @@ */ package org.graalvm.compiler.lir.phases; +import static org.graalvm.compiler.core.common.GraalOptions.TraceRA; + import org.graalvm.compiler.lir.alloc.lsra.LinearScanPhase; +import org.graalvm.compiler.lir.alloc.trace.GlobalLivenessAnalysisPhase; +import org.graalvm.compiler.lir.alloc.trace.TraceBuilderPhase; +import org.graalvm.compiler.lir.alloc.trace.TraceRegisterAllocationPhase; import org.graalvm.compiler.lir.dfa.LocationMarkerPhase; import org.graalvm.compiler.lir.phases.AllocationPhase.AllocationContext; import org.graalvm.compiler.lir.stackslotalloc.SimpleStackSlotAllocator; +import org.graalvm.compiler.options.OptionValues; public class EconomyAllocationStage extends LIRPhaseSuite { - public EconomyAllocationStage() { - appendPhase(new LinearScanPhase()); + public EconomyAllocationStage(OptionValues options) { + if (TraceRA.getValue(options)) { + appendPhase(new TraceBuilderPhase()); + appendPhase(new GlobalLivenessAnalysisPhase()); + appendPhase(new TraceRegisterAllocationPhase()); + } else { + appendPhase(new LinearScanPhase()); + } // build frame map appendPhase(new SimpleStackSlotAllocator()); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/phases/LIRPhase.java 2017-07-07 09:31:06.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/phases/LIRPhase.java 2017-07-07 09:31:06.000000000 -0700 @@ -24,11 +24,10 @@ import java.util.regex.Pattern; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; import org.graalvm.compiler.debug.DebugCloseable; -import org.graalvm.compiler.debug.DebugMemUseTracker; -import org.graalvm.compiler.debug.DebugTimer; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.MemUseTrackerKey; +import org.graalvm.compiler.debug.TimerKey; import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.gen.LIRGenerationResult; import org.graalvm.compiler.options.Option; @@ -53,27 +52,27 @@ /** * Records time spent within {@link #apply}. */ - private final DebugTimer timer; + private final TimerKey timer; /** * Records memory usage within {@link #apply}. */ - private final DebugMemUseTracker memUseTracker; + private final MemUseTrackerKey memUseTracker; public static final class LIRPhaseStatistics { /** * Records time spent within {@link #apply}. */ - public final DebugTimer timer; + public final TimerKey timer; /** * Records memory usage within {@link #apply}. */ - public final DebugMemUseTracker memUseTracker; + public final MemUseTrackerKey memUseTracker; public LIRPhaseStatistics(Class clazz) { - timer = Debug.timer("LIRPhaseTime_%s", clazz); - memUseTracker = Debug.memUseTracker("LIRPhaseMemUse_%s", clazz); + timer = DebugContext.timer("LIRPhaseTime_%s", clazz); + memUseTracker = DebugContext.memUseTracker("LIRPhaseMemUse_%s", clazz); } } @@ -110,23 +109,25 @@ @SuppressWarnings("try") public final void apply(TargetDescription target, LIRGenerationResult lirGenRes, C context, boolean dumpLIR) { - try (Scope s = Debug.scope(getName(), this)) { - try (DebugCloseable a = timer.start(); DebugCloseable c = memUseTracker.start()) { + DebugContext debug = lirGenRes.getLIR().getDebug(); + try (DebugContext.Scope s = debug.scope(getName(), this)) { + try (DebugCloseable a = timer.start(debug); DebugCloseable c = memUseTracker.start(debug)) { run(target, lirGenRes, context); - if (dumpLIR && Debug.isEnabled()) { + if (dumpLIR && debug.areScopesEnabled()) { dumpAfter(lirGenRes); } } } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } private void dumpAfter(LIRGenerationResult lirGenRes) { boolean isStage = this instanceof LIRPhaseSuite; if (!isStage) { - if (Debug.isDumpEnabled(Debug.INFO_LEVEL)) { - Debug.dump(Debug.INFO_LEVEL, lirGenRes.getLIR(), "After %s", getName()); + DebugContext debug = lirGenRes.getLIR().getDebug(); + if (debug.isDumpEnabled(DebugContext.INFO_LEVEL)) { + debug.dump(DebugContext.INFO_LEVEL, lirGenRes.getLIR(), "After %s", getName()); } } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ssa/SSAVerifier.java 2017-07-07 09:31:07.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ssa/SSAVerifier.java 2017-07-07 09:31:06.000000000 -0700 @@ -23,17 +23,16 @@ package org.graalvm.compiler.lir.ssa; +import static jdk.vm.ci.code.ValueUtil.isRegister; import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant; import static org.graalvm.compiler.lir.LIRValueUtil.isStackSlotValue; -import static jdk.vm.ci.code.ValueUtil.isRegister; import java.util.BitSet; import java.util.EnumSet; import java.util.HashMap; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.InstructionValueConsumer; import org.graalvm.compiler.lir.LIR; @@ -67,12 +66,13 @@ @SuppressWarnings("try") public boolean verify() { - try (Scope s = Debug.scope("SSAVerifier", lir)) { + DebugContext debug = lir.getDebug(); + try (DebugContext.Scope s = debug.scope("SSAVerifier", lir)) { for (AbstractBlockBase block : lir.getControlFlowGraph().getBlocks()) { doBlock(block); } } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } return true; } @@ -87,7 +87,7 @@ doBlock(pred); } } - try (Indent indent = Debug.logAndIndent(Debug.INFO_LEVEL, "handle block %s", b)) { + try (Indent indent = lir.getDebug().logAndIndent(DebugContext.INFO_LEVEL, "handle block %s", b)) { assert verifyBlock(b); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/FixPointIntervalBuilder.java 2017-07-07 09:31:07.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/FixPointIntervalBuilder.java 2017-07-07 09:31:07.000000000 -0700 @@ -33,8 +33,8 @@ import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; import org.graalvm.compiler.core.common.cfg.BlockMap; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.InstructionValueConsumer; import org.graalvm.compiler.lir.InstructionValueProcedure; @@ -42,9 +42,9 @@ import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.LIRInstruction.OperandFlag; import org.graalvm.compiler.lir.LIRInstruction.OperandMode; -import org.graalvm.util.Equivalence; -import org.graalvm.util.EconomicSet; import org.graalvm.compiler.lir.VirtualStackSlot; +import org.graalvm.util.EconomicSet; +import org.graalvm.util.Equivalence; import jdk.vm.ci.meta.Value; @@ -62,7 +62,7 @@ /** * The number of allocated stack slots. */ - private static final DebugCounter uninitializedSlots = Debug.counter("StackSlotAllocator[uninitializedSlots]"); + private static final CounterKey uninitializedSlots = DebugContext.counter("StackSlotAllocator[uninitializedSlots]"); FixPointIntervalBuilder(LIR lir, StackInterval[] stackSlotMap, int maxOpId) { this.lir = lir; @@ -113,8 +113,9 @@ @SuppressWarnings("try") private void processBlock(AbstractBlockBase block, Deque> worklist) { + DebugContext debug = lir.getDebug(); if (updateOutBlock(block)) { - try (Indent indent = Debug.logAndIndent("handle block %s", block)) { + try (Indent indent = debug.logAndIndent("handle block %s", block)) { ArrayList instructions = lir.getLIRforBlock(block); // get out set and mark intervals BitSet outSet = liveOutMap.get(block); @@ -143,9 +144,10 @@ @SuppressWarnings("try") private void printLiveSet(String label, BitSet liveSet) { - if (Debug.isLogEnabled()) { - try (Indent indent = Debug.logAndIndent(label)) { - Debug.log("%s", liveSetToString(liveSet)); + DebugContext debug = lir.getDebug(); + if (debug.isLogEnabled()) { + try (Indent indent = debug.logAndIndent(label)) { + debug.log("%s", liveSetToString(liveSet)); } } } @@ -160,17 +162,19 @@ } private void markOutInterval(BitSet outSet, int blockEndOpId) { + DebugContext debug = lir.getDebug(); for (int i = outSet.nextSetBit(0); i >= 0; i = outSet.nextSetBit(i + 1)) { StackInterval interval = getIntervalFromStackId(i); - Debug.log("mark live operand: %s", interval.getOperand()); + debug.log("mark live operand: %s", interval.getOperand()); interval.addTo(blockEndOpId); } } private void markInInterval(BitSet inSet, int blockFirstOpId) { + DebugContext debug = lir.getDebug(); for (int i = inSet.nextSetBit(0); i >= 0; i = inSet.nextSetBit(i + 1)) { StackInterval interval = getIntervalFromStackId(i); - Debug.log("mark live operand: %s", interval.getOperand()); + debug.log("mark live operand: %s", interval.getOperand()); interval.addFrom(blockFirstOpId); } } @@ -192,7 +196,8 @@ */ @SuppressWarnings("try") private void processInstructionBottomUp(LIRInstruction op) { - try (Indent indent = Debug.logAndIndent("handle op %d, %s", op.id(), op)) { + DebugContext debug = lir.getDebug(); + try (Indent indent = debug.logAndIndent("handle op %d, %s", op.id(), op)) { // kills op.visitEachTemp(defConsumer); op.visitEachOutput(defConsumer); @@ -210,11 +215,12 @@ @Override public void visitValue(LIRInstruction inst, Value operand, OperandMode mode, EnumSet flags) { if (isVirtualStackSlot(operand)) { + DebugContext debug = lir.getDebug(); VirtualStackSlot vslot = asVirtualStackSlot(operand); addUse(vslot, inst, flags); addRegisterHint(inst, vslot, mode, flags, false); usePos.add(inst); - Debug.log("set operand: %s", operand); + debug.log("set operand: %s", operand); currentSet.set(vslot.getId()); } } @@ -224,11 +230,12 @@ @Override public void visitValue(LIRInstruction inst, Value operand, OperandMode mode, EnumSet flags) { if (isVirtualStackSlot(operand)) { + DebugContext debug = lir.getDebug(); VirtualStackSlot vslot = asVirtualStackSlot(operand); addDef(vslot, inst); addRegisterHint(inst, vslot, mode, flags, true); usePos.add(inst); - Debug.log("clear operand: %s", operand); + debug.log("clear operand: %s", operand); currentSet.clear(vslot.getId()); } @@ -240,8 +247,9 @@ if (flags.contains(OperandFlag.UNINITIALIZED)) { // Stack slot is marked uninitialized so we have to assume it is live all // the time. - if (Debug.isCountEnabled() && !(interval.from() == 0 && interval.to() == maxOpId)) { - uninitializedSlots.increment(); + DebugContext debug = lir.getDebug(); + if (debug.isCountEnabled() && !(interval.from() == 0 && interval.to() == maxOpId)) { + uninitializedSlots.increment(debug); } interval.addFrom(0); interval.addTo(maxOpId); @@ -270,8 +278,9 @@ } else { from.setLocationHint(to); } - if (Debug.isLogEnabled()) { - Debug.log("operation %s at opId %d: added hint from interval %s to %s", op, op.id(), from, to); + DebugContext debug = lir.getDebug(); + if (debug.isLogEnabled()) { + debug.log("operation %s at opId %d: added hint from interval %s to %s", op, op.id(), from, to); } return registerHint; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/LSStackSlotAllocator.java 2017-07-07 09:31:07.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/LSStackSlotAllocator.java 2017-07-07 09:31:07.000000000 -0700 @@ -22,6 +22,7 @@ */ package org.graalvm.compiler.lir.stackslotalloc; +import static org.graalvm.compiler.debug.DebugContext.BASIC_LEVEL; import static org.graalvm.compiler.lir.LIRValueUtil.asVirtualStackSlot; import static org.graalvm.compiler.lir.LIRValueUtil.isVirtualStackSlot; import static org.graalvm.compiler.lir.phases.LIRPhase.Options.LIROptimization; @@ -35,11 +36,10 @@ import java.util.PriorityQueue; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; import org.graalvm.compiler.debug.DebugCloseable; -import org.graalvm.compiler.debug.DebugTimer; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; +import org.graalvm.compiler.debug.TimerKey; import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.LIRInstruction.OperandFlag; @@ -80,12 +80,12 @@ // @formatter:on } - private static final DebugTimer MainTimer = Debug.timer("LSStackSlotAllocator"); - private static final DebugTimer NumInstTimer = Debug.timer("LSStackSlotAllocator[NumberInstruction]"); - private static final DebugTimer BuildIntervalsTimer = Debug.timer("LSStackSlotAllocator[BuildIntervals]"); - private static final DebugTimer VerifyIntervalsTimer = Debug.timer("LSStackSlotAllocator[VerifyIntervals]"); - private static final DebugTimer AllocateSlotsTimer = Debug.timer("LSStackSlotAllocator[AllocateSlots]"); - private static final DebugTimer AssignSlotsTimer = Debug.timer("LSStackSlotAllocator[AssignSlots]"); + private static final TimerKey MainTimer = DebugContext.timer("LSStackSlotAllocator"); + private static final TimerKey NumInstTimer = DebugContext.timer("LSStackSlotAllocator[NumberInstruction]"); + private static final TimerKey BuildIntervalsTimer = DebugContext.timer("LSStackSlotAllocator[BuildIntervals]"); + private static final TimerKey VerifyIntervalsTimer = DebugContext.timer("LSStackSlotAllocator[VerifyIntervals]"); + private static final TimerKey AllocateSlotsTimer = DebugContext.timer("LSStackSlotAllocator[AllocateSlots]"); + private static final TimerKey AssignSlotsTimer = DebugContext.timer("LSStackSlotAllocator[AssignSlots]"); @Override protected void run(TargetDescription target, LIRGenerationResult lirGenRes, AllocationContext context) { @@ -96,7 +96,7 @@ @SuppressWarnings("try") public static void allocateStackSlots(FrameMapBuilderTool builder, LIRGenerationResult res) { if (builder.getNumberOfStackSlots() > 0) { - try (DebugCloseable t = MainTimer.start()) { + try (DebugCloseable t = MainTimer.start(res.getLIR().getDebug())) { new Allocator(res.getLIR(), builder).allocate(); } } @@ -105,6 +105,7 @@ private static final class Allocator { private final LIR lir; + private final DebugContext debug; private final FrameMapBuilderTool frameMapBuilder; private final StackInterval[] stackSlotMap; private final PriorityQueue unhandled; @@ -115,6 +116,7 @@ @SuppressWarnings("try") private Allocator(LIR lir, FrameMapBuilderTool frameMapBuilder) { this.lir = lir; + this.debug = lir.getDebug(); this.frameMapBuilder = frameMapBuilder; this.stackSlotMap = new StackInterval[frameMapBuilder.getNumberOfStackSlots()]; this.sortedBlocks = lir.getControlFlowGraph().getBlocks(); @@ -124,7 +126,7 @@ // insert by to this.active = new PriorityQueue<>((a, b) -> a.to() - b.to()); - try (DebugCloseable t = NumInstTimer.start()) { + try (DebugCloseable t = NumInstTimer.start(debug)) { // step 1: number instructions this.maxOpId = numberInstructions(lir, sortedBlocks); } @@ -132,37 +134,38 @@ @SuppressWarnings("try") private void allocate() { - Debug.dump(Debug.VERBOSE_LEVEL, lir, "After StackSlot numbering"); + debug.dump(DebugContext.VERBOSE_LEVEL, lir, "After StackSlot numbering"); - long currentFrameSize = StackSlotAllocatorUtil.allocatedFramesize.isEnabled() ? frameMapBuilder.getFrameMap().currentFrameSize() : 0; + boolean allocationFramesizeEnabled = StackSlotAllocatorUtil.allocatedFramesize.isEnabled(debug); + long currentFrameSize = allocationFramesizeEnabled ? frameMapBuilder.getFrameMap().currentFrameSize() : 0; EconomicSet usePos; // step 2: build intervals - try (Scope s = Debug.scope("StackSlotAllocationBuildIntervals"); Indent indent = Debug.logAndIndent("BuildIntervals"); DebugCloseable t = BuildIntervalsTimer.start()) { + try (DebugContext.Scope s = debug.scope("StackSlotAllocationBuildIntervals"); Indent indent = debug.logAndIndent("BuildIntervals"); DebugCloseable t = BuildIntervalsTimer.start(debug)) { usePos = buildIntervals(); } // step 3: verify intervals - if (Debug.isEnabled()) { - try (DebugCloseable t = VerifyIntervalsTimer.start()) { + if (debug.areScopesEnabled()) { + try (DebugCloseable t = VerifyIntervalsTimer.start(debug)) { assert verifyIntervals(); } } - if (Debug.isDumpEnabled(Debug.VERBOSE_LEVEL)) { + if (debug.isDumpEnabled(DebugContext.VERBOSE_LEVEL)) { dumpIntervals("Before stack slot allocation"); } // step 4: allocate stack slots - try (DebugCloseable t = AllocateSlotsTimer.start()) { + try (DebugCloseable t = AllocateSlotsTimer.start(debug)) { allocateStackSlots(); } - if (Debug.isDumpEnabled(Debug.VERBOSE_LEVEL)) { + if (debug.isDumpEnabled(DebugContext.VERBOSE_LEVEL)) { dumpIntervals("After stack slot allocation"); } // step 5: assign stack slots - try (DebugCloseable t = AssignSlotsTimer.start()) { + try (DebugCloseable t = AssignSlotsTimer.start(debug)) { assignStackSlots(usePos); } - if (StackSlotAllocatorUtil.allocatedFramesize.isEnabled()) { - StackSlotAllocatorUtil.allocatedFramesize.add(frameMapBuilder.getFrameMap().currentFrameSize() - currentFrameSize); + if (allocationFramesizeEnabled) { + StackSlotAllocatorUtil.allocatedFramesize.add(debug, frameMapBuilder.getFrameMap().currentFrameSize() - currentFrameSize); } } @@ -230,7 +233,7 @@ } for (StackInterval current = activateNext(); current != null; current = activateNext()) { - try (Indent indent = Debug.logAndIndent("allocate %s", current)) { + try (Indent indent = debug.logAndIndent("allocate %s", current)) { allocateSlot(current); } } @@ -244,8 +247,8 @@ // No reuse of ranges (yet). VirtualStackSlotRange slotRange = (VirtualStackSlotRange) virtualSlot; location = frameMapBuilder.getFrameMap().allocateStackSlots(slotRange.getSlots(), slotRange.getObjects()); - StackSlotAllocatorUtil.virtualFramesize.add(frameMapBuilder.getFrameMap().spillSlotRangeSize(slotRange.getSlots())); - StackSlotAllocatorUtil.allocatedSlots.increment(); + StackSlotAllocatorUtil.virtualFramesize.add(debug, frameMapBuilder.getFrameMap().spillSlotRangeSize(slotRange.getSlots())); + StackSlotAllocatorUtil.allocatedSlots.increment(debug); } else { assert virtualSlot instanceof SimpleVirtualStackSlot : "Unexpected VirtualStackSlot type: " + virtualSlot; StackSlot slot = findFreeSlot((SimpleVirtualStackSlot) virtualSlot); @@ -255,17 +258,17 @@ * might not match. */ location = StackSlot.get(current.kind(), slot.getRawOffset(), slot.getRawAddFrameSize()); - StackSlotAllocatorUtil.reusedSlots.increment(); - Debug.log(Debug.BASIC_LEVEL, "Reuse stack slot %s (reallocated from %s) for virtual stack slot %s", location, slot, virtualSlot); + StackSlotAllocatorUtil.reusedSlots.increment(debug); + debug.log(BASIC_LEVEL, "Reuse stack slot %s (reallocated from %s) for virtual stack slot %s", location, slot, virtualSlot); } else { // Allocate new stack slot. location = frameMapBuilder.getFrameMap().allocateSpillSlot(virtualSlot.getValueKind()); - StackSlotAllocatorUtil.virtualFramesize.add(frameMapBuilder.getFrameMap().spillSlotSize(virtualSlot.getValueKind())); - StackSlotAllocatorUtil.allocatedSlots.increment(); - Debug.log(Debug.BASIC_LEVEL, "New stack slot %s for virtual stack slot %s", location, virtualSlot); + StackSlotAllocatorUtil.virtualFramesize.add(debug, frameMapBuilder.getFrameMap().spillSlotSize(virtualSlot.getValueKind())); + StackSlotAllocatorUtil.allocatedSlots.increment(debug); + debug.log(BASIC_LEVEL, "New stack slot %s for virtual stack slot %s", location, virtualSlot); } } - Debug.log("Allocate location %s for interval %s", location, current); + debug.log("Allocate location %s for interval %s", location, current); current.setLocation(location); } @@ -364,7 +367,7 @@ for (int id = next.from(); activePeekId() < id;) { finished(active.poll()); } - Debug.log("active %s", next); + debug.log("active %s", next); active.add(next); return next; } @@ -386,7 +389,7 @@ */ private void finished(StackInterval interval) { StackSlot location = interval.location(); - Debug.log("finished %s (freeing %s)", interval, location); + debug.log("finished %s (freeing %s)", interval, location); freeSlot(location); } @@ -434,7 +437,7 @@ } private void dumpIntervals(String label) { - Debug.dump(Debug.VERBOSE_LEVEL, new StackIntervalDumper(Arrays.copyOf(stackSlotMap, stackSlotMap.length)), label); + debug.dump(DebugContext.VERBOSE_LEVEL, new StackIntervalDumper(Arrays.copyOf(stackSlotMap, stackSlotMap.length)), label); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/SimpleStackSlotAllocator.java 2017-07-07 09:31:08.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/SimpleStackSlotAllocator.java 2017-07-07 09:31:08.000000000 -0700 @@ -29,10 +29,9 @@ import static org.graalvm.compiler.lir.stackslotalloc.StackSlotAllocatorUtil.virtualFramesize; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; -import org.graalvm.compiler.debug.Indent; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.ValueProcedure; import org.graalvm.compiler.lir.VirtualStackSlot; @@ -54,44 +53,47 @@ } public void allocateStackSlots(FrameMapBuilderTool builder, LIRGenerationResult res) { + DebugContext debug = res.getLIR().getDebug(); StackSlot[] mapping = new StackSlot[builder.getNumberOfStackSlots()]; - long currentFrameSize = allocatedFramesize.isEnabled() ? builder.getFrameMap().currentFrameSize() : 0; + boolean allocatedFramesizeEnabled = allocatedFramesize.isEnabled(debug); + long currentFrameSize = allocatedFramesizeEnabled ? builder.getFrameMap().currentFrameSize() : 0; for (VirtualStackSlot virtualSlot : builder.getStackSlots()) { final StackSlot slot; if (virtualSlot instanceof SimpleVirtualStackSlot) { slot = mapSimpleVirtualStackSlot(builder, (SimpleVirtualStackSlot) virtualSlot); - virtualFramesize.add(builder.getFrameMap().spillSlotSize(virtualSlot.getValueKind())); + virtualFramesize.add(debug, builder.getFrameMap().spillSlotSize(virtualSlot.getValueKind())); } else if (virtualSlot instanceof VirtualStackSlotRange) { VirtualStackSlotRange slotRange = (VirtualStackSlotRange) virtualSlot; slot = mapVirtualStackSlotRange(builder, slotRange); - virtualFramesize.add(builder.getFrameMap().spillSlotRangeSize(slotRange.getSlots())); + virtualFramesize.add(debug, builder.getFrameMap().spillSlotRangeSize(slotRange.getSlots())); } else { throw GraalError.shouldNotReachHere("Unknown VirtualStackSlot: " + virtualSlot); } - allocatedSlots.increment(); + allocatedSlots.increment(debug); mapping[virtualSlot.getId()] = slot; } updateLIR(res, mapping); - if (allocatedFramesize.isEnabled()) { - allocatedFramesize.add(builder.getFrameMap().currentFrameSize() - currentFrameSize); + if (allocatedFramesizeEnabled) { + allocatedFramesize.add(debug, builder.getFrameMap().currentFrameSize() - currentFrameSize); } } @SuppressWarnings("try") protected void updateLIR(LIRGenerationResult res, StackSlot[] mapping) { - try (Scope scope = Debug.scope("StackSlotMappingLIR")) { + DebugContext debug = res.getLIR().getDebug(); + try (DebugContext.Scope scope = debug.scope("StackSlotMappingLIR")) { ValueProcedure updateProc = (value, mode, flags) -> { if (isVirtualStackSlot(value)) { StackSlot stackSlot = mapping[asVirtualStackSlot(value).getId()]; - Debug.log("map %s -> %s", value, stackSlot); + debug.log("map %s -> %s", value, stackSlot); return stackSlot; } return value; }; for (AbstractBlockBase block : res.getLIR().getControlFlowGraph().getBlocks()) { - try (Indent indent0 = Debug.logAndIndent("block: %s", block)) { + try (Indent indent0 = debug.logAndIndent("block: %s", block)) { for (LIRInstruction inst : res.getLIR().getLIRforBlock(block)) { - try (Indent indent1 = Debug.logAndIndent("Inst: %d: %s", inst.id(), inst)) { + try (Indent indent1 = debug.logAndIndent("Inst: %d: %s", inst.id(), inst)) { inst.forEachAlive(updateProc); inst.forEachInput(updateProc); inst.forEachOutput(updateProc); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/StackSlotAllocatorUtil.java 2017-07-07 09:31:08.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/StackSlotAllocatorUtil.java 2017-07-07 09:31:08.000000000 -0700 @@ -22,8 +22,8 @@ */ package org.graalvm.compiler.lir.stackslotalloc; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.lir.VirtualStackSlot; import org.graalvm.compiler.lir.gen.LIRGenerationResult; @@ -38,16 +38,16 @@ /** * The number of allocated stack slots. */ - public static DebugCounter allocatedSlots = Debug.counter("StackSlotAllocator[allocatedSlots]"); + public static CounterKey allocatedSlots = DebugContext.counter("StackSlotAllocator[allocatedSlots]"); /** * The number of reused stack slots. */ - public static DebugCounter reusedSlots = Debug.counter("StackSlotAllocator[reusedSlots]"); + public static CounterKey reusedSlots = DebugContext.counter("StackSlotAllocator[reusedSlots]"); /** * The size (in bytes) required for all allocated stack slots. Note that this number corresponds * to the actual frame size and might include alignment. */ - public static DebugCounter allocatedFramesize = Debug.counter("StackSlotAllocator[AllocatedFramesize]"); + public static CounterKey allocatedFramesize = DebugContext.counter("StackSlotAllocator[AllocatedFramesize]"); /** The size (in bytes) required for all virtual stack slots. */ - public static DebugCounter virtualFramesize = Debug.counter("StackSlotAllocator[VirtualFramesize]"); + public static CounterKey virtualFramesize = DebugContext.counter("StackSlotAllocator[VirtualFramesize]"); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopFullUnrollPhase.java 2017-07-07 09:31:09.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopFullUnrollPhase.java 2017-07-07 09:31:08.000000000 -0700 @@ -22,8 +22,8 @@ */ package org.graalvm.compiler.loop.phases; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.loop.LoopEx; import org.graalvm.compiler.loop.LoopPolicies; import org.graalvm.compiler.loop.LoopsData; @@ -33,7 +33,7 @@ public class LoopFullUnrollPhase extends LoopPhase { - private static final DebugCounter FULLY_UNROLLED_LOOPS = Debug.counter("FullUnrolls"); + private static final CounterKey FULLY_UNROLLED_LOOPS = DebugContext.counter("FullUnrolls"); private final CanonicalizerPhase canonicalizer; public LoopFullUnrollPhase(CanonicalizerPhase canonicalizer, LoopPolicies policies) { @@ -43,6 +43,7 @@ @Override protected void run(StructuredGraph graph, PhaseContext context) { + DebugContext debug = graph.getDebug(); if (graph.hasLoops()) { boolean peeled; do { @@ -51,10 +52,10 @@ dataCounted.detectedCountedLoops(); for (LoopEx loop : dataCounted.countedLoops()) { if (getPolicies().shouldFullUnroll(loop)) { - Debug.log("FullUnroll %s", loop); + debug.log("FullUnroll %s", loop); LoopTransformations.fullUnroll(loop, context, canonicalizer); - FULLY_UNROLLED_LOOPS.increment(); - Debug.dump(Debug.DETAILED_LEVEL, graph, "FullUnroll %s", loop); + FULLY_UNROLLED_LOOPS.increment(debug); + debug.dump(DebugContext.DETAILED_LEVEL, graph, "FullUnroll %s", loop); peeled = true; break; } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopPeelingPhase.java 2017-07-07 09:31:09.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopPeelingPhase.java 2017-07-07 09:31:09.000000000 -0700 @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.loop.phases; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.loop.LoopEx; import org.graalvm.compiler.loop.LoopPolicies; import org.graalvm.compiler.loop.LoopsData; @@ -38,19 +38,20 @@ @Override @SuppressWarnings("try") protected void run(StructuredGraph graph, PhaseContext context) { + DebugContext debug = graph.getDebug(); if (graph.hasLoops()) { LoopsData data = new LoopsData(graph); - try (Debug.Scope s = Debug.scope("peeling", data.getCFG())) { + try (DebugContext.Scope s = debug.scope("peeling", data.getCFG())) { for (LoopEx loop : data.outerFirst()) { if (getPolicies().shouldPeel(loop, data.getCFG(), context.getMetaAccess())) { - Debug.log("Peeling %s", loop); + debug.log("Peeling %s", loop); LoopTransformations.peel(loop); - Debug.dump(Debug.DETAILED_LEVEL, graph, "Peeling %s", loop); + debug.dump(DebugContext.DETAILED_LEVEL, graph, "Peeling %s", loop); } } data.deleteUnusedNodes(); } catch (Throwable t) { - throw Debug.handle(t); + throw debug.handle(t); } } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopTransformations.java 2017-07-07 09:31:09.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopTransformations.java 2017-07-07 09:31:09.000000000 -0700 @@ -23,25 +23,56 @@ package org.graalvm.compiler.loop.phases; import static org.graalvm.compiler.core.common.GraalOptions.MaximumDesiredSize; +import static org.graalvm.compiler.loop.MathUtil.add; +import static org.graalvm.compiler.loop.MathUtil.sub; import java.util.ArrayList; import java.util.Iterator; import java.util.List; -import org.graalvm.compiler.graph.Graph.Mark; import org.graalvm.compiler.core.common.RetryableBailoutException; +import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.graph.Graph.Mark; +import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.graph.NodeWorkList; import org.graalvm.compiler.graph.Position; +import org.graalvm.compiler.loop.BasicInductionVariable; +import org.graalvm.compiler.loop.CountedLoopInfo; +import org.graalvm.compiler.loop.DerivedInductionVariable; +import org.graalvm.compiler.loop.InductionVariable; +import org.graalvm.compiler.loop.InductionVariable.Direction; import org.graalvm.compiler.loop.LoopEx; +import org.graalvm.compiler.loop.LoopFragmentInside; import org.graalvm.compiler.loop.LoopFragmentWhole; import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodes.AbstractBeginNode; +import org.graalvm.compiler.nodes.AbstractEndNode; +import org.graalvm.compiler.nodes.AbstractMergeNode; import org.graalvm.compiler.nodes.BeginNode; +import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.ControlSplitNode; +import org.graalvm.compiler.nodes.EndNode; +import org.graalvm.compiler.nodes.FixedNode; +import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.IfNode; +import org.graalvm.compiler.nodes.LogicNode; import org.graalvm.compiler.nodes.LoopBeginNode; +import org.graalvm.compiler.nodes.LoopEndNode; +import org.graalvm.compiler.nodes.LoopExitNode; +import org.graalvm.compiler.nodes.PhiNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.ValuePhiNode; +import org.graalvm.compiler.nodes.calc.AddNode; +import org.graalvm.compiler.nodes.calc.BinaryArithmeticNode; +import org.graalvm.compiler.nodes.calc.CompareNode; +import org.graalvm.compiler.nodes.calc.ConditionalNode; +import org.graalvm.compiler.nodes.calc.IntegerLessThanNode; +import org.graalvm.compiler.nodes.calc.SubNode; import org.graalvm.compiler.nodes.extended.SwitchNode; +import org.graalvm.compiler.nodes.util.GraphUtil; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.tiers.PhaseContext; @@ -57,7 +88,7 @@ } public static void fullUnroll(LoopEx loop, PhaseContext context, CanonicalizerPhase canonicalizer) { - // assert loop.isCounted(); //TODO (gd) strenghten : counted with known trip count + // assert loop.isCounted(); //TODO (gd) strengthen : counted with known trip count LoopBeginNode loopBegin = loop.loopBegin(); StructuredGraph graph = loopBegin.graph(); int initialNodeCount = graph.getNodeCount(); @@ -123,6 +154,511 @@ // TODO (gd) probabilities need some amount of fixup.. (probably also in other transforms) } + public static boolean partialUnroll(LoopEx loop, StructuredGraph graph) { + assert loop.loopBegin().isMainLoop(); + graph.getDebug().log("LoopPartialUnroll %s", loop); + boolean changed = false; + CountedLoopInfo mainCounted = loop.counted(); + LoopBeginNode mainLoopBegin = loop.loopBegin(); + InductionVariable iv = mainCounted.getCounter(); + IfNode mainLimit = mainCounted.getLimitTest(); + LogicNode ifTest = mainLimit.condition(); + CompareNode compareNode = (CompareNode) ifTest; + ValueNode compareBound = null; + ValueNode curPhi = iv.valueNode(); + if (compareNode.getX() == curPhi) { + compareBound = compareNode.getY(); + } else if (compareNode.getY() == curPhi) { + compareBound = compareNode.getX(); + } + LoopFragmentInside newSegment = loop.inside().duplicate(); + newSegment.insertWithinAfter(loop); + graph.getDebug().dump(DebugContext.VERBOSE_LEVEL, graph, "After duplication inside %s", mainLoopBegin); + ValueNode inductionNode = iv.valueNode(); + Node newStrideNode = null; + for (PhiNode mainPhiNode : mainLoopBegin.phis()) { + Node segmentOrigOp = null; + Node replacementOp = null; + changed = false; + // Rework each phi with a loop carried dependence + for (Node phiUsage : mainPhiNode.usages()) { + if (!loop.isOutsideLoop(phiUsage)) { + for (int i = 1; i < mainPhiNode.valueCount(); i++) { + ValueNode v = mainPhiNode.valueAt(i); + if (mainPhiNode != inductionNode) { + if (closureOnPhiInputToPhiUse(v, phiUsage, loop, graph)) { + segmentOrigOp = v; + Node node = newSegment.getDuplicatedNode(v); + replacementOp = updateUnrollSegmentValue(mainPhiNode, inductionNode, phiUsage, v, newSegment); + + // Update the induction phi with new stride node + mainPhiNode.setValueAt(i, (ValueNode) node); + // This is for induction variables not referenced in the loop body + if (inductionNode == v) { + newStrideNode = node; + } + changed = true; + break; + } + } else if (v == phiUsage) { + segmentOrigOp = phiUsage; + Node node = newSegment.getDuplicatedNode(phiUsage); + newStrideNode = node; + replacementOp = updateUnrollSegmentValue(mainPhiNode, inductionNode, phiUsage, phiUsage, newSegment); + + // Update the induction phi with new stride node + mainPhiNode.setValueAt(i, (ValueNode) node); + changed = true; + break; + } + } + } + if (changed) { + break; + } + } + + if (changed) { + // Patch the new segments induction uses of replacementOp with the old stride node + for (Node usage : mainPhiNode.usages()) { + if (usage != segmentOrigOp) { + if (!loop.isOutsideLoop(usage)) { + Node node = newSegment.getDuplicatedNode(usage); + if (node instanceof CompareNode) { + continue; + } + node.replaceFirstInput(replacementOp, segmentOrigOp); + } + } + } + } + } + + if (changed && newStrideNode == null) { + throw GraalError.shouldNotReachHere("Can't find stride node"); + } + if (newStrideNode != null) { + // If merge the duplicate code into the loop and remove redundant code + placeNewSegmentAndCleanup(mainCounted, mainLoopBegin, newSegment); + int unrollFactor = mainLoopBegin.getUnrollFactor(); + // First restore the old pattern of the loop exit condition so we can update it one way + if (unrollFactor > 1) { + if (compareBound instanceof SubNode) { + SubNode newLimit = (SubNode) compareBound; + ValueNode oldcompareBound = newLimit.getX(); + compareNode.replaceFirstInput(newLimit, oldcompareBound); + newLimit.safeDelete(); + compareBound = oldcompareBound; + } else if (compareBound instanceof AddNode) { + AddNode newLimit = (AddNode) compareBound; + ValueNode oldcompareBound = newLimit.getX(); + compareNode.replaceFirstInput(newLimit, oldcompareBound); + newLimit.safeDelete(); + compareBound = oldcompareBound; + } + } + unrollFactor *= 2; + mainLoopBegin.setUnrollFactor(unrollFactor); + // Reset stride to include new segment in loop control. + long oldStride = iv.constantStride() * 2; + // Now update the induction op and the exit condition + if (iv instanceof BasicInductionVariable) { + BasicInductionVariable biv = (BasicInductionVariable) iv; + BinaryArithmeticNode newOp = (BinaryArithmeticNode) newStrideNode; + Stamp strideStamp = newOp.stamp(); + ConstantNode newStrideVal = graph.unique(ConstantNode.forIntegerStamp(strideStamp, oldStride)); + newOp.setY(newStrideVal); + biv.setOP(newOp); + // Now use the current unrollFactor to update the exit condition to power of two + if (unrollFactor > 1) { + if (iv.direction() == Direction.Up) { + int modulas = (unrollFactor - 1); + ConstantNode aboveVal = graph.unique(ConstantNode.forIntegerStamp(strideStamp, modulas)); + ValueNode newLimit = graph.addWithoutUnique(new SubNode(compareBound, aboveVal)); + compareNode.replaceFirstInput(compareBound, newLimit); + } else if (iv.direction() == Direction.Down) { + int modulas = (unrollFactor - 1); + ConstantNode aboveVal = graph.unique(ConstantNode.forIntegerStamp(strideStamp, modulas)); + ValueNode newLimit = graph.addWithoutUnique(new AddNode(compareBound, aboveVal)); + compareNode.replaceFirstInput(compareBound, newLimit); + } + } + mainLoopBegin.setLoopFrequency(mainLoopBegin.loopFrequency() / 2); + } + changed = true; + } + if (changed) { + graph.getDebug().dump(DebugContext.DETAILED_LEVEL, graph, "LoopPartialUnroll %s", loop); + } + return changed; + } + + private static Node updateUnrollSegmentValue(PhiNode mainPhiNode, Node inductionNode, Node phiUsage, Node patchNode, LoopFragmentInside newSegment) { + Node node = newSegment.getDuplicatedNode(phiUsage); + assert node != null : phiUsage; + Node replacementOp = null; + int inputCnt = 0; + for (Node input : phiUsage.inputs()) { + inputCnt++; + if (input == mainPhiNode) { + break; + } + } + int newInputCnt = 0; + for (Node input : node.inputs()) { + newInputCnt++; + if (newInputCnt == inputCnt) { + replacementOp = input; + if (mainPhiNode == inductionNode) { + node.replaceFirstInput(input, mainPhiNode); + } else { + node.replaceFirstInput(input, patchNode); + } + break; + } + } + return replacementOp; + } + + private static boolean closureOnPhiInputToPhiUse(Node inNode, Node usage, LoopEx loop, StructuredGraph graph) { + NodeWorkList nodes = graph.createNodeWorkList(); + nodes.add(inNode); + // Now walk from the inNode to usage if we can find it else we do not have closure + for (Node node : nodes) { + if (node == usage) { + return true; + } + for (Node input : node.inputs()) { + if (!loop.isOutsideLoop(input)) { + if (input != usage) { + nodes.add(input); + } else { + return true; + // For any reason if we have completed a closure, stop processing more + } + } + } + } + return false; + } + + private static void placeNewSegmentAndCleanup(CountedLoopInfo mainCounted, LoopBeginNode mainLoopBegin, LoopFragmentInside newSegment) { + // Discard the segment entry and its flow, after if merging it into the loop + StructuredGraph graph = mainLoopBegin.graph(); + IfNode loopTest = mainCounted.getLimitTest(); + IfNode newSegmentTest = newSegment.getDuplicatedNode(loopTest); + AbstractBeginNode trueSuccessor = loopTest.trueSuccessor(); + AbstractBeginNode falseSuccessor = loopTest.falseSuccessor(); + FixedNode firstNode; + boolean codeInTrueSide = false; + if (trueSuccessor == mainCounted.getBody()) { + firstNode = trueSuccessor.next(); + codeInTrueSide = true; + } else { + assert (falseSuccessor == mainCounted.getBody()); + firstNode = falseSuccessor.next(); + } + trueSuccessor = newSegmentTest.trueSuccessor(); + falseSuccessor = newSegmentTest.falseSuccessor(); + for (Node usage : falseSuccessor.anchored().snapshot()) { + usage.replaceFirstInput(falseSuccessor, loopTest.falseSuccessor()); + } + for (Node usage : trueSuccessor.anchored().snapshot()) { + usage.replaceFirstInput(trueSuccessor, loopTest.trueSuccessor()); + } + AbstractBeginNode startBlockNode; + if (codeInTrueSide) { + startBlockNode = trueSuccessor; + } else { + graph.getDebug().dump(DebugContext.VERBOSE_LEVEL, mainLoopBegin.graph(), "before"); + startBlockNode = falseSuccessor; + } + FixedNode lastNode = getBlockEnd(startBlockNode); + LoopEndNode loopEndNode = getSingleLoopEndFromLoop(mainLoopBegin); + FixedNode lastCodeNode = (FixedNode) loopEndNode.predecessor(); + FixedNode newSegmentFirstNode = newSegment.getDuplicatedNode(firstNode); + FixedNode newSegmentLastNode = newSegment.getDuplicatedNode(lastCodeNode); + graph.getDebug().dump(DebugContext.DETAILED_LEVEL, loopEndNode.graph(), "Before placing segment"); + if (firstNode instanceof LoopEndNode) { + GraphUtil.killCFG(newSegment.getDuplicatedNode(mainLoopBegin)); + } else { + newSegmentLastNode.clearSuccessors(); + startBlockNode.setNext(lastNode); + lastCodeNode.replaceFirstSuccessor(loopEndNode, newSegmentFirstNode); + newSegmentLastNode.replaceFirstSuccessor(lastNode, loopEndNode); + FixedWithNextNode oldLastNode = (FixedWithNextNode) lastCodeNode; + oldLastNode.setNext(newSegmentFirstNode); + FixedWithNextNode newLastNode = (FixedWithNextNode) newSegmentLastNode; + newLastNode.setNext(loopEndNode); + startBlockNode.clearSuccessors(); + lastNode.safeDelete(); + Node newSegmentTestStart = newSegmentTest.predecessor(); + LogicNode newSegmentIfTest = newSegmentTest.condition(); + newSegmentTestStart.clearSuccessors(); + newSegmentTest.safeDelete(); + newSegmentIfTest.safeDelete(); + trueSuccessor.safeDelete(); + falseSuccessor.safeDelete(); + newSegmentTestStart.safeDelete(); + } + graph.getDebug().dump(DebugContext.DETAILED_LEVEL, loopEndNode.graph(), "After placing segment"); + } + + // This function splits candidate loops into pre, main and post loops, + // dividing the iteration space to facilitate the majority of iterations + // being executed in a main loop, which will have RCE implemented upon it. + // The initial loop form is constrained to single entry/exit, but can have + // flow. The translation looks like: + // + // @formatter:off + // + // (Simple Loop entry) (Pre Loop Entry) + // | | + // (LoopBeginNode) (LoopBeginNode) + // | | + // (Loop Control Test)<------ ==> (Loop control Test)<------ + // / \ \ / \ \ + // (Loop Exit) (Loop Body) | (Loop Exit) (Loop Body) | + // | | | | | | + // (continue code) (Loop End) | if (M < length)* (Loop End) | + // \ / / \ \ / + // -----> / | -----> + // / if ( ... )* + // / / \ + // / / \ + // / / \ + // | / (Main Loop Entry) + // | | | + // | | (LoopBeginNode) + // | | | + // | | (Loop Control Test)<------ + // | | / \ \ + // | | (Loop Exit) (Loop Body) | + // \ \ | | | + // \ \ | (Loop End) | + // \ \ | \ / + // \ \ | ------> + // \ \ | + // (Main Loop Merge)* + // | + // (Post Loop Entry) + // | + // (LoopBeginNode) + // | + // (Loop Control Test)<----- + // / \ \ + // (Loop Exit) (Loop Body) | + // | | | + // (continue code) (Loop End) | + // \ / + // -----> + // + // Key: "*" = optional. + // @formatter:on + // + // The value "M" is the maximal value of the loop trip for the original + // loop. The value of "length" is applicable to the number of arrays found + // in the loop but is reduced if some or all of the arrays are known to be + // the same length as "M". The maximum number of tests can be equal to the + // number of arrays in the loop, where multiple instances of an array are + // subsumed into a single test for that arrays length. + // + // If the optional main loop entry tests are absent, the Pre Loop exit + // connects to the Main loops entry and there is no merge hanging off the + // main loops exit to converge flow from said tests. All split use data + // flow is mitigated through phi(s) in the main merge if present and + // passed through the main and post loop phi(s) from the originating pre + // loop with final phi(s) and data flow patched to the "continue code". + // The pre loop is constrained to one iteration for now and will likely + // be updated to produce vector alignment if applicable. + + public static void insertPrePostLoops(LoopEx loop, StructuredGraph graph) { + graph.getDebug().log("LoopTransformations.insertPrePostLoops %s", loop); + LoopFragmentWhole preLoop = loop.whole(); + CountedLoopInfo preCounted = preLoop.loop().counted(); + IfNode preLimit = preCounted.getLimitTest(); + if (preLimit != null) { + LoopBeginNode preLoopBegin = loop.loopBegin(); + InductionVariable preIv = preCounted.getCounter(); + LoopExitNode preLoopExitNode = getSingleExitFromLoop(preLoopBegin); + FixedNode continuationNode = preLoopExitNode.next(); + + // Each duplication is inserted after the original, ergo create the post loop first + LoopFragmentWhole mainLoop = preLoop.duplicate(); + LoopFragmentWhole postLoop = preLoop.duplicate(); + preLoopBegin.incrementSplits(); + preLoopBegin.incrementSplits(); + preLoopBegin.setPreLoop(); + graph.getDebug().dump(DebugContext.VERBOSE_LEVEL, graph, "After duplication"); + LoopBeginNode mainLoopBegin = mainLoop.getDuplicatedNode(preLoopBegin); + mainLoopBegin.setMainLoop(); + LoopBeginNode postLoopBegin = postLoop.getDuplicatedNode(preLoopBegin); + postLoopBegin.setPostLoop(); + + EndNode postEndNode = getBlockEndAfterLoopExit(postLoopBegin); + AbstractMergeNode postMergeNode = postEndNode.merge(); + LoopExitNode postLoopExitNode = getSingleExitFromLoop(postLoopBegin); + + // Update the main loop phi initialization to carry from the pre loop + for (PhiNode prePhiNode : preLoopBegin.phis()) { + PhiNode mainPhiNode = mainLoop.getDuplicatedNode(prePhiNode); + mainPhiNode.setValueAt(0, prePhiNode); + } + + EndNode mainEndNode = getBlockEndAfterLoopExit(mainLoopBegin); + AbstractMergeNode mainMergeNode = mainEndNode.merge(); + AbstractEndNode postEntryNode = postLoopBegin.forwardEnd(); + + // In the case of no Bounds tests, we just flow right into the main loop + AbstractBeginNode mainLandingNode = BeginNode.begin(postEntryNode); + LoopExitNode mainLoopExitNode = getSingleExitFromLoop(mainLoopBegin); + mainLoopExitNode.setNext(mainLandingNode); + preLoopExitNode.setNext(mainLoopBegin.forwardEnd()); + + // Add and update any phi edges as per merge usage as needed and update usages + processPreLoopPhis(loop, mainLoop, postLoop); + continuationNode.predecessor().clearSuccessors(); + postLoopExitNode.setNext(continuationNode); + cleanupMerge(postMergeNode, postLoopExitNode); + cleanupMerge(mainMergeNode, mainLandingNode); + + // Change the preLoop to execute one iteration for now + updateMainLoopLimit(preLimit, preIv, mainLoop); + updatePreLoopLimit(preLimit, preIv, preCounted); + preLoopBegin.setLoopFrequency(1); + mainLoopBegin.setLoopFrequency(Math.max(0.0, mainLoopBegin.loopFrequency() - 2)); + postLoopBegin.setLoopFrequency(Math.max(0.0, postLoopBegin.loopFrequency() - 1)); + } + graph.getDebug().dump(DebugContext.DETAILED_LEVEL, graph, "InsertPrePostLoops %s", loop); + } + + /** + * Cleanup the merge and remove the predecessors too. + */ + private static void cleanupMerge(AbstractMergeNode mergeNode, AbstractBeginNode landingNode) { + for (EndNode end : mergeNode.cfgPredecessors().snapshot()) { + mergeNode.removeEnd(end); + end.safeDelete(); + } + mergeNode.prepareDelete(landingNode); + mergeNode.safeDelete(); + } + + private static void processPreLoopPhis(LoopEx preLoop, LoopFragmentWhole mainLoop, LoopFragmentWhole postLoop) { + // process phis for the post loop + LoopBeginNode preLoopBegin = preLoop.loopBegin(); + for (PhiNode prePhiNode : preLoopBegin.phis()) { + PhiNode postPhiNode = postLoop.getDuplicatedNode(prePhiNode); + PhiNode mainPhiNode = mainLoop.getDuplicatedNode(prePhiNode); + postPhiNode.setValueAt(0, mainPhiNode); + + // Build a work list to update the pre loop phis to the post loops phis + for (Node usage : prePhiNode.usages().snapshot()) { + if (usage == mainPhiNode) { + continue; + } + if (preLoop.isOutsideLoop(usage)) { + usage.replaceFirstInput(prePhiNode, postPhiNode); + } + } + } + for (Node node : preLoop.inside().nodes()) { + for (Node externalUsage : node.usages().snapshot()) { + if (preLoop.isOutsideLoop(externalUsage)) { + Node postUsage = postLoop.getDuplicatedNode(node); + assert postUsage != null; + externalUsage.replaceFirstInput(node, postUsage); + } + } + } + } + + private static LoopExitNode getSingleExitFromLoop(LoopBeginNode curLoopBegin) { + assert curLoopBegin.loopExits().count() == 1; + return curLoopBegin.loopExits().first(); + } + + private static LoopEndNode getSingleLoopEndFromLoop(LoopBeginNode curLoopBegin) { + assert curLoopBegin.loopEnds().count() == 1; + return curLoopBegin.loopEnds().first(); + } + + /** + * Find the end of the block following the LoopExit. + */ + private static EndNode getBlockEndAfterLoopExit(LoopBeginNode curLoopBegin) { + FixedNode node = getSingleExitFromLoop(curLoopBegin).next(); + // Find the last node after the exit blocks starts + return getBlockEnd(node); + } + + private static EndNode getBlockEnd(FixedNode node) { + FixedNode curNode = node; + while (curNode instanceof FixedWithNextNode) { + curNode = ((FixedWithNextNode) curNode).next(); + } + return (EndNode) curNode; + } + + private static void updateMainLoopLimit(IfNode preLimit, InductionVariable preIv, LoopFragmentWhole mainLoop) { + // Update the main loops limit test to be different than the post loop + StructuredGraph graph = preLimit.graph(); + IfNode mainLimit = mainLoop.getDuplicatedNode(preLimit); + LogicNode ifTest = mainLimit.condition(); + CompareNode compareNode = (CompareNode) ifTest; + ValueNode prePhi = preIv.valueNode(); + ValueNode mainPhi = mainLoop.getDuplicatedNode(prePhi); + ValueNode preStride = preIv.strideNode(); + ValueNode mainStride; + if (preStride instanceof ConstantNode) { + mainStride = preStride; + } else { + mainStride = mainLoop.getDuplicatedNode(preStride); + } + // Fetch the bounds to pose lowering the range by one + ValueNode ub = null; + if (compareNode.getX() == mainPhi) { + ub = compareNode.getY(); + } else if (compareNode.getY() == mainPhi) { + ub = compareNode.getX(); + } else { + throw GraalError.shouldNotReachHere(); + } + + // Preloop always performs at least once iteration, so remove that from the main loop. + ValueNode newLimit = sub(graph, ub, mainStride); + + // Re-wire the condition with the new limit + compareNode.replaceFirstInput(ub, newLimit); + } + + private static void updatePreLoopLimit(IfNode preLimit, InductionVariable preIv, CountedLoopInfo preCounted) { + // Update the pre loops limit test + StructuredGraph graph = preLimit.graph(); + LogicNode ifTest = preLimit.condition(); + CompareNode compareNode = (CompareNode) ifTest; + ValueNode prePhi = preIv.valueNode(); + // Make new limit one iteration + ValueNode initIv = preCounted.getStart(); + ValueNode newLimit = add(graph, initIv, preIv.strideNode()); + + // Fetch the variable we are not replacing and configure the one we are + ValueNode ub; + if (compareNode.getX() == prePhi) { + ub = compareNode.getY(); + } else if (compareNode.getY() == prePhi) { + ub = compareNode.getX(); + } else { + throw GraalError.shouldNotReachHere(); + } + // Re-wire the condition with the new limit + if (preIv.direction() == Direction.Up) { + compareNode.replaceFirstInput(ub, graph.unique(new ConditionalNode(graph.unique(new IntegerLessThanNode(newLimit, ub)), newLimit, ub))); + } else { + compareNode.replaceFirstInput(ub, graph.unique(new ConditionalNode(graph.unique(new IntegerLessThanNode(ub, newLimit)), newLimit, ub))); + } + } + public static List findUnswitchable(LoopEx loop) { List controls = null; ValueNode invariantValue = null; @@ -155,4 +691,45 @@ } return controls; } + + public static boolean isUnrollableLoop(LoopEx loop) { + if (!loop.isCounted()) { + return false; + } + LoopBeginNode loopBegin = loop.loopBegin(); + boolean isCanonical = false; + if (loopBegin.isMainLoop() || loopBegin.isSimpleLoop()) { + // Flow-less loops to partial unroll for now. 3 blocks corresponds to an if that either + // exits or continues the loop. There might be fixed and floating work within the loop + // as well. + if (loop.loop().getBlocks().size() < 3) { + isCanonical = true; + } + } + if (!isCanonical) { + return false; + } + for (ValuePhiNode phi : loopBegin.valuePhis()) { + if (phi.usages().filter(x -> loopBegin.isPhiAtMerge(x)).isNotEmpty()) { + // Filter out Phis which reference Phis at the same merge until the duplication + // logic handles it properly. + return false; + } + InductionVariable iv = loop.getInductionVariables().get(phi); + if (iv == null) { + continue; + } + if (iv instanceof DerivedInductionVariable) { + return false; + } else if (iv instanceof BasicInductionVariable) { + BasicInductionVariable biv = (BasicInductionVariable) iv; + if (!biv.isConstantStride()) { + return false; + } + } else { + return false; + } + } + return true; + } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopUnswitchingPhase.java 2017-07-07 09:31:10.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopUnswitchingPhase.java 2017-07-07 09:31:10.000000000 -0700 @@ -25,8 +25,8 @@ import java.util.Iterator; import java.util.List; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.loop.LoopEx; import org.graalvm.compiler.loop.LoopPolicies; @@ -36,9 +36,9 @@ import org.graalvm.compiler.nodes.StructuredGraph; public class LoopUnswitchingPhase extends ContextlessLoopPhase { - private static final DebugCounter UNSWITCHED = Debug.counter("Unswitched"); - private static final DebugCounter UNSWITCH_CANDIDATES = Debug.counter("UnswitchCandidates"); - private static final DebugCounter UNSWITCH_EARLY_REJECTS = Debug.counter("UnswitchEarlyRejects"); + private static final CounterKey UNSWITCHED = DebugContext.counter("Unswitched"); + private static final CounterKey UNSWITCH_CANDIDATES = DebugContext.counter("UnswitchCandidates"); + private static final CounterKey UNSWITCH_EARLY_REJECTS = DebugContext.counter("UnswitchEarlyRejects"); public LoopUnswitchingPhase(LoopPolicies policies) { super(policies); @@ -46,6 +46,7 @@ @Override protected void run(StructuredGraph graph) { + DebugContext debug = graph.getDebug(); if (graph.hasLoops()) { boolean unswitched; do { @@ -55,20 +56,20 @@ if (getPolicies().shouldTryUnswitch(loop)) { List controlSplits = LoopTransformations.findUnswitchable(loop); if (controlSplits != null) { - UNSWITCH_CANDIDATES.increment(); + UNSWITCH_CANDIDATES.increment(debug); if (getPolicies().shouldUnswitch(loop, controlSplits)) { - if (Debug.isLogEnabled()) { + if (debug.isLogEnabled()) { logUnswitch(loop, controlSplits); } LoopTransformations.unswitch(loop, controlSplits); - Debug.dump(Debug.DETAILED_LEVEL, graph, "After unswitch %s", controlSplits); - UNSWITCHED.increment(); + debug.dump(DebugContext.DETAILED_LEVEL, graph, "After unswitch %s", controlSplits); + UNSWITCHED.increment(debug); unswitched = true; break; } } } else { - UNSWITCH_EARLY_REJECTS.increment(); + UNSWITCH_EARLY_REJECTS.increment(debug); } } } while (unswitched); @@ -89,7 +90,7 @@ } sb.append("]"); } - Debug.log("%s", sb); + loop.entryPoint().getDebug().log("%s", sb); } @Override --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/ReassociateInvariantPhase.java 2017-07-07 09:31:10.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/ReassociateInvariantPhase.java 2017-07-07 09:31:10.000000000 -0700 @@ -22,8 +22,7 @@ */ package org.graalvm.compiler.loop.phases; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.loop.LoopEx; import org.graalvm.compiler.loop.LoopsData; import org.graalvm.compiler.nodes.StructuredGraph; @@ -36,12 +35,13 @@ protected void run(StructuredGraph graph) { if (graph.hasLoops()) { final LoopsData dataReassociate = new LoopsData(graph); - try (Scope s = Debug.scope("ReassociateInvariants")) { + DebugContext debug = graph.getDebug(); + try (DebugContext.Scope s = debug.scope("ReassociateInvariants")) { for (LoopEx loop : dataReassociate.loops()) { loop.reassociateInvariants(); } } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } dataReassociate.deleteUnusedNodes(); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/BasicInductionVariable.java 2017-07-07 09:31:10.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/BasicInductionVariable.java 2017-07-07 09:31:10.000000000 -0700 @@ -43,8 +43,8 @@ private final ValuePhiNode phi; private final ValueNode init; - private final ValueNode rawStride; - private final BinaryArithmeticNode op; + private ValueNode rawStride; + private BinaryArithmeticNode op; public BasicInductionVariable(LoopEx loop, ValuePhiNode phi, ValueNode init, ValueNode rawStride, BinaryArithmeticNode op) { super(loop); @@ -63,6 +63,11 @@ return op; } + public void setOP(BinaryArithmeticNode newOp) { + rawStride = newOp.getY(); + op = newOp; + } + @Override public Direction direction() { Stamp stamp = rawStride.stamp(); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/CountedLoopInfo.java 2017-07-07 09:31:11.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/CountedLoopInfo.java 2017-07-07 09:31:11.000000000 -0700 @@ -32,6 +32,7 @@ import org.graalvm.compiler.nodes.AbstractBeginNode; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.GuardNode; +import org.graalvm.compiler.nodes.IfNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.CompareNode; @@ -51,13 +52,15 @@ private ValueNode end; private boolean oneOff; private AbstractBeginNode body; + private IfNode ifNode; - CountedLoopInfo(LoopEx loop, InductionVariable iv, ValueNode end, boolean oneOff, AbstractBeginNode body) { + CountedLoopInfo(LoopEx loop, InductionVariable iv, IfNode ifNode, ValueNode end, boolean oneOff, AbstractBeginNode body) { this.loop = loop; this.iv = iv; this.end = end; this.oneOff = oneOff; this.body = body; + this.ifNode = ifNode; } public ValueNode maxTripCountNode() { @@ -164,6 +167,10 @@ return end; } + public IfNode getLimitTest() { + return ifNode; + } + public ValueNode getStart() { return iv.initNode(); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/DefaultLoopPolicies.java 2017-07-07 09:31:11.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/DefaultLoopPolicies.java 2017-07-07 09:31:11.000000000 -0700 @@ -28,8 +28,8 @@ import java.util.List; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeBitMap; import org.graalvm.compiler.nodes.AbstractBeginNode; @@ -37,17 +37,20 @@ import org.graalvm.compiler.nodes.DeoptimizeNode; import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.FixedWithNextNode; +import org.graalvm.compiler.nodes.InvokeNode; import org.graalvm.compiler.nodes.LoopBeginNode; import org.graalvm.compiler.nodes.MergeNode; +import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.VirtualState; import org.graalvm.compiler.nodes.VirtualState.VirtualClosure; import org.graalvm.compiler.nodes.cfg.Block; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; +import org.graalvm.compiler.nodes.debug.ControlFlowAnchorNode; import org.graalvm.compiler.nodes.java.TypeSwitchNode; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.compiler.options.OptionKey; import jdk.vm.ci.meta.MetaAccessProvider; @@ -59,6 +62,9 @@ @Option(help = "", type = OptionType.Expert) public static final OptionKey FullUnrollMaxNodes = new OptionKey<>(300); @Option(help = "", type = OptionType.Expert) public static final OptionKey FullUnrollMaxIterations = new OptionKey<>(600); @Option(help = "", type = OptionType.Expert) public static final OptionKey ExactFullUnrollMaxNodes = new OptionKey<>(1200); + @Option(help = "", type = OptionType.Expert) public static final OptionKey ExactPartialUnrollMaxNodes = new OptionKey<>(200); + + @Option(help = "", type = OptionType.Expert) public static final OptionKey UnrollMaxIterations = new OptionKey<>(16); @Override public boolean shouldPeel(LoopEx loop, ControlFlowGraph cfg, MetaAccessProvider metaAccess) { @@ -93,6 +99,48 @@ } @Override + public boolean shouldPartiallyUnroll(LoopEx loop) { + if (!loop.isCounted()) { + return false; + } + OptionValues options = loop.entryPoint().getOptions(); + LoopBeginNode loopBegin = loop.loopBegin(); + int maxNodes = ExactPartialUnrollMaxNodes.getValue(options); + maxNodes = Math.min(maxNodes, Math.max(0, MaximumDesiredSize.getValue(options) - loop.loopBegin().graph().getNodeCount())); + int size = Math.max(1, loop.size() - 1 - loop.loopBegin().phis().count()); + int unrollFactor = loopBegin.getUnrollFactor(); + if (unrollFactor == 1) { + double loopFrequency = loopBegin.loopFrequency(); + if (loopBegin.isSimpleLoop() && loopFrequency < 5.0) { + return false; + } + loopBegin.setLoopOrigFrequency(loopFrequency); + } + int maxUnroll = UnrollMaxIterations.getValue(options); + // Now correct size for the next unroll. UnrollMaxIterations == 1 means perform the + // pre/main/post transformation but don't actually unroll the main loop. + size += size; + if (maxUnroll == 1 && loopBegin.isSimpleLoop() || size <= maxNodes && unrollFactor < maxUnroll) { + // Will the next unroll fit? + if ((int) loopBegin.loopOrigFrequency() < (unrollFactor * 2)) { + return false; + } + // Check whether we're allowed to unroll this loop + for (Node node : loop.inside().nodes()) { + if (node instanceof ControlFlowAnchorNode) { + return false; + } + if (node instanceof InvokeNode) { + return false; + } + } + return true; + } else { + return false; + } + } + + @Override public boolean shouldTryUnswitch(LoopEx loop) { LoopBeginNode loopBegin = loop.loopBegin(); double loopFrequency = loopBegin.loopFrequency(); @@ -113,13 +161,15 @@ } private static class IsolatedInitialization { - static final DebugCounter UNSWITCH_SPLIT_WITH_PHIS = Debug.counter("UnswitchSplitWithPhis"); + static final CounterKey UNSWITCH_SPLIT_WITH_PHIS = DebugContext.counter("UnswitchSplitWithPhis"); } @Override public boolean shouldUnswitch(LoopEx loop, List controlSplits) { int phis = 0; - NodeBitMap branchNodes = loop.loopBegin().graph().createNodeBitMap(); + StructuredGraph graph = loop.loopBegin().graph(); + DebugContext debug = graph.getDebug(); + NodeBitMap branchNodes = graph.createNodeBitMap(); for (ControlSplitNode controlSplit : controlSplits) { for (Node successor : controlSplit.successors()) { AbstractBeginNode branch = (AbstractBeginNode) successor; @@ -128,7 +178,7 @@ } Block postDomBlock = loop.loopsData().getCFG().blockFor(controlSplit).getPostdominator(); if (postDomBlock != null) { - IsolatedInitialization.UNSWITCH_SPLIT_WITH_PHIS.increment(); + IsolatedInitialization.UNSWITCH_SPLIT_WITH_PHIS.increment(debug); phis += ((MergeNode) postDomBlock.getBeginNode()).phis().count(); } } @@ -140,7 +190,7 @@ int maxDiff = LoopUnswitchTrivial.getValue(options) + (int) (LoopUnswitchFrequencyBoost.getValue(options) * (loopFrequency - 1.0 + phis)); maxDiff = Math.min(maxDiff, LoopUnswitchMaxIncrease.getValue(options)); - int remainingGraphSpace = MaximumDesiredSize.getValue(options) - loop.loopBegin().graph().getNodeCount(); + int remainingGraphSpace = MaximumDesiredSize.getValue(options) - graph.getNodeCount(); maxDiff = Math.min(maxDiff, remainingGraphSpace); loop.loopBegin().stateAfter().applyToVirtual(stateNodesCount); @@ -161,7 +211,7 @@ actualDiff = actualDiff * copies; } - Debug.log("shouldUnswitch(%s, %s) : delta=%d (%.2f%% inside of branches), max=%d, f=%.2f, phis=%d -> %b", loop, controlSplits, actualDiff, (double) (inBranchTotal) / loopTotal * 100, maxDiff, + debug.log("shouldUnswitch(%s, %s) : delta=%d (%.2f%% inside of branches), max=%d, f=%.2f, phis=%d -> %b", loop, controlSplits, actualDiff, (double) (inBranchTotal) / loopTotal * 100, maxDiff, loopFrequency, phis, actualDiff <= maxDiff); if (actualDiff <= maxDiff) { // check whether we're allowed to unswitch this loop --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopEx.java 2017-07-07 09:31:12.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopEx.java 2017-07-07 09:31:11.000000000 -0700 @@ -29,7 +29,7 @@ import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.core.common.cfg.Loop; import org.graalvm.compiler.core.common.type.IntegerStamp; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeBitMap; @@ -46,7 +46,6 @@ import org.graalvm.compiler.nodes.IfNode; import org.graalvm.compiler.nodes.LogicNode; import org.graalvm.compiler.nodes.LoopBeginNode; -import org.graalvm.compiler.nodes.LoopExitNode; import org.graalvm.compiler.nodes.PhiNode; import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.StructuredGraph; @@ -180,8 +179,9 @@ } ValueNode result = BinaryArithmeticNode.reassociate(binary, invariant, binary.getX(), binary.getY()); if (result != binary) { - if (Debug.isLogEnabled()) { - Debug.log("%s : Reassociated %s into %s", graph.method().format("%H::%n"), binary, result); + DebugContext debug = graph.getDebug(); + if (debug.isLogEnabled()) { + debug.log("%s : Reassociated %s into %s", graph.method().format("%H::%n"), binary, result); } if (!result.isAlive()) { assert !result.isDeleted(); @@ -211,7 +211,7 @@ LogicNode ifTest = ifNode.condition(); if (!(ifTest instanceof IntegerLessThanNode) && !(ifTest instanceof IntegerEqualsNode)) { if (ifTest instanceof IntegerBelowNode) { - Debug.log("Ignored potential Counted loop at %s with |<|", loopBegin); + ifTest.getDebug().log("Ignored potential Counted loop at %s with |<|", loopBegin); } return false; } @@ -286,7 +286,7 @@ default: throw GraalError.shouldNotReachHere(); } - counted = new CountedLoopInfo(this, iv, limit, oneOff, negated ? ifNode.falseSuccessor() : ifNode.trueSuccessor()); + counted = new CountedLoopInfo(this, iv, ifNode, limit, oneOff, negated ? ifNode.falseSuccessor() : ifNode.trueSuccessor()); return true; } return false; @@ -298,7 +298,7 @@ public void nodesInLoopBranch(NodeBitMap branchNodes, AbstractBeginNode branch) { EconomicSet blocks = EconomicSet.create(); - Collection exits = new LinkedList<>(); + Collection exits = new LinkedList<>(); Queue work = new LinkedList<>(); ControlFlowGraph cfg = loopsData().getCFG(); work.add(cfg.blockFor(branch)); @@ -306,7 +306,7 @@ Block b = work.remove(); if (loop().getExits().contains(b)) { assert !exits.contains(b.getBeginNode()); - exits.add((LoopExitNode) b.getBeginNode()); + exits.add(b.getBeginNode()); } else if (blocks.add(b.getBeginNode())) { Block d = b.getDominatedSibling(); while (d != null) { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragment.java 2017-07-07 09:31:12.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragment.java 2017-07-07 09:31:12.000000000 -0700 @@ -131,6 +131,8 @@ protected abstract DuplicationReplacement getDuplicationReplacement(); + protected abstract void beforeDuplication(); + protected abstract void finishDuplication(); protected void patchNodes(final DuplicationReplacement dataFix) { @@ -162,6 +164,7 @@ } else { dr = null; } + beforeDuplication(); NodeIterable nodesIterable = original().nodes(); duplicationMap = graph().addDuplicates(nodesIterable, graph(), nodesIterable.count(), dr); finishDuplication(); @@ -175,13 +178,13 @@ return computeNodes(graph, blocks, Collections.emptyList()); } - protected static NodeBitMap computeNodes(Graph graph, Iterable blocks, Iterable earlyExits) { + protected static NodeBitMap computeNodes(Graph graph, Iterable blocks, Iterable earlyExits) { final NodeBitMap nodes = graph.createNodeBitMap(); computeNodes(nodes, graph, blocks, earlyExits); return nodes; } - protected static void computeNodes(NodeBitMap nodes, Graph graph, Iterable blocks, Iterable earlyExits) { + protected static void computeNodes(NodeBitMap nodes, Graph graph, Iterable blocks, Iterable earlyExits) { for (AbstractBeginNode b : blocks) { if (b.isDeleted()) { continue; @@ -198,18 +201,22 @@ nodes.mark(n); } } - for (LoopExitNode earlyExit : earlyExits) { + for (AbstractBeginNode earlyExit : earlyExits) { if (earlyExit.isDeleted()) { continue; } - FrameState stateAfter = earlyExit.stateAfter(); - if (stateAfter != null) { - stateAfter.applyToVirtual(node -> nodes.mark(node)); - } nodes.mark(earlyExit); - for (ProxyNode proxy : earlyExit.proxies()) { - nodes.mark(proxy); + + if (earlyExit instanceof LoopExitNode) { + LoopExitNode loopExit = (LoopExitNode) earlyExit; + FrameState stateAfter = loopExit.stateAfter(); + if (stateAfter != null) { + stateAfter.applyToVirtual(node -> nodes.mark(node)); + } + for (ProxyNode proxy : loopExit.proxies()) { + nodes.mark(proxy); + } } } @@ -302,22 +309,30 @@ }; } - public static NodeIterable toHirExits(final Iterable blocks) { - return new NodeIterable() { + public static NodeIterable toHirExits(final Iterable blocks) { + return new NodeIterable() { @Override - public Iterator iterator() { + public Iterator iterator() { final Iterator it = blocks.iterator(); - return new Iterator() { + return new Iterator() { @Override public void remove() { throw new UnsupportedOperationException(); } + /** + * Return the true LoopExitNode for this loop or the BeginNode for the block. + */ @Override - public LoopExitNode next() { - return (LoopExitNode) it.next().getBeginNode(); + public AbstractBeginNode next() { + Block next = it.next(); + LoopExitNode exit = next.getLoopExit(); + if (exit != null) { + return exit; + } + return next.getBeginNode(); } @Override --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentInside.java 2017-07-07 09:31:13.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentInside.java 2017-07-07 09:31:12.000000000 -0700 @@ -50,8 +50,8 @@ import org.graalvm.compiler.nodes.VirtualState.NodeClosure; import org.graalvm.compiler.nodes.memory.MemoryPhiNode; import org.graalvm.compiler.nodes.util.GraphUtil; -import org.graalvm.util.Equivalence; import org.graalvm.util.EconomicMap; +import org.graalvm.util.Equivalence; public class LoopFragmentInside extends LoopFragment { @@ -74,6 +74,17 @@ } }; + private final DuplicationReplacement dataFixWithinAfter = new DuplicationReplacement() { + + @Override + public Node replacement(Node oriInput) { + if (!(oriInput instanceof ValueNode)) { + return oriInput; + } + return primAfter((ValueNode) oriInput); + } + }; + public LoopFragmentInside(LoopEx loop) { super(loop); } @@ -121,6 +132,12 @@ end.setNext(loop.entryPoint()); } + public void insertWithinAfter(LoopEx loop) { + assert this.isDuplicate() && this.original().loop() == loop; + + patchNodes(dataFixWithinAfter); + } + @Override public NodeBitMap nodes() { if (nodes == null) { @@ -205,6 +222,11 @@ // TODO (gd) ? } + @Override + protected void beforeDuplication() { + // Nothing to do + } + private static PhiNode patchPhi(StructuredGraph graph, PhiNode phi, AbstractMergeNode merge) { PhiNode ret; if (phi instanceof ValuePhiNode) { @@ -337,6 +359,24 @@ } } + protected ValueNode primAfter(ValueNode b) { + assert isDuplicate(); + LoopBeginNode loopBegin = original().loop().loopBegin(); + if (loopBegin.isPhiAtMerge(b)) { + PhiNode phi = (PhiNode) b; + assert phi.valueCount() == 2; + return phi.valueAt(1); + } else if (nodesReady) { + ValueNode v = getDuplicatedNode(b); + if (v == null) { + return b; + } + return v; + } else { + return b; + } + } + private AbstractBeginNode mergeEnds() { assert isDuplicate(); List endsToMerge = new LinkedList<>(); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentWhole.java 2017-07-07 09:31:13.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentWhole.java 2017-07-07 09:31:13.000000000 -0700 @@ -22,9 +22,8 @@ */ package org.graalvm.compiler.loop; -import java.util.Collections; - import org.graalvm.compiler.core.common.cfg.Loop; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Graph; import org.graalvm.compiler.graph.Graph.DuplicationReplacement; import org.graalvm.compiler.graph.Node; @@ -32,9 +31,11 @@ import org.graalvm.compiler.nodes.EndNode; import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.LoopBeginNode; -import org.graalvm.compiler.nodes.StructuredGraph.GuardsStage; +import org.graalvm.compiler.nodes.LoopExitNode; +import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.util.EconomicSet; public class LoopFragmentWhole extends LoopFragment { @@ -65,11 +66,7 @@ public NodeBitMap nodes() { if (nodes == null) { Loop loop = loop().loop(); - if (loop.getHeader().getBeginNode().graph().getGuardsStage() == GuardsStage.AFTER_FSA) { - nodes = LoopFragment.computeNodes(graph(), LoopFragment.toHirBlocks(loop.getBlocks()), Collections.emptyList()); - } else { - nodes = LoopFragment.computeNodes(graph(), LoopFragment.toHirBlocks(loop.getBlocks()), LoopFragment.toHirExits(loop.getExits())); - } + nodes = LoopFragment.computeNodes(graph(), LoopFragment.toHirBlocks(loop.getBlocks()), LoopFragment.toHirExits(loop.getExits())); } return nodes; } @@ -113,6 +110,44 @@ // TODO (gd) ? } + void cleanupLoopExits() { + LoopBeginNode loopBegin = original().loop().loopBegin(); + assert nodes == null || nodes.contains(loopBegin); + StructuredGraph graph = loopBegin.graph(); + if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) { + // After FrameStateAssignment ControlFlowGraph treats loop exits differently which means + // that the LoopExitNodes can be in a block which post dominates the true loop exit. For + // cloning to work right they must agree. + EconomicSet exits = EconomicSet.create(); + for (Block exitBlock : original().loop().loop().getExits()) { + LoopExitNode exitNode = exitBlock.getLoopExit(); + if (exitNode == null) { + exitNode = graph.add(new LoopExitNode(loopBegin)); + graph.addAfterFixed(exitBlock.getBeginNode(), exitNode); + if (nodes != null) { + nodes.mark(exitNode); + } + graph.getDebug().dump(DebugContext.VERBOSE_LEVEL, graph, "Adjusting loop exit node for %s", loopBegin); + } + exits.add(exitNode); + } + for (LoopExitNode exitNode : loopBegin.loopExits()) { + if (!exits.contains(exitNode)) { + if (nodes != null) { + nodes.clear(exitNode); + } + graph.removeFixed(exitNode); + } + } + } + + } + + @Override + protected void beforeDuplication() { + cleanupLoopExits(); + } + @Override public void insertBefore(LoopEx loop) { // TODO Auto-generated method stub --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopPolicies.java 2017-07-07 09:31:13.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopPolicies.java 2017-07-07 09:31:13.000000000 -0700 @@ -26,6 +26,7 @@ import org.graalvm.compiler.nodes.ControlSplitNode; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; + import jdk.vm.ci.meta.MetaAccessProvider; public interface LoopPolicies { @@ -33,6 +34,8 @@ boolean shouldFullUnroll(LoopEx loop); + boolean shouldPartiallyUnroll(LoopEx loop); + boolean shouldTryUnswitch(LoopEx loop); boolean shouldUnswitch(LoopEx loop, List controlSplits); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopsData.java 2017-07-07 09:31:14.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopsData.java 2017-07-07 09:31:14.000000000 -0700 @@ -28,16 +28,15 @@ import java.util.List; import org.graalvm.compiler.core.common.cfg.Loop; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.LoopBeginNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.cfg.Block; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; -import org.graalvm.util.Equivalence; import org.graalvm.util.EconomicMap; import org.graalvm.util.EconomicSet; +import org.graalvm.util.Equivalence; public class LoopsData { private final EconomicMap loopBeginToEx = EconomicMap.create(Equivalence.IDENTITY); @@ -46,10 +45,11 @@ @SuppressWarnings("try") public LoopsData(final StructuredGraph graph) { - try (Scope s = Debug.scope("ControlFlowGraph")) { + DebugContext debug = graph.getDebug(); + try (DebugContext.Scope s = debug.scope("ControlFlowGraph")) { cfg = ControlFlowGraph.compute(graph, true, true, true, true); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } assert checkLoopOrder(cfg.getLoops()); loops = new ArrayList<>(cfg.getLoops().size()); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/GraphCopyBenchmark.java 2017-07-07 09:31:14.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/GraphCopyBenchmark.java 2017-07-07 09:31:14.000000000 -0700 @@ -32,7 +32,7 @@ import org.graalvm.compiler.nodes.StructuredGraph; /** - * Benchmarks the performance of {@link Graph#copy()}. + * Benchmarks the performance of {@link Graph#copy(org.graalvm.compiler.debug.DebugContext)}. */ public class GraphCopyBenchmark extends GraalBenchmark { @@ -75,8 +75,8 @@ @Benchmark @Warmup(iterations = 20) - public StructuredGraph nullness(Nullness s, @SuppressWarnings("unused") GraalState g) { - return (StructuredGraph) s.graph.copy(); + public StructuredGraph nullness(Nullness s, GraalState g) { + return (StructuredGraph) s.graph.copy(g.debug); } @MethodSpec(declaringClass = GraphCopyBenchmark.class, name = "searchSnippet") @@ -127,7 +127,7 @@ @Benchmark @Warmup(iterations = 20) - public StructuredGraph search(Search s, @SuppressWarnings("unused") GraalState g) { - return (StructuredGraph) s.graph.copy(); + public StructuredGraph search(Search s, GraalState g) { + return (StructuredGraph) s.graph.copy(g.debug); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/util/GraalState.java 2017-07-07 09:31:15.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/util/GraalState.java 2017-07-07 09:31:15.000000000 -0700 @@ -22,30 +22,34 @@ */ package org.graalvm.compiler.microbenchmarks.graal.util; -import jdk.vm.ci.meta.MetaAccessProvider; - -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.State; - import org.graalvm.compiler.api.test.Graal; import org.graalvm.compiler.core.target.Backend; +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.runtime.RuntimeProvider; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +import jdk.vm.ci.meta.MetaAccessProvider; /** - * Read-only, benchmark-wide state providing Graal runtime context. + * Read-only, thread-local state providing Graal runtime context. This has to be thread-local due to + * requirements that {@link DebugContext} objects be single threaded in their usage. */ -@State(Scope.Benchmark) +@State(Scope.Thread) public class GraalState { public final OptionValues options; + public final DebugContext debug; public final Backend backend; public final Providers providers; public final MetaAccessProvider metaAccess; public GraalState() { options = Graal.getRequiredCapability(OptionValues.class); + debug = DebugContext.create(options, DebugHandlersFactory.LOADER); backend = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend(); providers = backend.getProviders(); metaAccess = providers.getMetaAccess(); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/util/GraalUtil.java 2017-07-07 09:31:16.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/util/GraalUtil.java 2017-07-07 09:31:16.000000000 -0700 @@ -25,7 +25,6 @@ import java.lang.reflect.Method; import java.util.List; -import org.graalvm.compiler.api.test.Graal; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.java.GraphBuilderPhase; import org.graalvm.compiler.nodes.StructuredGraph; @@ -33,7 +32,6 @@ import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; -import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.tiers.HighTierContext; @@ -133,7 +131,8 @@ } public static StructuredGraph getGraph(GraalState graal, ResolvedJavaMethod javaMethod, boolean useProfilingInfo) { - StructuredGraph graph = new StructuredGraph.Builder(Graal.getRequiredCapability(OptionValues.class), AllowAssumptions.YES).useProfilingInfo(useProfilingInfo).method(javaMethod).build(); + StructuredGraph graph = new StructuredGraph.Builder(graal.options, graal.debug, AllowAssumptions.YES).useProfilingInfo( + useProfilingInfo).method(javaMethod).build(); PhaseSuite graphBuilderSuite = new PhaseSuite<>(); graphBuilderSuite.appendPhase(new GraphBuilderPhase(GraphBuilderConfiguration.getDefault(new Plugins(new InvocationPlugins())))); graphBuilderSuite.apply(graph, new HighTierContext(graal.providers, graphBuilderSuite, OptimisticOptimizations.ALL)); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/util/GraphState.java 2017-07-07 09:31:17.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/util/GraphState.java 2017-07-07 09:31:17.000000000 -0700 @@ -25,8 +25,7 @@ import static org.graalvm.compiler.microbenchmarks.graal.util.GraalUtil.getGraph; import static org.graalvm.compiler.microbenchmarks.graal.util.GraalUtil.getMethodFromMethodSpec; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugEnvironment; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.StructuredGraph; import org.openjdk.jmh.annotations.Level; import org.openjdk.jmh.annotations.Scope; @@ -46,15 +45,13 @@ @SuppressWarnings("try") public GraphState() { GraalState graal = new GraalState(); - // Ensure a debug configuration for this thread is initialized - DebugEnvironment.ensureInitialized(graal.options); - + DebugContext debug = graal.debug; ResolvedJavaMethod method = graal.metaAccess.lookupJavaMethod(getMethodFromMethodSpec(getClass())); StructuredGraph structuredGraph = null; - try (Debug.Scope s = Debug.scope("GraphState", method)) { + try (DebugContext.Scope s = debug.scope("GraphState", method)) { structuredGraph = preprocessOriginal(getGraph(graal, method)); } catch (Throwable t) { - Debug.handle(t); + debug.handle(t); } this.originalGraph = structuredGraph; } @@ -75,6 +72,6 @@ @Setup(Level.Invocation) public void beforeInvocation() { - graph = (StructuredGraph) originalGraph.copy(); + graph = (StructuredGraph) originalGraph.copy(originalGraph.getDebug()); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/lir/GraalCompilerState.java 2017-07-07 09:31:17.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/lir/GraalCompilerState.java 2017-07-07 09:31:17.000000000 -0700 @@ -34,12 +34,6 @@ import java.lang.reflect.Field; import java.lang.reflect.Method; -import org.openjdk.jmh.annotations.Level; -import org.openjdk.jmh.annotations.Param; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.Setup; -import org.openjdk.jmh.annotations.State; - import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.api.test.Graal; import org.graalvm.compiler.code.CompilationResult; @@ -51,9 +45,8 @@ import org.graalvm.compiler.core.common.alloc.ComputeBlockOrder; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; import org.graalvm.compiler.core.target.Backend; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugEnvironment; -import org.graalvm.compiler.debug.internal.DebugScope; +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; import org.graalvm.compiler.lir.framemap.FrameMapBuilder; @@ -81,6 +74,11 @@ import org.graalvm.compiler.phases.tiers.TargetProvider; import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.runtime.RuntimeProvider; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; import jdk.vm.ci.code.CodeCacheProvider; import jdk.vm.ci.code.RegisterConfig; @@ -106,6 +104,7 @@ * The graph processed by the benchmark. */ private final OptionValues options; + private final DebugContext debug; private StructuredGraph graph; private final Backend backend; private final Providers providers; @@ -119,12 +118,7 @@ this.options = Graal.getRequiredCapability(OptionValues.class); this.backend = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend(); this.providers = backend.getProviders(); - - // Ensure a debug configuration for this thread is initialized - if (Debug.isEnabled() && DebugScope.getConfig() == null) { - DebugEnvironment.ensureInitialized(options); - } - + this.debug = DebugContext.create(options, DebugHandlersFactory.LOADER); } protected boolean useProfilingInfo() { @@ -136,10 +130,10 @@ GraalState graal = new GraalState(); ResolvedJavaMethod method = graal.metaAccess.lookupJavaMethod(getMethod()); StructuredGraph structuredGraph = null; - try (Debug.Scope s = Debug.scope("GraphState", method)) { + try (DebugContext.Scope s = debug.scope("GraphState", method)) { structuredGraph = preprocessOriginal(getGraph(graal, method, useProfilingInfo())); } catch (Throwable t) { - Debug.handle(t); + debug.handle(t); } this.originalGraph = structuredGraph; } @@ -321,7 +315,7 @@ protected final void prepareRequest() { assert originalGraph != null : "call initialzeMethod first"; CompilationIdentifier compilationId = backend.getCompilationIdentifier(originalGraph.method()); - graph = originalGraph.copyWithIdentifier(compilationId); + graph = originalGraph.copyWithIdentifier(compilationId, originalGraph.getDebug()); assert !graph.isFrozen(); ResolvedJavaMethod installedCodeOwner = graph.method(); request = new Request<>(graph, installedCodeOwner, getProviders(), getBackend(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL, @@ -376,7 +370,7 @@ codeEmittingOrder = ComputeBlockOrder.computeCodeEmittingOrder(blocks.length, startBlock); linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blocks.length, startBlock); - LIR lir = new LIR(cfg, linearScanOrder, codeEmittingOrder, getGraphOptions()); + LIR lir = new LIR(cfg, linearScanOrder, codeEmittingOrder, getGraphOptions(), getGraphDebug()); FrameMapBuilder frameMapBuilder = request.backend.newFrameMapBuilder(registerConfig); lirGenRes = request.backend.newLIRGenerationResult(graph.compilationId(), lir, frameMapBuilder, request.graph, stub); lirGenTool = request.backend.newLIRGenerator(lirGenRes); @@ -387,6 +381,10 @@ return graph.getOptions(); } + protected DebugContext getGraphDebug() { + return graph.getDebug(); + } + private static ControlFlowGraph deepCopy(ControlFlowGraph cfg) { return ControlFlowGraph.compute(cfg.graph, true, true, true, true); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/lir/trace/TraceBuilderBenchmark.java 2017-07-07 09:31:18.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/lir/trace/TraceBuilderBenchmark.java 2017-07-07 09:31:17.000000000 -0700 @@ -44,12 +44,12 @@ @Benchmark public TraceBuilderResult uniDirectionalTraceBuilder(State s) { - return UniDirectionalTraceBuilder.computeTraces(s.cfg.getStartBlock(), s.cfg.getBlocks(), TraceBuilderPhase.getTrivialTracePredicate(s.getLIR())); + return UniDirectionalTraceBuilder.computeTraces(s.getLIR().getDebug(), s.cfg.getStartBlock(), s.cfg.getBlocks(), TraceBuilderPhase.getTrivialTracePredicate(s.getLIR())); } @Benchmark public TraceBuilderResult biDirectionalTraceBuilder(State s) { - return BiDirectionalTraceBuilder.computeTraces(s.cfg.getStartBlock(), s.cfg.getBlocks(), TraceBuilderPhase.getTrivialTracePredicate(s.getLIR())); + return BiDirectionalTraceBuilder.computeTraces(s.getLIR().getDebug(), s.cfg.getStartBlock(), s.cfg.getBlocks(), TraceBuilderPhase.getTrivialTracePredicate(s.getLIR())); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/IntegerStampTest.java 2017-07-07 09:31:18.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/IntegerStampTest.java 2017-07-07 09:31:18.000000000 -0700 @@ -36,14 +36,17 @@ import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.graph.test.GraphTest; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.options.OptionValues; /** * This class tests that integer stamps are created correctly for constants. */ -public class IntegerStampTest { +public class IntegerStampTest extends GraphTest { private StructuredGraph graph; @@ -53,7 +56,9 @@ @Before public void before() { - graph = new StructuredGraph.Builder(getInitialOptions(), AllowAssumptions.YES).build(); + OptionValues options = getInitialOptions(); + DebugContext debug = getDebug(options); + graph = new StructuredGraph.Builder(options, debug, AllowAssumptions.YES).build(); } @Test --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/NegateNodeCanonicalizationTest.java 2017-07-07 09:31:18.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/NegateNodeCanonicalizationTest.java 2017-07-07 09:31:18.000000000 -0700 @@ -22,13 +22,16 @@ */ package org.graalvm.compiler.nodes.test; +import static org.graalvm.compiler.core.test.GraalCompilerTest.getInitialOptions; import static org.junit.Assert.assertEquals; import org.graalvm.compiler.core.common.type.ArithmeticOpTable; -import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.options.OptionValues; import org.junit.Before; import org.junit.Test; @@ -43,7 +46,9 @@ @Before public void before() { - graph = new StructuredGraph.Builder(GraalCompilerTest.getInitialOptions(), AllowAssumptions.YES).build(); + OptionValues options = getInitialOptions(); + DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER); + graph = new StructuredGraph.Builder(options, debug, AllowAssumptions.YES).build(); } @Test --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/StaticFieldAccessTest.java 2017-07-07 09:31:19.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/StaticFieldAccessTest.java 2017-07-07 09:31:19.000000000 -0700 @@ -40,7 +40,7 @@ if (c.length != 1) { throw new InternalError("can't find single constructor"); } - tester.parseDebug(tester.asResolvedJavaMethod(c[0]), AllowAssumptions.YES); + tester.parse(tester.builder(tester.asResolvedJavaMethod(c[0]), AllowAssumptions.YES), tester.getDebugGraphBuilderSuite()); } public Inner(Object o) { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/AbstractEndNode.java 2017-07-07 09:31:20.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/AbstractEndNode.java 2017-07-07 09:31:20.000000000 -0700 @@ -25,7 +25,6 @@ import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0; -import java.util.Arrays; import java.util.Collections; import org.graalvm.compiler.core.common.type.StampFactory; @@ -63,7 +62,7 @@ public Iterable cfgSuccessors() { AbstractMergeNode merge = merge(); if (merge != null) { - return Arrays.asList(merge); + return Collections.singletonList(merge); } return Collections.emptyList(); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/AbstractMergeNode.java 2017-07-07 09:31:20.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/AbstractMergeNode.java 2017-07-07 09:31:20.000000000 -0700 @@ -28,7 +28,6 @@ import java.util.List; -import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.graph.IterableNodeType; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; @@ -183,7 +182,7 @@ } } } - Debug.log("Split %s into ends for %s.", this, merge); + getDebug().log("Split %s into ends for %s.", this, merge); int numEnds = this.forwardEndCount(); for (int i = 0; i < numEnds - 1; i++) { AbstractEndNode end = forwardEndAt(numEnds - 1 - i); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/DeoptimizeNode.java 2017-07-07 09:31:21.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/DeoptimizeNode.java 2017-07-07 09:31:21.000000000 -0700 @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.nodes; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; @@ -83,8 +83,11 @@ @SuppressWarnings("deprecation") public int getDebugId() { int deoptDebugId = debugId; - if (deoptDebugId == DEFAULT_DEBUG_ID && (Debug.isDumpEnabledForMethod() || Debug.isLogEnabledForMethod())) { - deoptDebugId = this.getId(); + if (deoptDebugId == DEFAULT_DEBUG_ID) { + DebugContext debug = getDebug(); + if ((debug.isDumpEnabledForMethod() || debug.isLogEnabledForMethod())) { + deoptDebugId = this.getId(); + } } return deoptDebugId; } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FrameState.java 2017-07-07 09:31:22.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FrameState.java 2017-07-07 09:31:21.000000000 -0700 @@ -41,8 +41,6 @@ import org.graalvm.compiler.bytecode.Bytecode; import org.graalvm.compiler.bytecode.Bytecodes; import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.IterableNodeType; import org.graalvm.compiler.graph.NodeClass; @@ -72,8 +70,6 @@ public final class FrameState extends VirtualState implements IterableNodeType { public static final NodeClass TYPE = NodeClass.create(FrameState.class); - private static final DebugCounter FRAMESTATES_COUNTER = Debug.counter("FrameStateCount"); - /** * Marker value for the second slot of values that occupy two local variable or expression stack * slots. The marker value is used by the bytecode parser, but replaced with {@code null} in the @@ -157,7 +153,6 @@ this.duringCall = duringCall; assert !this.rethrowException || this.stackSize == 1 : "must have exception on top of the stack"; assert this.locksSize() == this.monitorIdCount(); - FRAMESTATES_COUNTER.increment(); } public FrameState(FrameState outerFrameState, Bytecode code, int bci, List values, int localsSize, int stackSize, boolean rethrowException, boolean duringCall, --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java 2017-07-07 09:31:22.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java 2017-07-07 09:31:22.000000000 -0700 @@ -41,7 +41,7 @@ import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.core.common.util.TypeReader; import org.graalvm.compiler.core.common.util.UnsafeArrayTypeReader; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Edges; import org.graalvm.compiler.graph.Graph; @@ -61,6 +61,7 @@ import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.extended.IntegerSwitchNode; import org.graalvm.compiler.nodes.graphbuilderconf.LoopExplosionPlugin.LoopExplosionKind; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.util.EconomicMap; import org.graalvm.util.EconomicSet; import org.graalvm.util.Equivalence; @@ -341,23 +342,28 @@ protected final Architecture architecture; /** The target graph where decoded nodes are added to. */ protected final StructuredGraph graph; + protected final OptionValues options; + protected final DebugContext debug; + private final EconomicMap, ArrayDeque> reusableFloatingNodes; public GraphDecoder(Architecture architecture, StructuredGraph graph) { this.architecture = architecture; this.graph = graph; + this.options = graph.getOptions(); + this.debug = graph.getDebug(); reusableFloatingNodes = EconomicMap.create(Equivalence.IDENTITY); } @SuppressWarnings("try") public final void decode(EncodedGraph encodedGraph) { - try (Debug.Scope scope = Debug.scope("GraphDecoder", graph)) { + try (DebugContext.Scope scope = debug.scope("GraphDecoder", graph)) { MethodScope methodScope = new MethodScope(null, graph, encodedGraph, LoopExplosionKind.NONE); decode(createInitialLoopScope(methodScope, null)); cleanupGraph(methodScope); assert graph.verify(); } catch (Throwable ex) { - Debug.handle(ex); + debug.handle(ex); } } @@ -1355,7 +1361,8 @@ @Override public void run() { - Debug.dump(Debug.DETAILED_LEVEL, graph, "Before loop detection"); + DebugContext debug = graph.getDebug(); + debug.dump(DebugContext.DETAILED_LEVEL, graph, "Before loop detection"); List orderedLoops = findLoops(); assert orderedLoops.get(orderedLoops.size() - 1) == irreducibleLoopHandler : "outermost loop must be the last element in the list"; @@ -1378,11 +1385,11 @@ } else { insertLoopNodes(loop); } - Debug.dump(Debug.DETAILED_LEVEL, graph, "After handling of loop %s", loop.header); + debug.dump(DebugContext.DETAILED_LEVEL, graph, "After handling of loop %s", loop.header); } logIrreducibleLoops(); - Debug.dump(Debug.DETAILED_LEVEL, graph, "After loop detection"); + debug.dump(DebugContext.DETAILED_LEVEL, graph, "After loop detection"); } private List findLoops() { @@ -1909,15 +1916,16 @@ */ @SuppressWarnings("try") private void logIrreducibleLoops() { - try (Debug.Scope s = Debug.scope("IrreducibleLoops")) { - if (Debug.isLogEnabled(Debug.BASIC_LEVEL) && irreducibleLoopSwitch != null) { + DebugContext debug = graph.getDebug(); + try (DebugContext.Scope s = debug.scope("IrreducibleLoops")) { + if (debug.isLogEnabled(DebugContext.BASIC_LEVEL) && irreducibleLoopSwitch != null) { StringBuilder msg = new StringBuilder("Inserted state machine to remove irreducible loops. Dispatching to the following states: "); String sep = ""; for (int i = 0; i < irreducibleLoopSwitch.keyCount(); i++) { msg.append(sep).append(irreducibleLoopSwitch.keyAt(i).asInt()); sep = ", "; } - Debug.log(Debug.BASIC_LEVEL, "%s", msg); + debug.log(DebugContext.BASIC_LEVEL, "%s", msg); } } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphEncoder.java 2017-07-07 09:31:23.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphEncoder.java 2017-07-07 09:31:23.000000000 -0700 @@ -33,7 +33,7 @@ import org.graalvm.compiler.core.common.util.TypeReader; import org.graalvm.compiler.core.common.util.TypeWriter; import org.graalvm.compiler.core.common.util.UnsafeArrayTypeWriter; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Edges; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; @@ -42,8 +42,8 @@ import org.graalvm.compiler.graph.iterators.NodeIterable; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.java.ExceptionObjectNode; -import org.graalvm.util.UnmodifiableMapCursor; import org.graalvm.util.Pair; +import org.graalvm.util.UnmodifiableMapCursor; import jdk.vm.ci.code.Architecture; @@ -418,7 +418,8 @@ */ @SuppressWarnings("try") public static boolean verifyEncoding(StructuredGraph originalGraph, EncodedGraph encodedGraph, Architecture architecture) { - StructuredGraph decodedGraph = new StructuredGraph.Builder(originalGraph.getOptions(), AllowAssumptions.YES).method(originalGraph.method()).build(); + DebugContext debug = originalGraph.getDebug(); + StructuredGraph decodedGraph = new StructuredGraph.Builder(originalGraph.getOptions(), debug, AllowAssumptions.YES).method(originalGraph.method()).build(); GraphDecoder decoder = new GraphDecoder(architecture, decodedGraph); decoder.decode(encodedGraph); @@ -426,9 +427,10 @@ try { GraphComparison.verifyGraphsEqual(originalGraph, decodedGraph); } catch (Throwable ex) { - try (Debug.Scope scope = Debug.scope("GraphEncoder")) { - Debug.dump(Debug.VERBOSE_LEVEL, originalGraph, "Original Graph"); - Debug.dump(Debug.VERBOSE_LEVEL, decodedGraph, "Decoded Graph"); + originalGraph.getDebug(); + try (DebugContext.Scope scope = debug.scope("GraphEncoder")) { + debug.dump(DebugContext.VERBOSE_LEVEL, originalGraph, "Original Graph"); + debug.dump(DebugContext.VERBOSE_LEVEL, decodedGraph, "Decoded Graph"); } throw ex; } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java 2017-07-07 09:31:23.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java 2017-07-07 09:31:23.000000000 -0700 @@ -34,8 +34,8 @@ import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; @@ -73,7 +73,7 @@ public final class IfNode extends ControlSplitNode implements Simplifiable, LIRLowerable { public static final NodeClass TYPE = NodeClass.create(IfNode.class); - private static final DebugCounter CORRECTED_PROBABILITIES = Debug.counter("CorrectedProbabilities"); + private static final CounterKey CORRECTED_PROBABILITIES = DebugContext.counter("CorrectedProbabilities"); @Successor AbstractBeginNode trueSuccessor; @Successor AbstractBeginNode falseSuccessor; @@ -179,12 +179,12 @@ public void simplify(SimplifierTool tool) { if (trueSuccessor().next() instanceof DeoptimizeNode) { if (trueSuccessorProbability != 0) { - CORRECTED_PROBABILITIES.increment(); + CORRECTED_PROBABILITIES.increment(getDebug()); trueSuccessorProbability = 0; } } else if (falseSuccessor().next() instanceof DeoptimizeNode) { if (trueSuccessorProbability != 1) { - CORRECTED_PROBABILITIES.increment(); + CORRECTED_PROBABILITIES.increment(getDebug()); trueSuccessorProbability = 1; } } @@ -453,12 +453,13 @@ } private static boolean prepareForSwap(ConstantReflectionProvider constantReflection, LogicNode a, LogicNode b) { + DebugContext debug = a.getDebug(); if (a instanceof InstanceOfNode) { InstanceOfNode instanceOfA = (InstanceOfNode) a; if (b instanceof IsNullNode) { IsNullNode isNullNode = (IsNullNode) b; if (isNullNode.getValue() == instanceOfA.getValue()) { - Debug.log("Can swap instanceof and isnull if"); + debug.log("Can swap instanceof and isnull if"); return true; } } else if (b instanceof InstanceOfNode) { @@ -466,7 +467,7 @@ if (instanceOfA.getValue() == instanceOfB.getValue() && !instanceOfA.type().getType().isInterface() && !instanceOfB.type().getType().isInterface() && !instanceOfA.type().getType().isAssignableFrom(instanceOfB.type().getType()) && !instanceOfB.type().getType().isAssignableFrom(instanceOfA.type().getType())) { // Two instanceof on the same value with mutually exclusive types. - Debug.log("Can swap instanceof for types %s and %s", instanceOfA.type(), instanceOfB.type()); + debug.log("Can swap instanceof for types %s and %s", instanceOfA.type(), instanceOfB.type()); return true; } } @@ -479,7 +480,7 @@ if (b instanceof CompareNode) { CompareNode compareB = (CompareNode) b; if (compareA == compareB) { - Debug.log("Same conditions => do not swap and leave the work for global value numbering."); + debug.log("Same conditions => do not swap and leave the work for global value numbering."); return false; } if (compareB.unorderedIsTrue()) { @@ -497,7 +498,7 @@ Condition combined = conditionA.join(comparableCondition); if (combined == null) { // The two conditions are disjoint => can reorder. - Debug.log("Can swap disjoint coditions on same values: %s and %s", conditionA, comparableCondition); + debug.log("Can swap disjoint coditions on same values: %s and %s", conditionA, comparableCondition); return true; } } else if (conditionA == Condition.EQ && conditionB == Condition.EQ) { @@ -513,7 +514,7 @@ } if (canSwap) { - Debug.log("Can swap equality condition with one shared and one disjoint value."); + debug.log("Can swap equality condition with one shared and one disjoint value."); return true; } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/LoopBeginNode.java 2017-07-07 09:31:24.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/LoopBeginNode.java 2017-07-07 09:31:24.000000000 -0700 @@ -43,9 +43,20 @@ public static final NodeClass TYPE = NodeClass.create(LoopBeginNode.class); protected double loopFrequency; + protected double loopOrigFrequency; protected int nextEndIndex; protected int unswitches; + protected int splits; protected int inversionCount; + protected LoopType loopType; + protected int unrollFactor; + + public enum LoopType { + SIMPLE_LOOP, + PRE_LOOP, + MAIN_LOOP, + POST_LOOP + } /** See {@link LoopEndNode#canSafepoint} for more information. */ boolean canEndsSafepoint; @@ -55,7 +66,51 @@ public LoopBeginNode() { super(TYPE); loopFrequency = 1; + loopOrigFrequency = 1; + unswitches = 0; + splits = 0; this.canEndsSafepoint = true; + loopType = LoopType.SIMPLE_LOOP; + unrollFactor = 1; + } + + public boolean isSimpleLoop() { + return (loopType == LoopType.SIMPLE_LOOP); + } + + public void setPreLoop() { + assert isSimpleLoop(); + loopType = LoopType.PRE_LOOP; + } + + public boolean isPreLoop() { + return (loopType == LoopType.PRE_LOOP); + } + + public void setMainLoop() { + assert isSimpleLoop(); + loopType = LoopType.MAIN_LOOP; + } + + public boolean isMainLoop() { + return (loopType == LoopType.MAIN_LOOP); + } + + public void setPostLoop() { + assert isSimpleLoop(); + loopType = LoopType.POST_LOOP; + } + + public boolean isPostLoop() { + return (loopType == LoopType.POST_LOOP); + } + + public int getUnrollFactor() { + return unrollFactor; + } + + public void setUnrollFactor(int currentUnrollFactor) { + unrollFactor = currentUnrollFactor; } /** Disables safepoint for the whole loop, i.e., for all {@link LoopEndNode loop ends}. */ @@ -68,6 +123,15 @@ } } + public double loopOrigFrequency() { + return loopOrigFrequency; + } + + public void setLoopOrigFrequency(double loopOrigFrequency) { + assert loopOrigFrequency >= 0; + this.loopOrigFrequency = loopOrigFrequency; + } + public double loopFrequency() { return loopFrequency; } @@ -122,11 +186,23 @@ return result; } + public boolean isSingleEntryLoop() { + return (forwardEndCount() == 1); + } + public AbstractEndNode forwardEnd() { assert forwardEndCount() == 1; return forwardEndAt(0); } + public int splits() { + return splits; + } + + public void incrementSplits() { + splits++; + } + @Override public void generate(NodeLIRBuilderTool gen) { // Nothing to emit, since this is node is used for structural purposes only. --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java 2017-07-07 09:31:24.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java 2017-07-07 09:31:24.000000000 -0700 @@ -33,6 +33,7 @@ import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.common.cfg.BlockMap; import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.JavaMethodContext; import org.graalvm.compiler.graph.Graph; import org.graalvm.compiler.graph.Node; @@ -167,60 +168,95 @@ private boolean useProfilingInfo = true; private final OptionValues options; private Cancellable cancellable = null; + private final DebugContext debug; /** * Creates a builder for a graph. */ - public Builder(OptionValues options, AllowAssumptions allowAssumptions) { + public Builder(OptionValues options, DebugContext debug, AllowAssumptions allowAssumptions) { this.options = options; + this.debug = debug; this.assumptions = allowAssumptions == AllowAssumptions.YES ? new Assumptions() : null; } /** * Creates a builder for a graph that does not support {@link Assumptions}. */ - public Builder(OptionValues options) { + public Builder(OptionValues options, DebugContext debug) { this.options = options; + this.debug = debug; assumptions = null; } + public String getName() { + return name; + } + public Builder name(String s) { this.name = s; return this; } + public ResolvedJavaMethod getMethod() { + return rootMethod; + } + public Builder method(ResolvedJavaMethod method) { this.rootMethod = method; return this; } + public DebugContext getDebug() { + return debug; + } + + public SpeculationLog getSpeculationLog() { + return speculationLog; + } + public Builder speculationLog(SpeculationLog log) { this.speculationLog = log; return this; } + public CompilationIdentifier getCompilationId() { + return compilationId; + } + public Builder compilationId(CompilationIdentifier id) { this.compilationId = id; return this; } + public Cancellable getCancellable() { + return cancellable; + } + public Builder cancellable(Cancellable cancel) { this.cancellable = cancel; return this; } + public int getEntryBCI() { + return entryBCI; + } + public Builder entryBCI(int bci) { this.entryBCI = bci; return this; } + public boolean getUseProfilingInfo() { + return useProfilingInfo; + } + public Builder useProfilingInfo(boolean flag) { this.useProfilingInfo = flag; return this; } public StructuredGraph build() { - return new StructuredGraph(name, rootMethod, entryBCI, assumptions, speculationLog, useProfilingInfo, compilationId, options, cancellable); + return new StructuredGraph(name, rootMethod, entryBCI, assumptions, speculationLog, useProfilingInfo, compilationId, options, debug, cancellable); } } @@ -280,8 +316,9 @@ boolean useProfilingInfo, CompilationIdentifier compilationId, OptionValues options, + DebugContext debug, Cancellable cancellable) { - super(name, options); + super(name, options, debug); this.setStart(add(new StartNode())); this.rootMethod = method; this.graphId = uniqueGraphIds.incrementAndGet(); @@ -404,13 +441,16 @@ * * @param newName the name of the copy, used for debugging purposes (can be null) * @param duplicationMapCallback consumer of the duplication map created during the copying + * @param debugForCopy the debug context for the graph copy. This must not be the debug for this + * graph if this graph can be accessed from multiple threads (e.g., it's in a cache + * accessed by multiple threads). */ @Override - protected Graph copy(String newName, Consumer> duplicationMapCallback) { - return copy(newName, duplicationMapCallback, compilationId); + protected Graph copy(String newName, Consumer> duplicationMapCallback, DebugContext debugForCopy) { + return copy(newName, duplicationMapCallback, compilationId, debugForCopy); } - private StructuredGraph copy(String newName, Consumer> duplicationMapCallback, CompilationIdentifier newCompilationId) { + private StructuredGraph copy(String newName, Consumer> duplicationMapCallback, CompilationIdentifier newCompilationId, DebugContext debugForCopy) { AllowAssumptions allowAssumptions = AllowAssumptions.ifNonNull(assumptions); StructuredGraph copy = new StructuredGraph(newName, method(), @@ -419,7 +459,7 @@ speculationLog, useProfilingInfo, newCompilationId, - getOptions(), null); + getOptions(), debugForCopy, null); if (allowAssumptions == AllowAssumptions.YES && assumptions != null) { copy.assumptions.record(assumptions); } @@ -437,8 +477,13 @@ return copy; } - public StructuredGraph copyWithIdentifier(CompilationIdentifier newCompilationId) { - return copy(name, null, newCompilationId); + /** + * @param debugForCopy the debug context for the graph copy. This must not be the debug for this + * graph if this graph can be accessed from multiple threads (e.g., it's in a cache + * accessed by multiple threads). + */ + public StructuredGraph copyWithIdentifier(CompilationIdentifier newCompilationId, DebugContext debugForCopy) { + return copy(name, null, newCompilationId, debugForCopy); } public ParameterNode getParameter(int index) { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/Block.java 2017-07-07 09:31:25.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/Block.java 2017-07-07 09:31:25.000000000 -0700 @@ -31,11 +31,13 @@ import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodeinfo.Verbosity; import org.graalvm.compiler.nodes.AbstractBeginNode; +import org.graalvm.compiler.nodes.BeginNode; import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.InvokeWithExceptionNode; import org.graalvm.compiler.nodes.LoopBeginNode; import org.graalvm.compiler.nodes.LoopEndNode; +import org.graalvm.compiler.nodes.LoopExitNode; import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; import org.graalvm.word.LocationIdentity; @@ -48,7 +50,7 @@ protected FixedNode endNode; protected double probability; - protected Loop loop; + private Loop loop; protected Block postdominator; protected Block distancedDominatorCache; @@ -67,6 +69,21 @@ return endNode; } + /** + * Return the {@link LoopExitNode} for this block if it exists. + */ + public LoopExitNode getLoopExit() { + if (beginNode instanceof BeginNode) { + if (beginNode.next() instanceof LoopExitNode) { + return (LoopExitNode) beginNode.next(); + } + } + if (beginNode instanceof LoopExitNode) { + return (LoopExitNode) beginNode; + } + return null; + } + @Override public Loop getLoop() { return loop; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java 2017-07-07 09:31:25.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java 2017-07-07 09:31:25.000000000 -0700 @@ -30,7 +30,7 @@ import org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph; import org.graalvm.compiler.core.common.cfg.CFGVerifier; import org.graalvm.compiler.core.common.cfg.Loop; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeMap; @@ -594,7 +594,7 @@ if (beginNode instanceof LoopBeginNode) { Loop loop = new HIRLoop(block.getLoop(), loops.size(), block); loops.add(loop); - block.loop = loop; + block.setLoop(loop); loop.getBlocks().add(block); LoopBeginNode loopBegin = (LoopBeginNode) beginNode; @@ -608,7 +608,7 @@ Block exitBlock = nodeToBlock.get(exit); assert exitBlock.getPredecessorCount() == 1; computeLoopBlocks(exitBlock.getFirstPredecessor(), loop, stack, true); - loop.getExits().add(exitBlock); + loop.addExit(exitBlock); } // The following loop can add new blocks to the end of the loop's block @@ -617,10 +617,10 @@ for (int i = 0; i < size; ++i) { Block b = loop.getBlocks().get(i); for (Block sux : b.getSuccessors()) { - if (sux.loop != loop) { + if (sux.getLoop() != loop) { AbstractBeginNode begin = sux.getBeginNode(); if (!(begin instanceof LoopExitNode && ((LoopExitNode) begin).loopBegin() == loopBegin)) { - Debug.log(Debug.VERBOSE_LEVEL, "Unexpected loop exit with %s, including whole branch in the loop", sux); + graph.getDebug().log(DebugContext.VERBOSE_LEVEL, "Unexpected loop exit with %s, including whole branch in the loop", sux); computeLoopBlocks(sux, loop, stack, false); } } @@ -645,7 +645,7 @@ // we might exit multiple loops if b.loops is not a loop at depth 0 Loop curr = b.getLoop(); while (curr != null) { - curr.getExits().add(succ); + curr.addExit(succ); curr = curr.getParent(); } } else { @@ -667,7 +667,7 @@ assert !Loop.transitiveParentLoop(succ.getLoop(), b.getLoop()); Loop curr = b.getLoop(); while (curr != null && curr != succ.getLoop()) { - curr.getExits().add(succ); + curr.addExit(succ); curr = curr.getParent(); } } @@ -681,8 +681,8 @@ } private static void computeLoopBlocks(Block start, Loop loop, Block[] stack, boolean usePred) { - if (start.loop != loop) { - start.loop = loop; + if (start.getLoop() != loop) { + start.setLoop(loop); stack[0] = start; loop.getBlocks().add(start); int tos = 0; @@ -691,9 +691,9 @@ // Add predecessors or successors to the loop. for (Block b : (usePred ? block.getPredecessors() : block.getSuccessors())) { - if (b.loop != loop) { + if (b.getLoop() != loop) { stack[++tos] = b; - b.loop = loop; + b.setLoop(loop); loop.getBlocks().add(b); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderTool.java 2017-07-07 09:31:26.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderTool.java 2017-07-07 09:31:25.000000000 -0700 @@ -23,6 +23,7 @@ package org.graalvm.compiler.nodes.graphbuilderconf; import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.StampProvider; @@ -66,6 +67,10 @@ return getGraph().getOptions(); } + default DebugContext getDebug() { + return getGraph().getDebug(); + } + /** * Determines if this parsing context is within the bytecode of an intrinsic or a method inlined * by an intrinsic. --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FloatingReadNode.java 2017-07-07 09:31:26.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FloatingReadNode.java 2017-07-07 09:31:26.000000000 -0700 @@ -88,7 +88,18 @@ @Override public Node canonical(CanonicalizerTool tool) { - return ReadNode.canonicalizeRead(this, getAddress(), getLocationIdentity(), tool); + Node result = ReadNode.canonicalizeRead(this, getAddress(), getLocationIdentity(), tool); + if (result != this) { + return result; + } + if (tool.canonicalizeReads() && getAddress().hasMoreThanOneUsage() && lastLocationAccess instanceof WriteNode) { + WriteNode write = (WriteNode) lastLocationAccess; + if (write.getAddress() == getAddress() && write.getAccessStamp().isCompatible(getAccessStamp())) { + // Same memory location with no intervening write + return write.value(); + } + } + return this; } @SuppressWarnings("try") --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/WriteNode.java 2017-07-07 09:31:26.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/WriteNode.java 2017-07-07 09:31:26.000000000 -0700 @@ -24,7 +24,10 @@ import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.graph.spi.Canonicalizable; +import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; @@ -35,7 +38,7 @@ * Writes a given {@linkplain #value() value} a {@linkplain FixedAccessNode memory location}. */ @NodeInfo(nameTemplate = "Write#{p#location/s}") -public class WriteNode extends AbstractWriteNode implements LIRLowerableAccess { +public class WriteNode extends AbstractWriteNode implements LIRLowerableAccess, Canonicalizable { public static final NodeClass TYPE = NodeClass.create(WriteNode.class); @@ -62,4 +65,16 @@ public Stamp getAccessStamp() { return value().stamp(); } + + @Override + public Node canonical(CanonicalizerTool tool) { + if (tool.canonicalizeReads() && hasExactlyOneUsage() && next() instanceof WriteNode) { + WriteNode write = (WriteNode) next(); + if (write.lastLocationAccess == this && write.getAddress() == getAddress() && getAccessStamp().isCompatible(write.getAccessStamp())) { + write.setLastLocationAccess(getLastLocationAccess()); + return write; + } + } + return this; + } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/VirtualizerTool.java 2017-07-07 09:31:27.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/VirtualizerTool.java 2017-07-07 09:31:27.000000000 -0700 @@ -24,6 +24,7 @@ import java.util.List; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.java.MonitorIdNode; @@ -158,4 +159,6 @@ boolean ensureMaterialized(VirtualObjectNode virtualObject); OptionValues getOptions(); + + DebugContext getDebug(); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java 2017-07-07 09:31:27.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java 2017-07-07 09:31:27.000000000 -0700 @@ -25,14 +25,16 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.Iterator; import java.util.List; +import java.util.function.BiFunction; import org.graalvm.compiler.bytecode.Bytecode; import org.graalvm.compiler.code.SourceStackTraceBailoutException; import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; import org.graalvm.compiler.core.common.type.ObjectStamp; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Graph; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeBitMap; @@ -44,6 +46,7 @@ import org.graalvm.compiler.nodes.AbstractBeginNode; import org.graalvm.compiler.nodes.AbstractEndNode; import org.graalvm.compiler.nodes.AbstractMergeNode; +import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.ControlSplitNode; import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.FixedWithNextNode; @@ -58,11 +61,16 @@ import org.graalvm.compiler.nodes.StateSplit; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.java.LoadIndexedNode; import org.graalvm.compiler.nodes.java.MethodCallTargetNode; +import org.graalvm.compiler.nodes.java.MonitorIdNode; import org.graalvm.compiler.nodes.spi.ArrayLengthProvider; import org.graalvm.compiler.nodes.spi.LimitedValueProxy; import org.graalvm.compiler.nodes.spi.LoweringProvider; import org.graalvm.compiler.nodes.spi.ValueProxy; +import org.graalvm.compiler.nodes.spi.VirtualizerTool; +import org.graalvm.compiler.nodes.virtual.VirtualArrayNode; +import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; @@ -77,8 +85,10 @@ import jdk.vm.ci.meta.Assumptions; import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.ConstantReflectionProvider; +import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; public class GraphUtil { @@ -98,7 +108,8 @@ fixSurvivingAffectedMerges(markedNodes, unmarkedMerges); - Debug.dump(Debug.DETAILED_LEVEL, node.graph(), "After fixing merges (killCFG %s)", node); + DebugContext debug = node.getDebug(); + debug.dump(DebugContext.DETAILED_LEVEL, node.graph(), "After fixing merges (killCFG %s)", node); // Mark non-fixed nodes markUsages(markedNodes); @@ -112,7 +123,7 @@ } } } - Debug.dump(Debug.VERY_DETAILED_LEVEL, node.graph(), "After disconnecting non-marked inputs (killCFG %s)", node); + debug.dump(DebugContext.VERY_DETAILED_LEVEL, node.graph(), "After disconnecting non-marked inputs (killCFG %s)", node); // Kill marked nodes for (Node marked : markedNodes) { if (marked.isAlive()) { @@ -218,7 +229,8 @@ @SuppressWarnings("try") public static void killCFG(FixedNode node) { - try (Debug.Scope scope = Debug.scope("KillCFG", node)) { + DebugContext debug = node.getDebug(); + try (DebugContext.Scope scope = debug.scope("KillCFG", node)) { EconomicSet unusedNodes = null; EconomicSet unsafeNodes = null; Graph.NodeEventScope nodeEventScope = null; @@ -237,9 +249,9 @@ } }); } - Debug.dump(Debug.VERY_DETAILED_LEVEL, node.graph(), "Before killCFG %s", node); + debug.dump(DebugContext.VERY_DETAILED_LEVEL, node.graph(), "Before killCFG %s", node); killCFGInner(node); - Debug.dump(Debug.VERY_DETAILED_LEVEL, node.graph(), "After killCFG %s", node); + debug.dump(DebugContext.VERY_DETAILED_LEVEL, node.graph(), "After killCFG %s", node); if (Graph.Options.VerifyGraalGraphEdges.getValue(options)) { EconomicSet newUnsafeNodes = collectUnsafeNodes(node.graph()); newUnsafeNodes.removeAll(unsafeNodes); @@ -257,7 +269,7 @@ assert unusedNodes.isEmpty() : "New unused nodes: " + unusedNodes; } } catch (Throwable t) { - throw Debug.handle(t); + throw debug.handle(t); } } @@ -935,4 +947,79 @@ } return null; } + + /** + * Virtualize an array copy. + * + * @param tool the virtualization tool + * @param source the source array + * @param sourceLength the length of the source array + * @param newLength the length of the new array + * @param from the start index in the source array + * @param newComponentType the component type of the new array + * @param elementKind the kind of the new array elements + * @param graph the node graph + * @param virtualArrayProvider a functional provider that returns a new virtual array given the + * component type and length + */ + public static void virtualizeArrayCopy(VirtualizerTool tool, ValueNode source, ValueNode sourceLength, ValueNode newLength, ValueNode from, ResolvedJavaType newComponentType, JavaKind elementKind, + StructuredGraph graph, BiFunction virtualArrayProvider) { + + ValueNode sourceAlias = tool.getAlias(source); + ValueNode replacedSourceLength = tool.getAlias(sourceLength); + ValueNode replacedNewLength = tool.getAlias(newLength); + ValueNode replacedFrom = tool.getAlias(from); + if (!replacedNewLength.isConstant() || !replacedFrom.isConstant() || !replacedSourceLength.isConstant()) { + return; + } + + assert newComponentType != null : "An array copy can be virtualized only if the real type of the resulting array is known statically."; + + int fromInt = replacedFrom.asJavaConstant().asInt(); + int newLengthInt = replacedNewLength.asJavaConstant().asInt(); + int sourceLengthInt = replacedSourceLength.asJavaConstant().asInt(); + if (sourceAlias instanceof VirtualObjectNode) { + VirtualObjectNode sourceVirtual = (VirtualObjectNode) sourceAlias; + assert sourceLengthInt == sourceVirtual.entryCount(); + } + + if (fromInt < 0 || newLengthInt < 0 || fromInt > sourceLengthInt) { + /* Illegal values for either from index, the new length or the source length. */ + return; + } + + if (newLengthInt >= tool.getMaximumEntryCount()) { + /* The new array size is higher than maximum allowed size of virtualized objects. */ + return; + } + + ValueNode[] newEntryState = new ValueNode[newLengthInt]; + int readLength = Math.min(newLengthInt, sourceLengthInt - fromInt); + + if (sourceAlias instanceof VirtualObjectNode) { + /* The source array is virtualized, just copy over the values. */ + VirtualObjectNode sourceVirtual = (VirtualObjectNode) sourceAlias; + for (int i = 0; i < readLength; i++) { + newEntryState[i] = tool.getEntry(sourceVirtual, fromInt + i); + } + } else { + /* The source array is not virtualized, emit index loads. */ + for (int i = 0; i < readLength; i++) { + LoadIndexedNode load = new LoadIndexedNode(null, sourceAlias, ConstantNode.forInt(i + fromInt, graph), elementKind); + tool.addNode(load); + newEntryState[i] = load; + } + } + if (readLength < newLengthInt) { + /* Pad the copy with the default value of its elment kind. */ + ValueNode defaultValue = ConstantNode.defaultForKind(elementKind, graph); + for (int i = readLength; i < newLengthInt; i++) { + newEntryState[i] = defaultValue; + } + } + /* Perform the replacement. */ + VirtualArrayNode newVirtualArray = virtualArrayProvider.apply(newComponentType, newLengthInt); + tool.createVirtualObject(newVirtualArray, newEntryState, Collections. emptyList(), false); + tool.replaceWithVirtual(newVirtualArray); + } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AddressLoweringByUsePhase.java 2017-07-07 09:31:28.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AddressLoweringByUsePhase.java 2017-07-07 09:31:27.000000000 -0700 @@ -23,8 +23,11 @@ */ package org.graalvm.compiler.phases.common; +import jdk.vm.ci.meta.JavaKind; import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.nodes.PrefetchAllocateNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.extended.JavaReadNode; @@ -81,13 +84,11 @@ Stamp stamp = abstractWriteNode.value().stamp(); address = abstractWriteNode.getAddress(); lowered = lowering.lower(abstractWriteNode, stamp, address); - // TODO -- PrefetchAllocateNode is not yet implemented for AArch64 - // } else if (node instanceof PrefetchAllocateNode) { - // PrefetchAllocateNode prefetchAllocateNode = (PrefetchAllocateNode) node; - // Stamp stamp = prefetchAllocateNode.value().stamp(); - // n.b.this getter is not provided! - // address = prefetchAllocateNode.getAddress(); - // lowered = lowering.lower(prefetchAllocateNode, stamp, address); + } else if (node instanceof PrefetchAllocateNode) { + PrefetchAllocateNode prefetchAllocateNode = (PrefetchAllocateNode) node; + Stamp stamp = StampFactory.forKind(JavaKind.Object); + address = (AddressNode) prefetchAllocateNode.inputs().first(); + lowered = lowering.lower(prefetchAllocateNode, stamp, address); } else { continue; } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/CanonicalizerPhase.java 2017-07-07 09:31:28.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/CanonicalizerPhase.java 2017-07-07 09:31:28.000000000 -0700 @@ -23,9 +23,9 @@ package org.graalvm.compiler.phases.common; import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.CounterKey; import org.graalvm.compiler.debug.DebugCloseable; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.GraalGraphError; import org.graalvm.compiler.graph.Graph; import org.graalvm.compiler.graph.Graph.Mark; @@ -62,13 +62,13 @@ public class CanonicalizerPhase extends BasePhase { private static final int MAX_ITERATION_PER_NODE = 10; - private static final DebugCounter COUNTER_CANONICALIZED_NODES = Debug.counter("CanonicalizedNodes"); - private static final DebugCounter COUNTER_PROCESSED_NODES = Debug.counter("ProcessedNodes"); - private static final DebugCounter COUNTER_CANONICALIZATION_CONSIDERED_NODES = Debug.counter("CanonicalizationConsideredNodes"); - private static final DebugCounter COUNTER_INFER_STAMP_CALLED = Debug.counter("InferStampCalled"); - private static final DebugCounter COUNTER_STAMP_CHANGED = Debug.counter("StampChanged"); - private static final DebugCounter COUNTER_SIMPLIFICATION_CONSIDERED_NODES = Debug.counter("SimplificationConsideredNodes"); - private static final DebugCounter COUNTER_GLOBAL_VALUE_NUMBERING_HITS = Debug.counter("GlobalValueNumberingHits"); + private static final CounterKey COUNTER_CANONICALIZED_NODES = DebugContext.counter("CanonicalizedNodes"); + private static final CounterKey COUNTER_PROCESSED_NODES = DebugContext.counter("ProcessedNodes"); + private static final CounterKey COUNTER_CANONICALIZATION_CONSIDERED_NODES = DebugContext.counter("CanonicalizationConsideredNodes"); + private static final CounterKey COUNTER_INFER_STAMP_CALLED = DebugContext.counter("InferStampCalled"); + private static final CounterKey COUNTER_STAMP_CHANGED = DebugContext.counter("StampChanged"); + private static final CounterKey COUNTER_SIMPLIFICATION_CONSIDERED_NODES = DebugContext.counter("SimplificationConsideredNodes"); + private static final CounterKey COUNTER_GLOBAL_VALUE_NUMBERING_HITS = DebugContext.counter("GlobalValueNumberingHits"); private boolean globalValueNumber = true; private boolean canonicalizeReads = true; @@ -161,6 +161,7 @@ private NodeWorkList workList; private Tool tool; + private DebugContext debug; private Instance(PhaseContext context) { this(context, null, null); @@ -187,6 +188,7 @@ @Override protected void run(StructuredGraph graph) { + this.debug = graph.getDebug(); boolean wholeGraph = newNodesMark == null || newNodesMark.isStart(); if (initWorkingSet == null) { workList = graph.createIterativeNodeWorkList(wholeGraph, MAX_ITERATION_PER_NODE); @@ -229,8 +231,8 @@ try (NodeEventScope nes = graph.trackNodeEvents(listener)) { for (Node n : workList) { boolean changed = processNode(n); - if (changed && Debug.isDumpEnabled(Debug.DETAILED_LEVEL)) { - Debug.dump(Debug.DETAILED_LEVEL, graph, "CanonicalizerPhase %s", n); + if (changed && debug.isDumpEnabled(DebugContext.DETAILED_LEVEL)) { + debug.dump(DebugContext.DETAILED_LEVEL, graph, "CanonicalizerPhase %s", n); } } } @@ -243,7 +245,7 @@ if (!node.isAlive()) { return false; } - COUNTER_PROCESSED_NODES.increment(); + COUNTER_PROCESSED_NODES.increment(debug); if (GraphUtil.tryKillUnused(node)) { return true; } @@ -261,7 +263,7 @@ Constant constant = valueNode.stamp().asConstant(); if (constant != null && !(node instanceof ConstantNode)) { ConstantNode stampConstant = ConstantNode.forConstant(valueNode.stamp(), constant, context.getMetaAccess(), graph); - Debug.log("Canonicalizer: constant stamp replaces %1s with %1s", valueNode, stampConstant); + debug.log("Canonicalizer: constant stamp replaces %1s with %1s", valueNode, stampConstant); valueNode.replaceAtUsages(InputType.Value, stampConstant); GraphUtil.tryKillUnused(valueNode); return true; @@ -282,8 +284,8 @@ if (newNode != null) { assert !(node instanceof FixedNode || newNode instanceof FixedNode); node.replaceAtUsagesAndDelete(newNode); - COUNTER_GLOBAL_VALUE_NUMBERING_HITS.increment(); - Debug.log("GVN applied and new node is %1s", newNode); + COUNTER_GLOBAL_VALUE_NUMBERING_HITS.increment(debug); + debug.log("GVN applied and new node is %1s", newNode); return true; } } @@ -319,7 +321,7 @@ } } if (nodeClass.isCanonicalizable()) { - COUNTER_CANONICALIZATION_CONSIDERED_NODES.increment(); + COUNTER_CANONICALIZATION_CONSIDERED_NODES.increment(debug); Node canonical; try (AutoCloseable verify = getCanonicalizeableContractAssertion(node)) { canonical = ((Canonicalizable) node).canonical(tool); @@ -335,8 +337,8 @@ } if (nodeClass.isSimplifiable() && simplify) { - Debug.log(Debug.VERBOSE_LEVEL, "Canonicalizer: simplifying %s", node); - COUNTER_SIMPLIFICATION_CONSIDERED_NODES.increment(); + debug.log(DebugContext.VERBOSE_LEVEL, "Canonicalizer: simplifying %s", node); + COUNTER_SIMPLIFICATION_CONSIDERED_NODES.increment(debug); node.simplify(tool); return node.isDeleted(); } @@ -362,12 +364,12 @@ // @formatter:on private boolean performReplacement(final Node node, Node newCanonical) { if (newCanonical == node) { - Debug.log(Debug.VERBOSE_LEVEL, "Canonicalizer: work on %1s", node); + debug.log(DebugContext.VERBOSE_LEVEL, "Canonicalizer: work on %1s", node); return false; } else { Node canonical = newCanonical; - Debug.log("Canonicalizer: replacing %1s with %1s", node, canonical); - COUNTER_CANONICALIZED_NODES.increment(); + debug.log("Canonicalizer: replacing %1s with %1s", node, canonical); + COUNTER_CANONICALIZED_NODES.increment(debug); StructuredGraph graph = (StructuredGraph) node.graph(); if (canonical != null && !canonical.isAlive()) { assert !canonical.isDeleted(); @@ -428,9 +430,9 @@ */ private boolean tryInferStamp(ValueNode node) { if (node.isAlive()) { - COUNTER_INFER_STAMP_CALLED.increment(); + COUNTER_INFER_STAMP_CALLED.increment(debug); if (node.inferStamp()) { - COUNTER_STAMP_CHANGED.increment(); + COUNTER_STAMP_CHANGED.increment(debug); for (Node usage : node.usages()) { workList.add(usage); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java 2017-07-07 09:31:28.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java 2017-07-07 09:31:28.000000000 -0700 @@ -35,9 +35,9 @@ import org.graalvm.compiler.core.common.type.ObjectStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.CounterKey; import org.graalvm.compiler.debug.DebugCloseable; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeMap; import org.graalvm.compiler.graph.NodeStack; @@ -63,10 +63,10 @@ import org.graalvm.compiler.nodes.ProxyNode; import org.graalvm.compiler.nodes.ShortCircuitOrNode; import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; import org.graalvm.compiler.nodes.UnaryOpLogicNode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.ValuePhiNode; -import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; import org.graalvm.compiler.nodes.calc.AndNode; import org.graalvm.compiler.nodes.calc.BinaryArithmeticNode; import org.graalvm.compiler.nodes.calc.BinaryNode; @@ -96,10 +96,10 @@ public class ConditionalEliminationPhase extends BasePhase { - private static final DebugCounter counterStampsRegistered = Debug.counter("StampsRegistered"); - private static final DebugCounter counterStampsFound = Debug.counter("StampsFound"); - private static final DebugCounter counterIfsKilled = Debug.counter("CE_KilledIfs"); - private static final DebugCounter counterPhiStampsImproved = Debug.counter("CE_ImprovedPhis"); + private static final CounterKey counterStampsRegistered = DebugContext.counter("StampsRegistered"); + private static final CounterKey counterStampsFound = DebugContext.counter("StampsFound"); + private static final CounterKey counterIfsKilled = DebugContext.counter("CE_KilledIfs"); + private static final CounterKey counterPhiStampsImproved = DebugContext.counter("CE_ImprovedPhis"); private final boolean fullSchedule; private final boolean moveGuards; @@ -115,7 +115,7 @@ @Override @SuppressWarnings("try") protected void run(StructuredGraph graph, PhaseContext context) { - try (Debug.Scope s = Debug.scope("DominatorConditionalElimination")) { + try (DebugContext.Scope s = graph.getDebug().scope("DominatorConditionalElimination")) { BlockMap> blockToNodes = null; NodeMap nodeToBlock = null; ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, true); @@ -242,6 +242,7 @@ protected final CanonicalizerTool tool; protected final NodeStack undoOperations; protected final StructuredGraph graph; + protected final DebugContext debug; protected final EconomicMap> mergeMaps; /** @@ -251,6 +252,7 @@ public Instance(StructuredGraph graph, BlockMap> blockToNodes, PhaseContext context) { this.graph = graph; + this.debug = graph.getDebug(); this.blockToNodes = blockToNodes; this.undoOperations = new NodeStack(); this.map = graph.createNodeMap(); @@ -304,7 +306,7 @@ node.replaceAtPredecessor(deopt); GraphUtil.killCFG(node); } - Debug.log("Kill fixed guard guard"); + debug.log("Kill fixed guard guard"); return true; })) { registerNewCondition(node.condition(), node.isNegated(), node); @@ -318,7 +320,7 @@ survivingSuccessor.replaceAtPredecessor(null); node.replaceAtPredecessor(survivingSuccessor); GraphUtil.killCFG(node); - counterIfsKilled.increment(); + counterIfsKilled.increment(debug); return true; }); } @@ -326,7 +328,7 @@ @Override public Integer enter(Block block) { int mark = undoOperations.size(); - Debug.log("[Pre Processing block %s]", block); + debug.log("[Pre Processing block %s]", block); // For now conservatively collect guards only within the same block. pendingTests.clear(); processNodes(block); @@ -348,7 +350,7 @@ private void processBlock(Block block) { FixedNode n = block.getBeginNode(); FixedNode endNode = block.getEndNode(); - Debug.log("[Processing block %s]", block); + debug.log("[Processing block %s]", block); while (n != endNode) { if (n.isDeleted() || endNode.isDeleted()) { // This branch was deleted! @@ -473,7 +475,7 @@ } newPhi.addInput(valueAt); } - counterPhiStampsImproved.increment(); + counterPhiStampsImproved.increment(debug); phi.replaceAtUsagesAndDelete(newPhi); } } @@ -697,7 +699,7 @@ } protected boolean rewireGuards(GuardingNode guard, boolean result, ValueNode proxifiedInput, Stamp guardedValueStamp, GuardRewirer rewireGuardFunction) { - counterStampsFound.increment(); + counterStampsFound.increment(debug); return rewireGuardFunction.rewire(guard, result, guardedValueStamp, proxifiedInput); } @@ -893,8 +895,8 @@ proxiedValue = value; } do { - counterStampsRegistered.increment(); - Debug.log("\t Saving stamp for node %s stamp %s guarded by %s", value, stamp, guard); + counterStampsRegistered.increment(debug); + debug.log("\t Saving stamp for node %s stamp %s guarded by %s", value, stamp, guard); assert value instanceof LogicNode || stamp.isCompatible(value.stamp()) : stamp + " vs. " + value.stamp() + " (" + value + ")"; map.setAndGrow(value, new InfoElement(stamp, guard, proxiedValue, map.getAndGrow(value))); undoOperations.push(value); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConvertDeoptimizeToGuardPhase.java 2017-07-07 09:31:29.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConvertDeoptimizeToGuardPhase.java 2017-07-07 09:31:29.000000000 -0700 @@ -26,8 +26,8 @@ import java.util.List; -import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.DebugCloseable; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.spi.SimplifierTool; import org.graalvm.compiler.nodeinfo.InputType; @@ -169,9 +169,10 @@ return; } + DebugContext debug = deoptBegin.getDebug(); if (deoptBegin instanceof AbstractMergeNode) { AbstractMergeNode mergeNode = (AbstractMergeNode) deoptBegin; - Debug.log("Visiting %s", mergeNode); + debug.log("Visiting %s", mergeNode); FixedNode next = mergeNode.next(); while (mergeNode.isAlive()) { AbstractEndNode end = mergeNode.forwardEnds().first(); @@ -201,7 +202,7 @@ } survivingSuccessor.replaceAtUsages(InputType.Guard, newGuard); - Debug.log("Converting deopt on %-5s branch of %s to guard for remaining branch %s.", deoptBegin == ifNode.trueSuccessor() ? "true" : "false", ifNode, survivingSuccessor); + debug.log("Converting deopt on %-5s branch of %s to guard for remaining branch %s.", deoptBegin == ifNode.trueSuccessor() ? "true" : "false", ifNode, survivingSuccessor); FixedNode next = pred.next(); pred.setNext(guard); guard.setNext(next); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/DeadCodeEliminationPhase.java 2017-07-07 09:31:29.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/DeadCodeEliminationPhase.java 2017-07-07 09:31:29.000000000 -0700 @@ -22,16 +22,16 @@ */ package org.graalvm.compiler.phases.common; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeFlood; import org.graalvm.compiler.nodes.AbstractEndNode; import org.graalvm.compiler.nodes.GuardNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.options.Option; -import org.graalvm.compiler.options.OptionType; import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionType; import org.graalvm.compiler.phases.Phase; public class DeadCodeEliminationPhase extends Phase { @@ -44,7 +44,7 @@ // @formatter:on } - private static final DebugCounter counterNodesRemoved = Debug.counter("NodesRemoved"); + private static final CounterKey counterNodesRemoved = DebugContext.counter("NodesRemoved"); public enum Optionality { Optional, @@ -133,11 +133,12 @@ } }; + DebugContext debug = graph.getDebug(); for (Node node : graph.getNodes()) { if (!flood.isMarked(node)) { node.markDeleted(); node.applyInputs(consumer); - counterNodesRemoved.increment(); + counterNodesRemoved.increment(debug); } } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FixReadsPhase.java 2017-07-07 09:31:30.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FixReadsPhase.java 2017-07-07 09:31:29.000000000 -0700 @@ -27,8 +27,8 @@ import org.graalvm.compiler.core.common.type.FloatStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeMap; import org.graalvm.compiler.graph.NodeStack; @@ -81,13 +81,13 @@ */ public class FixReadsPhase extends BasePhase { - private static final DebugCounter counterStampsRegistered = Debug.counter("FixReads_StampsRegistered"); - private static final DebugCounter counterIfsKilled = Debug.counter("FixReads_KilledIfs"); - private static final DebugCounter counterConditionalsKilled = Debug.counter("FixReads_KilledConditionals"); - private static final DebugCounter counterCanonicalizedSwitches = Debug.counter("FixReads_CanonicalizedSwitches"); - private static final DebugCounter counterConstantReplacements = Debug.counter("FixReads_ConstantReplacement"); - private static final DebugCounter counterConstantInputReplacements = Debug.counter("FixReads_ConstantInputReplacement"); - private static final DebugCounter counterBetterMergedStamps = Debug.counter("FixReads_BetterMergedStamp"); + private static final CounterKey counterStampsRegistered = DebugContext.counter("FixReads_StampsRegistered"); + private static final CounterKey counterIfsKilled = DebugContext.counter("FixReads_KilledIfs"); + private static final CounterKey counterConditionalsKilled = DebugContext.counter("FixReads_KilledConditionals"); + private static final CounterKey counterCanonicalizedSwitches = DebugContext.counter("FixReads_CanonicalizedSwitches"); + private static final CounterKey counterConstantReplacements = DebugContext.counter("FixReads_ConstantReplacement"); + private static final CounterKey counterConstantInputReplacements = DebugContext.counter("FixReads_ConstantInputReplacement"); + private static final CounterKey counterBetterMergedStamps = DebugContext.counter("FixReads_BetterMergedStamp"); protected boolean replaceInputsWithConstants; protected Phase schedulePhase; @@ -137,9 +137,11 @@ private final boolean replaceConstantInputs; private final BlockMap blockActionStart; private final EconomicMap> endMaps; + private final DebugContext debug; protected RawConditionalEliminationVisitor(StructuredGraph graph, ScheduleResult schedule, MetaAccessProvider metaAccess, boolean replaceInputsWithConstants) { this.graph = graph; + this.debug = graph.getDebug(); this.schedule = schedule; this.metaAccess = metaAccess; blockActionStart = new BlockMap<>(schedule.getCFG()); @@ -174,7 +176,7 @@ continue; } } - counterConstantInputReplacements.increment(); + counterConstantInputReplacements.increment(node.getDebug()); ConstantNode stampConstant = ConstantNode.forConstant(bestStamp, constant, metaAccess, graph); assert stampConstant.stamp().isCompatible(valueNode.stamp()); replaceInput(p, node, stampConstant); @@ -220,7 +222,7 @@ MapCursor entries = endMap.getEntries(); while (entries.advance()) { if (registerNewValueStamp(entries.getKey(), entries.getValue())) { - counterBetterMergedStamps.increment(); + counterBetterMergedStamps.increment(debug); } } } @@ -320,8 +322,8 @@ Constant constant = newStamp.asConstant(); if (constant != null && !(node instanceof ConstantNode)) { ConstantNode stampConstant = ConstantNode.forConstant(newStamp, constant, metaAccess, graph); - Debug.log("RawConditionElimination: constant stamp replaces %1s with %1s", node, stampConstant); - counterConstantReplacements.increment(); + debug.log("RawConditionElimination: constant stamp replaces %1s with %1s", node, stampConstant); + counterConstantReplacements.increment(debug); node.replaceAtUsages(InputType.Value, stampConstant); GraphUtil.tryKillUnused(node); return true; @@ -341,8 +343,8 @@ protected void processIntegerSwitch(IntegerSwitchNode node) { Stamp bestStamp = getBestStamp(node.value()); if (node.tryRemoveUnreachableKeys(null, bestStamp)) { - Debug.log("\t Canonicalized integer switch %s for value %s and stamp %s", node, node.value(), bestStamp); - counterCanonicalizedSwitches.increment(); + debug.log("\t Canonicalized integer switch %s for value %s and stamp %s", node, node.value(), bestStamp); + counterCanonicalizedSwitches.increment(debug); } } @@ -356,7 +358,7 @@ node.replaceAtPredecessor(survivingSuccessor); GraphUtil.killCFG(node); - counterIfsKilled.increment(); + counterIfsKilled.increment(debug); } } @@ -364,7 +366,7 @@ TriState result = tryProveCondition(node.condition()); if (result != TriState.UNKNOWN) { boolean isTrue = (result == TriState.TRUE); - counterConditionalsKilled.increment(); + counterConditionalsKilled.increment(debug); node.replaceAndDelete(isTrue ? node.trueValue() : node.falseValue()); } else { Stamp trueStamp = getBestStamp(node.trueValue()); @@ -444,8 +446,8 @@ } protected void registerNewStamp(ValueNode value, Stamp newStamp) { - counterStampsRegistered.increment(); - Debug.log("\t Saving stamp for node %s stamp %s", value, newStamp); + counterStampsRegistered.increment(debug); + debug.log("\t Saving stamp for node %s stamp %s", value, newStamp); ValueNode originalNode = value; stampMap.setAndGrow(originalNode, new StampElement(newStamp, stampMap.getAndGrow(originalNode))); undoOperations.push(originalNode); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/GuardLoweringPhase.java 2017-07-07 09:31:30.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/GuardLoweringPhase.java 2017-07-07 09:31:30.000000000 -0700 @@ -23,8 +23,8 @@ package org.graalvm.compiler.phases.common; import org.graalvm.compiler.core.common.cfg.Loop; -import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.DebugCloseable; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.AbstractBeginNode; import org.graalvm.compiler.nodes.BeginNode; @@ -139,6 +139,7 @@ } private static void processBlock(Block block, ScheduleResult schedule) { - new LowerGuards(block, Debug.isDumpEnabledForMethod() || Debug.isLogEnabledForMethod()).processNodes(block, schedule); + DebugContext debug = block.getBeginNode().getDebug(); + new LowerGuards(block, debug.isDumpEnabledForMethod() || debug.isLogEnabledForMethod()).processNodes(block, schedule); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/UseTrappingNullChecksPhase.java 2017-07-07 09:31:30.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/UseTrappingNullChecksPhase.java 2017-07-07 09:31:30.000000000 -0700 @@ -26,8 +26,8 @@ import java.util.List; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodes.AbstractBeginNode; @@ -58,10 +58,10 @@ public class UseTrappingNullChecksPhase extends BasePhase { - private static final DebugCounter counterTrappingNullCheck = Debug.counter("TrappingNullCheck"); - private static final DebugCounter counterTrappingNullCheckExistingRead = Debug.counter("TrappingNullCheckExistingRead"); - private static final DebugCounter counterTrappingNullCheckUnreached = Debug.counter("TrappingNullCheckUnreached"); - private static final DebugCounter counterTrappingNullCheckDynamicDeoptimize = Debug.counter("TrappingNullCheckDynamicDeoptimize"); + private static final CounterKey counterTrappingNullCheck = DebugContext.counter("TrappingNullCheck"); + private static final CounterKey counterTrappingNullCheckExistingRead = DebugContext.counter("TrappingNullCheckExistingRead"); + private static final CounterKey counterTrappingNullCheckUnreached = DebugContext.counter("TrappingNullCheckUnreached"); + private static final CounterKey counterTrappingNullCheckDynamicDeoptimize = DebugContext.counter("TrappingNullCheckDynamicDeoptimize"); @Override protected void run(StructuredGraph graph, LowTierContext context) { @@ -175,12 +175,13 @@ } private static void replaceWithTrappingNullCheck(AbstractDeoptimizeNode deopt, IfNode ifNode, LogicNode condition, DeoptimizationReason deoptimizationReason, long implicitNullCheckLimit) { - counterTrappingNullCheck.increment(); + DebugContext debug = deopt.getDebug(); + counterTrappingNullCheck.increment(debug); if (deopt instanceof DynamicDeoptimizeNode) { - counterTrappingNullCheckDynamicDeoptimize.increment(); + counterTrappingNullCheckDynamicDeoptimize.increment(debug); } if (deoptimizationReason == DeoptimizationReason.UnreachedCode) { - counterTrappingNullCheckUnreached.increment(); + counterTrappingNullCheckUnreached.increment(debug); } IsNullNode isNullNode = (IsNullNode) condition; AbstractBeginNode nonTrappingContinuation = ifNode.falseSuccessor(); @@ -202,7 +203,7 @@ fixedAccessNode.setNullCheck(true); deopt.graph().removeSplit(ifNode, nonTrappingContinuation); trappingNullCheck = fixedAccessNode; - counterTrappingNullCheckExistingRead.increment(); + counterTrappingNullCheckExistingRead.increment(debug); } } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java 2017-07-07 09:31:31.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java 2017-07-07 09:31:31.000000000 -0700 @@ -22,25 +22,24 @@ */ package org.graalvm.compiler.phases.common.inlining; -import jdk.vm.ci.code.BytecodeFrame; -import jdk.vm.ci.meta.Assumptions; -import jdk.vm.ci.meta.DeoptimizationAction; -import jdk.vm.ci.meta.DeoptimizationReason; -import jdk.vm.ci.meta.JavaConstant; -import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaType; +import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateReprofile; +import static jdk.vm.ci.meta.DeoptimizationReason.NullCheckException; +import static org.graalvm.compiler.core.common.GraalOptions.HotSpotPrintInlining; + +import java.lang.reflect.Constructor; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + import org.graalvm.compiler.api.replacements.MethodSubstitution; import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.TypeReference; import org.graalvm.compiler.core.common.util.Util; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.debug.internal.method.MethodMetricsImpl; -import org.graalvm.compiler.debug.internal.method.MethodMetricsInlineeScopeInfo; import org.graalvm.compiler.graph.GraalGraphError; import org.graalvm.compiler.graph.Graph; import org.graalvm.compiler.graph.Graph.DuplicationReplacement; @@ -97,15 +96,14 @@ import org.graalvm.util.UnmodifiableEconomicMap; import org.graalvm.util.UnmodifiableMapCursor; -import java.lang.reflect.Constructor; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Consumer; - -import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateReprofile; -import static jdk.vm.ci.meta.DeoptimizationReason.NullCheckException; -import static org.graalvm.compiler.core.common.GraalOptions.HotSpotPrintInlining; +import jdk.vm.ci.code.BytecodeFrame; +import jdk.vm.ci.meta.Assumptions; +import jdk.vm.ci.meta.DeoptimizationAction; +import jdk.vm.ci.meta.DeoptimizationReason; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; public class InliningUtil extends ValueMergeUtil { @@ -135,24 +133,26 @@ public static void logInliningDecision(InlineInfo info, int inliningDepth, boolean allowLogging, boolean success, String msg, final Object... args) { if (allowLogging) { printInlining(info, inliningDepth, success, msg, args); - if (shouldLogInliningDecision()) { - logInliningDecision(methodName(info), success, msg, args); + DebugContext debug = info.graph().getDebug(); + if (shouldLogInliningDecision(debug)) { + logInliningDecision(debug, methodName(info), success, msg, args); } } } @SuppressWarnings("try") - public static void logInliningDecision(final String msg, final Object... args) { - try (Scope s = Debug.scope(inliningDecisionsScopeString)) { + public static void logInliningDecision(DebugContext debug, final String msg, final Object... args) { + try (DebugContext.Scope s = debug.scope(inliningDecisionsScopeString)) { // Can't use log here since we are varargs - if (Debug.isLogEnabled()) { - Debug.logv(msg, args); + if (debug.isLogEnabled()) { + debug.logv(msg, args); } } } public static void logNotInlinedMethod(Invoke invoke, String msg) { - if (shouldLogInliningDecision()) { + DebugContext debug = invoke.asNode().getDebug(); + if (shouldLogInliningDecision(debug)) { String methodString = invoke.toString(); if (invoke.callTarget() == null) { methodString += " callTarget=null"; @@ -162,7 +162,7 @@ methodString += " " + targetName; } } - logInliningDecision(methodString, false, msg, new Object[0]); + logInliningDecision(debug, methodString, false, msg, new Object[0]); } } @@ -171,25 +171,26 @@ } public static void logNotInlinedInvoke(Invoke invoke, int inliningDepth, ResolvedJavaMethod method, String msg, Object... args) { + DebugContext debug = invoke.asNode().getDebug(); printInlining(method, invoke, inliningDepth, false, msg, args); - if (shouldLogInliningDecision()) { + if (shouldLogInliningDecision(debug)) { String methodString = methodName(method, invoke); - logInliningDecision(methodString, false, msg, args); + logInliningDecision(debug, methodString, false, msg, args); } } - private static void logInliningDecision(final String methodString, final boolean success, final String msg, final Object... args) { + private static void logInliningDecision(DebugContext debug, final String methodString, final boolean success, final String msg, final Object... args) { String inliningMsg = "inlining " + methodString + ": " + msg; if (!success) { inliningMsg = "not " + inliningMsg; } - logInliningDecision(inliningMsg, args); + logInliningDecision(debug, inliningMsg, args); } @SuppressWarnings("try") - public static boolean shouldLogInliningDecision() { - try (Scope s = Debug.scope(inliningDecisionsScopeString)) { - return Debug.isLogEnabled(); + public static boolean shouldLogInliningDecision(DebugContext debug) { + try (DebugContext.Scope s = debug.scope(inliningDecisionsScopeString)) { + return debug.isLogEnabled(); } } @@ -278,121 +279,115 @@ public static UnmodifiableEconomicMap inline(Invoke invoke, StructuredGraph inlineGraph, boolean receiverNullCheck, ResolvedJavaMethod inlineeMethod) { FixedNode invokeNode = invoke.asNode(); StructuredGraph graph = invokeNode.graph(); - MethodMetricsInlineeScopeInfo m = MethodMetricsInlineeScopeInfo.create(graph.getOptions()); - try (Debug.Scope s = Debug.methodMetricsScope("InlineEnhancement", m, false)) { - final NodeInputList parameters = invoke.callTarget().arguments(); - - assert inlineGraph.getGuardsStage().ordinal() >= graph.getGuardsStage().ordinal(); - assert !invokeNode.graph().isAfterFloatingReadPhase() : "inline isn't handled correctly after floating reads phase"; - - if (receiverNullCheck && !((MethodCallTargetNode) invoke.callTarget()).isStatic()) { - nonNullReceiver(invoke); - } - - ArrayList nodes = new ArrayList<>(inlineGraph.getNodes().count()); - ArrayList returnNodes = new ArrayList<>(4); - ArrayList partialIntrinsicExits = new ArrayList<>(); - UnwindNode unwindNode = null; - final StartNode entryPointNode = inlineGraph.start(); - FixedNode firstCFGNode = entryPointNode.next(); - if (firstCFGNode == null) { - throw new IllegalStateException("Inlined graph is in invalid state: " + inlineGraph); - } - for (Node node : inlineGraph.getNodes()) { - if (node == entryPointNode || (node == entryPointNode.stateAfter() && node.usages().count() == 1) || node instanceof ParameterNode) { - // Do nothing. - } else { - nodes.add(node); - if (node instanceof ReturnNode) { - returnNodes.add((ReturnNode) node); - } else if (node instanceof Invoke) { - Invoke invokeInInlineGraph = (Invoke) node; - if (invokeInInlineGraph.bci() == BytecodeFrame.UNKNOWN_BCI) { - ResolvedJavaMethod target1 = inlineeMethod; - ResolvedJavaMethod target2 = invokeInInlineGraph.callTarget().targetMethod(); - assert target1.equals(target2) : String.format("invoke in inlined method expected to be partial intrinsic exit (i.e., call to %s), not a call to %s", - target1.format("%H.%n(%p)"), target2.format("%H.%n(%p)")); - partialIntrinsicExits.add(invokeInInlineGraph); - } - } else if (node instanceof UnwindNode) { - assert unwindNode == null; - unwindNode = (UnwindNode) node; + final NodeInputList parameters = invoke.callTarget().arguments(); + + assert inlineGraph.getGuardsStage().ordinal() >= graph.getGuardsStage().ordinal(); + assert !invokeNode.graph().isAfterFloatingReadPhase() : "inline isn't handled correctly after floating reads phase"; + + if (receiverNullCheck && !((MethodCallTargetNode) invoke.callTarget()).isStatic()) { + nonNullReceiver(invoke); + } + + ArrayList nodes = new ArrayList<>(inlineGraph.getNodes().count()); + ArrayList returnNodes = new ArrayList<>(4); + ArrayList partialIntrinsicExits = new ArrayList<>(); + UnwindNode unwindNode = null; + final StartNode entryPointNode = inlineGraph.start(); + FixedNode firstCFGNode = entryPointNode.next(); + if (firstCFGNode == null) { + throw new IllegalStateException("Inlined graph is in invalid state: " + inlineGraph); + } + for (Node node : inlineGraph.getNodes()) { + if (node == entryPointNode || (node == entryPointNode.stateAfter() && node.usages().count() == 1) || node instanceof ParameterNode) { + // Do nothing. + } else { + nodes.add(node); + if (node instanceof ReturnNode) { + returnNodes.add((ReturnNode) node); + } else if (node instanceof Invoke) { + Invoke invokeInInlineGraph = (Invoke) node; + if (invokeInInlineGraph.bci() == BytecodeFrame.UNKNOWN_BCI) { + ResolvedJavaMethod target1 = inlineeMethod; + ResolvedJavaMethod target2 = invokeInInlineGraph.callTarget().targetMethod(); + assert target1.equals(target2) : String.format("invoke in inlined method expected to be partial intrinsic exit (i.e., call to %s), not a call to %s", + target1.format("%H.%n(%p)"), target2.format("%H.%n(%p)")); + partialIntrinsicExits.add(invokeInInlineGraph); } + } else if (node instanceof UnwindNode) { + assert unwindNode == null; + unwindNode = (UnwindNode) node; } } + } - final AbstractBeginNode prevBegin = AbstractBeginNode.prevBegin(invokeNode); - DuplicationReplacement localReplacement = new DuplicationReplacement() { + final AbstractBeginNode prevBegin = AbstractBeginNode.prevBegin(invokeNode); + DuplicationReplacement localReplacement = new DuplicationReplacement() { - @Override - public Node replacement(Node node) { - if (node instanceof ParameterNode) { - return parameters.get(((ParameterNode) node).index()); - } else if (node == entryPointNode) { - return prevBegin; - } - return node; + @Override + public Node replacement(Node node) { + if (node instanceof ParameterNode) { + return parameters.get(((ParameterNode) node).index()); + } else if (node == entryPointNode) { + return prevBegin; } - }; + return node; + } + }; - assert invokeNode.successors().first() != null : invoke; - assert invokeNode.predecessor() != null; + assert invokeNode.successors().first() != null : invoke; + assert invokeNode.predecessor() != null; - EconomicMap duplicates = graph.addDuplicates(nodes, inlineGraph, inlineGraph.getNodeCount(), localReplacement); + EconomicMap duplicates = graph.addDuplicates(nodes, inlineGraph, inlineGraph.getNodeCount(), localReplacement); - FrameState stateAfter = invoke.stateAfter(); - assert stateAfter == null || stateAfter.isAlive(); + FrameState stateAfter = invoke.stateAfter(); + assert stateAfter == null || stateAfter.isAlive(); - FrameState stateAtExceptionEdge = null; - if (invoke instanceof InvokeWithExceptionNode) { - InvokeWithExceptionNode invokeWithException = ((InvokeWithExceptionNode) invoke); - if (unwindNode != null) { - ExceptionObjectNode obj = (ExceptionObjectNode) invokeWithException.exceptionEdge(); - stateAtExceptionEdge = obj.stateAfter(); - } + FrameState stateAtExceptionEdge = null; + if (invoke instanceof InvokeWithExceptionNode) { + InvokeWithExceptionNode invokeWithException = ((InvokeWithExceptionNode) invoke); + if (unwindNode != null) { + ExceptionObjectNode obj = (ExceptionObjectNode) invokeWithException.exceptionEdge(); + stateAtExceptionEdge = obj.stateAfter(); } + } - updateSourcePositions(invoke, inlineGraph, duplicates); - if (stateAfter != null) { - processFrameStates(invoke, inlineGraph, duplicates, stateAtExceptionEdge, returnNodes.size() > 1); - int callerLockDepth = stateAfter.nestedLockDepth(); - if (callerLockDepth != 0) { - for (MonitorIdNode original : inlineGraph.getNodes(MonitorIdNode.TYPE)) { - MonitorIdNode monitor = (MonitorIdNode) duplicates.get(original); - processMonitorId(invoke.stateAfter(), monitor); - } + updateSourcePositions(invoke, inlineGraph, duplicates); + if (stateAfter != null) { + processFrameStates(invoke, inlineGraph, duplicates, stateAtExceptionEdge, returnNodes.size() > 1); + int callerLockDepth = stateAfter.nestedLockDepth(); + if (callerLockDepth != 0) { + for (MonitorIdNode original : inlineGraph.getNodes(MonitorIdNode.TYPE)) { + MonitorIdNode monitor = (MonitorIdNode) duplicates.get(original); + processMonitorId(invoke.stateAfter(), monitor); } - } else { - assert checkContainsOnlyInvalidOrAfterFrameState(duplicates); } + } else { + assert checkContainsOnlyInvalidOrAfterFrameState(duplicates); + } - firstCFGNode = (FixedNode) duplicates.get(firstCFGNode); - for (int i = 0; i < returnNodes.size(); i++) { - returnNodes.set(i, (ReturnNode) duplicates.get(returnNodes.get(i))); - } - for (Invoke exit : partialIntrinsicExits) { - // A partial intrinsic exit must be replaced with a call to - // the intrinsified method. - Invoke dup = (Invoke) duplicates.get(exit.asNode()); - if (dup instanceof InvokeNode) { - InvokeNode repl = graph.add(new InvokeNode(invoke.callTarget(), invoke.bci())); - dup.intrinsify(repl.asNode()); - } else { - ((InvokeWithExceptionNode) dup).replaceWithNewBci(invoke.bci()); - } - } - if (unwindNode != null) { - unwindNode = (UnwindNode) duplicates.get(unwindNode); + firstCFGNode = (FixedNode) duplicates.get(firstCFGNode); + for (int i = 0; i < returnNodes.size(); i++) { + returnNodes.set(i, (ReturnNode) duplicates.get(returnNodes.get(i))); + } + for (Invoke exit : partialIntrinsicExits) { + // A partial intrinsic exit must be replaced with a call to + // the intrinsified method. + Invoke dup = (Invoke) duplicates.get(exit.asNode()); + if (dup instanceof InvokeNode) { + InvokeNode repl = graph.add(new InvokeNode(invoke.callTarget(), invoke.bci())); + dup.intrinsify(repl.asNode()); + } else { + ((InvokeWithExceptionNode) dup).replaceWithNewBci(invoke.bci()); } + } + if (unwindNode != null) { + unwindNode = (UnwindNode) duplicates.get(unwindNode); + } - finishInlining(invoke, graph, firstCFGNode, returnNodes, unwindNode, inlineGraph.getAssumptions(), inlineGraph); - GraphUtil.killCFG(invokeNode); + finishInlining(invoke, graph, firstCFGNode, returnNodes, unwindNode, inlineGraph.getAssumptions(), inlineGraph); + GraphUtil.killCFG(invokeNode); - if (Debug.isMethodMeterEnabled() && m != null) { - MethodMetricsImpl.recordInlinee(m.getRootMethod(), invoke.asNode().graph().method(), inlineeMethod); - } - return duplicates; - } + return duplicates; } /** --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/AbstractInlineInfo.java 2017-07-07 09:31:31.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/AbstractInlineInfo.java 2017-07-07 09:31:31.000000000 -0700 @@ -22,8 +22,6 @@ */ package org.graalvm.compiler.phases.common.inlining.info; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.internal.method.MethodMetricsInlineeScopeInfo; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.StructuredGraph; @@ -66,10 +64,8 @@ @SuppressWarnings("try") public final void populateInlinableElements(HighTierContext context, StructuredGraph caller, CanonicalizerPhase canonicalizer, OptionValues options) { for (int i = 0; i < numberOfMethods(); i++) { - try (Debug.Scope s = Debug.methodMetricsScope("InlineEnhancement", MethodMetricsInlineeScopeInfo.create(options), false)) { - Inlineable elem = Inlineable.getInlineableElement(methodAt(i), invoke, context, canonicalizer); - setInlinableElement(i, elem); - } + Inlineable elem = Inlineable.getInlineableElement(methodAt(i), invoke, context, canonicalizer); + setInlinableElement(i, elem); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/MultiTypeGuardInlineInfo.java 2017-07-07 09:31:32.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/MultiTypeGuardInlineInfo.java 2017-07-07 09:31:32.000000000 -0700 @@ -26,7 +26,6 @@ import java.util.List; import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.AbstractBeginNode; import org.graalvm.compiler.nodes.AbstractMergeNode; @@ -342,7 +341,7 @@ ValueNode nonNullReceiver = InliningUtil.nonNullReceiver(invoke); LoadHubNode hub = graph.unique(new LoadHubNode(stampProvider, nonNullReceiver)); - Debug.log("Type switch with %d types", concretes.size()); + graph.getDebug().log("Type switch with %d types", concretes.size()); ResolvedJavaType[] keys = new ResolvedJavaType[ptypes.size()]; double[] keyProbabilities = new double[ptypes.size() + 1]; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/elem/InlineableGraph.java 2017-07-07 09:31:32.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/elem/InlineableGraph.java 2017-07-07 09:31:32.000000000 -0700 @@ -28,7 +28,7 @@ import java.util.List; import org.graalvm.compiler.core.common.type.Stamp; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeInputList; import org.graalvm.compiler.nodes.ConstantNode; @@ -69,7 +69,7 @@ public InlineableGraph(final ResolvedJavaMethod method, final Invoke invoke, final HighTierContext context, CanonicalizerPhase canonicalizer) { StructuredGraph original = getOriginalGraph(method, context, canonicalizer, invoke.asNode().graph(), invoke.bci()); // TODO copying the graph is only necessary if it is modified or if it contains any invokes - this.graph = (StructuredGraph) original.copy(); + this.graph = (StructuredGraph) original.copy(invoke.asNode().getDebug()); specializeGraphToArguments(invoke, context, canonicalizer); } @@ -92,7 +92,8 @@ */ @SuppressWarnings("try") private boolean specializeGraphToArguments(final Invoke invoke, final HighTierContext context, CanonicalizerPhase canonicalizer) { - try (Debug.Scope s = Debug.scope("InlineGraph", graph)) { + DebugContext debug = graph.getDebug(); + try (DebugContext.Scope s = debug.scope("InlineGraph", graph)) { ArrayList parameterUsages = replaceParamsWithMoreInformativeArguments(invoke, context); if (parameterUsages != null) { @@ -107,7 +108,7 @@ } } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } @@ -193,8 +194,9 @@ */ @SuppressWarnings("try") private static StructuredGraph parseBytecodes(ResolvedJavaMethod method, HighTierContext context, CanonicalizerPhase canonicalizer, StructuredGraph caller) { - StructuredGraph newGraph = new StructuredGraph.Builder(caller.getOptions(), AllowAssumptions.ifNonNull(caller.getAssumptions())).method(method).build(); - try (Debug.Scope s = Debug.scope("InlineGraph", newGraph)) { + DebugContext debug = caller.getDebug(); + StructuredGraph newGraph = new StructuredGraph.Builder(caller.getOptions(), debug, AllowAssumptions.ifNonNull(caller.getAssumptions())).method(method).build(); + try (DebugContext.Scope s = debug.scope("InlineGraph", newGraph)) { if (!caller.isUnsafeAccessTrackingEnabled()) { newGraph.disableUnsafeAccessTracking(); } @@ -209,7 +211,7 @@ return newGraph; } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/GreedyInliningPolicy.java 2017-07-07 09:31:32.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/GreedyInliningPolicy.java 2017-07-07 09:31:32.000000000 -0700 @@ -31,8 +31,8 @@ import java.util.Map; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.spi.Replacements; @@ -43,7 +43,7 @@ public class GreedyInliningPolicy extends AbstractInliningPolicy { - private static final DebugCounter inliningStoppedByMaxDesiredSizeCounter = Debug.counter("InliningStoppedByMaxDesiredSize"); + private static final CounterKey inliningStoppedByMaxDesiredSizeCounter = DebugContext.counter("InliningStoppedByMaxDesiredSize"); public GreedyInliningPolicy(Map hints) { super(hints); @@ -52,8 +52,9 @@ @Override public boolean continueInlining(StructuredGraph currentGraph) { if (InliningUtil.getNodeCount(currentGraph) >= MaximumDesiredSize.getValue(currentGraph.getOptions())) { - InliningUtil.logInliningDecision("inlining is cut off by MaximumDesiredSize"); - inliningStoppedByMaxDesiredSizeCounter.increment(); + DebugContext debug = currentGraph.getDebug(); + InliningUtil.logInliningDecision(debug, "inlining is cut off by MaximumDesiredSize"); + inliningStoppedByMaxDesiredSizeCounter.increment(debug); return false; } return true; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java 2017-07-07 09:31:33.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java 2017-07-07 09:31:33.000000000 -0700 @@ -35,10 +35,9 @@ import java.util.List; import org.graalvm.compiler.core.common.type.ObjectStamp; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.debug.internal.method.MethodMetricsInlineeScopeInfo; import org.graalvm.compiler.graph.Graph; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.CallTargetNode; @@ -101,9 +100,9 @@ public class InliningData { // Counters - private static final DebugCounter counterInliningPerformed = Debug.counter("InliningPerformed"); - private static final DebugCounter counterInliningRuns = Debug.counter("InliningRuns"); - private static final DebugCounter counterInliningConsidered = Debug.counter("InliningConsidered"); + private static final CounterKey counterInliningPerformed = DebugContext.counter("InliningPerformed"); + private static final CounterKey counterInliningRuns = DebugContext.counter("InliningRuns"); + private static final CounterKey counterInliningConsidered = DebugContext.counter("InliningConsidered"); /** * Call hierarchy from outer most call (i.e., compilation unit) to inner most callee. @@ -116,6 +115,7 @@ private final CanonicalizerPhase canonicalizer; private final InliningPolicy inliningPolicy; private final StructuredGraph rootGraph; + private final DebugContext debug; private int maxGraphs; @@ -127,6 +127,7 @@ this.inliningPolicy = inliningPolicy; this.maxGraphs = 1; this.rootGraph = rootGraph; + this.debug = rootGraph.getDebug(); invocationQueue.push(new MethodInvocation(null, 1.0, 1.0, null)); graphQueue.push(new CallsiteHolderExplorable(rootGraph, 1.0, 1.0, null, rootInvokes)); @@ -395,14 +396,13 @@ StructuredGraph callerGraph = callerCallsiteHolder.graph(); InlineInfo calleeInfo = calleeInvocation.callee(); try { - OptionValues options = rootGraph.getOptions(); - try (Debug.Scope scope = Debug.scope("doInline", callerGraph); Debug.Scope s = Debug.methodMetricsScope("InlineEnhancement", MethodMetricsInlineeScopeInfo.create(options), false)) { + try (DebugContext.Scope scope = debug.scope("doInline", callerGraph)) { EconomicSet canonicalizedNodes = EconomicSet.create(Equivalence.IDENTITY); canonicalizedNodes.addAll(calleeInfo.invoke().asNode().usages()); EconomicSet parameterUsages = calleeInfo.inline(new Providers(context)); canonicalizedNodes.addAll(parameterUsages); - counterInliningRuns.increment(); - Debug.dump(Debug.DETAILED_LEVEL, callerGraph, "after %s", calleeInfo); + counterInliningRuns.increment(debug); + debug.dump(DebugContext.DETAILED_LEVEL, callerGraph, "after %s", calleeInfo); Graph.Mark markBeforeCanonicalization = callerGraph.getMark(); @@ -417,7 +417,7 @@ callerCallsiteHolder.computeProbabilities(); - counterInliningPerformed.increment(); + counterInliningPerformed.increment(debug); } } catch (BailoutException bailout) { throw bailout; @@ -426,7 +426,7 @@ } catch (GraalError e) { throw e.addContext(calleeInfo.toString()); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } @@ -446,7 +446,7 @@ CallsiteHolderExplorable callerCallsiteHolder = (CallsiteHolderExplorable) currentGraph(); InlineInfo calleeInfo = calleeInvocation.callee(); assert callerCallsiteHolder.containsInvoke(calleeInfo.invoke()); - counterInliningConsidered.increment(); + counterInliningConsidered.increment(debug); if (inliningPolicy.isWorthInlining(context.getReplacements(), calleeInvocation, inliningDepth, true)) { doInline(callerCallsiteHolder, calleeInvocation); @@ -572,7 +572,7 @@ * Gets the call hierarchy of this inlining from outer most call to inner most callee. */ private Object[] inliningContext() { - if (!Debug.isDumpEnabled(Debug.INFO_LEVEL)) { + if (!debug.isDumpEnabled(DebugContext.INFO_LEVEL)) { return NO_CONTEXT; } Object[] result = new Object[graphQueue.size()]; @@ -737,14 +737,14 @@ * "all concrete methods that come into question already had the callees they contain analyzed for inlining" */ popInvocation(); - try (Debug.Scope s = Debug.scope("Inlining", inliningContext())) { + try (DebugContext.Scope s = debug.scope("Inlining", inliningContext())) { if (tryToInline(currentInvocation, inliningDepth() + 1)) { // Report real progress only if we inline into the root graph return currentGraph().graph() == rootGraph; } return false; } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/BasePhase.java 2017-07-07 09:31:33.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/BasePhase.java 2017-07-07 09:31:33.000000000 -0700 @@ -24,13 +24,12 @@ import java.util.regex.Pattern; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.CounterKey; import org.graalvm.compiler.debug.DebugCloseable; -import org.graalvm.compiler.debug.DebugCounter; -import org.graalvm.compiler.debug.DebugMemUseTracker; -import org.graalvm.compiler.debug.DebugTimer; -import org.graalvm.compiler.debug.GraalDebugConfig; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DebugOptions; +import org.graalvm.compiler.debug.MemUseTrackerKey; +import org.graalvm.compiler.debug.TimerKey; import org.graalvm.compiler.graph.Graph; import org.graalvm.compiler.graph.Graph.Mark; import org.graalvm.compiler.graph.Graph.NodeEvent; @@ -62,23 +61,23 @@ /** * Records time spent in {@link #apply(StructuredGraph, Object, boolean)}. */ - private final DebugTimer timer; + private final TimerKey timer; /** * Counts calls to {@link #apply(StructuredGraph, Object, boolean)}. */ - private final DebugCounter executionCount; + private final CounterKey executionCount; /** * Accumulates the {@linkplain Graph#getNodeCount() live node count} of all graphs sent to * {@link #apply(StructuredGraph, Object, boolean)}. */ - private final DebugCounter inputNodesCount; + private final CounterKey inputNodesCount; /** * Records memory usage within {@link #apply(StructuredGraph, Object, boolean)}. */ - private final DebugMemUseTracker memUseTracker; + private final MemUseTrackerKey memUseTracker; /** Lazy initialization to create pattern only when assertions are enabled. */ static class NamePatternHolder { @@ -89,29 +88,29 @@ /** * Records time spent in {@link #apply(StructuredGraph, Object, boolean)}. */ - private final DebugTimer timer; + private final TimerKey timer; /** * Counts calls to {@link #apply(StructuredGraph, Object, boolean)}. */ - private final DebugCounter executionCount; + private final CounterKey executionCount; /** * Accumulates the {@linkplain Graph#getNodeCount() live node count} of all graphs sent to * {@link #apply(StructuredGraph, Object, boolean)}. */ - private final DebugCounter inputNodesCount; + private final CounterKey inputNodesCount; /** * Records memory usage within {@link #apply(StructuredGraph, Object, boolean)}. */ - private final DebugMemUseTracker memUseTracker; + private final MemUseTrackerKey memUseTracker; public BasePhaseStatistics(Class clazz) { - timer = Debug.timer("PhaseTime_%s", clazz); - executionCount = Debug.counter("PhaseCount_%s", clazz); - memUseTracker = Debug.memUseTracker("PhaseMemUse_%s", clazz); - inputNodesCount = Debug.counter("PhaseNodes_%s", clazz); + timer = DebugContext.timer("PhaseTime_%s", clazz).doc("Time spent in phase."); + executionCount = DebugContext.counter("PhaseCount_%s", clazz).doc("Number of phase executions."); + memUseTracker = DebugContext.memUseTracker("PhaseMemUse_%s", clazz).doc("Memory allocated in phase."); + inputNodesCount = DebugContext.counter("PhaseNodes_%s", clazz).doc("Number of nodes input to phase."); } } @@ -138,8 +137,8 @@ apply(graph, context, true); } - private BasePhase getEnclosingPhase() { - for (Object c : Debug.context()) { + private BasePhase getEnclosingPhase(DebugContext debug) { + for (Object c : debug.context()) { if (c != this && c instanceof BasePhase) { if (!(c instanceof PhaseSuite)) { return (BasePhase) c; @@ -150,16 +149,17 @@ } private boolean dumpBefore(final StructuredGraph graph, final C context, boolean isTopLevel) { - if (isTopLevel && (Debug.isDumpEnabled(Debug.VERBOSE_LEVEL) || shouldDumpBeforeAtBasicLevel() && Debug.isDumpEnabled(Debug.BASIC_LEVEL))) { + DebugContext debug = graph.getDebug(); + if (isTopLevel && (debug.isDumpEnabled(DebugContext.VERBOSE_LEVEL) || shouldDumpBeforeAtBasicLevel() && debug.isDumpEnabled(DebugContext.BASIC_LEVEL))) { if (shouldDumpBeforeAtBasicLevel()) { - Debug.dump(Debug.BASIC_LEVEL, graph, "Before phase %s", getName()); + debug.dump(DebugContext.BASIC_LEVEL, graph, "Before phase %s", getName()); } else { - Debug.dump(Debug.VERBOSE_LEVEL, graph, "Before phase %s", getName()); + debug.dump(DebugContext.VERBOSE_LEVEL, graph, "Before phase %s", getName()); } - } else if (!isTopLevel && Debug.isDumpEnabled(Debug.VERBOSE_LEVEL + 1)) { - Debug.dump(Debug.VERBOSE_LEVEL + 1, graph, "Before subphase %s", getName()); - } else if (Debug.isDumpEnabled(Debug.ENABLED_LEVEL) && shouldDump(graph, context)) { - Debug.dump(Debug.ENABLED_LEVEL, graph, "Before %s %s", isTopLevel ? "phase" : "subphase", getName()); + } else if (!isTopLevel && debug.isDumpEnabled(DebugContext.VERBOSE_LEVEL + 1)) { + debug.dump(DebugContext.VERBOSE_LEVEL + 1, graph, "Before subphase %s", getName()); + } else if (debug.isDumpEnabled(DebugContext.ENABLED_LEVEL) && shouldDump(graph, context)) { + debug.dump(DebugContext.ENABLED_LEVEL, graph, "Before %s %s", isTopLevel ? "phase" : "subphase", getName()); return true; } return false; @@ -176,7 +176,8 @@ @SuppressWarnings("try") protected final void apply(final StructuredGraph graph, final C context, final boolean dumpGraph) { graph.checkCancellation(); - try (DebugCloseable a = timer.start(); Scope s = Debug.scope(getClass(), this); DebugCloseable c = memUseTracker.start()) { + DebugContext debug = graph.getDebug(); + try (DebugCloseable a = timer.start(debug); DebugContext.Scope s = debug.scope(getClass(), this); DebugCloseable c = memUseTracker.start(debug)) { int sizeBefore = 0; Mark before = null; OptionValues options = graph.getOptions(); @@ -185,14 +186,14 @@ sizeBefore = NodeCostUtil.computeGraphSize(graph); before = graph.getMark(); } - boolean isTopLevel = getEnclosingPhase() == null; + boolean isTopLevel = getEnclosingPhase(graph.getDebug()) == null; boolean dumpedBefore = false; - if (dumpGraph && Debug.isEnabled()) { + if (dumpGraph && debug.areScopesEnabled()) { dumpedBefore = dumpBefore(graph, context, isTopLevel); } - inputNodesCount.add(graph.getNodeCount()); + inputNodesCount.add(debug, graph.getNodeCount()); this.run(graph, context); - executionCount.increment(); + executionCount.increment(debug); if (verifySizeContract) { if (!before.isCurrent()) { int sizeAfter = NodeCostUtil.computeGraphSize(graph); @@ -200,54 +201,56 @@ } } - if (dumpGraph && Debug.isEnabled()) { + if (dumpGraph && debug.areScopesEnabled()) { dumpAfter(graph, isTopLevel, dumpedBefore); } - if (Debug.isVerifyEnabled()) { - Debug.verify(graph, "%s", getName()); + if (debug.isVerifyEnabled()) { + debug.verify(graph, "%s", getName()); } assert graph.verify(); } catch (Throwable t) { - throw Debug.handle(t); + throw debug.handle(t); } } private void dumpAfter(final StructuredGraph graph, boolean isTopLevel, boolean dumpedBefore) { boolean dumped = false; + DebugContext debug = graph.getDebug(); if (isTopLevel) { if (shouldDumpAfterAtBasicLevel()) { - if (Debug.isDumpEnabled(Debug.BASIC_LEVEL)) { - Debug.dump(Debug.BASIC_LEVEL, graph, "After phase %s", getName()); + if (debug.isDumpEnabled(DebugContext.BASIC_LEVEL)) { + debug.dump(DebugContext.BASIC_LEVEL, graph, "After phase %s", getName()); dumped = true; } } else { - if (Debug.isDumpEnabled(Debug.INFO_LEVEL)) { - Debug.dump(Debug.INFO_LEVEL, graph, "After phase %s", getName()); + if (debug.isDumpEnabled(DebugContext.INFO_LEVEL)) { + debug.dump(DebugContext.INFO_LEVEL, graph, "After phase %s", getName()); dumped = true; } } } else { - if (Debug.isDumpEnabled(Debug.INFO_LEVEL + 1)) { - Debug.dump(Debug.INFO_LEVEL + 1, graph, "After subphase %s", getName()); + if (debug.isDumpEnabled(DebugContext.INFO_LEVEL + 1)) { + debug.dump(DebugContext.INFO_LEVEL + 1, graph, "After subphase %s", getName()); dumped = true; } } - if (!dumped && Debug.isDumpEnabled(Debug.ENABLED_LEVEL) && dumpedBefore) { - Debug.dump(Debug.ENABLED_LEVEL, graph, "After %s %s", isTopLevel ? "phase" : "subphase", getName()); + if (!dumped && debug.isDumpEnabled(DebugContext.ENABLED_LEVEL) && dumpedBefore) { + debug.dump(DebugContext.ENABLED_LEVEL, graph, "After %s %s", isTopLevel ? "phase" : "subphase", getName()); } } @SuppressWarnings("try") private boolean shouldDump(StructuredGraph graph, C context) { - String phaseChange = GraalDebugConfig.Options.DumpOnPhaseChange.getValue(graph.getOptions()); - if (phaseChange != null && getClass().getSimpleName().contains(phaseChange)) { - StructuredGraph graphCopy = (StructuredGraph) graph.copy(); + DebugContext debug = graph.getDebug(); + String phaseChange = DebugOptions.DumpOnPhaseChange.getValue(graph.getOptions()); + if (phaseChange != null && Pattern.matches(phaseChange, getClass().getSimpleName())) { + StructuredGraph graphCopy = (StructuredGraph) graph.copy(graph.getDebug()); GraphChangeListener listener = new GraphChangeListener(graphCopy); try (NodeEventScope s = graphCopy.trackNodeEvents(listener)) { - try (Scope s2 = Debug.sandbox("GraphChangeListener", null)) { + try (DebugContext.Scope s2 = debug.sandbox("GraphChangeListener", null)) { run(graphCopy, context); } catch (Throwable t) { - Debug.handle(t); + debug.handle(t); } } return listener.changed; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/LazyName.java 2017-07-07 09:31:34.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/LazyName.java 2017-07-07 09:31:34.000000000 -0700 @@ -22,11 +22,11 @@ */ package org.graalvm.compiler.phases; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; /** * A name whose {@link String} value is computed only when it is needed. This is useful in - * combination with debugging facilities such as {@link Debug#scope(Object)} where the + * combination with debugging facilities such as {@link DebugContext#scope(Object)} where the * {@link String} value of a name is only needed if debugging is enabled. */ public abstract class LazyName implements CharSequence { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/OptimisticOptimizations.java 2017-07-07 09:31:34.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/OptimisticOptimizations.java 2017-07-07 09:31:34.000000000 -0700 @@ -26,8 +26,6 @@ import java.util.Set; import org.graalvm.compiler.core.common.GraalOptions; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.meta.DeoptimizationReason; @@ -37,7 +35,6 @@ public static final OptimisticOptimizations ALL = new OptimisticOptimizations(EnumSet.allOf(Optimization.class)); public static final OptimisticOptimizations NONE = new OptimisticOptimizations(EnumSet.noneOf(Optimization.class)); - private static final DebugCounter disabledOptimisticOptsCounter = Debug.counter("DisabledOptimisticOpts"); public enum Optimization { RemoveNeverExecutedCode, @@ -64,8 +61,6 @@ private void addOptimization(OptionValues options, ProfilingInfo info, DeoptimizationReason deoptReason, Optimization optimization) { if (checkDeoptimizations(options, info, deoptReason)) { enabledOpts.add(optimization); - } else { - disabledOptimisticOptsCounter.increment(); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/PhaseSuite.java 2017-07-07 09:31:34.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/PhaseSuite.java 2017-07-07 09:31:34.000000000 -0700 @@ -72,6 +72,30 @@ } /** + * Inserts a phase before the last phase in the suite. If the suite contains no phases the new + * phase will be inserted as the first phase. + */ + public final void addBeforeLast(BasePhase phase) { + ListIterator> last = findLastPhase(); + if (last.hasPrevious()) { + last.previous(); + } + last.add(phase); + } + + /** + * Returns a {@link ListIterator} at the position of the last phase in the suite. If the suite + * has no phases then it will return an empty iterator. + */ + private ListIterator> findLastPhase() { + ListIterator> it = phases.listIterator(); + while (it.hasNext()) { + it.next(); + } + return it; + } + + /** * Returns a {@link ListIterator} at the position of the first phase which is an instance of * {@code phaseClass} or null if no such phase can be found. * --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/contract/NodeCostUtil.java 2017-07-07 09:31:35.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/contract/NodeCostUtil.java 2017-07-07 09:31:35.000000000 -0700 @@ -27,8 +27,8 @@ import java.util.function.Function; import org.graalvm.compiler.core.common.cfg.BlockMap; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.VerificationError; import org.graalvm.compiler.nodes.FixedNode; @@ -41,12 +41,12 @@ public class NodeCostUtil { - private static final DebugCounter sizeComputationCount = Debug.counter("GraphCostComputationCount_Size"); - private static final DebugCounter sizeVerificationCount = Debug.counter("GraphCostVerificationCount_Size"); + private static final CounterKey sizeComputationCount = DebugContext.counter("GraphCostComputationCount_Size"); + private static final CounterKey sizeVerificationCount = DebugContext.counter("GraphCostVerificationCount_Size"); @SuppressWarnings("try") public static int computeGraphSize(StructuredGraph graph) { - sizeComputationCount.increment(); + sizeComputationCount.increment(graph.getDebug()); int size = 0; for (Node n : graph.getNodes()) { size += n.estimatedNodeSize().value; @@ -77,14 +77,15 @@ blockToNodes = b -> nodes.get(b); } double weightedCycles = 0D; - try (Debug.Scope s = Debug.scope("NodeCostSummary")) { + DebugContext debug = graph.getDebug(); + try (DebugContext.Scope s = debug.scope("NodeCostSummary")) { for (Block block : cfg.getBlocks()) { for (Node n : blockToNodes.apply(block)) { double probWeighted = n.estimatedNodeCycles().value * block.probability(); assert Double.isFinite(probWeighted); weightedCycles += probWeighted; - if (Debug.isLogEnabled()) { - Debug.log("Node %s contributes cycles:%f size:%d to graph %s [block prob:%f]", n, n.estimatedNodeCycles().value * block.probability(), + if (debug.isLogEnabled()) { + debug.log("Node %s contributes cycles:%f size:%d to graph %s [block prob:%f]", n, n.estimatedNodeCycles().value * block.probability(), n.estimatedNodeSize().value, graph, block.probability()); } } @@ -111,7 +112,7 @@ private static final double DELTA = 0.001D; public static void phaseFulfillsSizeContract(StructuredGraph graph, int codeSizeBefore, int codeSizeAfter, PhaseSizeContract contract) { - sizeVerificationCount.increment(); + sizeVerificationCount.increment(graph.getDebug()); final double codeSizeIncrease = contract.codeSizeIncrease(); final double graphSizeDelta = codeSizeBefore * DELTA; if (deltaCompare(codeSizeAfter, codeSizeBefore * codeSizeIncrease, graphSizeDelta) > 0) { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/FixedNodeProbabilityCache.java 2017-07-07 09:31:35.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/FixedNodeProbabilityCache.java 2017-07-07 09:31:35.000000000 -0700 @@ -24,8 +24,8 @@ import java.util.function.ToDoubleFunction; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeInputList; import org.graalvm.compiler.nodes.AbstractBeginNode; @@ -36,15 +36,15 @@ import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.LoopBeginNode; import org.graalvm.compiler.nodes.StartNode; -import org.graalvm.util.Equivalence; import org.graalvm.util.EconomicMap; +import org.graalvm.util.Equivalence; /** * Compute probabilities for fixed nodes on the fly and cache them at {@link AbstractBeginNode}s. */ public class FixedNodeProbabilityCache implements ToDoubleFunction { - private static final DebugCounter computeNodeProbabilityCounter = Debug.counter("ComputeNodeProbability"); + private static final CounterKey computeNodeProbabilityCounter = DebugContext.counter("ComputeNodeProbability"); private final EconomicMap cache = EconomicMap.create(Equivalence.IDENTITY); @@ -82,7 +82,7 @@ @Override public double applyAsDouble(FixedNode node) { assert node != null; - computeNodeProbabilityCounter.increment(); + computeNodeProbabilityCounter.increment(node.getDebug()); FixedNode current = findBegin(node); if (current == null) { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/MemoryScheduleVerification.java 2017-07-07 09:31:36.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/MemoryScheduleVerification.java 2017-07-07 09:31:35.000000000 -0700 @@ -26,7 +26,7 @@ import org.graalvm.compiler.core.common.cfg.BlockMap; import org.graalvm.compiler.core.common.cfg.Loop; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.AbstractBeginNode; import org.graalvm.compiler.nodes.AbstractMergeNode; @@ -40,9 +40,9 @@ import org.graalvm.compiler.nodes.memory.MemoryPhiNode; import org.graalvm.compiler.phases.graph.ReentrantBlockIterator; import org.graalvm.compiler.phases.graph.ReentrantBlockIterator.BlockIteratorClosure; +import org.graalvm.util.EconomicSet; import org.graalvm.util.Equivalence; import org.graalvm.word.LocationIdentity; -import org.graalvm.util.EconomicSet; public final class MemoryScheduleVerification extends BlockIteratorClosure> { @@ -123,7 +123,7 @@ for (FloatingReadNode r : cloneState(currentState)) { if (r.getLocationIdentity().overlaps(location)) { // This read is killed by this location. - Debug.log(Debug.VERBOSE_LEVEL, "%s removing %s from state", n, r); + r.getDebug().log(DebugContext.VERBOSE_LEVEL, "%s removing %s from state", n, r); currentState.remove(r); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/SchedulePhase.java 2017-07-07 09:31:36.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/SchedulePhase.java 2017-07-07 09:31:36.000000000 -0700 @@ -22,12 +22,19 @@ */ package org.graalvm.compiler.phases.schedule; +import static org.graalvm.compiler.core.common.GraalOptions.OptScheduleOutOfLoops; +import static org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph.strictlyDominates; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Formatter; +import java.util.List; + import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.common.SuppressFBWarnings; import org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph; import org.graalvm.compiler.core.common.cfg.BlockMap; import org.graalvm.compiler.debug.Assertions; -import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.graph.Graph.NodeEvent; import org.graalvm.compiler.graph.Graph.NodeEventListener; import org.graalvm.compiler.graph.Graph.NodeEventScope; @@ -69,14 +76,6 @@ import org.graalvm.compiler.phases.Phase; import org.graalvm.word.LocationIdentity; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Formatter; -import java.util.List; - -import static org.graalvm.compiler.core.common.GraalOptions.OptScheduleOutOfLoops; -import static org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph.strictlyDominates; - public final class SchedulePhase extends Phase { public enum SchedulingStrategy { @@ -1014,7 +1013,7 @@ } else if (n instanceof GuardNode) { buf.format(", anchor: %s", ((GuardNode) n).getAnchor()); } - Debug.log("%s", buf); + n.getDebug().log("%s", buf); } public ControlFlowGraph getCFG() { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/GraphOrder.java 2017-07-07 09:31:36.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/GraphOrder.java 2017-07-07 09:31:36.000000000 -0700 @@ -26,7 +26,6 @@ import java.util.List; import org.graalvm.compiler.core.common.cfg.Loop; -import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.GraalGraphError; import org.graalvm.compiler.graph.Node; @@ -290,7 +289,7 @@ ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock()); } catch (Throwable t) { - Debug.handle(t); + graph.getDebug().handle(t); } return true; } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyDebugUsage.java 2017-07-07 09:31:37.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyDebugUsage.java 2017-07-07 09:31:37.000000000 -0700 @@ -22,12 +22,7 @@ */ package org.graalvm.compiler.phases.verify; -import static org.graalvm.compiler.debug.Debug.BASIC_LEVEL; -import static org.graalvm.compiler.debug.Debug.DETAILED_LEVEL; -import static org.graalvm.compiler.debug.Debug.ENABLED_LEVEL; -import static org.graalvm.compiler.debug.Debug.INFO_LEVEL; -import static org.graalvm.compiler.debug.Debug.VERBOSE_LEVEL; -import static org.graalvm.compiler.debug.Debug.VERY_DETAILED_LEVEL; +import static org.graalvm.compiler.debug.DebugContext.BASIC_LEVEL; import java.util.ArrayList; import java.util.Arrays; @@ -36,8 +31,7 @@ import java.util.Set; import org.graalvm.compiler.core.common.type.ObjectStamp; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugMethodMetrics; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Graph; import org.graalvm.compiler.graph.Node; @@ -59,16 +53,17 @@ import jdk.vm.ci.meta.ResolvedJavaType; /** - * Verifies that call sites calling one of the methods in {@link Debug} use them correctly. Correct - * usage of the methods in {@link Debug} requires call sites to not eagerly evaluate their - * arguments. Additionally this phase verifies that no argument is the result of a call to + * Verifies that call sites calling one of the methods in {@link DebugContext} use them correctly. + * Correct usage of the methods in {@link DebugContext} requires call sites to not eagerly evaluate + * their arguments. Additionally this phase verifies that no argument is the result of a call to * {@link StringBuilder#toString()} or {@link StringBuffer#toString()}. Ideally the parameters at - * call sites of {@link Debug} are eliminated, and do not produce additional allocations, if - * {@link Debug#isDumpEnabled(int)} (or {@link Debug#isLogEnabled(int)}, ...) is {@code false}. + * call sites of {@link DebugContext} are eliminated, and do not produce additional allocations, if + * {@link DebugContext#isDumpEnabled(int)} (or {@link DebugContext#isLogEnabled(int)}, ...) is + * {@code false}. * - * Methods in {@link Debug} checked by this phase are various different versions of - * {@link Debug#log(String)} , {@link Debug#dump(int, Object, String)}, - * {@link Debug#logAndIndent(String)} and {@link Debug#verify(Object, String)}. + * Methods in {@link DebugContext} checked by this phase are various different versions of + * {@link DebugContext#log(String)} , {@link DebugContext#dump(int, Object, String)}, + * {@link DebugContext#logAndIndent(String)} and {@link DebugContext#verify(Object, String)}. */ public class VerifyDebugUsage extends VerifyPhase { @@ -82,10 +77,9 @@ @Override protected boolean verify(StructuredGraph graph, PhaseContext context) { metaAccess = context.getMetaAccess(); - ResolvedJavaType debugType = metaAccess.lookupJavaType(Debug.class); + ResolvedJavaType debugType = metaAccess.lookupJavaType(DebugContext.class); ResolvedJavaType nodeType = metaAccess.lookupJavaType(Node.class); ResolvedJavaType stringType = metaAccess.lookupJavaType(String.class); - ResolvedJavaType debugMethodMetricsType = metaAccess.lookupJavaType(DebugMethodMetrics.class); ResolvedJavaType graalErrorType = metaAccess.lookupJavaType(GraalError.class); for (MethodCallTargetNode t : graph.getNodes(MethodCallTargetNode.TYPE)) { @@ -102,11 +96,6 @@ verifyParameters(t, graph, t.arguments(), stringType, 1); } } - if (callee.getDeclaringClass().equals(debugMethodMetricsType)) { - if (calleeName.equals("addToMetric") || calleeName.equals("getCurrentMetricValue") || calleeName.equals("incrementMetric")) { - verifyParameters(t, graph, t.arguments(), stringType, 1); - } - } if (callee.getDeclaringClass().isAssignableFrom(graalErrorType) && !graph.method().getDeclaringClass().isAssignableFrom(graalErrorType)) { if (calleeName.equals("guarantee")) { verifyParameters(t, graph, t.arguments(), stringType, 0); @@ -137,16 +126,17 @@ } } - private static final Set DebugLevels = new HashSet<>(Arrays.asList(ENABLED_LEVEL, BASIC_LEVEL, INFO_LEVEL, VERBOSE_LEVEL, DETAILED_LEVEL, VERY_DETAILED_LEVEL)); + private static final Set DebugLevels = new HashSet<>( + Arrays.asList(DebugContext.ENABLED_LEVEL, BASIC_LEVEL, DebugContext.INFO_LEVEL, DebugContext.VERBOSE_LEVEL, DebugContext.DETAILED_LEVEL, DebugContext.VERY_DETAILED_LEVEL)); /** * The set of methods allowed to call a {@code Debug.dump(...)} method with the {@code level} - * parameter bound to {@link Debug#BASIC_LEVEL} and the {@code object} parameter bound to a - * {@link StructuredGraph} value. + * parameter bound to {@link DebugContext#BASIC_LEVEL} and the {@code object} parameter bound to + * a {@link StructuredGraph} value. * * This whitelist exists to ensure any increase in graph dumps is in line with the policy - * outlined by {@link Debug#BASIC_LEVEL}. If you add a *justified* graph dump at this level, - * then update the whitelist. + * outlined by {@link DebugContext#BASIC_LEVEL}. If you add a *justified* graph dump at this + * level, then update the whitelist. */ private static final Set BasicLevelStructuredGraphDumpWhitelist = new HashSet<>(Arrays.asList( "org.graalvm.compiler.phases.BasePhase.dumpAfter", @@ -161,12 +151,12 @@ /** * The set of methods allowed to call a {@code Debug.dump(...)} method with the {@code level} - * parameter bound to {@link Debug#INFO_LEVEL} and the {@code object} parameter bound to a - * {@link StructuredGraph} value. + * parameter bound to {@link DebugContext#INFO_LEVEL} and the {@code object} parameter bound to + * a {@link StructuredGraph} value. * * This whitelist exists to ensure any increase in graph dumps is in line with the policy - * outlined by {@link Debug#INFO_LEVEL}. If you add a *justified* graph dump at this level, then - * update the whitelist. + * outlined by {@link DebugContext#INFO_LEVEL}. If you add a *justified* graph dump at this + * level, then update the whitelist. */ private static final Set InfoLevelStructuredGraphDumpWhitelist = new HashSet<>(Arrays.asList( "org.graalvm.compiler.core.GraalCompiler.emitFrontEnd", @@ -202,13 +192,13 @@ } } } - if (i == 0) { + if (i == 1) { if (verifiedCallee.getName().equals("dump")) { dumpLevel = verifyDumpLevelParameter(callerGraph, debugCallTarget, verifiedCallee, arg); } - } else if (i == 1) { + } else if (i == 2) { if (dumpLevel != null) { - verifyDumpObjectParameter(callerGraph, debugCallTarget, args, verifiedCallee, dumpLevel); + verifyDumpObjectParameter(callerGraph, debugCallTarget, arg, verifiedCallee, dumpLevel); } } if (varArgsIndex >= 0 && i >= varArgsIndex) { @@ -233,38 +223,38 @@ if (!DebugLevels.contains(dumpLevel)) { StackTraceElement e = callerGraph.method().asStackTraceElement(debugCallTarget.invoke().bci()); throw new VerificationError( - "In %s: parameter 0 of call to %s does not match a Debug.*_LEVEL constant.%n", e, verifiedCallee.format("%H.%n(%p)")); + "In %s: parameter 0 of call to %s does not match a Debug.*_LEVEL constant: %s.%n", e, verifiedCallee.format("%H.%n(%p)"), dumpLevel); } return dumpLevel; } StackTraceElement e = callerGraph.method().asStackTraceElement(debugCallTarget.invoke().bci()); throw new VerificationError( - "In %s: parameter 0 of call to %s must be a constant.%n", e, verifiedCallee.format("%H.%n(%p)")); + "In %s: parameter 0 of call to %s must be a constant, not %s.%n", e, verifiedCallee.format("%H.%n(%p)"), arg); } - protected void verifyDumpObjectParameter(StructuredGraph callerGraph, MethodCallTargetNode debugCallTarget, List args, ResolvedJavaMethod verifiedCallee, Integer dumpLevel) + protected void verifyDumpObjectParameter(StructuredGraph callerGraph, MethodCallTargetNode debugCallTarget, ValueNode arg, ResolvedJavaMethod verifiedCallee, Integer dumpLevel) throws org.graalvm.compiler.phases.VerifyPhase.VerificationError { - ResolvedJavaType arg1Type = ((ObjectStamp) args.get(1).stamp()).type(); - if (metaAccess.lookupJavaType(Graph.class).isAssignableFrom(arg1Type)) { + ResolvedJavaType argType = ((ObjectStamp) arg.stamp()).type(); + if (metaAccess.lookupJavaType(Graph.class).isAssignableFrom(argType)) { verifyStructuredGraphDumping(callerGraph, debugCallTarget, verifiedCallee, dumpLevel); } } /** - * Verifies that dumping a {@link StructuredGraph} at level {@link Debug#BASIC_LEVEL} or - * {@link Debug#INFO_LEVEL} only occurs in white-listed methods. + * Verifies that dumping a {@link StructuredGraph} at level {@link DebugContext#BASIC_LEVEL} or + * {@link DebugContext#INFO_LEVEL} only occurs in white-listed methods. */ protected void verifyStructuredGraphDumping(StructuredGraph callerGraph, MethodCallTargetNode debugCallTarget, ResolvedJavaMethod verifiedCallee, Integer dumpLevel) throws org.graalvm.compiler.phases.VerifyPhase.VerificationError { - if (dumpLevel == Debug.BASIC_LEVEL) { + if (dumpLevel == DebugContext.BASIC_LEVEL) { StackTraceElement e = callerGraph.method().asStackTraceElement(debugCallTarget.invoke().bci()); String qualifiedMethod = e.getClassName() + "." + e.getMethodName(); if (!BasicLevelStructuredGraphDumpWhitelist.contains(qualifiedMethod)) { throw new VerificationError( - "In %s: call to %s with level == Debug.BASIC_LEVEL not in %s.BasicLevelDumpWhitelist.%n", e, verifiedCallee.format("%H.%n(%p)"), + "In %s: call to %s with level == DebugContext.BASIC_LEVEL not in %s.BasicLevelDumpWhitelist.%n", e, verifiedCallee.format("%H.%n(%p)"), getClass().getName()); } - } else if (dumpLevel == Debug.INFO_LEVEL) { + } else if (dumpLevel == DebugContext.INFO_LEVEL) { StackTraceElement e = callerGraph.method().asStackTraceElement(debugCallTarget.invoke().bci()); String qualifiedMethod = e.getClassName() + "." + e.getMethodName(); if (!InfoLevelStructuredGraphDumpWhitelist.contains(qualifiedMethod)) { @@ -288,7 +278,7 @@ verifiedCallee.format("%H.%n(%p)")); } else { throw new VerificationError( - "In %s: parameter %d of call to %s appears to be a String concatenation expression.%n", e, argIdx, verifiedCallee.format("%H.%n(%p)")); + "In %s: parameter %d of call to %s appears to be a String concatenation expression.", e, argIdx, verifiedCallee.format("%H.%n(%p)")); } } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java 2017-07-07 09:31:37.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java 2017-07-07 09:31:37.000000000 -0700 @@ -40,8 +40,8 @@ import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.bytecode.Bytecode; import org.graalvm.compiler.core.common.cfg.BlockMap; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.GraalDebugConfig.Options; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DebugOptions; import org.graalvm.compiler.graph.CachedGraph; import org.graalvm.compiler.graph.Edges; import org.graalvm.compiler.graph.Graph; @@ -59,12 +59,10 @@ import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.PhiNode; import org.graalvm.compiler.nodes.ProxyNode; -import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; import org.graalvm.compiler.nodes.VirtualState; import org.graalvm.compiler.nodes.cfg.Block; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; -import org.graalvm.compiler.phases.schedule.SchedulePhase; import jdk.vm.ci.meta.JavaType; import jdk.vm.ci.meta.ResolvedJavaField; @@ -152,78 +150,57 @@ private final ConstantPool constantPool; private final ByteBuffer buffer; private final WritableByteChannel channel; - private SnippetReflectionProvider snippetReflection; + private final SnippetReflectionProvider snippetReflection; private static final Charset utf8 = Charset.forName("UTF-8"); - public BinaryGraphPrinter(WritableByteChannel channel) throws IOException { + public BinaryGraphPrinter(WritableByteChannel channel, SnippetReflectionProvider snippetReflection) throws IOException { constantPool = new ConstantPool(); + this.snippetReflection = snippetReflection; buffer = ByteBuffer.allocateDirect(256 * 1024); this.channel = channel; writeVersion(); } @Override - public void setSnippetReflectionProvider(SnippetReflectionProvider snippetReflection) { - this.snippetReflection = snippetReflection; - } - - @Override public SnippetReflectionProvider getSnippetReflectionProvider() { return snippetReflection; } @SuppressWarnings("all") @Override - public void print(Graph graph, Map properties, int id, String format, Object... args) throws IOException { + public void print(DebugContext debug, Graph graph, Map properties, int id, String format, Object... args) throws IOException { writeByte(BEGIN_GRAPH); if (CURRENT_MAJOR_VERSION >= 3) { writeInt(id); writeString(format); writeInt(args.length); for (Object a : args) { - writePropertyObject(a); + writePropertyObject(debug, a); } } else { - writePoolObject(formatTitle(id, format, args)); + writePoolObject(id + ": " + String.format(format, simplifyClassArgs(args))); } - writeGraph(graph, properties); + writeGraph(debug, graph, properties); flush(); } - private void writeGraph(Graph graph, Map properties) throws IOException { - ScheduleResult scheduleResult = null; - if (graph instanceof StructuredGraph) { - - StructuredGraph structuredGraph = (StructuredGraph) graph; - scheduleResult = structuredGraph.getLastSchedule(); - if (scheduleResult == null) { - - // Also provide a schedule when an error occurs - if (Options.PrintGraphWithSchedule.getValue(graph.getOptions()) || Debug.contextLookup(Throwable.class) != null) { - try { - SchedulePhase schedule = new SchedulePhase(graph.getOptions()); - schedule.apply(structuredGraph); - scheduleResult = structuredGraph.getLastSchedule(); - } catch (Throwable t) { - } - } - - } - } - ControlFlowGraph cfg = scheduleResult == null ? Debug.contextLookup(ControlFlowGraph.class) : scheduleResult.getCFG(); + private void writeGraph(DebugContext debug, Graph graph, Map properties) throws IOException { + boolean needSchedule = DebugOptions.PrintGraphWithSchedule.getValue(graph.getOptions()) || debug.contextLookup(Throwable.class) != null; + ScheduleResult scheduleResult = needSchedule ? GraphPrinter.getScheduleOrNull(graph) : null; + ControlFlowGraph cfg = scheduleResult == null ? debug.contextLookup(ControlFlowGraph.class) : scheduleResult.getCFG(); BlockMap> blockToNodes = scheduleResult == null ? null : scheduleResult.getBlockToNodesMap(); NodeMap nodeToBlocks = scheduleResult == null ? null : scheduleResult.getNodeToBlockMap(); List blocks = cfg == null ? null : Arrays.asList(cfg.getBlocks()); - writeProperties(properties); - writeNodes(graph, nodeToBlocks, cfg); + writeProperties(debug, properties); + writeNodes(debug, graph, nodeToBlocks, cfg); writeBlocks(blocks, blockToNodes); } private void flush() throws IOException { buffer.flip(); /* - * Try not to let interrupted threads aborting the write. There's still a race here but an + * Try not to let interrupted threads abort the write. There's still a race here but an * interrupt that's been pending for a long time shouldn't stop this writing. */ boolean interrupted = Thread.interrupted(); @@ -438,8 +415,11 @@ writeInt(bci); StackTraceElement ste = method.asStackTraceElement(bci); if (ste != null) { - writePoolObject(ste.getFileName()); - writeInt(ste.getLineNumber()); + String fn = ste.getFileName(); + writePoolObject(fn); + if (fn != null) { + writeInt(ste.getLineNumber()); + } } else { writePoolObject(null); } @@ -462,7 +442,7 @@ } } - private void writePropertyObject(Object obj) throws IOException { + private void writePropertyObject(DebugContext debug, Object obj) throws IOException { if (obj instanceof Integer) { writeByte(PROPERTY_INT); writeInt(((Integer) obj).intValue()); @@ -483,10 +463,10 @@ } } else if (obj instanceof Graph) { writeByte(PROPERTY_SUBGRAPH); - writeGraph((Graph) obj, null); + writeGraph(debug, (Graph) obj, null); } else if (obj instanceof CachedGraph) { writeByte(PROPERTY_SUBGRAPH); - writeGraph(((CachedGraph) obj).getReadonlyCopy(), null); + writeGraph(debug, ((CachedGraph) obj).getReadonlyCopy(), null); } else if (obj != null && obj.getClass().isArray()) { Class componentType = obj.getClass().getComponentType(); if (componentType.isPrimitive()) { @@ -536,7 +516,7 @@ return null; } - private void writeNodes(Graph graph, NodeMap nodeToBlocks, ControlFlowGraph cfg) throws IOException { + private void writeNodes(DebugContext debug, Graph graph, NodeMap nodeToBlocks, ControlFlowGraph cfg) throws IOException { Map props = new HashMap<>(); writeInt(graph.getNodeCount()); @@ -544,7 +524,7 @@ for (Node node : graph.getNodes()) { NodeClass nodeClass = node.getNodeClass(); node.getDebugProperties(props); - if (cfg != null && Options.PrintGraphProbabilities.getValue(graph.getOptions()) && node instanceof FixedNode) { + if (cfg != null && DebugOptions.PrintGraphProbabilities.getValue(graph.getOptions()) && node instanceof FixedNode) { try { props.put("probability", cfg.blockFor(node).probability()); } catch (Throwable t) { @@ -596,7 +576,7 @@ writeInt(getNodeId(node)); writePoolObject(nodeClass); writeByte(node.predecessor() == null ? 0 : 1); - writeProperties(props); + writeProperties(debug, props); writeEdges(node, Inputs); writeEdges(node, Successors); @@ -604,7 +584,7 @@ } } - private void writeProperties(Map props) throws IOException { + private void writeProperties(DebugContext debug, Map props) throws IOException { if (props == null) { writeShort((char) 0); return; @@ -614,7 +594,7 @@ for (Entry entry : props.entrySet()) { String key = entry.getKey().toString(); writePoolObject(key); - writePropertyObject(entry.getValue()); + writePropertyObject(debug, entry.getValue()); } } @@ -690,13 +670,13 @@ } @Override - public void beginGroup(String name, String shortName, ResolvedJavaMethod method, int bci, Map properties) throws IOException { + public void beginGroup(DebugContext debug, String name, String shortName, ResolvedJavaMethod method, int bci, Map properties) throws IOException { writeByte(BEGIN_GROUP); writePoolObject(name); writePoolObject(shortName); writePoolObject(method); writeInt(bci); - writeProperties(properties); + writeProperties(debug, properties); } @Override --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinterObserver.java 2017-07-07 09:31:38.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinterObserver.java 2017-07-07 09:31:38.000000000 -0700 @@ -22,12 +22,14 @@ */ package org.graalvm.compiler.printer; +import static org.graalvm.compiler.debug.DebugOptions.PrintCFG; +import static org.graalvm.compiler.printer.GraalDebugHandlersFactory.createDumpPath; + import java.io.BufferedOutputStream; import java.io.File; -import java.io.FileNotFoundException; import java.io.FileOutputStream; +import java.io.IOException; import java.io.OutputStream; -import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -39,13 +41,11 @@ import org.graalvm.compiler.core.common.alloc.TraceBuilderResult; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; import org.graalvm.compiler.core.gen.NodeLIRBuilder; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugDumpHandler; import org.graalvm.compiler.debug.DebugDumpScope; -import org.graalvm.compiler.debug.GraalDebugConfig.Options; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.TTY; -import org.graalvm.compiler.debug.internal.DebugScope; import org.graalvm.compiler.graph.Graph; import org.graalvm.compiler.java.BciBlockMapping; import org.graalvm.compiler.lir.LIR; @@ -55,7 +55,7 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; -import org.graalvm.compiler.options.UniquePathUtilities; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.serviceprovider.GraalServices; import jdk.vm.ci.code.CodeCacheProvider; @@ -73,17 +73,12 @@ private File cfgFile; private JavaMethod curMethod; private List curDecorators = Collections.emptyList(); - private final boolean dumpFrontend; - - public CFGPrinterObserver(boolean dumpFrontend) { - this.dumpFrontend = dumpFrontend; - } @Override - public void dump(Object object, String format, Object... arguments) { + public void dump(DebugContext debug, Object object, String format, Object... arguments) { String message = String.format(format, arguments); try { - dumpSandboxed(object, message); + dumpSandboxed(debug, object, message); } catch (Throwable ex) { TTY.println("CFGPrinter: Exception during output of " + message + ": " + ex); ex.printStackTrace(); @@ -95,10 +90,10 @@ * debug scope and opens a new compilation scope if this pair does not match the current method * and decorator pair. */ - private boolean checkMethodScope() { + private boolean checkMethodScope(DebugContext debug) { JavaMethod method = null; ArrayList decorators = new ArrayList<>(); - for (Object o : Debug.context()) { + for (Object o : debug.context()) { if (o instanceof JavaMethod) { method = (JavaMethod) o; decorators.clear(); @@ -122,7 +117,6 @@ if (!method.equals(curMethod) || !curDecorators.equals(decorators)) { cfgPrinter.printCompilation(method); - TTY.println("CFGPrinter: Dumping method %s to %s", method, cfgFile.getAbsolutePath()); } curMethod = method; curDecorators = decorators; @@ -136,30 +130,25 @@ private LIR lastLIR = null; private IntervalDumper delayedIntervals = null; - public void dumpSandboxed(Object object, String message) { + public void dumpSandboxed(DebugContext debug, Object object, String message) { + OptionValues options = debug.getOptions(); + boolean dumpFrontend = PrintCFG.getValue(options); if (!dumpFrontend && isFrontendObject(object)) { return; } if (cfgPrinter == null) { - cfgFile = getCFGPath().toFile(); try { - /* - * Initializing a debug environment multiple times by calling - * DebugEnvironment#initialize will create new CFGPrinterObserver objects that refer - * to the same file path. This means the CFG file may be overridden by another - * instance. Appending to an existing CFG file is not an option as the writing - * happens buffered. - */ + Graph graph = debug.contextLookupTopdown(Graph.class); + cfgFile = createDumpPath(options, graph, "cfg", false).toFile(); OutputStream out = new BufferedOutputStream(new FileOutputStream(cfgFile)); cfgPrinter = new CFGPrinter(out); - } catch (FileNotFoundException e) { - throw new GraalError("Could not open " + cfgFile.getAbsolutePath()); + } catch (IOException e) { + throw (GraalError) new GraalError("Could not open %s", cfgFile.getAbsolutePath()).initCause(e); } - TTY.println("CFGPrinter: Output to file %s", cfgFile.getAbsolutePath()); } - if (!checkMethodScope()) { + if (!checkMethodScope(debug)) { return; } try { @@ -170,11 +159,11 @@ if (object instanceof LIR) { cfgPrinter.lir = (LIR) object; } else { - cfgPrinter.lir = Debug.contextLookup(LIR.class); + cfgPrinter.lir = debug.contextLookup(LIR.class); } - cfgPrinter.nodeLirGenerator = Debug.contextLookup(NodeLIRBuilder.class); - cfgPrinter.livenessInfo = Debug.contextLookup(GlobalLivenessInfo.class); - cfgPrinter.res = Debug.contextLookup(LIRGenerationResult.class); + cfgPrinter.nodeLirGenerator = debug.contextLookup(NodeLIRBuilder.class); + cfgPrinter.livenessInfo = debug.contextLookup(GlobalLivenessInfo.class); + cfgPrinter.res = debug.contextLookup(LIRGenerationResult.class); if (cfgPrinter.nodeLirGenerator != null) { cfgPrinter.target = cfgPrinter.nodeLirGenerator.getLIRGeneratorTool().target(); } @@ -182,7 +171,7 @@ cfgPrinter.cfg = (ControlFlowGraph) cfgPrinter.lir.getControlFlowGraph(); } - CodeCacheProvider codeCache = Debug.contextLookup(CodeCacheProvider.class); + CodeCacheProvider codeCache = debug.contextLookup(CodeCacheProvider.class); if (codeCache != null) { cfgPrinter.target = codeCache.getTarget(); } @@ -217,7 +206,7 @@ final CompilationResult compResult = (CompilationResult) object; cfgPrinter.printMachineCode(disassemble(codeCache, compResult, null), message); } else if (object instanceof InstalledCode) { - CompilationResult compResult = Debug.contextLookup(CompilationResult.class); + CompilationResult compResult = debug.contextLookup(CompilationResult.class); if (compResult != null) { cfgPrinter.printMachineCode(disassemble(codeCache, compResult, (InstalledCode) object), message); } @@ -226,7 +215,7 @@ cfgPrinter.printIntervals(message, (IntervalDumper) object); } else { if (delayedIntervals != null) { - Debug.log("Some delayed intervals were dropped (%s)", delayedIntervals); + debug.log("Some delayed intervals were dropped (%s)", delayedIntervals); } delayedIntervals = (IntervalDumper) object; } @@ -248,10 +237,6 @@ } } - private static Path getCFGPath() { - return UniquePathUtilities.getPath(DebugScope.getConfig().getOptions(), Options.PrintCFGFileName, Options.DumpPath, "cfg"); - } - /** Lazy initialization to delay service lookup until disassembler is actually needed. */ static class DisassemblerHolder { private static final DisassemblerProvider disassembler; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CanonicalStringGraphPrinter.java 2017-07-07 09:31:38.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CanonicalStringGraphPrinter.java 2017-07-07 09:31:38.000000000 -0700 @@ -22,10 +22,11 @@ */ package org.graalvm.compiler.printer; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.CanonicalGraphStringsCheckConstants; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.CanonicalGraphStringsExcludeVirtuals; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.CanonicalGraphStringsRemoveIdentities; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.PrintCanonicalGraphStringFlavor; +import static org.graalvm.compiler.debug.DebugOptions.CanonicalGraphStringsCheckConstants; +import static org.graalvm.compiler.debug.DebugOptions.CanonicalGraphStringsExcludeVirtuals; +import static org.graalvm.compiler.debug.DebugOptions.CanonicalGraphStringsRemoveIdentities; +import static org.graalvm.compiler.debug.DebugOptions.PrintCanonicalGraphStringFlavor; +import static org.graalvm.compiler.printer.GraalDebugHandlersFactory.sanitizedFileName; import java.io.BufferedWriter; import java.io.FileWriter; @@ -42,7 +43,7 @@ import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.core.common.Fields; -import org.graalvm.compiler.debug.TTY; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Graph; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeMap; @@ -61,23 +62,14 @@ import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.compiler.phases.schedule.SchedulePhase; import jdk.vm.ci.meta.ResolvedJavaMethod; public class CanonicalStringGraphPrinter implements GraphPrinter { private static final Pattern IDENTITY_PATTERN = Pattern.compile("([A-Za-z0-9$_]+)@[0-9a-f]+"); - private Path currentDirectory; - private Path root; - private SnippetReflectionProvider snippetReflection; - - public CanonicalStringGraphPrinter(Path directory) { - this.currentDirectory = directory; - this.root = directory; - } + private final SnippetReflectionProvider snippetReflection; - @Override - public void setSnippetReflectionProvider(SnippetReflectionProvider snippetReflection) { + public CanonicalStringGraphPrinter(SnippetReflectionProvider snippetReflection) { this.snippetReflection = snippetReflection; } @@ -86,20 +78,6 @@ return snippetReflection; } - protected static String escapeFileName(String name) { - byte[] bytes = name.getBytes(); - StringBuilder sb = new StringBuilder(); - for (byte b : bytes) { - if ((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || (b >= '0' && b <= '9') || b == '.' || b == '-' || b == '_') { - sb.append((char) b); - } else { - sb.append('%'); - sb.append(Integer.toHexString(b)); - } - } - return sb.toString(); - } - private static String removeIdentities(String str) { return IDENTITY_PATTERN.matcher(str).replaceAll("$1"); } @@ -144,99 +122,122 @@ } protected static void writeCanonicalExpressionCFGString(StructuredGraph graph, boolean checkConstants, boolean removeIdentities, PrintWriter writer) { - ControlFlowGraph controlFlowGraph = ControlFlowGraph.compute(graph, true, true, false, false); - for (Block block : controlFlowGraph.getBlocks()) { - writer.print("Block "); - writer.print(block); - writer.print(" "); - if (block == controlFlowGraph.getStartBlock()) { - writer.print("* "); - } - writer.print("-> "); - for (Block successor : block.getSuccessors()) { - writer.print(successor); + ControlFlowGraph controlFlowGraph = getControlFlowGraph(graph); + if (controlFlowGraph == null) { + return; + } + try { + for (Block block : controlFlowGraph.getBlocks()) { + writer.print("Block "); + writer.print(block); writer.print(" "); - } - writer.println(); - FixedNode node = block.getBeginNode(); - while (node != null) { - writeCanonicalGraphExpressionString(node, checkConstants, removeIdentities, writer); + if (block == controlFlowGraph.getStartBlock()) { + writer.print("* "); + } + writer.print("-> "); + for (Block successor : block.getSuccessors()) { + writer.print(successor); + writer.print(" "); + } writer.println(); - if (node instanceof FixedWithNextNode) { - node = ((FixedWithNextNode) node).next(); - } else { - node = null; + FixedNode node = block.getBeginNode(); + while (node != null) { + writeCanonicalGraphExpressionString(node, checkConstants, removeIdentities, writer); + writer.println(); + if (node instanceof FixedWithNextNode) { + node = ((FixedWithNextNode) node).next(); + } else { + node = null; + } } } + } catch (Throwable e) { + writer.println(); + e.printStackTrace(writer); + } + } + + protected static ControlFlowGraph getControlFlowGraph(StructuredGraph graph) { + try { + return ControlFlowGraph.compute(graph, true, true, false, false); + } catch (Throwable e) { + // Ignore a non-well formed graph + return null; } } protected static void writeCanonicalGraphString(StructuredGraph graph, boolean excludeVirtual, boolean checkConstants, PrintWriter writer) { - SchedulePhase schedule = new SchedulePhase(SchedulePhase.SchedulingStrategy.EARLIEST); - schedule.apply(graph); - StructuredGraph.ScheduleResult scheduleResult = graph.getLastSchedule(); - - NodeMap canonicalId = graph.createNodeMap(); - int nextId = 0; - - List constantsLines = null; - if (checkConstants) { - constantsLines = new ArrayList<>(); + StructuredGraph.ScheduleResult scheduleResult = GraphPrinter.getScheduleOrNull(graph); + if (scheduleResult == null) { + return; } + try { + + NodeMap canonicalId = graph.createNodeMap(); + int nextId = 0; - for (Block block : scheduleResult.getCFG().getBlocks()) { - writer.print("Block "); - writer.print(block); - writer.print(" "); - if (block == scheduleResult.getCFG().getStartBlock()) { - writer.print("* "); + List constantsLines = null; + if (checkConstants) { + constantsLines = new ArrayList<>(); } - writer.print("-> "); - for (Block successor : block.getSuccessors()) { - writer.print(successor); + + for (Block block : scheduleResult.getCFG().getBlocks()) { + writer.print("Block "); + writer.print(block); writer.print(" "); - } - writer.println(); - for (Node node : scheduleResult.getBlockToNodesMap().get(block)) { - if (node instanceof ValueNode && node.isAlive()) { - if (!excludeVirtual || !(node instanceof VirtualObjectNode || node instanceof ProxyNode || node instanceof FullInfopointNode)) { - if (node instanceof ConstantNode) { - if (constantsLines != null) { - String name = node.toString(Verbosity.Name); - String str = name + (excludeVirtual ? "" : " (" + filteredUsageCount(node) + ")"); - constantsLines.add(str); - } - } else { - int id; - if (canonicalId.get(node) != null) { - id = canonicalId.get(node); + if (block == scheduleResult.getCFG().getStartBlock()) { + writer.print("* "); + } + writer.print("-> "); + for (Block successor : block.getSuccessors()) { + writer.print(successor); + writer.print(" "); + } + writer.println(); + for (Node node : scheduleResult.getBlockToNodesMap().get(block)) { + if (node instanceof ValueNode && node.isAlive()) { + if (!excludeVirtual || !(node instanceof VirtualObjectNode || node instanceof ProxyNode || node instanceof FullInfopointNode)) { + if (node instanceof ConstantNode) { + if (constantsLines != null) { + String name = node.toString(Verbosity.Name); + String str = name + (excludeVirtual ? "" : " (" + filteredUsageCount(node) + ")"); + constantsLines.add(str); + } } else { - id = nextId++; - canonicalId.set(node, id); - } - String name = node.getClass().getSimpleName(); - writer.print(" "); - writer.print(id); - writer.print("|"); - writer.print(name); - if (!excludeVirtual) { - writer.print(" ("); - writer.print(filteredUsageCount(node)); - writer.print(")"); + int id; + if (canonicalId.get(node) != null) { + id = canonicalId.get(node); + } else { + id = nextId++; + canonicalId.set(node, id); + } + String name = node.getClass().getSimpleName(); + writer.print(" "); + writer.print(id); + writer.print("|"); + writer.print(name); + if (!excludeVirtual) { + writer.print(" ("); + writer.print(filteredUsageCount(node)); + writer.print(")"); + } + writer.println(); } - writer.println(); } } } } - } - if (constantsLines != null) { - writer.print(constantsLines.size()); - writer.println(" constants:"); - Collections.sort(constantsLines); - for (String s : constantsLines) { - writer.println(s); + if (constantsLines != null) { + writer.print(constantsLines.size()); + writer.println(" constants:"); + Collections.sort(constantsLines); + for (String s : constantsLines) { + writer.println(s); + } } + } catch (Throwable t) { + writer.println(); + t.printStackTrace(writer); } } @@ -253,22 +254,29 @@ } @Override - public void beginGroup(String name, String shortName, ResolvedJavaMethod method, int bci, Map properties) throws IOException { - currentDirectory = currentDirectory.resolve(escapeFileName(name)); + public void beginGroup(DebugContext debug, String name, String shortName, ResolvedJavaMethod method, int bci, Map properties) throws IOException { + } + + private StructuredGraph currentGraph; + private Path currentDirectory; + + private Path getDirectory(StructuredGraph graph) throws IOException { + if (graph == currentGraph) { + return currentDirectory; + } + currentDirectory = GraalDebugHandlersFactory.createDumpPath(graph.getOptions(), graph, "graph-strings", true); + currentGraph = graph; + return currentDirectory; } @Override - public void print(Graph graph, Map properties, int id, String format, Object... args) throws IOException { + public void print(DebugContext debug, Graph graph, Map properties, int id, String format, Object... args) throws IOException { if (graph instanceof StructuredGraph) { OptionValues options = graph.getOptions(); StructuredGraph structuredGraph = (StructuredGraph) graph; - currentDirectory.toFile().mkdirs(); - if (this.root != null) { - TTY.println("Dumping string graphs in %s", this.root); - this.root = null; - } - String title = formatTitle(id, format, args); - Path filePath = currentDirectory.resolve(escapeFileName(title)); + Path outDirectory = getDirectory(structuredGraph); + String title = String.format("%03d-%s.txt", id, String.format(format, simplifyClassArgs(args))); + Path filePath = outDirectory.resolve(sanitizedFileName(title)); try (PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(filePath.toFile())))) { switch (PrintCanonicalGraphStringFlavor.getValue(options)) { case 1: @@ -285,8 +293,6 @@ @Override public void endGroup() throws IOException { - currentDirectory = currentDirectory.getParent(); - assert currentDirectory != null; } @Override --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinter.java 2017-07-07 09:31:38.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinter.java 2017-07-07 09:31:38.000000000 -0700 @@ -30,8 +30,12 @@ import java.util.Map; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DebugContext.Scope; import org.graalvm.compiler.graph.Graph; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.graalvm.compiler.serviceprovider.JDK9Method; import jdk.vm.ci.meta.JavaConstant; @@ -48,18 +52,16 @@ * Starts a new group of graphs with the given name, short name and method byte code index (BCI) * as properties. */ - void beginGroup(String name, String shortName, ResolvedJavaMethod method, int bci, Map properties) throws IOException; + void beginGroup(DebugContext debug, String name, String shortName, ResolvedJavaMethod method, int bci, Map properties) throws IOException; /** * Prints an entire {@link Graph} with the specified title, optionally using short names for * nodes. */ - void print(Graph graph, Map properties, int id, String format, Object... args) throws IOException; + void print(DebugContext debug, Graph graph, Map properties, int id, String format, Object... args) throws IOException; SnippetReflectionProvider getSnippetReflectionProvider(); - void setSnippetReflectionProvider(SnippetReflectionProvider snippetReflection); - /** * Ends the current group. */ @@ -142,20 +144,30 @@ } } - default String formatTitle(int id, String format, Object... args) { - /* - * If an argument is a Class, replace it with the simple name. - */ - Object[] newArgs = new Object[args.length]; - for (int i = 0; i < newArgs.length; i++) { + /** + * Replaces all {@link JavaType} elements in {@code args} with the result of + * {@link JavaType#getUnqualifiedName()}. + * + * @return a copy of {@code args} with the above mentioned substitutions or {@code args} if no + * substitutions were performed + */ + default Object[] simplifyClassArgs(Object... args) { + Object[] res = args; + for (int i = 0; i < args.length; i++) { Object arg = args[i]; if (arg instanceof JavaType) { - newArgs[i] = ((JavaType) arg).getUnqualifiedName(); + if (args == res) { + res = new Object[args.length]; + for (int a = 0; a < i; a++) { + res[a] = args[a]; + } + } + res[i] = ((JavaType) arg).getUnqualifiedName(); } else { - newArgs[i] = arg; + res[i] = arg; } } - return id + ": " + String.format(format, newArgs); + return res; } static String truncate(String s) { @@ -198,4 +210,23 @@ } return buf.append('}').toString(); } + + @SuppressWarnings("try") + static StructuredGraph.ScheduleResult getScheduleOrNull(Graph graph) { + if (graph instanceof StructuredGraph) { + StructuredGraph sgraph = (StructuredGraph) graph; + StructuredGraph.ScheduleResult scheduleResult = sgraph.getLastSchedule(); + if (scheduleResult == null) { + DebugContext debug = graph.getDebug(); + try (Scope scope = debug.disable()) { + SchedulePhase schedule = new SchedulePhase(graph.getOptions()); + schedule.apply(sgraph); + scheduleResult = sgraph.getLastSchedule(); + } catch (Throwable t) { + } + } + return scheduleResult; + } + return null; + } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinterDumpHandler.java 2017-07-07 09:31:39.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinterDumpHandler.java 2017-07-07 09:31:39.000000000 -0700 @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.printer; -import static org.graalvm.compiler.debug.GraalDebugConfig.asJavaMethod; +import static org.graalvm.compiler.debug.DebugConfig.asJavaMethod; import java.io.IOException; import java.lang.management.ManagementFactory; @@ -36,19 +36,15 @@ import java.util.Map; import java.util.WeakHashMap; -import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; -import org.graalvm.compiler.debug.DebugConfig; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugDumpHandler; import org.graalvm.compiler.debug.DebugDumpScope; -import org.graalvm.compiler.debug.GraalDebugConfig; -import org.graalvm.compiler.debug.GraalDebugConfig.Options; +import org.graalvm.compiler.debug.DebugOptions; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.TTY; -import org.graalvm.compiler.debug.internal.DebugScope; import org.graalvm.compiler.graph.Graph; import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.contract.NodeCostUtil; import jdk.vm.ci.meta.JavaMethod; @@ -58,15 +54,13 @@ /** * Observes compilation events and uses {@link IdealGraphPrinter} to generate a graph representation - * that can be inspected with the Ideal Graph Visualizer - * . + * that can be inspected with the Graph Visualizer. */ public class GraphPrinterDumpHandler implements DebugDumpHandler { private static final int FAILURE_LIMIT = 8; private final GraphPrinterSupplier printerSupplier; protected GraphPrinter printer; - private SnippetReflectionProvider snippetReflection; private List previousInlineContext; private int[] dumpIds = {}; private int failuresCount; @@ -76,7 +70,7 @@ @FunctionalInterface public interface GraphPrinterSupplier { - GraphPrinter get() throws IOException; + GraphPrinter get(Graph graph) throws IOException; } /** @@ -92,20 +86,18 @@ this.sunJavaCommand = System.getProperty("sun.java.command"); } - private void ensureInitialized() { + private void ensureInitialized(Graph graph) { if (printer == null) { if (failuresCount >= FAILURE_LIMIT) { return; } previousInlineContext = new ArrayList<>(); inlineContextMap = new WeakHashMap<>(); + DebugContext debug = graph.getDebug(); try { - printer = printerSupplier.get(); - if (snippetReflection != null) { - printer.setSnippetReflectionProvider(snippetReflection); - } + printer = printerSupplier.get(graph); } catch (IOException e) { - handleException(e); + handleException(debug, e); } } } @@ -120,13 +112,14 @@ @Override @SuppressWarnings("try") - public void dump(Object object, final String format, Object... arguments) { - if (object instanceof Graph && Options.PrintGraph.getValue(DebugScope.getConfig().getOptions())) { - ensureInitialized(); + public void dump(DebugContext debug, Object object, final String format, Object... arguments) { + OptionValues options = debug.getOptions(); + if (object instanceof Graph && DebugOptions.PrintGraph.getValue(options)) { + final Graph graph = (Graph) object; + ensureInitialized(graph); if (printer == null) { return; } - final Graph graph = (Graph) object; // Get all current JavaMethod instances in the context. List inlineContext = getInlineContext(graph); @@ -135,21 +128,20 @@ Map properties = new HashMap<>(); properties.put("graph", graph.toString()); addCompilationId(properties, graph); - addCFGFileName(properties); if (inlineContext.equals(previousInlineContext)) { /* * two different graphs have the same inline context, so make sure they appear * in different folders by closing and reopening the top scope. */ int inlineDepth = previousInlineContext.size() - 1; - closeScope(inlineDepth); - openScope(inlineContext.get(inlineDepth), inlineDepth, properties); + closeScope(debug, inlineDepth); + openScope(debug, inlineContext.get(inlineDepth), inlineDepth, properties); } else { // Check for method scopes that must be closed since the previous dump. for (int i = 0; i < previousInlineContext.size(); ++i) { if (i >= inlineContext.size() || !inlineContext.get(i).equals(previousInlineContext.get(i))) { for (int inlineDepth = previousInlineContext.size() - 1; inlineDepth >= i; --inlineDepth) { - closeScope(inlineDepth); + closeScope(debug, inlineDepth); } break; } @@ -158,7 +150,7 @@ for (int i = 0; i < inlineContext.size(); ++i) { if (i >= previousInlineContext.size() || !inlineContext.get(i).equals(previousInlineContext.get(i))) { for (int inlineDepth = i; inlineDepth < inlineContext.size(); ++inlineDepth) { - openScope(inlineContext.get(inlineDepth), inlineDepth, inlineDepth == inlineContext.size() - 1 ? properties : null); + openScope(debug, inlineContext.get(inlineDepth), inlineDepth, inlineDepth == inlineContext.size() - 1 ? properties : null); } break; } @@ -169,11 +161,11 @@ // Save inline context for next dump. previousInlineContext = inlineContext; - try (Scope s = Debug.sandbox("PrintingGraph", null)) { + try (DebugContext.Scope s = debug.sandbox("PrintingGraph", null)) { // Finally, output the graph. Map properties = new HashMap<>(); properties.put("graph", graph.toString()); - properties.put("scope", Debug.currentScope()); + properties.put("scope", debug.getCurrentScopeName()); if (graph instanceof StructuredGraph) { properties.put("compilationIdentifier", ((StructuredGraph) graph).compilationId()); try { @@ -183,18 +175,17 @@ properties.put("node-cost-exception", t.getMessage()); } } - addCFGFileName(properties); - printer.print(graph, properties, nextDumpId(), format, arguments); + printer.print(debug, graph, properties, nextDumpId(), format, arguments); } catch (IOException e) { - handleException(e); + handleException(debug, e); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } } - void handleException(IOException e) { - if (GraalDebugConfig.Options.DumpingErrorsAreFatal.getValue(DebugScope.getConfig().getOptions())) { + void handleException(DebugContext debug, IOException e) { + if (debug != null && DebugOptions.DumpingErrorsAreFatal.getValue(debug.getOptions())) { throw new GraalError(e); } if (e instanceof ClosedByInterruptException) { @@ -206,11 +197,9 @@ failuresCount++; } printer = null; + e.printStackTrace(TTY.out); if (failuresCount > FAILURE_LIMIT) { - e.printStackTrace(TTY.out); - TTY.println("Too many failures with dumping. Disabling dump in thread " + Thread.currentThread()); - } else { - TTY.println(e.getMessage()); + TTY.println("Too many failures with dumping. Disabling dump in thread " + Thread.currentThread()); } } @@ -220,29 +209,14 @@ } } - private static void addCFGFileName(Map properties) { - DebugConfig config = DebugScope.getConfig(); - if (config != null) { - for (DebugDumpHandler dumpHandler : config.dumpHandlers()) { - if (dumpHandler instanceof CFGPrinterObserver) { - CFGPrinterObserver cfg = (CFGPrinterObserver) dumpHandler; - String path = cfg.getDumpPath(); - if (path != null) { - properties.put("PrintCFGFileName", path); - } - return; - } - } - } - } - private List getInlineContext(Graph graph) { List result = inlineContextMap.get(graph); if (result == null) { result = new ArrayList<>(); Object lastMethodOrGraph = null; boolean graphSeen = false; - for (Object o : Debug.context()) { + DebugContext debug = graph.getDebug(); + for (Object o : debug.context()) { if (o == graph) { graphSeen = true; } @@ -307,7 +281,7 @@ } } - private void openScope(String name, int inlineDepth, Map properties) { + private void openScope(DebugContext debug, String name, int inlineDepth, Map properties) { try { Map props = properties; if (inlineDepth == 0) { @@ -321,18 +295,20 @@ } props.put("date", new Date().toString()); } - printer.beginGroup(name, name, Debug.contextLookup(ResolvedJavaMethod.class), -1, props); + printer.beginGroup(debug, name, name, debug.contextLookup(ResolvedJavaMethod.class), -1, props); } catch (IOException e) { - handleException(e); + handleException(debug, e); } } - private void closeScope(int inlineDepth) { + private void closeScope(DebugContext debug, int inlineDepth) { dumpIds[inlineDepth] = 0; try { - printer.endGroup(); + if (printer != null) { + printer.endGroup(); + } } catch (IOException e) { - handleException(e); + handleException(debug, e); } } @@ -340,7 +316,7 @@ public void close() { if (previousInlineContext != null) { for (int inlineDepth = 0; inlineDepth < previousInlineContext.size(); inlineDepth++) { - closeScope(inlineDepth); + closeScope(null, inlineDepth); } } if (printer != null) { @@ -348,14 +324,4 @@ printer = null; } } - - @Override - public void addCapability(Object capability) { - if (capability instanceof SnippetReflectionProvider) { - snippetReflection = (SnippetReflectionProvider) capability; - if (printer != null && printer.getSnippetReflectionProvider() == null) { - printer.setSnippetReflectionProvider(snippetReflection); - } - } - } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/IdealGraphPrinter.java 2017-07-07 09:31:39.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/IdealGraphPrinter.java 2017-07-07 09:31:39.000000000 -0700 @@ -32,8 +32,8 @@ import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.bytecode.BytecodeDisassembler; -import org.graalvm.compiler.debug.GraalDebugConfig.Options; -import org.graalvm.compiler.debug.internal.DebugScope; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DebugOptions; import org.graalvm.compiler.graph.Graph; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeMap; @@ -50,6 +50,7 @@ import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; import org.graalvm.compiler.nodes.cfg.Block; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.graalvm.util.EconomicSet; import org.graalvm.util.Equivalence; @@ -63,7 +64,7 @@ public class IdealGraphPrinter extends BasicIdealGraphPrinter implements GraphPrinter { private final boolean tryToSchedule; - private SnippetReflectionProvider snippetReflection; + private final SnippetReflectionProvider snippetReflection; /** * Creates a new {@link IdealGraphPrinter} that writes to the specified output stream. @@ -71,18 +72,14 @@ * @param tryToSchedule If false, no scheduling is done, which avoids exceptions for * non-schedulable graphs. */ - public IdealGraphPrinter(OutputStream stream, boolean tryToSchedule) { + public IdealGraphPrinter(OutputStream stream, boolean tryToSchedule, SnippetReflectionProvider snippetReflection) { super(stream); + this.snippetReflection = snippetReflection; this.begin(); this.tryToSchedule = tryToSchedule; } @Override - public void setSnippetReflectionProvider(SnippetReflectionProvider snippetReflection) { - this.snippetReflection = snippetReflection; - } - - @Override public SnippetReflectionProvider getSnippetReflectionProvider() { return snippetReflection; } @@ -92,7 +89,7 @@ * as properties. */ @Override - public void beginGroup(String name, String shortName, ResolvedJavaMethod method, int bci, Map properties) { + public void beginGroup(DebugContext debug, String name, String shortName, ResolvedJavaMethod method, int bci, Map properties) { beginGroup(); beginProperties(); printProperty("name", name); @@ -114,8 +111,8 @@ * nodes. */ @Override - public void print(Graph graph, Map properties, int id, String format, Object... args) { - String title = formatTitle(id, format, args); + public void print(DebugContext debug, Graph graph, Map properties, int id, String format, Object... args) { + String title = id + ": " + String.format(format, simplifyClassArgs(args)); beginGraph(title); EconomicSet noBlockNodes = EconomicSet.create(Equivalence.IDENTITY); ScheduleResult schedule = null; @@ -123,9 +120,10 @@ StructuredGraph structuredGraph = (StructuredGraph) graph; schedule = structuredGraph.getLastSchedule(); if (schedule == null && tryToSchedule) { - if (Options.PrintGraphWithSchedule.getValue(DebugScope.getConfig().getOptions())) { + OptionValues options = graph.getOptions(); + if (DebugOptions.PrintGraphWithSchedule.getValue(options)) { try { - SchedulePhase schedulePhase = new SchedulePhase(graph.getOptions()); + SchedulePhase schedulePhase = new SchedulePhase(options); schedulePhase.apply(structuredGraph); schedule = structuredGraph.getLastSchedule(); } catch (Throwable t) { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/NoDeadCodeVerifyHandler.java 2017-07-07 09:31:40.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/NoDeadCodeVerifyHandler.java 2017-07-07 09:31:40.000000000 -0700 @@ -26,9 +26,9 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugVerifyHandler; import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.debug.internal.DebugScope; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.options.Option; @@ -63,8 +63,8 @@ private static final Map discovered = new ConcurrentHashMap<>(); @Override - public void verify(Object object, String format, Object... args) { - OptionValues options = DebugScope.getConfig().getOptions(); + public void verify(DebugContext debug, Object object, String format, Object... args) { + OptionValues options = debug.getOptions(); if (Options.NDCV.getValue(options) != OFF && object instanceof StructuredGraph) { StructuredGraph graph = (StructuredGraph) object; List before = graph.getNodes().snapshot(); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64FloatArithmeticSnippets.java 2017-07-07 09:31:40.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64FloatArithmeticSnippets.java 2017-07-07 09:31:40.000000000 -0700 @@ -28,6 +28,7 @@ import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.graph.Node.NodeIntrinsic; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; @@ -54,8 +55,9 @@ private final SnippetTemplate.SnippetInfo drem; private final SnippetTemplate.SnippetInfo frem; - public AArch64FloatArithmeticSnippets(OptionValues options, Providers providers, SnippetReflectionProvider snippetReflection, TargetDescription target) { - super(options, providers, snippetReflection, target); + public AArch64FloatArithmeticSnippets(OptionValues options, Iterable factories, Providers providers, SnippetReflectionProvider snippetReflection, + TargetDescription target) { + super(options, factories, providers, snippetReflection, target); drem = snippet(AArch64FloatArithmeticSnippets.class, "dremSnippet"); frem = snippet(AArch64FloatArithmeticSnippets.class, "fremSnippet"); } @@ -72,7 +74,7 @@ Arguments args = new Arguments(snippet, graph.getGuardsStage(), tool.getLoweringStage()); args.add("x", node.getX()); args.add("y", node.getY()); - template(args).instantiate(providers.getMetaAccess(), node, SnippetTemplate.DEFAULT_REPLACER, tool, args); + template(graph.getDebug(), args).instantiate(providers.getMetaAccess(), node, SnippetTemplate.DEFAULT_REPLACER, tool, args); } @Snippet --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64IntegerArithmeticSnippets.java 2017-07-07 09:31:40.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64IntegerArithmeticSnippets.java 2017-07-07 09:31:40.000000000 -0700 @@ -25,6 +25,7 @@ import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node.NodeIntrinsic; import org.graalvm.compiler.graph.NodeClass; @@ -68,8 +69,9 @@ private final SnippetTemplate.SnippetInfo uirem; private final SnippetTemplate.SnippetInfo ulrem; - public AArch64IntegerArithmeticSnippets(OptionValues options, Providers providers, SnippetReflectionProvider snippetReflection, TargetDescription target) { - super(options, providers, snippetReflection, target); + public AArch64IntegerArithmeticSnippets(OptionValues options, Iterable factories, Providers providers, SnippetReflectionProvider snippetReflection, + TargetDescription target) { + super(options, factories, providers, snippetReflection, target); idiv = snippet(AArch64IntegerArithmeticSnippets.class, "idivSnippet"); ldiv = snippet(AArch64IntegerArithmeticSnippets.class, "ldivSnippet"); irem = snippet(AArch64IntegerArithmeticSnippets.class, "iremSnippet"); @@ -103,7 +105,7 @@ Arguments args = new Arguments(snippet, graph.getGuardsStage(), tool.getLoweringStage()); args.add("x", node.getX()); args.add("y", node.getY()); - template(args).instantiate(providers.getMetaAccess(), node, SnippetTemplate.DEFAULT_REPLACER, args); + template(graph.getDebug(), args).instantiate(providers.getMetaAccess(), node, SnippetTemplate.DEFAULT_REPLACER, args); } @Snippet --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64ConvertSnippets.java 2017-07-07 09:31:41.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64ConvertSnippets.java 2017-07-07 09:31:41.000000000 -0700 @@ -28,7 +28,7 @@ import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.calc.FloatConvertNode; import org.graalvm.compiler.nodes.spi.LoweringTool; @@ -155,8 +155,8 @@ private final SnippetInfo d2i; private final SnippetInfo d2l; - public Templates(OptionValues options, Providers providers, SnippetReflectionProvider snippetReflection, TargetDescription target) { - super(options, providers, snippetReflection, target); + public Templates(OptionValues options, Iterable factories, Providers providers, SnippetReflectionProvider snippetReflection, TargetDescription target) { + super(options, factories, providers, snippetReflection, target); f2i = snippet(AMD64ConvertSnippets.class, "f2i"); f2l = snippet(AMD64ConvertSnippets.class, "f2l"); @@ -189,8 +189,8 @@ args.add("input", convert.getValue()); args.add("result", graph.unique(new AMD64FloatConvertNode(convert.getFloatConvert(), convert.getValue()))); - SnippetTemplate template = template(args); - Debug.log("Lowering %s in %s: node=%s, template=%s, arguments=%s", convert.getFloatConvert(), graph, convert, template, args); + SnippetTemplate template = template(convert.getDebug(), args); + convert.getDebug().log("Lowering %s in %s: node=%s, template=%s, arguments=%s", convert.getFloatConvert(), graph, convert, template, args); template.instantiate(providers.getMetaAccess(), convert, DEFAULT_REPLACER, tool, args); convert.safeDelete(); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/CompiledExceptionHandlerTest.java 2017-07-07 09:31:41.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/CompiledExceptionHandlerTest.java 2017-07-07 09:31:41.000000000 -0700 @@ -22,16 +22,17 @@ */ package org.graalvm.compiler.replacements.test; -import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.phases.HighTier; import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.nodes.StructuredGraph.Builder; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo; import org.graalvm.compiler.nodes.java.ExceptionObjectNode; import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.phases.PhaseSuite; +import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.tiers.Suites; import org.junit.Assert; import org.junit.Test; @@ -59,8 +60,8 @@ } @Override - protected StructuredGraph parseEager(ResolvedJavaMethod m, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId, OptionValues options) { - StructuredGraph graph = super.parseEager(m, allowAssumptions, compilationId, options); + protected StructuredGraph parse(Builder builder, PhaseSuite graphBuilderSuite) { + StructuredGraph graph = super.parse(builder, graphBuilderSuite); int handlers = graph.getNodes().filter(ExceptionObjectNode.class).count(); Assert.assertEquals(1, handlers); return graph; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/CompiledNullPointerExceptionTest.java 2017-07-07 09:31:42.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/CompiledNullPointerExceptionTest.java 2017-07-07 09:31:42.000000000 -0700 @@ -24,17 +24,18 @@ import static org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.BytecodeExceptionMode.CheckAll; -import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.phases.HighTier; import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.nodes.StructuredGraph.Builder; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo; import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.phases.PhaseSuite; +import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.tiers.Suites; import org.junit.Assert; import org.junit.Test; @@ -63,8 +64,8 @@ } @Override - protected StructuredGraph parseEager(ResolvedJavaMethod m, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId, OptionValues options) { - StructuredGraph graph = super.parseEager(m, allowAssumptions, compilationId, options); + protected StructuredGraph parse(Builder builder, PhaseSuite graphBuilderSuite) { + StructuredGraph graph = super.parse(builder, graphBuilderSuite); int handlers = graph.getNodes().filter(BytecodeExceptionNode.class).count(); Assert.assertEquals(1, handlers); return graph; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/DerivedOopTest.java 2017-07-07 09:31:42.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/DerivedOopTest.java 2017-07-07 09:31:42.000000000 -0700 @@ -25,8 +25,8 @@ import java.util.Objects; import org.graalvm.compiler.api.directives.GraalDirectives; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugConfigScope; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DebugContext.Scope; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; @@ -147,7 +147,8 @@ public void testFieldOffsetMergeNonLiveBasePointer() { thrown.expect(GraalError.class); thrown.expectMessage(UNKNOWN_REFERENCE_AT_SAFEPOINT_MSG); - try (DebugConfigScope s = Debug.setConfig(Debug.silentConfig())) { + DebugContext debug = getDebugContext(); + try (Scope s = debug.disable()) { // Run a couple times to encourage objects to move for (int i = 0; i < 4; i++) { Result r = new Result(); @@ -171,7 +172,8 @@ public void testFieldOffsetMergeLiveBasePointer() { thrown.expect(GraalError.class); thrown.expectMessage(UNKNOWN_REFERENCE_AT_SAFEPOINT_MSG); - try (DebugConfigScope s = Debug.setConfig(Debug.silentConfig())) { + DebugContext debug = getDebugContext(); + try (Scope s = debug.disable()) { // Run a couple times to encourage objects to move for (int i = 0; i < 4; i++) { Result r = new Result(); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/EdgesTest.java 2017-07-07 09:31:43.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/EdgesTest.java 2017-07-07 09:31:43.000000000 -0700 @@ -42,6 +42,7 @@ import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.java.InstanceOfNode; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.inlining.InliningPhase; import org.graalvm.compiler.phases.common.inlining.policy.InlineMethodSubstitutionsPolicy; @@ -64,7 +65,12 @@ } - StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions()).build(); + protected StructuredGraph createGraph() { + OptionValues options = getInitialOptions(); + return new StructuredGraph.Builder(options, getDebugContext(options)).build(); + } + + StructuredGraph graph = createGraph(); TestNode node; ConstantNode i1; ConstantNode i2; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/InstanceOfTest.java 2017-07-07 09:31:43.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/InstanceOfTest.java 2017-07-07 09:31:43.000000000 -0700 @@ -28,16 +28,14 @@ import java.util.Map; import java.util.TreeMap; -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.IfNode; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.java.InstanceOfNode; import org.graalvm.compiler.phases.common.AbstractInliningPhase; +import org.junit.Test; import jdk.vm.ci.code.site.Call; import jdk.vm.ci.code.site.Mark; @@ -485,13 +483,14 @@ @SuppressWarnings("try") protected StructuredGraph buildGraph(final String snippet) { - try (Scope s = Debug.scope("InstanceOfTest", getMetaAccess().lookupJavaMethod(getMethod(snippet)))) { - StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); + DebugContext debug = getDebugContext(); + try (DebugContext.Scope s = debug.scope("InstanceOfTest", getMetaAccess().lookupJavaMethod(getMethod(snippet)))) { + StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES, debug); compile(graph.method(), graph); - Debug.dump(Debug.BASIC_LEVEL, graph, snippet); + debug.dump(DebugContext.BASIC_LEVEL, graph, snippet); return graph; } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/MethodSubstitutionTest.java 2017-07-07 09:31:43.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/MethodSubstitutionTest.java 2017-07-07 09:31:43.000000000 -0700 @@ -26,8 +26,7 @@ import org.graalvm.compiler.api.replacements.MethodSubstitution; import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.StructuredGraph; @@ -53,12 +52,13 @@ @SuppressWarnings("try") protected StructuredGraph testGraph(final String snippet) { - try (Scope s = Debug.scope("MethodSubstitutionTest", getResolvedJavaMethod(snippet))) { - StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); + DebugContext debug = getDebugContext(); + try (DebugContext.Scope s = debug.scope("MethodSubstitutionTest", getResolvedJavaMethod(snippet))) { + StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES, debug); HighTierContext context = getDefaultHighTierContext(); - Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); + debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); new InliningPhase(new CanonicalizerPhase()).apply(graph, context); - Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); + debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); new CanonicalizerPhase().apply(graph, context); new DeadCodeEliminationPhase().apply(graph); // Try to ensure any macro nodes are lowered to expose any resulting invokes @@ -72,7 +72,7 @@ assertNotInGraph(graph, Invoke.class); return graph; } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/PEGraphDecoderTest.java 2017-07-07 09:31:44.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/PEGraphDecoderTest.java 2017-07-07 09:31:44.000000000 -0700 @@ -24,10 +24,9 @@ import static org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo.createStandardInlineInfo; -import org.junit.Test; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.AbstractBeginNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; @@ -47,6 +46,7 @@ import org.graalvm.compiler.phases.tiers.PhaseContext; import org.graalvm.compiler.replacements.CachingPEGraphDecoder; import org.graalvm.word.LocationIdentity; +import org.junit.Test; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -130,15 +130,16 @@ public void test() { ResolvedJavaMethod testMethod = getResolvedJavaMethod(PEGraphDecoderTest.class, "doTest", Object.class); StructuredGraph targetGraph = null; - try (Debug.Scope scope = Debug.scope("GraphPETest", testMethod)) { + DebugContext debug = getDebugContext(); + try (DebugContext.Scope scope = debug.scope("GraphPETest", testMethod)) { GraphBuilderConfiguration graphBuilderConfig = GraphBuilderConfiguration.getDefault(getDefaultGraphBuilderPlugins()).withEagerResolving(true); registerPlugins(graphBuilderConfig.getPlugins().getInvocationPlugins()); - targetGraph = new StructuredGraph.Builder(getInitialOptions(), AllowAssumptions.YES).method(testMethod).build(); + targetGraph = new StructuredGraph.Builder(getInitialOptions(), debug, AllowAssumptions.YES).method(testMethod).build(); CachingPEGraphDecoder decoder = new CachingPEGraphDecoder(getTarget().arch, targetGraph, getProviders(), graphBuilderConfig, OptimisticOptimizations.NONE, AllowAssumptions.YES, - getInitialOptions(), null, null, new InlineInvokePlugin[]{new InlineAll()}, null, null); + null, null, new InlineInvokePlugin[]{new InlineAll()}, null, null); decoder.decode(testMethod); - Debug.dump(Debug.BASIC_LEVEL, targetGraph, "Target Graph"); + debug.dump(DebugContext.BASIC_LEVEL, targetGraph, "Target Graph"); targetGraph.verify(); PhaseContext context = new PhaseContext(getProviders()); @@ -147,9 +148,9 @@ } catch (Throwable ex) { if (targetGraph != null) { - Debug.dump(Debug.BASIC_LEVEL, targetGraph, ex.toString()); + debug.dump(DebugContext.BASIC_LEVEL, targetGraph, ex.toString()); } - Debug.handle(ex); + debug.handle(ex); } } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/PointerTrackingTest.java 2017-07-07 09:31:44.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/PointerTrackingTest.java 2017-07-07 09:31:44.000000000 -0700 @@ -24,8 +24,6 @@ import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.bytecode.BytecodeProvider; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugConfigScope; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; @@ -82,9 +80,7 @@ @Test(expected = GraalError.class) @SuppressWarnings("try") public void testVerification() { - try (DebugConfigScope scope = Debug.disableIntercept()) { - compile(getResolvedJavaMethod("verificationSnippet"), null); - } + compile(getResolvedJavaMethod("verificationSnippet"), null); } public static long verificationSnippet(Object obj) { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ReplacementsParseTest.java 2017-07-07 09:31:45.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ReplacementsParseTest.java 2017-07-07 09:31:45.000000000 -0700 @@ -30,8 +30,6 @@ import org.graalvm.compiler.api.replacements.ClassSubstitution; import org.graalvm.compiler.api.replacements.MethodSubstitution; import org.graalvm.compiler.bytecode.BytecodeProvider; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugConfigScope; import org.graalvm.compiler.graph.GraalGraphError; import org.graalvm.compiler.graph.Node.ConstantNodeParameter; import org.graalvm.compiler.graph.Node.NodeIntrinsic; @@ -471,9 +469,7 @@ byte[] in = {0, 1, 2, 3, 4}; byte[] out = new byte[in.length]; try { - try (DebugConfigScope s = Debug.setConfig(Debug.silentConfig())) { - test("callCopyFirstL2R", in, out); - } + test("callCopyFirstL2R", in, out); } catch (GraalGraphError e) { assertTrue(e.getMessage().startsWith("Invalid frame state")); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SnippetsTest.java 2017-07-07 09:31:45.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SnippetsTest.java 2017-07-07 09:31:45.000000000 -0700 @@ -22,15 +22,13 @@ */ package org.graalvm.compiler.replacements.test; -import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.nodes.StructuredGraph.Builder; +import org.graalvm.compiler.phases.PhaseSuite; +import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.replacements.ReplacementsImpl; import org.graalvm.compiler.replacements.classfile.ClassfileBytecodeProvider; -import jdk.vm.ci.meta.ResolvedJavaMethod; - public abstract class SnippetsTest extends ReplacementsTest { protected final ReplacementsImpl installer; @@ -39,12 +37,12 @@ protected SnippetsTest() { ReplacementsImpl d = (ReplacementsImpl) getReplacements(); bytecodeProvider = getSystemClassLoaderBytecodeProvider(); - installer = new ReplacementsImpl(getInitialOptions(), d.providers, d.snippetReflection, bytecodeProvider, d.target); + installer = new ReplacementsImpl(getInitialOptions(), null, d.providers, d.snippetReflection, bytecodeProvider, d.target); installer.setGraphBuilderPlugins(d.getGraphBuilderPlugins()); } @Override - protected StructuredGraph parseEager(ResolvedJavaMethod m, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId, OptionValues options) { - return installer.makeGraph(bytecodeProvider, m, null, null); + protected StructuredGraph parse(Builder builder, PhaseSuite graphBuilderSuite) { + return installer.makeGraph(getDebugContext(), bytecodeProvider, builder.getMethod(), null, null); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/WordTest.java 2017-07-07 09:31:45.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/WordTest.java 2017-07-07 09:31:45.000000000 -0700 @@ -23,10 +23,11 @@ package org.graalvm.compiler.replacements.test; import org.graalvm.compiler.api.replacements.Snippet; -import org.graalvm.compiler.core.common.CompilationIdentifier; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.nodes.StructuredGraph.Builder; +import org.graalvm.compiler.phases.PhaseSuite; +import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.word.Word; import org.graalvm.word.Pointer; import org.graalvm.word.Unsigned; @@ -34,17 +35,17 @@ import org.graalvm.word.WordFactory; import org.junit.Test; -import jdk.vm.ci.meta.ResolvedJavaMethod; - /** * Tests for the {@link Word} type. */ public class WordTest extends SnippetsTest { @Override - protected StructuredGraph parseEager(ResolvedJavaMethod m, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId, OptionValues options) { + protected StructuredGraph parse(Builder builder, PhaseSuite graphBuilderSuite) { // create a copy to assign a valid compilation id - return installer.makeGraph(bytecodeProvider, m, null, null).copyWithIdentifier(compilationId); + DebugContext debug = getDebugContext(); + StructuredGraph originalGraph = installer.makeGraph(debug, bytecodeProvider, builder.getMethod(), null, null); + return originalGraph.copyWithIdentifier(builder.getCompilationId(), debug); } @Test --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/BoxingSnippets.java 2017-07-07 09:31:46.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/BoxingSnippets.java 2017-07-07 09:31:46.000000000 -0700 @@ -29,8 +29,8 @@ import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; -import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.ValueNode; @@ -185,8 +185,9 @@ private final SnippetCounter valueOfCounter; private final SnippetCounter valueCounter; - public Templates(OptionValues options, SnippetCounter.Group.Factory factory, Providers providers, SnippetReflectionProvider snippetReflection, TargetDescription target) { - super(options, providers, snippetReflection, target); + public Templates(OptionValues options, Iterable factories, SnippetCounter.Group.Factory factory, Providers providers, SnippetReflectionProvider snippetReflection, + TargetDescription target) { + super(options, factories, providers, snippetReflection, target); for (JavaKind kind : new JavaKind[]{JavaKind.Boolean, JavaKind.Byte, JavaKind.Char, JavaKind.Double, JavaKind.Float, JavaKind.Int, JavaKind.Long, JavaKind.Short}) { boxSnippets.put(kind, snippet(BoxingSnippets.class, kind.getJavaName() + "ValueOf")); unboxSnippets.put(kind, snippet(BoxingSnippets.class, kind.getJavaName() + "Value")); @@ -206,8 +207,8 @@ args.add("value", box.getValue()); args.addConst("valueOfCounter", valueOfCounter); - SnippetTemplate template = template(args); - Debug.log("Lowering integerValueOf in %s: node=%s, template=%s, arguments=%s", box.graph(), box, template, args); + SnippetTemplate template = template(box.getDebug(), args); + box.getDebug().log("Lowering integerValueOf in %s: node=%s, template=%s, arguments=%s", box.graph(), box, template, args); template.instantiate(providers.getMetaAccess(), box, DEFAULT_REPLACER, args); } } @@ -217,8 +218,8 @@ args.add("value", unbox.getValue()); args.addConst("valueCounter", valueCounter); - SnippetTemplate template = template(args); - Debug.log("Lowering integerValueOf in %s: node=%s, template=%s, arguments=%s", unbox.graph(), unbox, template, args); + SnippetTemplate template = template(unbox.getDebug(), args); + unbox.getDebug().log("Lowering integerValueOf in %s: node=%s, template=%s, arguments=%s", unbox.graph(), unbox, template, args); template.instantiate(providers.getMetaAccess(), unbox, DEFAULT_REPLACER, args); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java 2017-07-07 09:31:46.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java 2017-07-07 09:31:46.000000000 -0700 @@ -25,7 +25,7 @@ import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; import org.graalvm.compiler.bytecode.BytecodeProvider; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.java.GraphBuilderPhase; import org.graalvm.compiler.nodes.EncodedGraph; import org.graalvm.compiler.nodes.GraphEncoder; @@ -38,7 +38,6 @@ import org.graalvm.compiler.nodes.graphbuilderconf.LoopExplosionPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.NodePlugin; import org.graalvm.compiler.nodes.graphbuilderconf.ParameterPlugin; -import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.ConvertDeoptimizeToGuardPhase; @@ -62,9 +61,10 @@ private final EconomicMap graphCache; public CachingPEGraphDecoder(Architecture architecture, StructuredGraph graph, Providers providers, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, - AllowAssumptions allowAssumptions, OptionValues options, LoopExplosionPlugin loopExplosionPlugin, InvocationPlugins invocationPlugins, InlineInvokePlugin[] inlineInvokePlugins, - ParameterPlugin parameterPlugin, NodePlugin[] nodePlugins) { - super(architecture, graph, providers.getMetaAccess(), providers.getConstantReflection(), providers.getConstantFieldProvider(), providers.getStampProvider(), options, loopExplosionPlugin, + AllowAssumptions allowAssumptions, LoopExplosionPlugin loopExplosionPlugin, InvocationPlugins invocationPlugins, InlineInvokePlugin[] inlineInvokePlugins, + ParameterPlugin parameterPlugin, + NodePlugin[] nodePlugins) { + super(architecture, graph, providers.getMetaAccess(), providers.getConstantReflection(), providers.getConstantFieldProvider(), providers.getStampProvider(), loopExplosionPlugin, invocationPlugins, inlineInvokePlugins, parameterPlugin, nodePlugins); this.providers = providers; @@ -81,8 +81,8 @@ @SuppressWarnings("try") private EncodedGraph createGraph(ResolvedJavaMethod method, BytecodeProvider intrinsicBytecodeProvider) { - StructuredGraph graphToEncode = new StructuredGraph.Builder(options, allowAssumptions).useProfilingInfo(false).method(method).build(); - try (Debug.Scope scope = Debug.scope("createGraph", graphToEncode)) { + StructuredGraph graphToEncode = new StructuredGraph.Builder(options, debug, allowAssumptions).useProfilingInfo(false).method(method).build(); + try (DebugContext.Scope scope = debug.scope("createGraph", graphToEncode)) { IntrinsicContext initialIntrinsicContext = intrinsicBytecodeProvider != null ? new IntrinsicContext(method, method, intrinsicBytecodeProvider, INLINE_AFTER_PARSING) : null; GraphBuilderPhase.Instance graphBuilderPhaseInstance = createGraphBuilderPhaseInstance(initialIntrinsicContext); graphBuilderPhaseInstance.apply(graphToEncode); @@ -101,7 +101,7 @@ return encodedGraph; } catch (Throwable ex) { - throw Debug.handle(ex); + throw debug.handle(ex); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ConstantStringIndexOfSnippets.java 2017-07-07 09:31:47.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ConstantStringIndexOfSnippets.java 2017-07-07 09:31:47.000000000 -0700 @@ -26,6 +26,7 @@ import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.spi.LoweringTool; @@ -44,8 +45,8 @@ private final SnippetInfo indexOfConstant = snippet(ConstantStringIndexOfSnippets.class, "indexOfConstant"); - public Templates(OptionValues options, Providers providers, SnippetReflectionProvider snippetReflection, TargetDescription target) { - super(options, providers, snippetReflection, target); + public Templates(OptionValues options, Iterable factories, Providers providers, SnippetReflectionProvider snippetReflection, TargetDescription target) { + super(options, factories, providers, snippetReflection, target); } public void lower(SnippetLowerableMemoryNode stringIndexOf, LoweringTool tool) { @@ -61,7 +62,7 @@ char[] targetCharArray = snippetReflection.asObject(char[].class, stringIndexOf.getArgument(3).asJavaConstant()); args.addConst("md2", md2(targetCharArray)); args.addConst("cache", computeCache(targetCharArray)); - template(args).instantiate(providers.getMetaAccess(), stringIndexOf, DEFAULT_REPLACER, args); + template(graph.getDebug(), args).instantiate(providers.getMetaAccess(), stringIndexOf, DEFAULT_REPLACER, args); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java 2017-07-07 09:31:47.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java 2017-07-07 09:31:47.000000000 -0700 @@ -46,6 +46,7 @@ import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.TypeReference; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodeinfo.InputType; @@ -157,10 +158,10 @@ this.target = target; } - public void initialize(OptionValues options, SnippetCounter.Group.Factory factory, Providers providers, SnippetReflectionProvider snippetReflection) { - boxingSnippets = new BoxingSnippets.Templates(options, factory, providers, snippetReflection, target); - indexOfSnippets = new ConstantStringIndexOfSnippets.Templates(options, providers, snippetReflection, target); - providers.getReplacements().registerSnippetTemplateCache(new SnippetCounterNode.SnippetCounterSnippets.Templates(options, providers, snippetReflection, target)); + public void initialize(OptionValues options, Iterable factories, SnippetCounter.Group.Factory factory, Providers providers, SnippetReflectionProvider snippetReflection) { + boxingSnippets = new BoxingSnippets.Templates(options, factories, factory, providers, snippetReflection, target); + indexOfSnippets = new ConstantStringIndexOfSnippets.Templates(options, factories, providers, snippetReflection, target); + providers.getReplacements().registerSnippetTemplateCache(new SnippetCounterNode.SnippetCounterSnippets.Templates(options, factories, providers, snippetReflection, target)); } public final TargetDescription getTarget() { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/GraphKit.java 2017-07-07 09:31:48.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/GraphKit.java 2017-07-07 09:31:47.000000000 -0700 @@ -307,7 +307,7 @@ Plugins plugins = new Plugins(graphBuilderPlugins); GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(plugins); - StructuredGraph calleeGraph = new StructuredGraph.Builder(invoke.getOptions()).method(method).build(); + StructuredGraph calleeGraph = new StructuredGraph.Builder(invoke.getOptions(), invoke.getDebug()).method(method).build(); IntrinsicContext initialReplacementContext = new IntrinsicContext(method, method, providers.getReplacements().getDefaultReplacementBytecodeProvider(), INLINE_AFTER_PARSING); GraphBuilderPhase.Instance instance = new GraphBuilderPhase.Instance(metaAccess, providers.getStampProvider(), providers.getConstantReflection(), providers.getConstantFieldProvider(), config, OptimisticOptimizations.NONE, --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/InstanceOfSnippetsTemplates.java 2017-07-07 09:31:48.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/InstanceOfSnippetsTemplates.java 2017-07-07 09:31:48.000000000 -0700 @@ -28,6 +28,7 @@ import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.core.common.calc.Condition; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.ConditionAnchorNode; import org.graalvm.compiler.nodes.ConstantNode; @@ -70,8 +71,8 @@ */ public abstract class InstanceOfSnippetsTemplates extends AbstractTemplates { - public InstanceOfSnippetsTemplates(OptionValues options, Providers providers, SnippetReflectionProvider snippetReflection, TargetDescription target) { - super(options, providers, snippetReflection, target); + public InstanceOfSnippetsTemplates(OptionValues options, Iterable factories, Providers providers, SnippetReflectionProvider snippetReflection, TargetDescription target) { + super(options, factories, providers, snippetReflection, target); } /** @@ -94,7 +95,7 @@ replacer.replaceUsingInstantiation(); } else { Arguments args = makeArguments(replacer, tool); - template(args).instantiate(providers.getMetaAccess(), instanceOf, replacer, tool, args); + template(instanceOf.getDebug(), args).instantiate(providers.getMetaAccess(), instanceOf, replacer, tool, args); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/IntrinsicGraphBuilder.java 2017-07-07 09:31:48.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/IntrinsicGraphBuilder.java 2017-07-07 09:31:48.000000000 -0700 @@ -29,6 +29,7 @@ import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.StampPair; import org.graalvm.compiler.core.common.type.TypeReference; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.nodes.CallTargetNode; import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind; @@ -76,22 +77,20 @@ protected ValueNode[] arguments; protected ValueNode returnValue; - public IntrinsicGraphBuilder(OptionValues options, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantFieldProvider, - StampProvider stampProvider, - Bytecode code, int invokeBci) { - this(options, metaAccess, constantReflection, constantFieldProvider, stampProvider, code, invokeBci, AllowAssumptions.YES); + public IntrinsicGraphBuilder(OptionValues options, DebugContext debug, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantFieldProvider, + StampProvider stampProvider, Bytecode code, int invokeBci) { + this(options, debug, metaAccess, constantReflection, constantFieldProvider, stampProvider, code, invokeBci, AllowAssumptions.YES); } - protected IntrinsicGraphBuilder(OptionValues options, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantFieldProvider, - StampProvider stampProvider, - Bytecode code, int invokeBci, AllowAssumptions allowAssumptions) { + protected IntrinsicGraphBuilder(OptionValues options, DebugContext debug, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantFieldProvider, + StampProvider stampProvider, Bytecode code, int invokeBci, AllowAssumptions allowAssumptions) { this.metaAccess = metaAccess; this.constantReflection = constantReflection; this.constantFieldProvider = constantFieldProvider; this.stampProvider = stampProvider; this.code = code; this.method = code.getMethod(); - this.graph = new StructuredGraph.Builder(options, allowAssumptions).method(method).build(); + this.graph = new StructuredGraph.Builder(options, debug, allowAssumptions).method(method).build(); this.invokeBci = invokeBci; this.lastInstr = graph.start(); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java 2017-07-07 09:31:49.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java 2017-07-07 09:31:49.000000000 -0700 @@ -40,8 +40,8 @@ import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.StampPair; -import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.DebugCloseable; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; @@ -413,7 +413,6 @@ } } - protected final OptionValues options; private final LoopExplosionPlugin loopExplosionPlugin; private final InvocationPlugins invocationPlugins; private final InlineInvokePlugin[] inlineInvokePlugins; @@ -423,14 +422,14 @@ private final EconomicMap invocationPluginCache; public PEGraphDecoder(Architecture architecture, StructuredGraph graph, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantFieldProvider, - StampProvider stampProvider, OptionValues options, LoopExplosionPlugin loopExplosionPlugin, InvocationPlugins invocationPlugins, InlineInvokePlugin[] inlineInvokePlugins, - ParameterPlugin parameterPlugin, NodePlugin[] nodePlugins) { + StampProvider stampProvider, LoopExplosionPlugin loopExplosionPlugin, InvocationPlugins invocationPlugins, InlineInvokePlugin[] inlineInvokePlugins, + ParameterPlugin parameterPlugin, + NodePlugin[] nodePlugins) { super(architecture, graph, metaAccess, constantReflection, constantFieldProvider, stampProvider, true); this.loopExplosionPlugin = loopExplosionPlugin; this.invocationPlugins = invocationPlugins; this.inlineInvokePlugins = inlineInvokePlugins; this.parameterPlugin = parameterPlugin; - this.options = options; this.nodePlugins = nodePlugins; this.specialCallTargetCache = EconomicMap.create(Equivalence.DEFAULT); this.invocationPluginCache = EconomicMap.create(Equivalence.DEFAULT); @@ -449,7 +448,7 @@ decode(createInitialLoopScope(methodScope, null)); cleanupGraph(methodScope); - Debug.dump(Debug.VERBOSE_LEVEL, graph, "After graph cleanup"); + debug.dump(DebugContext.VERBOSE_LEVEL, graph, "After graph cleanup"); assert graph.verify(); try { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java 2017-07-07 09:31:49.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java 2017-07-07 09:31:49.000000000 -0700 @@ -23,14 +23,18 @@ package org.graalvm.compiler.replacements; import static org.graalvm.compiler.core.common.GraalOptions.UseSnippetGraphCache; +import static org.graalvm.compiler.debug.DebugContext.DEFAULT_LOG_STREAM; import static org.graalvm.compiler.java.BytecodeParserOptions.InlineDuringParsing; import static org.graalvm.compiler.java.BytecodeParserOptions.InlineIntrinsicsDuringParsing; import static org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo.createIntrinsicInlineInfo; import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Required; +import java.util.Collections; +import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.atomic.AtomicInteger; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.MethodSubstitution; @@ -42,11 +46,12 @@ import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode; import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; import org.graalvm.compiler.debug.DebugCloseable; -import org.graalvm.compiler.debug.DebugTimer; +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DebugContext.Description; import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.debug.TimerKey; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.Node.NodeIntrinsic; import org.graalvm.compiler.java.GraphBuilderPhase; @@ -92,6 +97,7 @@ public final SnippetReflectionProvider snippetReflection; public final TargetDescription target; private GraphBuilderConfiguration.Plugins graphBuilderPlugins; + private final DebugHandlersFactory debugHandlersFactory; @Override public OptionValues getOptions() { @@ -180,7 +186,8 @@ // it is stable across VM executions (in support of replay compilation). private final EconomicMap snippetTemplateCache; - public ReplacementsImpl(OptionValues options, Providers providers, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider, TargetDescription target) { + public ReplacementsImpl(OptionValues options, DebugHandlersFactory debugHandlersFactory, Providers providers, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider, + TargetDescription target) { this.options = options; this.providers = providers.copyWith(this); this.snippetReflection = snippetReflection; @@ -188,15 +195,26 @@ this.graphs = new ConcurrentHashMap<>(); this.snippetTemplateCache = EconomicMap.create(Equivalence.DEFAULT); this.defaultBytecodeProvider = bytecodeProvider; + this.debugHandlersFactory = debugHandlersFactory; + } - private static final DebugTimer SnippetPreparationTime = Debug.timer("SnippetPreparationTime"); + private static final TimerKey SnippetPreparationTime = DebugContext.timer("SnippetPreparationTime"); @Override public StructuredGraph getSnippet(ResolvedJavaMethod method, Object[] args) { return getSnippet(method, null, args); } + private static final AtomicInteger nextDebugContextId = new AtomicInteger(); + + protected DebugContext openDebugContext(String idPrefix, ResolvedJavaMethod method) { + DebugContext outer = DebugContext.forCurrentThread(); + Description description = new Description(method, idPrefix + nextDebugContextId.incrementAndGet()); + List factories = debugHandlersFactory == null ? Collections.emptyList() : Collections.singletonList(debugHandlersFactory); + return DebugContext.create(options, description, outer.getGlobalMetrics(), DEFAULT_LOG_STREAM, factories); + } + @Override @SuppressWarnings("try") public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod recursiveEntry, Object[] args) { @@ -205,12 +223,14 @@ StructuredGraph graph = UseSnippetGraphCache.getValue(options) ? graphs.get(method) : null; if (graph == null) { - try (DebugCloseable a = SnippetPreparationTime.start()) { - StructuredGraph newGraph = makeGraph(defaultBytecodeProvider, method, args, recursiveEntry); - Debug.counter("SnippetNodeCount[%#s]", method).add(newGraph.getNodeCount()); + try (DebugContext debug = openDebugContext("Snippet_", method); + DebugCloseable a = SnippetPreparationTime.start(debug)) { + StructuredGraph newGraph = makeGraph(debug, defaultBytecodeProvider, method, args, recursiveEntry); + DebugContext.counter("SnippetNodeCount[%#s]", method).add(newGraph.getDebug(), newGraph.getNodeCount()); if (!UseSnippetGraphCache.getValue(options) || args != null) { return newGraph; } + newGraph.freeze(); graphs.putIfAbsent(method, newGraph); graph = graphs.get(method); } @@ -256,10 +276,12 @@ ResolvedJavaMethod substitute = msPlugin.getSubstitute(metaAccess); StructuredGraph graph = graphs.get(substitute); if (graph == null) { - graph = makeGraph(msPlugin.getBytecodeProvider(), substitute, null, method); - graph.freeze(); - graphs.putIfAbsent(substitute, graph); - graph = graphs.get(substitute); + try (DebugContext debug = openDebugContext("Substitution_", method)) { + graph = makeGraph(debug, msPlugin.getBytecodeProvider(), substitute, null, method); + graph.freeze(); + graphs.putIfAbsent(substitute, graph); + graph = graphs.get(substitute); + } } assert graph.isFrozen(); result = graph; @@ -268,7 +290,9 @@ ConstantReflectionProvider constantReflection = providers.getConstantReflection(); ConstantFieldProvider constantFieldProvider = providers.getConstantFieldProvider(); StampProvider stampProvider = providers.getStampProvider(); - result = new IntrinsicGraphBuilder(options, metaAccess, constantReflection, constantFieldProvider, stampProvider, code, invokeBci).buildGraph(plugin); + try (DebugContext debug = openDebugContext("Substitution_", method)) { + result = new IntrinsicGraphBuilder(options, debug, metaAccess, constantReflection, constantFieldProvider, stampProvider, code, invokeBci).buildGraph(plugin); + } } } else { result = null; @@ -285,8 +309,8 @@ * @param original the original method if {@code method} is a {@linkplain MethodSubstitution * substitution} otherwise null */ - public StructuredGraph makeGraph(BytecodeProvider bytecodeProvider, ResolvedJavaMethod method, Object[] args, ResolvedJavaMethod original) { - return createGraphMaker(method, original).makeGraph(bytecodeProvider, args); + public StructuredGraph makeGraph(DebugContext debug, BytecodeProvider bytecodeProvider, ResolvedJavaMethod method, Object[] args, ResolvedJavaMethod original) { + return createGraphMaker(method, original).makeGraph(debug, bytecodeProvider, args); } /** @@ -323,18 +347,18 @@ } @SuppressWarnings("try") - public StructuredGraph makeGraph(BytecodeProvider bytecodeProvider, Object[] args) { - try (Scope s = Debug.scope("BuildSnippetGraph", method)) { + public StructuredGraph makeGraph(DebugContext debug, BytecodeProvider bytecodeProvider, Object[] args) { + try (DebugContext.Scope s = debug.scope("BuildSnippetGraph", method)) { assert method.hasBytecodes() : method; - StructuredGraph graph = buildInitialGraph(bytecodeProvider, method, args); + StructuredGraph graph = buildInitialGraph(debug, bytecodeProvider, method, args); finalizeGraph(graph); - Debug.dump(Debug.INFO_LEVEL, graph, "%s: Final", method.getName()); + debug.dump(DebugContext.INFO_LEVEL, graph, "%s: Final", method.getName()); return graph; } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } @@ -390,16 +414,16 @@ * Builds the initial graph for a replacement. */ @SuppressWarnings("try") - protected StructuredGraph buildInitialGraph(BytecodeProvider bytecodeProvider, final ResolvedJavaMethod methodToParse, Object[] args) { + protected StructuredGraph buildInitialGraph(DebugContext debug, BytecodeProvider bytecodeProvider, final ResolvedJavaMethod methodToParse, Object[] args) { // Replacements cannot have optimistic assumptions since they have // to be valid for the entire run of the VM. + final StructuredGraph graph = new StructuredGraph.Builder(replacements.options, debug).method(methodToParse).build(); - final StructuredGraph graph = new StructuredGraph.Builder(replacements.options).method(methodToParse).build(); - - // They are not user code so they do not participate in unsafe access tracking + // Replacements are not user code so they do not participate in unsafe access + // tracking graph.disableUnsafeAccessTracking(); - try (Scope s = Debug.scope("buildInitialGraph", graph)) { + try (DebugContext.Scope s = debug.scope("buildInitialGraph", graph)) { MetaAccessProvider metaAccess = replacements.providers.getMetaAccess(); Plugins plugins = new Plugins(replacements.graphBuilderPlugins); @@ -423,7 +447,7 @@ new CanonicalizerPhase().apply(graph, new PhaseContext(replacements.providers)); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } return graph; } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetCounterNode.java 2017-07-07 09:31:50.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetCounterNode.java 2017-07-07 09:31:50.000000000 -0700 @@ -34,6 +34,7 @@ import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.core.common.type.StampFactory; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; @@ -145,8 +146,8 @@ private final SnippetInfo add = snippet(SnippetCounterSnippets.class, "add", SNIPPET_COUNTER_LOCATION); - Templates(OptionValues options, Providers providers, SnippetReflectionProvider snippetReflection, TargetDescription target) { - super(options, providers, snippetReflection, target); + Templates(OptionValues options, Iterable factories, Providers providers, SnippetReflectionProvider snippetReflection, TargetDescription target) { + super(options, factories, providers, snippetReflection, target); } public void lower(SnippetCounterNode counter, LoweringTool tool) { @@ -155,7 +156,7 @@ args.addConst("counter", counter.getCounter()); args.add("increment", counter.getIncrement()); - template(args).instantiate(providers.getMetaAccess(), counter, DEFAULT_REPLACER, args); + template(counter.getDebug(), args).instantiate(providers.getMetaAccess(), counter, DEFAULT_REPLACER, args); } } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java 2017-07-07 09:31:50.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java 2017-07-07 09:31:50.000000000 -0700 @@ -23,8 +23,9 @@ package org.graalvm.compiler.replacements; import static java.util.FormattableFlags.ALTERNATE; -import static org.graalvm.compiler.debug.Debug.applyFormattingFlagsAndWidth; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.DebugStubsAndSnippets; +import static org.graalvm.compiler.debug.DebugContext.DEFAULT_LOG_STREAM; +import static org.graalvm.compiler.debug.DebugContext.applyFormattingFlagsAndWidth; +import static org.graalvm.compiler.debug.DebugOptions.DebugStubsAndSnippets; import static org.graalvm.compiler.graph.iterators.NodePredicates.isNotA; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED; @@ -42,6 +43,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Predicate; @@ -55,14 +57,13 @@ import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.StampPair; import org.graalvm.compiler.core.common.type.TypeReference; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; -import org.graalvm.compiler.debug.internal.DebugScope; +import org.graalvm.compiler.debug.CounterKey; import org.graalvm.compiler.debug.DebugCloseable; -import org.graalvm.compiler.debug.DebugConfig; -import org.graalvm.compiler.debug.DebugCounter; -import org.graalvm.compiler.debug.DebugTimer; +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DebugContext.Description; import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.debug.TimerKey; import org.graalvm.compiler.graph.Graph.Mark; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; @@ -227,22 +228,22 @@ * * @see SnippetTemplate#instantiationTimer */ - private final DebugTimer instantiationTimer; + private final TimerKey instantiationTimer; /** * Counts instantiations of all templates derived from this snippet. * * @see SnippetTemplate#instantiationCounter */ - private final DebugCounter instantiationCounter; + private final CounterKey instantiationCounter; protected abstract Lazy lazy(); protected SnippetInfo(ResolvedJavaMethod method, LocationIdentity[] privateLocations) { this.method = method; this.privateLocations = privateLocations; - instantiationCounter = Debug.counter("SnippetInstantiationCount[%s]", method.getName()); - instantiationTimer = Debug.timer("SnippetInstantiationTime[%s]", method.getName()); + instantiationCounter = DebugContext.counter("SnippetInstantiationCount[%s]", method.getName()); + instantiationTimer = DebugContext.timer("SnippetInstantiationTime[%s]", method.getName()); assert method.isStatic() : "snippet method must be static: " + method.format("%H.%n"); } @@ -562,8 +563,8 @@ } } - private static final DebugTimer SnippetTemplateCreationTime = Debug.timer("SnippetTemplateCreationTime"); - private static final DebugCounter SnippetTemplates = Debug.counter("SnippetTemplateCount"); + private static final TimerKey SnippetTemplateCreationTime = DebugContext.timer("SnippetTemplateCreationTime"); + private static final CounterKey SnippetTemplates = DebugContext.counter("SnippetTemplateCount"); static class Options { @Option(help = "Use a LRU cache for snippet templates.")// @@ -581,14 +582,16 @@ protected final OptionValues options; protected final Providers providers; protected final SnippetReflectionProvider snippetReflection; + protected final Iterable factories; protected final TargetDescription target; private final Map templates; - protected AbstractTemplates(OptionValues options, Providers providers, SnippetReflectionProvider snippetReflection, TargetDescription target) { + protected AbstractTemplates(OptionValues options, Iterable factories, Providers providers, SnippetReflectionProvider snippetReflection, TargetDescription target) { this.options = options; this.providers = providers; this.snippetReflection = snippetReflection; this.target = target; + this.factories = factories; if (Options.UseSnippetTemplateCache.getValue(options)) { int size = Options.MaxTemplatesPerSnippet.getValue(options); this.templates = Collections.synchronizedMap(new LRUCache<>(size, size)); @@ -627,22 +630,33 @@ } } + static final AtomicInteger nextSnippetTemplateId = new AtomicInteger(); + + private DebugContext openDebugContext(DebugContext outer, Arguments args) { + if (DebugStubsAndSnippets.getValue(options)) { + Description description = new Description(args.cacheKey.method, "SnippetTemplate_" + nextSnippetTemplateId.incrementAndGet()); + return DebugContext.create(options, description, outer.getGlobalMetrics(), DEFAULT_LOG_STREAM, factories); + } + return DebugContext.DISABLED; + } + /** * Gets a template for a given key, creating it first if necessary. */ @SuppressWarnings("try") - protected SnippetTemplate template(final Arguments args) { + protected SnippetTemplate template(DebugContext outer, final Arguments args) { SnippetTemplate template = Options.UseSnippetTemplateCache.getValue(options) && args.cacheable ? templates.get(args.cacheKey) : null; if (template == null) { - SnippetTemplates.increment(); - DebugConfig config = DebugStubsAndSnippets.getValue(options) ? DebugScope.getConfig() : Debug.silentConfig(); - try (DebugCloseable a = SnippetTemplateCreationTime.start(); Scope s = Debug.sandbox("SnippetSpecialization", config, args.info.method)) { - template = new SnippetTemplate(options, providers, snippetReflection, args); - if (Options.UseSnippetTemplateCache.getValue(options) && args.cacheable) { - templates.put(args.cacheKey, template); + try (DebugContext debug = openDebugContext(outer, args)) { + try (DebugCloseable a = SnippetTemplateCreationTime.start(debug); DebugContext.Scope s = debug.scope("SnippetSpecialization", args.info.method)) { + SnippetTemplates.increment(debug); + template = new SnippetTemplate(options, debug, providers, snippetReflection, args); + if (Options.UseSnippetTemplateCache.getValue(options) && args.cacheable) { + templates.put(args.cacheKey, template); + } + } catch (Throwable e) { + throw debug.handle(e); } - } catch (Throwable e) { - throw Debug.handle(e); } } return template; @@ -686,14 +700,14 @@ * Creates a snippet template. */ @SuppressWarnings("try") - protected SnippetTemplate(OptionValues options, final Providers providers, SnippetReflectionProvider snippetReflection, Arguments args) { + protected SnippetTemplate(OptionValues options, DebugContext debug, final Providers providers, SnippetReflectionProvider snippetReflection, Arguments args) { this.snippetReflection = snippetReflection; this.info = args.info; Object[] constantArgs = getConstantArgs(args); StructuredGraph snippetGraph = providers.getReplacements().getSnippet(args.info.method, args.info.original, constantArgs); - instantiationTimer = Debug.timer("SnippetTemplateInstantiationTime[%#s]", args); - instantiationCounter = Debug.counter("SnippetTemplateInstantiationCount[%#s]", args); + instantiationTimer = DebugContext.timer("SnippetTemplateInstantiationTime[%#s]", args); + instantiationCounter = DebugContext.counter("SnippetTemplateInstantiationCount[%#s]", args); ResolvedJavaMethod method = snippetGraph.method(); Signature signature = method.getSignature(); @@ -701,9 +715,9 @@ PhaseContext phaseContext = new PhaseContext(providers); // Copy snippet graph, replacing constant parameters with given arguments - final StructuredGraph snippetCopy = new StructuredGraph.Builder(options).name(snippetGraph.name).method(snippetGraph.method()).build(); + final StructuredGraph snippetCopy = new StructuredGraph.Builder(options, debug).name(snippetGraph.name).method(snippetGraph.method()).build(); - try (Debug.Scope scope = Debug.scope("SpecializeSnippet", snippetCopy)) { + try (DebugContext.Scope scope = debug.scope("SpecializeSnippet", snippetCopy)) { if (!snippetGraph.isUnsafeAccessTrackingEnabled()) { snippetCopy.disableUnsafeAccessTracking(); } @@ -748,7 +762,7 @@ } snippetCopy.addDuplicates(snippetGraph.getNodes(), snippetGraph, snippetGraph.getNodeCount(), nodeReplacements); - Debug.dump(Debug.INFO_LEVEL, snippetCopy, "Before specialization"); + debug.dump(DebugContext.INFO_LEVEL, snippetCopy, "Before specialization"); // Gather the template parameters parameters = new Object[parameterCount]; @@ -776,10 +790,10 @@ for (Node usage : placeholder.usages().snapshot()) { if (usage instanceof LoadIndexedNode) { LoadIndexedNode loadIndexed = (LoadIndexedNode) usage; - Debug.dump(Debug.INFO_LEVEL, snippetCopy, "Before replacing %s", loadIndexed); + debug.dump(DebugContext.INFO_LEVEL, snippetCopy, "Before replacing %s", loadIndexed); LoadSnippetVarargParameterNode loadSnippetParameter = snippetCopy.add(new LoadSnippetVarargParameterNode(params, loadIndexed.index(), loadIndexed.stamp())); snippetCopy.replaceFixedWithFixed(loadIndexed, loadSnippetParameter); - Debug.dump(Debug.INFO_LEVEL, snippetCopy, "After replacing %s", loadIndexed); + debug.dump(DebugContext.INFO_LEVEL, snippetCopy, "After replacing %s", loadIndexed); } else if (usage instanceof StoreIndexedNode) { /* * The template lowering doesn't really treat this as an array so @@ -809,10 +823,10 @@ new GuardLoweringPhase().apply(snippetCopy, null); } snippetCopy.setGuardsStage(guardsStage); - try (Scope s = Debug.scope("LoweringSnippetTemplate", snippetCopy)) { + try (DebugContext.Scope s = debug.scope("LoweringSnippetTemplate", snippetCopy)) { new LoweringPhase(new CanonicalizerPhase(), args.cacheKey.loweringStage).apply(snippetCopy, phaseContext); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } ArrayList curSideEffectNodes = new ArrayList<>(); @@ -897,7 +911,7 @@ this.memoryAnchor = null; } } - Debug.dump(Debug.INFO_LEVEL, snippet, "SnippetTemplate after fixing memory anchoring"); + debug.dump(DebugContext.INFO_LEVEL, snippet, "SnippetTemplate after fixing memory anchoring"); List returnNodes = snippet.getNodes(ReturnNode.TYPE).snapshot(); if (returnNodes.isEmpty()) { @@ -941,11 +955,14 @@ } } - Debug.counter("SnippetTemplateNodeCount[%#s]", args).add(nodes.size()); - Debug.dump(Debug.INFO_LEVEL, snippet, "SnippetTemplate final state"); + if (debug.areMetricsEnabled()) { + DebugContext.counter("SnippetTemplateNodeCount[%#s]", args).add(debug, nodes.size()); + } + debug.dump(DebugContext.INFO_LEVEL, snippet, "SnippetTemplate final state"); + this.snippet.freeze(); } catch (Throwable ex) { - throw Debug.handle(ex); + throw debug.handle(ex); } } @@ -1065,14 +1082,14 @@ * * @see SnippetInfo#instantiationTimer */ - private final DebugTimer instantiationTimer; + private final TimerKey instantiationTimer; /** * Counts instantiations of this template. * * @see SnippetInfo#instantiationCounter */ - private final DebugCounter instantiationCounter; + private final CounterKey instantiationCounter; /** * Gets the instantiation-time bindings to this template's parameters. @@ -1387,10 +1404,11 @@ */ @SuppressWarnings("try") public UnmodifiableEconomicMap instantiate(MetaAccessProvider metaAccess, FixedNode replacee, UsageReplacer replacer, Arguments args, boolean killReplacee) { + DebugContext debug = replacee.getDebug(); assert assertSnippetKills(replacee); - try (DebugCloseable a = args.info.instantiationTimer.start(); DebugCloseable b = instantiationTimer.start()) { - args.info.instantiationCounter.increment(); - instantiationCounter.increment(); + try (DebugCloseable a = args.info.instantiationTimer.start(debug); DebugCloseable b = instantiationTimer.start(debug)) { + args.info.instantiationCounter.increment(debug); + instantiationCounter.increment(debug); // Inline the snippet nodes, replacing parameters with the given args in the process StartNode entryPointNode = snippet.start(); FixedNode firstCFGNode = entryPointNode.next(); @@ -1398,7 +1416,7 @@ EconomicMap replacements = bind(replaceeGraph, metaAccess, args); replacements.put(entryPointNode, AbstractBeginNode.prevBegin(replacee)); UnmodifiableEconomicMap duplicates = replaceeGraph.addDuplicates(nodes, snippet, snippet.getNodeCount(), replacements); - Debug.dump(Debug.DETAILED_LEVEL, replaceeGraph, "After inlining snippet %s", snippet.method()); + debug.dump(DebugContext.DETAILED_LEVEL, replaceeGraph, "After inlining snippet %s", snippet.method()); // Re-wire the control flow graph around the replacee FixedNode firstCFGNodeDuplicate = (FixedNode) duplicates.get(firstCFGNode); @@ -1486,7 +1504,7 @@ GraphUtil.killCFG(replacee); } - Debug.dump(Debug.DETAILED_LEVEL, replaceeGraph, "After lowering %s with %s", replacee, this); + debug.dump(DebugContext.DETAILED_LEVEL, replaceeGraph, "After lowering %s with %s", replacee, this); return duplicates; } } @@ -1524,8 +1542,8 @@ /** * Gets a copy of the specialized graph. */ - public StructuredGraph copySpecializedGraph() { - return (StructuredGraph) snippet.copy(); + public StructuredGraph copySpecializedGraph(DebugContext debugForCopy) { + return (StructuredGraph) snippet.copy(debugForCopy); } /** @@ -1539,10 +1557,11 @@ */ @SuppressWarnings("try") public void instantiate(MetaAccessProvider metaAccess, FloatingNode replacee, UsageReplacer replacer, LoweringTool tool, Arguments args) { + DebugContext debug = replacee.getDebug(); assert assertSnippetKills(replacee); - try (DebugCloseable a = args.info.instantiationTimer.start()) { - args.info.instantiationCounter.increment(); - instantiationCounter.increment(); + try (DebugCloseable a = args.info.instantiationTimer.start(debug)) { + args.info.instantiationCounter.increment(debug); + instantiationCounter.increment(debug); // Inline the snippet nodes, replacing parameters with the given args in the process StartNode entryPointNode = snippet.start(); @@ -1551,7 +1570,7 @@ EconomicMap replacements = bind(replaceeGraph, metaAccess, args); replacements.put(entryPointNode, tool.getCurrentGuardAnchor().asNode()); UnmodifiableEconomicMap duplicates = replaceeGraph.addDuplicates(nodes, snippet, snippet.getNodeCount(), replacements); - Debug.dump(Debug.DETAILED_LEVEL, replaceeGraph, "After inlining snippet %s", snippet.method()); + debug.dump(DebugContext.DETAILED_LEVEL, replaceeGraph, "After inlining snippet %s", snippet.method()); FixedWithNextNode lastFixedNode = tool.lastFixedNode(); assert lastFixedNode != null && lastFixedNode.isAlive() : replaceeGraph + " lastFixed=" + lastFixedNode; @@ -1575,7 +1594,7 @@ returnDuplicate.replaceAndDelete(next); } - Debug.dump(Debug.DETAILED_LEVEL, replaceeGraph, "After lowering %s with %s", replacee, this); + debug.dump(DebugContext.DETAILED_LEVEL, replaceeGraph, "After lowering %s with %s", replacee, this); } } @@ -1591,10 +1610,11 @@ */ @SuppressWarnings("try") public void instantiate(MetaAccessProvider metaAccess, FloatingNode replacee, UsageReplacer replacer, Arguments args) { + DebugContext debug = replacee.getDebug(); assert assertSnippetKills(replacee); - try (DebugCloseable a = args.info.instantiationTimer.start()) { - args.info.instantiationCounter.increment(); - instantiationCounter.increment(); + try (DebugCloseable a = args.info.instantiationTimer.start(debug)) { + args.info.instantiationCounter.increment(debug); + instantiationCounter.increment(debug); // Inline the snippet nodes, replacing parameters with the given args in the process StartNode entryPointNode = snippet.start(); @@ -1613,7 +1633,7 @@ } } UnmodifiableEconomicMap duplicates = replaceeGraph.addDuplicates(floatingNodes, snippet, floatingNodes.size(), replacements); - Debug.dump(Debug.DETAILED_LEVEL, replaceeGraph, "After inlining snippet %s", snippet.method()); + debug.dump(DebugContext.DETAILED_LEVEL, replaceeGraph, "After inlining snippet %s", snippet.method()); rewireFrameStates(replacee, duplicates); updateStamps(replacee, duplicates); @@ -1625,7 +1645,7 @@ ValueNode returnValue = (ValueNode) duplicates.get(returnNode.result()); replacer.replace(replacee, returnValue); - Debug.dump(Debug.DETAILED_LEVEL, replaceeGraph, "After lowering %s with %s", replacee, this); + debug.dump(DebugContext.DETAILED_LEVEL, replaceeGraph, "After lowering %s with %s", replacee, this); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java 2017-07-07 09:31:51.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java 2017-07-07 09:31:50.000000000 -0700 @@ -29,7 +29,7 @@ import static org.graalvm.word.LocationIdentity.any; import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.NodeInputList; import org.graalvm.compiler.nodeinfo.NodeInfo; @@ -218,8 +218,9 @@ tool.setVirtualEntry(destVirtual, destPosInt + i, tool.getEntry(srcVirtual, srcPosInt + i), false); } tool.delete(); - if (Debug.isLogEnabled()) { - Debug.log("virtualized arraycopyf(%s, %d, %s, %d, %d)", getSource(), srcPosInt, getDestination(), destPosInt, len); + DebugContext debug = getDebug(); + if (debug.isLogEnabled()) { + debug.log("virtualized arraycopy(%s, %d, %s, %d, %d)", getSource(), srcPosInt, getDestination(), destPosInt, len); } } else { ResolvedJavaType sourceType = StampTool.typeOrNull(srcAlias); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroNode.java 2017-07-07 09:31:51.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroNode.java 2017-07-07 09:31:51.000000000 -0700 @@ -22,15 +22,14 @@ */ package org.graalvm.compiler.replacements.nodes; +import static jdk.vm.ci.code.BytecodeFrame.isPlaceholderBci; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_UNKNOWN; -import static jdk.vm.ci.code.BytecodeFrame.isPlaceholderBci; import org.graalvm.compiler.api.replacements.MethodSubstitution; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.core.common.type.StampPair; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.NodeInputList; @@ -149,10 +148,11 @@ new FrameStateAssignmentPhase().apply(replacementGraph); } } - try (Scope s = Debug.scope("LoweringSnippetTemplate", replacementGraph)) { + DebugContext debug = replacementGraph.getDebug(); + try (DebugContext.Scope s = debug.scope("LoweringSnippetTemplate", replacementGraph)) { new LoweringPhase(new CanonicalizerPhase(), tool.getLoweringStage()).apply(replacementGraph, c); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } return replacementGraph; } @@ -174,7 +174,7 @@ } } InliningUtil.inline(invoke, replacementGraph, false, targetMethod); - Debug.dump(Debug.DETAILED_LEVEL, graph(), "After inlining replacement %s", replacementGraph); + replacementGraph.getDebug().dump(DebugContext.DETAILED_LEVEL, graph(), "After inlining replacement %s", replacementGraph); } else { if (isPlaceholderBci(invoke.bci())) { throw new GraalError("%s: cannot lower to invoke with placeholder BCI: %s", graph(), this); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/GraalTest.java 2017-07-07 09:31:51.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/GraalTest.java 2017-07-07 09:31:51.000000000 -0700 @@ -22,12 +22,25 @@ */ package org.graalvm.compiler.test; +import static org.graalvm.compiler.debug.DebugContext.DEFAULT_LOG_STREAM; +import static org.graalvm.compiler.debug.DebugContext.NO_DESCRIPTION; +import static org.graalvm.compiler.debug.DebugContext.NO_GLOBAL_METRIC_VALUES; + import java.io.PrintStream; import java.io.PrintWriter; import java.lang.reflect.Field; import java.lang.reflect.Method; +import java.util.ArrayList; import java.util.Arrays; - +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DebugDumpHandler; +import org.graalvm.compiler.options.OptionValues; +import org.junit.After; import org.junit.Assert; import org.junit.internal.ComparisonCriteria; import org.junit.internal.ExactComparisonCriteria; @@ -365,4 +378,44 @@ public static void assertFalse(boolean condition, String message, Object... objects) { assertTrue(!condition, message, objects); } + + /** + * Gets the {@link DebugHandlersFactory}s available for a {@link DebugContext}. + */ + protected Collection getDebugHandlersFactories() { + return Collections.emptyList(); + } + + /** + * Gets a {@link DebugContext} object corresponding to {@code options}, creating a new one if + * none currently exists. Debug contexts created by this method will have their + * {@link DebugDumpHandler}s closed in {@link #afterTest()}. + */ + protected DebugContext getDebugContext(OptionValues options) { + List cached = cachedDebugs.get(); + if (cached == null) { + cached = new ArrayList<>(); + cachedDebugs.set(cached); + } + for (DebugContext debug : cached) { + if (debug.getOptions() == options) { + return debug; + } + } + DebugContext debug = DebugContext.create(options, NO_DESCRIPTION, NO_GLOBAL_METRIC_VALUES, DEFAULT_LOG_STREAM, getDebugHandlersFactories()); + cached.add(debug); + return debug; + } + + private final ThreadLocal> cachedDebugs = new ThreadLocal<>(); + + @After + public void afterTest() { + List cached = cachedDebugs.get(); + if (cached != null) { + for (DebugContext debug : cached) { + debug.closeDumpHandlers(true); + } + } + } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectList.java 2017-07-07 09:31:52.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectList.java 2017-07-07 09:31:52.000000000 -0700 @@ -27,7 +27,7 @@ import java.util.Arrays; import java.util.Iterator; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.StructuredGraph; @@ -62,10 +62,15 @@ private static final Effect[] EMPTY_ARRAY = new Effect[0]; private static final String[] EMPTY_STRING_ARRAY = new String[0]; + private final DebugContext debug; private Effect[] effects = EMPTY_ARRAY; private String[] names = EMPTY_STRING_ARRAY; private int size; + public EffectList(DebugContext debug) { + this.debug = debug; + } + private void enlarge(int elements) { int length = effects.length; if (size + elements > length) { @@ -73,7 +78,7 @@ length = Math.max(length * 2, 4); } effects = Arrays.copyOf(effects, length); - if (Debug.isEnabled()) { + if (debug.isLogEnabled()) { names = Arrays.copyOf(names, length); } } @@ -86,7 +91,7 @@ public void add(String name, Effect effect) { assert effect != null; enlarge(1); - if (Debug.isEnabled()) { + if (debug.isLogEnabled()) { names[size] = name; } effects[size++] = effect; @@ -95,7 +100,7 @@ public void addAll(EffectList list) { enlarge(list.size); System.arraycopy(list.effects, 0, effects, size, list.size); - if (Debug.isEnabled()) { + if (debug.isLogEnabled()) { System.arraycopy(list.names, 0, names, size, list.size); } size += list.size; @@ -106,7 +111,7 @@ enlarge(list.size); System.arraycopy(effects, position, effects, position + list.size, size - position); System.arraycopy(list.effects, 0, effects, position, list.size); - if (Debug.isEnabled()) { + if (debug.isLogEnabled()) { System.arraycopy(names, position, names, position + list.size, size - position); System.arraycopy(list.names, 0, names, position, list.size); } @@ -176,10 +181,10 @@ toString(str, i); throw new GraalError(t).addContext("effect", str); } - if (effect.isVisible() && Debug.isLogEnabled()) { + if (effect.isVisible() && debug.isLogEnabled()) { StringBuilder str = new StringBuilder(); toString(str, i); - Debug.log(" %s", str); + debug.log(" %s", str); } } } @@ -227,7 +232,7 @@ } private String getName(int i) { - if (Debug.isEnabled()) { + if (debug.isLogEnabled()) { return names[i]; } else { return ""; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsClosure.java 2017-07-07 09:31:52.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsClosure.java 2017-07-07 09:31:52.000000000 -0700 @@ -28,7 +28,7 @@ import org.graalvm.compiler.core.common.cfg.BlockMap; import org.graalvm.compiler.core.common.cfg.Loop; import org.graalvm.compiler.core.common.type.Stamp; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.graph.Node; @@ -59,10 +59,10 @@ import org.graalvm.compiler.phases.graph.ReentrantBlockIterator; import org.graalvm.compiler.phases.graph.ReentrantBlockIterator.BlockIteratorClosure; import org.graalvm.compiler.phases.graph.ReentrantBlockIterator.LoopInfo; -import org.graalvm.util.Equivalence; -import org.graalvm.word.LocationIdentity; import org.graalvm.util.EconomicMap; import org.graalvm.util.EconomicSet; +import org.graalvm.util.Equivalence; +import org.graalvm.word.LocationIdentity; public abstract class EffectsClosure> extends EffectsPhase.Closure { @@ -112,6 +112,7 @@ protected final EconomicMap, LoopKillCache> loopLocationKillCache = EconomicMap.create(Equivalence.IDENTITY); protected boolean changed; + protected final DebugContext debug; public EffectsClosure(ScheduleResult schedule, ControlFlowGraph cfg) { this.schedule = schedule; @@ -119,8 +120,9 @@ this.aliases = cfg.graph.createNodeMap(); this.hasScalarReplacedInputs = cfg.graph.createNodeBitMap(); this.blockEffects = new BlockMap<>(cfg); + this.debug = cfg.graph.getDebug(); for (Block block : cfg.getBlocks()) { - blockEffects.put(block, new GraphEffectList()); + blockEffects.put(block, new GraphEffectList(debug)); } } @@ -182,7 +184,7 @@ }; ReentrantBlockIterator.apply(closure, cfg.getStartBlock()); for (GraphEffectList effects : effectList) { - Debug.log(" ==== effects"); + debug.log(" ==== effects"); effects.apply(graph, obsoleteNodes, false); } /* @@ -191,10 +193,10 @@ * indexes. */ for (GraphEffectList effects : effectList) { - Debug.log(" ==== cfg kill effects"); + debug.log(" ==== cfg kill effects"); effects.apply(graph, obsoleteNodes, true); } - Debug.dump(Debug.DETAILED_LEVEL, graph, "After applying effects"); + debug.dump(DebugContext.DETAILED_LEVEL, graph, "After applying effects"); assert VirtualUtil.assertNonReachable(graph, obsoleteNodes); for (Node node : obsoleteNodes) { if (node.isAlive() && node.hasNoUsages()) { @@ -233,7 +235,7 @@ } OptionValues options = block.getBeginNode().getOptions(); - VirtualUtil.trace(options, "\nBlock: %s, preds: %s, succ: %s (", block, block.getPredecessors(), block.getSuccessors()); + VirtualUtil.trace(options, debug, "\nBlock: %s, preds: %s, succ: %s (", block, block.getPredecessors(), block.getSuccessors()); // a lastFixedNode is needed in case we want to insert fixed nodes FixedWithNextNode lastFixedNode = null; @@ -257,7 +259,7 @@ break; } } - VirtualUtil.trace(options, ")\n end state: %s\n", state); + VirtualUtil.trace(options, debug, ")\n end state: %s\n", state); } return state; } @@ -329,7 +331,7 @@ * more generic, e.g., adding phis instead of non-phi values. */ for (int iteration = 0; iteration < 10; iteration++) { - try (Indent i = Debug.logAndIndent("================== Process Loop Effects Closure: block:%s begin node:%s", loop.getHeader(), loop.getHeader().getBeginNode())) { + try (Indent i = debug.logAndIndent("================== Process Loop Effects Closure: block:%s begin node:%s", loop.getHeader(), loop.getHeader().getBeginNode())) { LoopInfo info = ReentrantBlockIterator.processLoop(this, loop, cloneState(lastMergedState)); List states = new ArrayList<>(); @@ -337,9 +339,9 @@ states.addAll(info.endStates); doMergeWithoutDead(mergeProcessor, states); - Debug.log("MergeProcessor New State: %s", mergeProcessor.newState); - Debug.log("===== vs."); - Debug.log("Last Merged State: %s", lastMergedState); + debug.log("MergeProcessor New State: %s", mergeProcessor.newState); + debug.log("===== vs."); + debug.log("Last Merged State: %s", lastMergedState); if (mergeProcessor.newState.equivalentTo(lastMergedState)) { blockEffects.get(loop.getHeader()).insertAll(mergeProcessor.mergeEffects, 0); @@ -441,8 +443,8 @@ public MergeProcessor(Block mergeBlock) { this.mergeBlock = mergeBlock; this.merge = (AbstractMergeNode) mergeBlock.getBeginNode(); - this.mergeEffects = new GraphEffectList(); - this.afterMergeEffects = new GraphEffectList(); + this.mergeEffects = new GraphEffectList(debug); + this.afterMergeEffects = new GraphEffectList(debug); } /** --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsPhase.java 2017-07-07 09:31:53.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsPhase.java 2017-07-07 09:31:53.000000000 -0700 @@ -22,12 +22,10 @@ */ package org.graalvm.compiler.virtual.phases.ea; -import static org.graalvm.compiler.debug.Debug.isEnabled; import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Required; import org.graalvm.compiler.core.common.util.CompilationAlarm; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Graph.NodeEventScope; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.spi.Simplifiable; @@ -77,8 +75,9 @@ public boolean runAnalysis(StructuredGraph graph, PhaseContextT context) { boolean changed = false; CompilationAlarm compilationAlarm = CompilationAlarm.current(); + DebugContext debug = graph.getDebug(); for (int iteration = 0; iteration < maxIterations && !compilationAlarm.hasExpired(); iteration++) { - try (Scope s = Debug.scope(isEnabled() ? "iteration " + iteration : null)) { + try (DebugContext.Scope s = debug.scope(debug.areScopesEnabled() ? "iteration " + iteration : null)) { ScheduleResult schedule; ControlFlowGraph cfg; if (unscheduled) { @@ -89,7 +88,7 @@ schedule = graph.getLastSchedule(); cfg = schedule.getCFG(); } - try (Scope scheduleScope = Debug.scope("EffectsPhaseWithSchedule", schedule)) { + try (DebugContext.Scope scheduleScope = debug.scope("EffectsPhaseWithSchedule", schedule)) { Closure closure = createEffectsClosure(context, schedule, cfg); ReentrantBlockIterator.apply(closure, cfg.getStartBlock()); @@ -100,8 +99,8 @@ closure.applyEffects(); } - if (Debug.isDumpEnabled(Debug.INFO_LEVEL)) { - Debug.dump(Debug.DETAILED_LEVEL, graph, "%s iteration", getName()); + if (debug.isDumpEnabled(DebugContext.INFO_LEVEL)) { + debug.dump(DebugContext.DETAILED_LEVEL, graph, "%s iteration", getName()); } new DeadCodeEliminationPhase(Required).apply(graph); @@ -121,7 +120,7 @@ break; } } catch (Throwable t) { - throw Debug.handle(t); + throw debug.handle(t); } } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/GraphEffectList.java 2017-07-07 09:31:53.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/GraphEffectList.java 2017-07-07 09:31:53.000000000 -0700 @@ -24,6 +24,7 @@ import java.util.ArrayList; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.ControlSinkNode; import org.graalvm.compiler.nodes.FixedNode; @@ -43,6 +44,10 @@ public final class GraphEffectList extends EffectList { + public GraphEffectList(DebugContext debug) { + super(debug); + } + /** * Determines how many objects are virtualized (positive) or materialized (negative) by this * effect. --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ObjectState.java 2017-07-07 09:31:53.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ObjectState.java 2017-07-07 09:31:53.000000000 -0700 @@ -25,8 +25,8 @@ import java.util.Arrays; import java.util.List; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.java.MonitorIdNode; import org.graalvm.compiler.nodes.virtual.EscapeObjectState; @@ -44,8 +44,8 @@ */ public class ObjectState { - public static final DebugCounter CREATE_ESCAPED_OBJECT_STATE = Debug.counter("CreateEscapeObjectState"); - public static final DebugCounter GET_ESCAPED_OBJECT_STATE = Debug.counter("GetEscapeObjectState"); + public static final CounterKey CREATE_ESCAPED_OBJECT_STATE = DebugContext.counter("CreateEscapeObjectState"); + public static final CounterKey GET_ESCAPED_OBJECT_STATE = DebugContext.counter("GetEscapeObjectState"); private ValueNode[] entries; private ValueNode materializedValue; @@ -92,10 +92,10 @@ return new ObjectState(this); } - public EscapeObjectState createEscapeObjectState(VirtualObjectNode virtual) { - GET_ESCAPED_OBJECT_STATE.increment(); + public EscapeObjectState createEscapeObjectState(DebugContext debug, VirtualObjectNode virtual) { + GET_ESCAPED_OBJECT_STATE.increment(debug); if (cachedState == null) { - CREATE_ESCAPED_OBJECT_STATE.increment(); + CREATE_ESCAPED_OBJECT_STATE.increment(debug); if (isVirtual()) { /* * Clear out entries that are default values anyway. --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationBlockState.java 2017-07-07 09:31:54.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationBlockState.java 2017-07-07 09:31:54.000000000 -0700 @@ -25,6 +25,7 @@ import java.util.Iterator; import java.util.List; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.FieldLocationIdentity; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.virtual.AllocatedObjectNode; @@ -73,8 +74,8 @@ } } - public PEReadEliminationBlockState(OptionValues options) { - super(options); + public PEReadEliminationBlockState(OptionValues options, DebugContext debug) { + super(options, debug); readCache = EconomicMap.create(Equivalence.DEFAULT); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationClosure.java 2017-07-07 09:31:54.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationClosure.java 2017-07-07 09:31:54.000000000 -0700 @@ -31,8 +31,8 @@ import org.graalvm.compiler.core.common.cfg.Loop; import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; -import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.nodes.AbstractBeginNode; import org.graalvm.compiler.nodes.FieldLocationIdentity; import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.FixedWithNextNode; @@ -45,9 +45,9 @@ import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.ValueProxyNode; import org.graalvm.compiler.nodes.cfg.Block; -import org.graalvm.compiler.nodes.extended.UnboxNode; import org.graalvm.compiler.nodes.extended.RawLoadNode; import org.graalvm.compiler.nodes.extended.RawStoreNode; +import org.graalvm.compiler.nodes.extended.UnboxNode; import org.graalvm.compiler.nodes.java.ArrayLengthNode; import org.graalvm.compiler.nodes.java.LoadFieldNode; import org.graalvm.compiler.nodes.java.LoadIndexedNode; @@ -91,7 +91,7 @@ @Override protected PEReadEliminationBlockState getInitialState() { - return new PEReadEliminationBlockState(tool.getOptions()); + return new PEReadEliminationBlockState(tool.getOptions(), tool.getDebug()); } @Override @@ -117,11 +117,11 @@ } else if (node instanceof RawStoreNode) { return processUnsafeStore((RawStoreNode) node, state, effects); } else if (node instanceof MemoryCheckpoint.Single) { - COUNTER_MEMORYCHECKPOINT.increment(); + COUNTER_MEMORYCHECKPOINT.increment(node.getDebug()); LocationIdentity identity = ((MemoryCheckpoint.Single) node).getLocationIdentity(); processIdentity(state, identity); } else if (node instanceof MemoryCheckpoint.Multi) { - COUNTER_MEMORYCHECKPOINT.increment(); + COUNTER_MEMORYCHECKPOINT.increment(node.getDebug()); for (LocationIdentity identity : ((MemoryCheckpoint.Multi) node).getLocationIdentities()) { processIdentity(state, identity); } @@ -426,7 +426,8 @@ loopKilledLocations = new LoopKillCache(1/* 1.visit */); loopLocationKillCache.put(loop, loopKilledLocations); } else { - OptionValues options = loop.getHeader().getBeginNode().getOptions(); + AbstractBeginNode beginNode = loop.getHeader().getBeginNode(); + OptionValues options = beginNode.getOptions(); if (loopKilledLocations.visits() > ReadEliminationMaxLoopVisits.getValue(options)) { // we have processed the loop too many times, kill all locations so the inner // loop will never be processed more than once again on visit @@ -445,9 +446,9 @@ for (LocationIdentity location : forwardEndLiveLocations) { loopKilledLocations.rememberLoopKilledLocation(location); } - if (Debug.isLogEnabled() && loopKilledLocations != null) { - Debug.log("[Early Read Elimination] Setting loop killed locations of loop at node %s with %s", - loop.getHeader().getBeginNode(), forwardEndLiveLocations); + if (debug.isLogEnabled() && loopKilledLocations != null) { + debug.log("[Early Read Elimination] Setting loop killed locations of loop at node %s with %s", + beginNode, forwardEndLiveLocations); } } // remember the loop visit --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapeBlockState.java 2017-07-07 09:31:55.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapeBlockState.java 2017-07-07 09:31:55.000000000 -0700 @@ -28,6 +28,7 @@ import java.util.List; import java.util.Map; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.FixedWithNextNode; @@ -63,6 +64,7 @@ private RefCount arrayRefCount; private final OptionValues options; + private final DebugContext debug; /** * Final subclass of PartialEscapeBlockState, for performance and to make everything behave @@ -70,8 +72,8 @@ */ public static final class Final extends PartialEscapeBlockState { - public Final(OptionValues options) { - super(options); + public Final(OptionValues options, DebugContext debug) { + super(options, debug); } public Final(Final other) { @@ -79,16 +81,18 @@ } } - protected PartialEscapeBlockState(OptionValues options) { + protected PartialEscapeBlockState(OptionValues options, DebugContext debug) { objectStates = EMPTY_ARRAY; arrayRefCount = new RefCount(); this.options = options; + this.debug = debug; } protected PartialEscapeBlockState(PartialEscapeBlockState other) { super(other); adoptAddObjectStates(other); options = other.options; + debug = other.debug; } public ObjectState getObjectState(int object) { @@ -169,14 +173,13 @@ * entries. */ public void materializeBefore(FixedNode fixed, VirtualObjectNode virtual, GraphEffectList materializeEffects) { - PartialEscapeClosure.COUNTER_MATERIALIZATIONS.increment(); + PartialEscapeClosure.COUNTER_MATERIALIZATIONS.increment(fixed.getDebug()); List objects = new ArrayList<>(2); List values = new ArrayList<>(8); List> locks = new ArrayList<>(); List otherAllocations = new ArrayList<>(2); List ensureVirtual = new ArrayList<>(2); materializeWithCommit(fixed, virtual, objects, locks, values, ensureVirtual, otherAllocations); - assert fixed != null; materializeEffects.addVirtualizationDelta(-(objects.size() + otherAllocations.size())); materializeEffects.add("materializeBefore", new Effect() { @@ -255,14 +258,14 @@ } objectMaterialized(virtual, (AllocatedObjectNode) representation, values.subList(pos, pos + entries.length)); } else { - VirtualUtil.trace(options, "materialized %s as %s", virtual, representation); + VirtualUtil.trace(options, debug, "materialized %s as %s", virtual, representation); otherAllocations.add(representation); assert obj.getLocks() == null; } } protected void objectMaterialized(VirtualObjectNode virtual, AllocatedObjectNode representation, List values) { - VirtualUtil.trace(options, "materialized %s as %s with values %s", virtual, representation, values); + VirtualUtil.trace(options, debug, "materialized %s as %s with values %s", virtual, representation, values); } public void addObject(int virtual, ObjectState state) { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapeClosure.java 2017-07-07 09:31:55.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapeClosure.java 2017-07-07 09:31:55.000000000 -0700 @@ -33,8 +33,8 @@ import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeBitMap; import org.graalvm.compiler.graph.Position; @@ -78,14 +78,14 @@ public abstract class PartialEscapeClosure> extends EffectsClosure { - public static final DebugCounter COUNTER_MATERIALIZATIONS = Debug.counter("Materializations"); - public static final DebugCounter COUNTER_MATERIALIZATIONS_PHI = Debug.counter("MaterializationsPhi"); - public static final DebugCounter COUNTER_MATERIALIZATIONS_MERGE = Debug.counter("MaterializationsMerge"); - public static final DebugCounter COUNTER_MATERIALIZATIONS_UNHANDLED = Debug.counter("MaterializationsUnhandled"); - public static final DebugCounter COUNTER_MATERIALIZATIONS_LOOP_REITERATION = Debug.counter("MaterializationsLoopReiteration"); - public static final DebugCounter COUNTER_MATERIALIZATIONS_LOOP_END = Debug.counter("MaterializationsLoopEnd"); - public static final DebugCounter COUNTER_ALLOCATION_REMOVED = Debug.counter("AllocationsRemoved"); - public static final DebugCounter COUNTER_MEMORYCHECKPOINT = Debug.counter("MemoryCheckpoint"); + public static final CounterKey COUNTER_MATERIALIZATIONS = DebugContext.counter("Materializations"); + public static final CounterKey COUNTER_MATERIALIZATIONS_PHI = DebugContext.counter("MaterializationsPhi"); + public static final CounterKey COUNTER_MATERIALIZATIONS_MERGE = DebugContext.counter("MaterializationsMerge"); + public static final CounterKey COUNTER_MATERIALIZATIONS_UNHANDLED = DebugContext.counter("MaterializationsUnhandled"); + public static final CounterKey COUNTER_MATERIALIZATIONS_LOOP_REITERATION = DebugContext.counter("MaterializationsLoopReiteration"); + public static final CounterKey COUNTER_MATERIALIZATIONS_LOOP_END = DebugContext.counter("MaterializationsLoopEnd"); + public static final CounterKey COUNTER_ALLOCATION_REMOVED = DebugContext.counter("AllocationsRemoved"); + public static final CounterKey COUNTER_MEMORYCHECKPOINT = DebugContext.counter("MemoryCheckpoint"); /** * Nodes with inputs that were modified during analysis are marked in this bitset - this way @@ -102,6 +102,7 @@ * The indexes into this array correspond to {@link VirtualObjectNode#getObjectId()}. */ public final ArrayList virtualObjects = new ArrayList<>(); + public final DebugContext debug; @Override public boolean needsApplyEffects() { @@ -171,7 +172,7 @@ @Override protected PartialEscapeBlockState.Final getInitialState() { - return new PartialEscapeBlockState.Final(tool.getOptions()); + return new PartialEscapeBlockState.Final(tool.getOptions(), tool.getDebug()); } @Override @@ -189,7 +190,8 @@ super(schedule, schedule.getCFG()); StructuredGraph graph = schedule.getCFG().graph; this.hasVirtualInputs = graph.createNodeBitMap(); - this.tool = new VirtualizerToolImpl(metaAccess, constantReflection, constantFieldProvider, this, graph.getAssumptions(), graph.getOptions(), loweringProvider); + this.debug = graph.getDebug(); + this.tool = new VirtualizerToolImpl(metaAccess, constantReflection, constantFieldProvider, this, graph.getAssumptions(), graph.getOptions(), debug, loweringProvider); } /** @@ -212,14 +214,14 @@ private boolean processNodeInternal(Node node, BlockT state, GraphEffectList effects, FixedWithNextNode lastFixedNode) { FixedNode nextFixedNode = lastFixedNode == null ? null : lastFixedNode.next(); - VirtualUtil.trace(node.getOptions(), "%s", node); + VirtualUtil.trace(node.getOptions(), debug, "%s", node); if (requiresProcessing(node)) { if (processVirtualizable((ValueNode) node, nextFixedNode, state, effects) == false) { return false; } if (tool.isDeleted()) { - VirtualUtil.trace(node.getOptions(), "deleted virtualizable allocation %s", node); + VirtualUtil.trace(node.getOptions(), debug, "deleted virtualizable allocation %s", node); return true; } } @@ -229,7 +231,7 @@ return false; } if (tool.isDeleted()) { - VirtualUtil.trace(node.getOptions(), "deleted virtualizable node %s", node); + VirtualUtil.trace(node.getOptions(), debug, "deleted virtualizable node %s", node); return true; } } @@ -296,7 +298,7 @@ } } else { if (!prepareCanonicalNode(canonicalizedValue, state, effects)) { - VirtualUtil.trace(node.getOptions(), "replacement via canonicalization too complex: %s -> %s", node, canonicalizedValue); + VirtualUtil.trace(node.getOptions(), debug, "replacement via canonicalization too complex: %s -> %s", node, canonicalizedValue); return false; } if (canonicalizedValue instanceof ControlSinkNode) { @@ -307,7 +309,7 @@ addScalarAlias(node, canonicalizedValue); } } - VirtualUtil.trace(node.getOptions(), "replaced via canonicalization: %s -> %s", node, canonicalizedValue); + VirtualUtil.trace(node.getOptions(), debug, "replaced via canonicalization: %s -> %s", node, canonicalizedValue); return true; } return false; @@ -350,7 +352,7 @@ * {@link VirtualObjectState}. */ private void processNodeInputs(ValueNode node, FixedNode insertBefore, BlockT state, GraphEffectList effects) { - VirtualUtil.trace(node.getOptions(), "processing nodewithstate: %s", node); + VirtualUtil.trace(node.getOptions(), debug, "processing nodewithstate: %s", node); for (Node input : node.inputs()) { if (input instanceof ValueNode) { ValueNode alias = getAlias((ValueNode) input); @@ -358,7 +360,7 @@ int id = ((VirtualObjectNode) alias).getObjectId(); ensureMaterialized(state, id, insertBefore, effects, COUNTER_MATERIALIZATIONS_UNHANDLED); effects.replaceFirstInput(node, input, state.getObjectState(id).getMaterializedValue()); - VirtualUtil.trace(node.getOptions(), "replacing input %s at %s", input, node); + VirtualUtil.trace(node.getOptions(), debug, "replacing input %s at %s", input, node); } } } @@ -390,7 +392,7 @@ private void addVirtualMappings(FrameState frameState, EconomicSet virtual, BlockT state, GraphEffectList effects) { for (VirtualObjectNode obj : virtual) { - effects.addVirtualMapping(frameState, state.getObjectState(obj).createEscapeObjectState(obj)); + effects.addVirtualMapping(frameState, state.getObjectState(obj).createEscapeObjectState(debug, obj)); } } @@ -427,9 +429,9 @@ /** * @return true if materialization happened, false if not. */ - protected boolean ensureMaterialized(PartialEscapeBlockState state, int object, FixedNode materializeBefore, GraphEffectList effects, DebugCounter counter) { + protected boolean ensureMaterialized(PartialEscapeBlockState state, int object, FixedNode materializeBefore, GraphEffectList effects, CounterKey counter) { if (state.getObjectState(object).isVirtual()) { - counter.increment(); + counter.increment(debug); VirtualObjectNode virtual = virtualObjects.get(object); state.materializeBefore(materializeBefore, virtual, effects); assert !updateStatesForMaterialized(state, virtual, state.getObjectState(object).getMaterializedValue()) : "method must already have been called before"; @@ -566,7 +568,7 @@ exitState.updateMaterializedValue(object, proxy); } else { if (initialObjState.getMaterializedValue() != exitObjState.getMaterializedValue()) { - Debug.log("materialized value changes within loop: %s vs. %s at %s", initialObjState.getMaterializedValue(), exitObjState.getMaterializedValue(), exitNode); + exitNode.getDebug().log("materialized value changes within loop: %s vs. %s at %s", initialObjState.getMaterializedValue(), exitObjState.getMaterializedValue(), exitNode); } } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationClosure.java 2017-07-07 09:31:56.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationClosure.java 2017-07-07 09:31:56.000000000 -0700 @@ -30,7 +30,6 @@ import org.graalvm.compiler.core.common.cfg.Loop; import org.graalvm.compiler.core.common.type.Stamp; -import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.FieldLocationIdentity; import org.graalvm.compiler.nodes.FixedWithNextNode; @@ -44,9 +43,9 @@ import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.nodes.extended.GuardedNode; import org.graalvm.compiler.nodes.extended.GuardingNode; -import org.graalvm.compiler.nodes.extended.UnsafeAccessNode; import org.graalvm.compiler.nodes.extended.RawLoadNode; import org.graalvm.compiler.nodes.extended.RawStoreNode; +import org.graalvm.compiler.nodes.extended.UnsafeAccessNode; import org.graalvm.compiler.nodes.java.AccessFieldNode; import org.graalvm.compiler.nodes.java.LoadFieldNode; import org.graalvm.compiler.nodes.java.StoreFieldNode; @@ -58,9 +57,9 @@ import org.graalvm.compiler.virtual.phases.ea.ReadEliminationBlockState.CacheEntry; import org.graalvm.compiler.virtual.phases.ea.ReadEliminationBlockState.LoadCacheEntry; import org.graalvm.compiler.virtual.phases.ea.ReadEliminationBlockState.UnsafeLoadCacheEntry; -import org.graalvm.util.Equivalence; import org.graalvm.util.EconomicMap; import org.graalvm.util.EconomicSet; +import org.graalvm.util.Equivalence; import org.graalvm.util.MapCursor; import org.graalvm.word.LocationIdentity; @@ -359,8 +358,8 @@ for (LocationIdentity location : forwardEndLiveLocations) { loopKilledLocations.rememberLoopKilledLocation(location); } - if (Debug.isLogEnabled() && loopKilledLocations != null) { - Debug.log("[Early Read Elimination] Setting loop killed locations of loop at node %s with %s", + if (debug.isLogEnabled() && loopKilledLocations != null) { + debug.log("[Early Read Elimination] Setting loop killed locations of loop at node %s with %s", loop.getHeader().getBeginNode(), forwardEndLiveLocations); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualUtil.java 2017-07-07 09:31:56.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualUtil.java 2017-07-07 09:31:56.000000000 -0700 @@ -26,7 +26,7 @@ import java.util.List; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.graph.Node; @@ -51,6 +51,7 @@ // Nodes with support for GVN can be kept alive by GVN and are therefore not part of the // assertion. + DebugContext debug = graph.getDebug(); NodeFlood flood = graph.createNodeFlood(); EconomicMap path = EconomicMap.create(Equivalence.IDENTITY); flood.add(graph.start()); @@ -115,38 +116,38 @@ } if (!success) { TTY.println(); - Debug.forceDump(graph, "assertNonReachable"); + debug.forceDump(graph, "assertNonReachable"); } return success; } - public static void trace(OptionValues options, String msg) { - if (Debug.isEnabled() && TraceEscapeAnalysis.getValue(options) && Debug.isLogEnabled()) { - Debug.log(msg); + public static void trace(OptionValues options, DebugContext debug, String msg) { + if (debug.areScopesEnabled() && TraceEscapeAnalysis.getValue(options) && debug.isLogEnabled()) { + debug.log(msg); } } - public static void trace(OptionValues options, String format, Object obj) { - if (Debug.isEnabled() && TraceEscapeAnalysis.getValue(options) && Debug.isLogEnabled()) { - Debug.logv(format, obj); + public static void trace(OptionValues options, DebugContext debug, String format, Object obj) { + if (debug.areScopesEnabled() && TraceEscapeAnalysis.getValue(options) && debug.isLogEnabled()) { + debug.logv(format, obj); } } - public static void trace(OptionValues options, String format, Object obj, Object obj2) { - if (Debug.isEnabled() && TraceEscapeAnalysis.getValue(options) && Debug.isLogEnabled()) { - Debug.logv(format, obj, obj2); + public static void trace(OptionValues options, DebugContext debug, String format, Object obj, Object obj2) { + if (debug.areScopesEnabled() && TraceEscapeAnalysis.getValue(options) && debug.isLogEnabled()) { + debug.logv(format, obj, obj2); } } - public static void trace(OptionValues options, String format, Object obj, Object obj2, Object obj3) { - if (Debug.isEnabled() && TraceEscapeAnalysis.getValue(options) && Debug.isLogEnabled()) { - Debug.logv(format, obj, obj2, obj3); + public static void trace(OptionValues options, DebugContext debug, String format, Object obj, Object obj2, Object obj3) { + if (debug.areScopesEnabled() && TraceEscapeAnalysis.getValue(options) && debug.isLogEnabled()) { + debug.logv(format, obj, obj2, obj3); } } - public static void trace(OptionValues options, String format, Object obj, Object obj2, Object obj3, Object obj4) { - if (Debug.isEnabled() && TraceEscapeAnalysis.getValue(options) && Debug.isLogEnabled()) { - Debug.logv(format, obj, obj2, obj3, obj4); + public static void trace(OptionValues options, DebugContext debug, String format, Object obj, Object obj2, Object obj3, Object obj4) { + if (debug.areScopesEnabled() && TraceEscapeAnalysis.getValue(options) && debug.isLogEnabled()) { + debug.logv(format, obj, obj2, obj3, obj4); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualizerToolImpl.java 2017-07-07 09:31:57.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualizerToolImpl.java 2017-07-07 09:31:56.000000000 -0700 @@ -27,6 +27,7 @@ import java.util.List; import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodes.FixedNode; @@ -55,16 +56,18 @@ private final PartialEscapeClosure closure; private final Assumptions assumptions; private final OptionValues options; + private final DebugContext debug; private final LoweringProvider loweringProvider; VirtualizerToolImpl(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantFieldProvider, PartialEscapeClosure closure, - Assumptions assumptions, OptionValues options, LoweringProvider loweringProvider) { + Assumptions assumptions, OptionValues options, DebugContext debug, LoweringProvider loweringProvider) { this.metaAccess = metaAccess; this.constantReflection = constantReflection; this.constantFieldProvider = constantFieldProvider; this.closure = closure; this.assumptions = assumptions; this.options = options; + this.debug = debug; this.loweringProvider = loweringProvider; } @@ -80,6 +83,11 @@ } @Override + public DebugContext getDebug() { + return debug; + } + + @Override public MetaAccessProvider getMetaAccessProvider() { return metaAccess; } @@ -181,7 +189,7 @@ @Override public void createVirtualObject(VirtualObjectNode virtualObject, ValueNode[] entryState, List locks, boolean ensureVirtualized) { - VirtualUtil.trace(options, "{{%s}} ", current); + VirtualUtil.trace(options, debug, "{{%s}} ", current); if (!virtualObject.isAlive()) { effects.addFloatingNode(virtualObject, "newVirtualObject"); } @@ -197,7 +205,7 @@ } state.addObject(id, new ObjectState(entryState, locks, ensureVirtualized)); closure.addVirtualAlias(virtualObject, virtualObject); - PartialEscapeClosure.COUNTER_ALLOCATION_REMOVED.increment(); + PartialEscapeClosure.COUNTER_ALLOCATION_REMOVED.increment(debug); effects.addVirtualizationDelta(1); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/Word.java 2017-07-07 09:31:57.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/Word.java 2017-07-07 09:31:57.000000000 -0700 @@ -80,6 +80,8 @@ public enum Opcode { NODE_CLASS, COMPARISON, + IS_NULL, + IS_NON_NULL, NOT, READ_POINTER, READ_OBJECT, @@ -426,6 +428,18 @@ } @Override + @Operation(opcode = Opcode.IS_NULL) + public boolean isNull() { + return equal(WordFactory.zero()); + } + + @Override + @Operation(opcode = Opcode.IS_NON_NULL) + public boolean isNonNull() { + return notEqual(WordFactory.zero()); + } + + @Override @Operation(opcode = Opcode.COMPARISON, condition = Condition.EQ) public boolean equal(ComparableWord val) { return equal((Word) val); @@ -716,7 +730,7 @@ @Override @Operation(opcode = Opcode.READ_POINTER) public T readWord(int offset, LocationIdentity locationIdentity) { - return readWord((WordBase)signed(offset), locationIdentity); + return readWord(signed(offset), locationIdentity); } @Override @@ -943,7 +957,7 @@ @Override @Operation(opcode = Opcode.READ_POINTER) public T readWord(int offset) { - return readWord((WordBase)signed(offset)); + return readWord(signed(offset)); } @Override @@ -1116,7 +1130,7 @@ @Override @Operation(opcode = Opcode.CAS_POINTER) public T compareAndSwapWord(int offset, T expectedValue, T newValue, LocationIdentity locationIdentity) { - return compareAndSwapWord((WordBase)signed(offset), expectedValue, newValue, locationIdentity); + return compareAndSwapWord(signed(offset), expectedValue, newValue, locationIdentity); } @Override --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordOperationPlugin.java 2017-07-07 09:31:58.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordOperationPlugin.java 2017-07-07 09:31:57.000000000 -0700 @@ -282,6 +282,16 @@ b.push(returnKind, comparisonOp(b, operation.condition(), args[0], fromSigned(b, args[1]))); break; + case IS_NULL: + assert args.length == 1; + b.push(returnKind, comparisonOp(b, Condition.EQ, args[0], ConstantNode.forIntegerKind(wordKind, 0L))); + break; + + case IS_NON_NULL: + assert args.length == 1; + b.push(returnKind, comparisonOp(b, Condition.NE, args[0], ConstantNode.forIntegerKind(wordKind, 0L))); + break; + case NOT: assert args.length == 1; b.addPush(returnKind, new XorNode(args[0], b.add(forIntegerKind(wordKind, -1)))); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionDescriptor.java 2017-07-07 09:31:58.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionDescriptor.java 2017-07-07 09:31:58.000000000 -0700 @@ -24,6 +24,8 @@ */ package org.graalvm.options; +import java.util.Objects; + /** * Represents meta-data for a single option. * @@ -92,6 +94,8 @@ } /** + * {@inheritDoc} + * * @since 1.0 */ @Override @@ -100,12 +104,53 @@ } /** + * {@inheritDoc} + * + * @since 1.0 + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + (deprecated ? 1231 : 1237); + result = prime * result + ((help == null) ? 0 : help.hashCode()); + result = prime * result + ((key == null) ? 0 : key.hashCode()); + result = prime * result + ((kind == null) ? 0 : kind.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + /** + * {@inheritDoc} + * + * @since 1.0 + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } else if (obj == null) { + return false; + } else if (getClass() != obj.getClass()) { + return false; + } + OptionDescriptor other = (OptionDescriptor) obj; + return Objects.equals(name, other.name) && + Objects.equals(deprecated, other.deprecated) && + Objects.equals(help, other.help) && + Objects.equals(key, other.key) && + Objects.equals(kind, other.kind); + } + + /** * Creates a new option descriptor builder by key. The option group and name is inferred by the * key. * * @since 1.0 */ public static Builder newBuilder(OptionKey key, String name) { + Objects.requireNonNull(key); + Objects.requireNonNull(name); return new Builder(key, name); } @@ -134,6 +179,7 @@ * @since 1.0 */ public Builder category(@SuppressWarnings("hiding") OptionCategory category) { + Objects.requireNonNull(category); this.category = category; return this; } @@ -155,6 +201,7 @@ * @since 1.0 */ public Builder help(@SuppressWarnings("hiding") String help) { + Objects.requireNonNull(help); this.help = help; return this; } @@ -165,7 +212,7 @@ * @since 1.0 */ public OptionDescriptor build() { - return new OptionDescriptor(key, name, help, category, deprecated); + return new OptionDescriptor(key, name, help == null ? "" : help, category == null ? OptionCategory.DEBUG : category, deprecated); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionDescriptors.java 2017-07-07 09:31:58.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionDescriptors.java 2017-07-07 09:31:58.000000000 -0700 @@ -81,6 +81,14 @@ } /** + * {@inheritDoc} + * + * @since 1.0 + */ + @Override + Iterator iterator(); + + /** * Create an {@link OptionDescriptors} instance from a list. The option descriptors * implementation is backed by a {@link LinkedHashMap} that preserves ordering. * --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/PointerBase.java 2017-07-07 09:31:59.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/PointerBase.java 2017-07-07 09:31:59.000000000 -0700 @@ -29,4 +29,14 @@ * necessarily all the memory access methods defined in {@link Pointer}). */ public interface PointerBase extends ComparableWord { + + /** + * Returns true if this pointer is the {@link WordFactory#nullPointer null pointer}. + */ + boolean isNull(); + + /** + * Returns true if this pointer is not the {@link WordFactory#nullPointer null pointer}. + */ + boolean isNonNull(); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/PointerUtils.java 2017-07-07 09:31:59.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/PointerUtils.java 2017-07-07 09:31:59.000000000 -0700 @@ -38,9 +38,9 @@ * * @return A null Pointer value. */ - @SuppressWarnings("unchecked") public static T nullPointer() { - return (T) WordFactory.zero(); + /* This method will be deleted soon. */ + return WordFactory.nullPointer(); } /** @@ -49,7 +49,8 @@ * @return Whether that Pointer is the null Pointer. */ public static boolean isNull(ComparableWord that) { - return that.equal(nullPointer()); + /* This method will be deleted soon. */ + return ((PointerBase) that).isNull(); } /** @@ -58,7 +59,8 @@ * @return Whether that Pointer is not the null Pointer. */ public static boolean isNonNull(ComparableWord that) { - return that.notEqual(nullPointer()); + /* This method will be deleted soon. */ + return ((PointerBase) that).isNonNull(); } /** --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/WordFactory.java 2017-07-07 09:32:00.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/WordFactory.java 2017-07-07 09:31:59.000000000 -0700 @@ -87,6 +87,17 @@ } /** + * The null pointer, i.e., the pointer with no bits set. There is no difference to a signed or + * unsigned {@link #zero}. + * + * @return the null pointer. + */ + @FactoryOperation(opcode = FactoryOpcode.ZERO) + public static T nullPointer() { + return boxFactory.box(0L); + } + + /** * Unsafe conversion from a Java long value to a Word. The parameter is treated as an unsigned * 64-bit value (in contrast to the semantics of a Java long). * --- old/test/compiler/aot/scripts/build-bootmodules.sh 2017-07-07 09:32:00.000000000 -0700 +++ new/test/compiler/aot/scripts/build-bootmodules.sh 2017-07-07 09:32:00.000000000 -0700 @@ -36,7 +36,7 @@ $JAVA_HOME/bin/javac -d . $DIR/$TEST.java -JAOTC_OPTS="-J-Xmx4g -J-ea --compile-for-tiered --info" +JAOTC_OPTS="-J-Xmx4g --compile-for-tiered --info" JAVA_OPTS="-Xmx4g -XX:+UseAOT -XX:+UnlockDiagnosticVMOptions -XX:+UseAOTStrictLoading" # Compile with: +UseCompressedOops +UseG1GC --- /dev/null 2017-07-07 09:32:00.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalDebugHandlersFactoryTest.java 2017-07-07 09:32:00.000000000 -0700 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2017, 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 org.graalvm.compiler.core.test; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Comparator; + +import org.graalvm.compiler.printer.GraalDebugHandlersFactory; +import org.graalvm.compiler.test.AddExports; +import org.junit.Test; + +@AddExports("jdk.internal.vm.compiler/org.graalvm.compiler.printer") +public class GraalDebugHandlersFactoryTest extends GraalCompilerTest { + + @Test + public void createUniqueTest() throws Exception { + Field maxFileNameLengthField = GraalDebugHandlersFactory.class.getDeclaredField("MAX_FILE_NAME_LENGTH"); + maxFileNameLengthField.setAccessible(true); + int maxFileNameLength = maxFileNameLengthField.getInt(null); + Method createUniqueMethod = GraalDebugHandlersFactory.class.getDeclaredMethod("createUnique", Path.class, String.class, String.class, String.class, boolean.class); + createUniqueMethod.setAccessible(true); + Path tmpDir = Files.createTempDirectory(Paths.get("."), "createUniqueTest"); + try { + for (boolean createDirectory : new boolean[]{true, false}) { + for (String ext : new String[]{"", ".bgv", ".graph-strings"}) { + for (int i = 0; i < maxFileNameLength + 5; i++) { + String id = new String(new char[i]).replace('\0', 'i'); + String label = ""; + createUniqueMethod.invoke(null, tmpDir, id, label, ext, createDirectory); + + id = ""; + label = new String(new char[i]).replace('\0', 'l'); + createUniqueMethod.invoke(null, tmpDir, id, label, ext, createDirectory); + } + } + } + } finally { + deleteTree(tmpDir); + } + } + + private static void deleteTree(Path root) throws IOException { + Files.walk(root).sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete); + } +} --- /dev/null 2017-07-07 09:32:01.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryGraphCanonicalizeTest.java 2017-07-07 09:32:01.000000000 -0700 @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2017, 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 org.graalvm.compiler.core.test; + +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.memory.WriteNode; +import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.phases.common.CanonicalizerPhase; +import org.graalvm.compiler.phases.common.FloatingReadPhase; +import org.graalvm.compiler.phases.common.IncrementalCanonicalizerPhase; +import org.graalvm.compiler.phases.common.LoweringPhase; +import org.graalvm.compiler.phases.tiers.HighTierContext; +import org.junit.Test; + +public class MemoryGraphCanonicalizeTest extends GraalCompilerTest { + static class TestObject { + Object object; + Integer integer; + int value; + volatile boolean written; + } + + public static void simpleElimination(TestObject object) { + object.object = object; + object.value = object.integer; + object.value = object.integer + 2; + object.value = object.integer + 3; + } + + @Test + public void testSimpleElimination() { + testGraph("simpleElimination", 2); + } + + public static void complexElimination(TestObject object) { + object.object = object; + object.value = object.integer; + object.value = object.integer + 2; + if (object.object == null) { + object.value = object.integer + 3; + } else { + object.object = new Object(); + } + object.written = true; + object.value = 5; + } + + @Test + public void testComplexElimination() { + testGraph("complexElimination", 6); + } + + public void testGraph(String name, int expectedWrites) { + StructuredGraph graph = parseEager(name, StructuredGraph.AllowAssumptions.YES); + HighTierContext context = getDefaultHighTierContext(); + CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); + new IncrementalCanonicalizerPhase<>(canonicalizer, new FloatingReadPhase()).apply(graph, context); + new CanonicalizerPhase().apply(graph, context); + int writes = graph.getNodes().filter(WriteNode.class).count(); + assertTrue(writes == expectedWrites, "Expected %d writes, found %d", expectedWrites, writes); + } +} --- /dev/null 2017-07-07 09:32:01.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/DebugContextTest.java 2017-07-07 09:32:01.000000000 -0700 @@ -0,0 +1,281 @@ +/* + * 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 org.graalvm.compiler.debug.test; + +import static org.graalvm.compiler.debug.DebugContext.NO_DESCRIPTION; +import static org.graalvm.compiler.debug.DebugContext.NO_GLOBAL_METRIC_VALUES; + +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.util.Arrays; +import java.util.Collections; +import java.util.Formatter; +import java.util.List; + +import org.graalvm.compiler.debug.Assertions; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugCloseable; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DebugContext.Scope; +import org.graalvm.compiler.debug.DebugDumpHandler; +import org.graalvm.compiler.debug.DebugHandler; +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.debug.DebugOptions; +import org.graalvm.compiler.debug.DebugVerifyHandler; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicMap; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Test; + +@SuppressWarnings("try") +public class DebugContextTest { + + static class DebugContextSetup { + final Formatter dumpOutput = new Formatter(); + final Formatter verifyOutput = new Formatter(); + final ByteArrayOutputStream logOutput = new ByteArrayOutputStream(); + DebugHandlersFactory handlers = new DebugHandlersFactory() { + @Override + public List createHandlers(OptionValues options) { + return Arrays.asList(new DebugDumpHandler() { + @Override + public void dump(DebugContext ignore, Object object, String format, Object... arguments) { + dumpOutput.format("Dumping %s with label \"%s\"%n", object, String.format(format, arguments)); + } + }, new DebugVerifyHandler() { + @Override + public void verify(DebugContext ignore, Object object, String format, Object... args) { + verifyOutput.format("Verifying %s with label \"%s\"%n", object, String.format(format, args)); + } + }); + } + }; + + DebugContext openDebugContext(OptionValues options) { + return DebugContext.create(options, NO_DESCRIPTION, NO_GLOBAL_METRIC_VALUES, new PrintStream(logOutput), Collections.singletonList(handlers)); + + } + } + + @Test + public void testDisabledScopes() { + OptionValues options = new OptionValues(EconomicMap.create()); + DebugContextSetup setup = new DebugContextSetup(); + try (DebugContext debug = setup.openDebugContext(options); + DebugContext.Scope d = debug.scope("TestDisabledScoping")) { + for (int level = DebugContext.BASIC_LEVEL; level <= DebugContext.VERY_DETAILED_LEVEL; level++) { + debug.dump(level, "an object", "at level %d", level); + debug.verify("an object", "at level %d", level); + debug.log(level, "log statement at level %d", level); + } + } + String log = setup.logOutput.toString(); + String dumpOutput = setup.dumpOutput.toString(); + String verifyOutput = setup.verifyOutput.toString(); + Assert.assertTrue(log, log.isEmpty()); + Assert.assertTrue(dumpOutput, dumpOutput.isEmpty()); + Assert.assertTrue(verifyOutput, verifyOutput.isEmpty()); + } + + @Test + public void testDumping() { + for (int level = DebugContext.BASIC_LEVEL; level <= DebugContext.VERY_DETAILED_LEVEL; level++) { + OptionValues options = new OptionValues(EconomicMap.create()); + options = new OptionValues(options, DebugOptions.Dump, "Scope" + level + ":" + level); + DebugContextSetup setup = new DebugContextSetup(); + try (DebugContext debug = setup.openDebugContext(options); + DebugContext.Scope s0 = debug.scope("TestDumping")) { + try (DebugContext.Scope s1 = debug.scope("Scope1")) { + try (DebugContext.Scope s2 = debug.scope("Scope2")) { + try (DebugContext.Scope s3 = debug.scope("Scope3")) { + try (DebugContext.Scope s4 = debug.scope("Scope4")) { + try (DebugContext.Scope s5 = debug.scope("Scope5")) { + debug.dump(level, "an object", "at level %d", level); + } + } + } + } + } + + } + + String expect = String.format("Dumping an object with label \"at level %d\"%n", level); + String dump = setup.dumpOutput.toString(); + Assert.assertEquals(expect, dump); + } + } + + @Test + public void testLogging() throws IOException { + OptionValues options = new OptionValues(EconomicMap.create()); + options = new OptionValues(options, DebugOptions.Log, ":5"); + DebugContextSetup setup = new DebugContextSetup(); + try (DebugContext debug = setup.openDebugContext(options)) { + for (int level = DebugContext.BASIC_LEVEL; level <= DebugContext.VERY_DETAILED_LEVEL; level++) { + try (DebugContext.Scope s0 = debug.scope("TestLogging")) { + debug.log(level, "log statement at level %d", level); + try (DebugContext.Scope s1 = debug.scope("Level1")) { + debug.log(level, "log statement at level %d", level); + try (DebugContext.Scope s2 = debug.scope("Level2")) { + debug.log(level, "log statement at level %d", level); + try (DebugContext.Scope s3 = debug.scope("Level3")) { + debug.log(level, "log statement at level %d", level); + try (DebugContext.Scope s4 = debug.scope("Level4")) { + debug.log(level, "log statement at level %d", level); + try (DebugContext.Scope s5 = debug.scope("Level5")) { + debug.log(level, "log statement at level %d", level); + } + } + } + } + } + } + } + } + DataInputStream in = new DataInputStream(getClass().getResourceAsStream(getClass().getSimpleName() + ".testLogging.input")); + byte[] buf = new byte[in.available()]; + in.readFully(buf); + String threadLabel = "[thread:" + Thread.currentThread().getId() + "]"; + String expect = new String(buf).replace("[thread:1]", threadLabel); + + String log = setup.logOutput.toString(); + Assert.assertEquals(expect, log); + } + + @Test + public void testEnabledSandbox() { + EconomicMap, Object> map = EconomicMap.create(); + // Configure with an option that enables scopes + map.put(DebugOptions.DumpOnError, true); + OptionValues options = new OptionValues(map); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DebugContext debug = DebugContext.create(options, NO_DESCRIPTION, NO_GLOBAL_METRIC_VALUES, new PrintStream(baos), DebugHandlersFactory.LOADER); + Exception e = new Exception("testEnabledSandbox"); + String scopeName = ""; + try { + try (DebugContext.Scope d = debug.sandbox("TestExceptionHandling", debug.getConfig())) { + scopeName = d.getQualifiedName(); + throw e; + } catch (Throwable t) { + assert e == t; + debug.handle(t); + } + } catch (Throwable t) { + // The exception object should propagate all the way out through + // a enabled sandbox scope + Assert.assertEquals(e, t); + } + String logged = baos.toString(); + String expected = String.format("Exception raised in scope %s: %s", scopeName, e); + String line = "-------------------------------------------------------"; + Assert.assertTrue(String.format("Could not find \"%s\" in content between lines below:%n%s%n%s%s", expected, line, logged, line), logged.contains(expected)); + } + + @Test + public void testDisabledSandbox() { + EconomicMap, Object> map = EconomicMap.create(); + // Configure with an option that enables scopes + map.put(DebugOptions.DumpOnError, true); + OptionValues options = new OptionValues(map); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DebugContext debug = DebugContext.create(options, NO_DESCRIPTION, NO_GLOBAL_METRIC_VALUES, new PrintStream(baos), DebugHandlersFactory.LOADER); + Exception e = new Exception("testDisabledSandbox"); + try { + // Test a disabled sandbox scope + try (DebugContext.Scope d = debug.sandbox("TestExceptionHandling", null)) { + throw e; + } catch (Throwable t) { + assert e == t; + debug.handle(t); + } + } catch (Throwable t) { + // The exception object should propagate all the way out through + // a disabled sandbox scope + Assert.assertEquals(e, t); + } + String logged = baos.toString(); + Assert.assertTrue(logged, logged.isEmpty()); + } + + /** + * Tests that using a {@link DebugContext} on a thread other than the one on which it was + * created causes an assertion failure. + */ + @Test + public void testInvariantChecking() throws InterruptedException { + Assume.assumeTrue(Assertions.ENABLED); + EconomicMap, Object> map = EconomicMap.create(); + // Configure with an option that enables counters + map.put(DebugOptions.Counters, ""); + OptionValues options = new OptionValues(map); + DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER); + CounterKey counter = DebugContext.counter("DebugContextTestCounter"); + AssertionError[] result = {null}; + Thread thread = new Thread() { + + @Override + public void run() { + try { + counter.add(debug, 1); + } catch (AssertionError e) { + result[0] = e; + } + } + }; + thread.start(); + thread.join(); + + Assert.assertNotNull("Expected thread to throw AssertionError", result[0]); + } + + @Test + public void testDisableIntercept() { + EconomicMap, Object> map = EconomicMap.create(); + // Configure with an option that enables scopes + map.put(DebugOptions.DumpOnError, true); + OptionValues options = new OptionValues(map); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DebugContext debug = DebugContext.create(options, NO_DESCRIPTION, NO_GLOBAL_METRIC_VALUES, new PrintStream(baos), DebugHandlersFactory.LOADER); + Exception e = new Exception(); + try { + try (DebugCloseable disabled = debug.disableIntercept(); Scope s1 = debug.scope("ScopeWithDisabledIntercept")) { + try (Scope s2 = debug.scope("InnerScopeInheritsDisabledIntercept")) { + throw e; + } + } catch (Throwable t) { + assert e == t; + debug.handle(t); + } + } catch (Throwable t) { + // The exception object should propagate all the way out through + // an intercept disabled scope + Assert.assertEquals(e, t); + } + String logged = baos.toString(); + Assert.assertEquals("Exception should not have been intercepted", "", logged); + } +} --- /dev/null 2017-07-07 09:32:01.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/DebugContextTest.testLogging.input 2017-07-07 09:32:01.000000000 -0700 @@ -0,0 +1,61 @@ +[thread:1] scope: main + [thread:1] scope: main.TestLogging + log statement at level 1 + [thread:1] scope: main.TestLogging.Level1 + log statement at level 1 + [thread:1] scope: main.TestLogging.Level1.Level2 + log statement at level 1 + [thread:1] scope: main.TestLogging.Level1.Level2.Level3 + log statement at level 1 + [thread:1] scope: main.TestLogging.Level1.Level2.Level3.Level4 + log statement at level 1 + [thread:1] scope: main.TestLogging.Level1.Level2.Level3.Level4.Level5 + log statement at level 1 + [thread:1] scope: main.TestLogging + log statement at level 2 + [thread:1] scope: main.TestLogging.Level1 + log statement at level 2 + [thread:1] scope: main.TestLogging.Level1.Level2 + log statement at level 2 + [thread:1] scope: main.TestLogging.Level1.Level2.Level3 + log statement at level 2 + [thread:1] scope: main.TestLogging.Level1.Level2.Level3.Level4 + log statement at level 2 + [thread:1] scope: main.TestLogging.Level1.Level2.Level3.Level4.Level5 + log statement at level 2 + [thread:1] scope: main.TestLogging + log statement at level 3 + [thread:1] scope: main.TestLogging.Level1 + log statement at level 3 + [thread:1] scope: main.TestLogging.Level1.Level2 + log statement at level 3 + [thread:1] scope: main.TestLogging.Level1.Level2.Level3 + log statement at level 3 + [thread:1] scope: main.TestLogging.Level1.Level2.Level3.Level4 + log statement at level 3 + [thread:1] scope: main.TestLogging.Level1.Level2.Level3.Level4.Level5 + log statement at level 3 + [thread:1] scope: main.TestLogging + log statement at level 4 + [thread:1] scope: main.TestLogging.Level1 + log statement at level 4 + [thread:1] scope: main.TestLogging.Level1.Level2 + log statement at level 4 + [thread:1] scope: main.TestLogging.Level1.Level2.Level3 + log statement at level 4 + [thread:1] scope: main.TestLogging.Level1.Level2.Level3.Level4 + log statement at level 4 + [thread:1] scope: main.TestLogging.Level1.Level2.Level3.Level4.Level5 + log statement at level 4 + [thread:1] scope: main.TestLogging + log statement at level 5 + [thread:1] scope: main.TestLogging.Level1 + log statement at level 5 + [thread:1] scope: main.TestLogging.Level1.Level2 + log statement at level 5 + [thread:1] scope: main.TestLogging.Level1.Level2.Level3 + log statement at level 5 + [thread:1] scope: main.TestLogging.Level1.Level2.Level3.Level4 + log statement at level 5 + [thread:1] scope: main.TestLogging.Level1.Level2.Level3.Level4.Level5 + log statement at level 5 --- /dev/null 2017-07-07 09:32:02.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/TimerKeyTest.java 2017-07-07 09:32:02.000000000 -0700 @@ -0,0 +1,103 @@ +/* + * 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 org.graalvm.compiler.debug.test; + +import static org.graalvm.compiler.debug.DebugContext.DEFAULT_LOG_STREAM; +import static org.graalvm.compiler.debug.DebugContext.NO_CONFIG_CUSTOMIZERS; +import static org.graalvm.compiler.debug.DebugContext.NO_DESCRIPTION; +import static org.graalvm.compiler.debug.DebugContext.NO_GLOBAL_METRIC_VALUES; +import static org.junit.Assert.assertEquals; + +import java.lang.management.ThreadMXBean; + +import org.graalvm.compiler.debug.DebugCloseable; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DebugOptions; +import org.graalvm.compiler.debug.Management; +import org.graalvm.compiler.debug.TimerKey; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicMap; +import org.junit.Assume; +import org.junit.Before; +import org.junit.Test; + +@SuppressWarnings("try") +public class TimerKeyTest { + + private static final ThreadMXBean threadMXBean = Management.getThreadMXBean(); + + @Before + public void checkCapabilities() { + Assume.assumeTrue("skipping management interface test", threadMXBean.isCurrentThreadCpuTimeSupported()); + } + + /** + * Actively spins the current thread for at least a given number of milliseconds in such a way + * that timers for the current thread keep ticking over. + * + * @return the number of milliseconds actually spent spinning which is guaranteed to be >= + * {@code ms} + */ + private static long spin(long ms) { + long start = threadMXBean.getCurrentThreadCpuTime(); + do { + long durationMS = (threadMXBean.getCurrentThreadCpuTime() - start) / 1000; + if (durationMS >= ms) { + return durationMS; + } + } while (true); + } + + /** + * Asserts that a timer replied recursively without any other interleaving timers has the same + * flat and accumulated times. + */ + @Test + public void test2() { + EconomicMap, Object> map = EconomicMap.create(); + map.put(DebugOptions.Time, ""); + OptionValues options = new OptionValues(map); + DebugContext debug = DebugContext.create(options, NO_DESCRIPTION, NO_GLOBAL_METRIC_VALUES, DEFAULT_LOG_STREAM, NO_CONFIG_CUSTOMIZERS); + + TimerKey timerC = DebugContext.timer("TimerC"); + try (DebugCloseable c1 = timerC.start(debug)) { + spin(50); + try (DebugCloseable c2 = timerC.start(debug)) { + spin(50); + try (DebugCloseable c3 = timerC.start(debug)) { + spin(50); + try (DebugCloseable c4 = timerC.start(debug)) { + spin(50); + try (DebugCloseable c5 = timerC.start(debug)) { + spin(50); + } + } + } + } + } + if (timerC.getFlat() != null) { + assertEquals(timerC.getFlat().getCurrentValue(debug), timerC.getCurrentValue(debug)); + } + } +} --- /dev/null 2017-07-07 09:32:02.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/AbstractKey.java 2017-07-07 09:32:02.000000000 -0700 @@ -0,0 +1,107 @@ +/* + * 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 org.graalvm.compiler.debug; + +/** + * A name and index for a metric value. + */ +abstract class AbstractKey implements MetricKey { + + private final String nameFormat; + private final Object nameArg1; + private final Object nameArg2; + + private String name; + private int index; + private String doc; + + protected AbstractKey(String nameFormat, Object nameArg1, Object nameArg2) { + this.nameFormat = nameFormat; + this.nameArg1 = nameArg1; + this.nameArg2 = nameArg2; + this.index = -1; + } + + protected void setDoc(String doc) { + this.doc = doc; + } + + @Override + public String getDoc() { + return doc; + } + + @Override + public String getDocName() { + return getName(); + } + + public long getCurrentValue(DebugContext debug) { + ensureInitialized(); + return debug.getMetricValue(index); + } + + void setCurrentValue(DebugContext debug, long l) { + ensureInitialized(); + debug.setMetricValue(index, l); + } + + void ensureInitialized() { + if (index == -1) { + index = KeyRegistry.register(this); + } + } + + void addToCurrentValue(DebugContext debug, long value) { + ensureInitialized(); + debug.setMetricValue(index, debug.getMetricValue(index) + value); + } + + /** + * Gets the globally unique index for the value represented by this object. + */ + public int getIndex() { + ensureInitialized(); + return index; + } + + /** + * Gets the globally unique name for the value represented by this object. + */ + @Override + public String getName() { + if (name == null) { + name = createName(nameFormat, nameArg1, nameArg2); + } + return name; + } + + protected String createName(String format, Object arg1, Object arg2) { + return DebugContext.formatDebugName(format, arg1, arg2); + } + + @Override + public String toString() { + return getName() + "@" + index; + } +} --- /dev/null 2017-07-07 09:32:02.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/AccumulatedKey.java 2017-07-07 09:32:02.000000000 -0700 @@ -0,0 +1,46 @@ +/* + * 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 org.graalvm.compiler.debug; + +abstract class AccumulatedKey extends AbstractKey { + protected final AbstractKey flat; + + static final String ACCUMULATED_KEY_SUFFIX = "_Accm"; + static final String FLAT_KEY_SUFFIX = "_Flat"; + + protected AccumulatedKey(AbstractKey flat, String nameFormat, Object nameArg1, Object nameArg2) { + super(nameFormat, nameArg1, nameArg2); + this.flat = flat; + } + + @Override + protected String createName(String format, Object arg1, Object arg2) { + return super.createName(format, arg1, arg2) + ACCUMULATED_KEY_SUFFIX; + } + + @Override + public String getDocName() { + String name = getName(); + return name.substring(0, name.length() - ACCUMULATED_KEY_SUFFIX.length()); + } +} --- /dev/null 2017-07-07 09:32:03.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/CloseableCounter.java 2017-07-07 09:32:03.000000000 -0700 @@ -0,0 +1,97 @@ +/* + * 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 org.graalvm.compiler.debug; + +/** + * A helper class for {@link AbstractKey}s that can nest and need to split out accumulated and flat + * values for some kind of counter-like measurement. + */ +public abstract class CloseableCounter implements DebugCloseable { + + protected final DebugContext debug; + protected final CloseableCounter parent; + protected final AccumulatedKey counter; + protected final long start; + protected long nestedAmountToSubtract; + + CloseableCounter(DebugContext debug, CloseableCounter parent, AccumulatedKey counter) { + this.debug = debug; + this.parent = parent; + this.start = getCounterValue(); + this.counter = counter; + } + + @Override + public DebugContext getDebug() { + return debug; + } + + /** + * A hook for subclasses. Lets them perform custom operations with the value since the last + * invocation of {@link CloseableCounter#close()} of this accumulated + * {@link CloseableCounter#counter}. + * + * @param difference since the last invocation of this counter flat + */ + protected void interceptDifferenceAccm(long difference) { + // hook for subclasses + } + + /** + * A hook for subclasses. Lets them perform custom operations with the value since the last + * invocation of {@link CloseableCounter#close()} of this flat {@link CloseableCounter#counter}. + * + * @param difference since the last invocation of this counter flat + */ + protected void interceptDifferenceFlat(long difference) { + // hook for subclasses + } + + @Override + public void close() { + long end = getCounterValue(); + long difference = end - start; + if (parent != null) { + if (!counter.getName().equals(parent.counter.getName())) { + parent.nestedAmountToSubtract += difference; + // Look for our counter in an outer scope and fix up + // the adjustment to the flat count + CloseableCounter ancestor = parent.parent; + while (ancestor != null) { + if (ancestor.counter.getName().equals(counter.getName())) { + ancestor.nestedAmountToSubtract -= difference; + break; + } + ancestor = ancestor.parent; + } + } + } + long flatAmount = difference - nestedAmountToSubtract; + counter.addToCurrentValue(debug, difference); + counter.flat.addToCurrentValue(debug, flatAmount); + interceptDifferenceAccm(difference); + interceptDifferenceFlat(flatAmount); + } + + abstract long getCounterValue(); +} --- /dev/null 2017-07-07 09:32:03.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/CounterKey.java 2017-07-07 09:32:03.000000000 -0700 @@ -0,0 +1,52 @@ +/* + * 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 org.graalvm.compiler.debug; + +/** + * A counter for some value of interest. + */ +public interface CounterKey extends MetricKey { + + /** + * Adds 1 to this counter. + */ + void increment(DebugContext debug); + + /** + * Adds {@code value} to this counter. + */ + void add(DebugContext debug, long value); + + /** + * Gets the current value of this counter. + */ + long getCurrentValue(DebugContext debug); + + /** + * Determines if this counter is enabled. + */ + boolean isEnabled(DebugContext debug); + + @Override + CounterKey doc(String string); +} --- /dev/null 2017-07-07 09:32:03.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/CounterKeyImpl.java 2017-07-07 09:32:03.000000000 -0700 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.debug; + +import org.graalvm.util.Pair; + +class CounterKeyImpl extends AbstractKey implements CounterKey { + + CounterKeyImpl(String format, Object arg1, Object arg2) { + super(format, arg1, arg2); + } + + @Override + public void increment(DebugContext debug) { + add(debug, 1); + } + + @Override + public Pair toCSVFormat(long value) { + return Pair.create(String.valueOf(value), ""); + } + + @Override + public String toHumanReadableFormat(long value) { + return Long.toString(value); + } + + @Override + public void add(DebugContext debug, long value) { + if (debug.isCounterEnabled(this)) { + addToCurrentValue(debug, value); + } + } + + @Override + public boolean isEnabled(DebugContext debug) { + return debug.isCounterEnabled(this); + } + + @Override + public CounterKey doc(String doc) { + setDoc(doc); + return this; + } +} --- /dev/null 2017-07-07 09:32:04.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfigImpl.java 2017-07-07 09:32:04.000000000 -0700 @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2012, 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 org.graalvm.compiler.debug; + +import static org.graalvm.compiler.debug.DebugContext.BASIC_LEVEL; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; + +import org.graalvm.compiler.options.OptionValues; + +import jdk.vm.ci.code.BailoutException; +import jdk.vm.ci.meta.JavaMethod; + +final class DebugConfigImpl implements DebugConfig { + + private final OptionValues options; + + private final DebugFilter countFilter; + private final DebugFilter logFilter; + private final DebugFilter trackMemUseFilter; + private final DebugFilter timerFilter; + private final DebugFilter dumpFilter; + private final DebugFilter verifyFilter; + private final MethodFilter[] methodFilter; + private final List dumpHandlers; + private final List verifyHandlers; + private final PrintStream output; + + DebugConfigImpl(OptionValues options) { + this(options, TTY.out, Collections.emptyList(), Collections.emptyList()); + } + + DebugConfigImpl(OptionValues options, PrintStream output, + List dumpHandlers, + List verifyHandlers) { + this(options, DebugOptions.Log.getValue(options), + DebugOptions.Count.getValue(options), + DebugOptions.TrackMemUse.getValue(options), + DebugOptions.Time.getValue(options), + DebugOptions.Dump.getValue(options), + DebugOptions.Verify.getValue(options), + DebugOptions.MethodFilter.getValue(options), + output, dumpHandlers, verifyHandlers); + } + + DebugConfigImpl(OptionValues options, + String logFilter, + String countFilter, + String trackMemUseFilter, + String timerFilter, + String dumpFilter, + String verifyFilter, + String methodFilter, + PrintStream output, + List dumpHandlers, + List verifyHandlers) { + this.options = options; + this.logFilter = DebugFilter.parse(logFilter); + this.countFilter = DebugFilter.parse(countFilter); + this.trackMemUseFilter = DebugFilter.parse(trackMemUseFilter); + this.timerFilter = DebugFilter.parse(timerFilter); + this.dumpFilter = DebugFilter.parse(dumpFilter); + this.verifyFilter = DebugFilter.parse(verifyFilter); + if (methodFilter == null || methodFilter.isEmpty()) { + this.methodFilter = null; + } else { + this.methodFilter = org.graalvm.compiler.debug.MethodFilter.parse(methodFilter); + } + + this.dumpHandlers = Collections.unmodifiableList(dumpHandlers); + this.verifyHandlers = Collections.unmodifiableList(verifyHandlers); + this.output = output; + } + + @Override + public OptionValues getOptions() { + return options; + } + + @Override + public int getLogLevel(DebugContext.Scope scope) { + return getLevel(scope, logFilter); + } + + @Override + public boolean isLogEnabledForMethod(DebugContext.Scope scope) { + return isEnabledForMethod(scope, logFilter); + } + + @Override + public boolean isCountEnabled(DebugContext.Scope scope) { + return isEnabled(scope, countFilter); + } + + @Override + public boolean isMemUseTrackingEnabled(DebugContext.Scope scope) { + return isEnabled(scope, trackMemUseFilter); + } + + @Override + public int getDumpLevel(DebugContext.Scope scope) { + return getLevel(scope, dumpFilter); + } + + @Override + public boolean isDumpEnabledForMethod(DebugContext.Scope scope) { + return isEnabledForMethod(scope, dumpFilter); + } + + @Override + public boolean isVerifyEnabled(DebugContext.Scope scope) { + return isEnabled(scope, verifyFilter); + } + + @Override + public boolean isVerifyEnabledForMethod(DebugContext.Scope scope) { + return isEnabledForMethod(scope, verifyFilter); + } + + @Override + public boolean isTimeEnabled(DebugContext.Scope scope) { + return isEnabled(scope, timerFilter); + } + + @Override + public PrintStream output() { + return output; + } + + private boolean isEnabled(DebugContext.Scope scope, DebugFilter filter) { + return getLevel(scope, filter) > 0; + } + + private int getLevel(DebugContext.Scope scope, DebugFilter filter) { + int level; + if (filter == null) { + level = 0; + } else { + String currentScope = scope.getQualifiedName(); + level = filter.matchLevel(currentScope); + } + if (level >= 0 && !checkMethodFilter(scope)) { + level = -1; + } + return level; + } + + private boolean isEnabledForMethod(DebugContext.Scope scope, DebugFilter filter) { + return filter != null && checkMethodFilter(scope); + } + + private boolean checkMethodFilter(DebugContext.Scope scope) { + if (methodFilter == null) { + return true; + } else { + JavaMethod lastMethod = null; + Iterable context = scope.getCurrentContext(); + for (Object o : context) { + if (methodFilter != null) { + JavaMethod method = DebugConfig.asJavaMethod(o); + if (method != null) { + if (!DebugOptions.MethodFilterRootOnly.getValue(options)) { + if (org.graalvm.compiler.debug.MethodFilter.matches(methodFilter, method)) { + return true; + } + } else { + /* + * The context values operate as a stack so if we want MethodFilter to + * only apply to the root method we have to check only the last method + * seen. + */ + lastMethod = method; + } + } + } + } + if (lastMethod != null && org.graalvm.compiler.debug.MethodFilter.matches(methodFilter, lastMethod)) { + return true; + } + return false; + } + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("Debug config:"); + add(sb, "Log", logFilter); + add(sb, "Count", countFilter); + add(sb, "Time", timerFilter); + add(sb, "Dump", dumpFilter); + add(sb, "MethodFilter", methodFilter); + return sb.toString(); + } + + private static void add(StringBuilder sb, String name, Object filter) { + if (filter != null) { + sb.append(' '); + sb.append(name); + sb.append('='); + if (filter instanceof Object[]) { + sb.append(Arrays.toString((Object[]) filter)); + } else { + sb.append(String.valueOf(filter)); + } + } + } + + @Override + public RuntimeException interceptException(DebugContext debug, Throwable e) { + if (e instanceof BailoutException && !DebugOptions.InterceptBailout.getValue(options)) { + return null; + } + + OptionValues interceptOptions = new OptionValues(options, + DebugOptions.Count, null, + DebugOptions.Time, null, + DebugOptions.TrackMemUse, null, + DebugOptions.Verify, null, + DebugOptions.Dump, ":" + BASIC_LEVEL, + DebugOptions.Log, ":" + BASIC_LEVEL); + DebugConfigImpl config = new DebugConfigImpl(interceptOptions, output, dumpHandlers, verifyHandlers); + ScopeImpl scope = debug.currentScope; + scope.updateFlags(config); + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + e.printStackTrace(new PrintStream(baos)); + debug.log("Exception raised in scope %s: %s", debug.getCurrentScopeName(), baos); + Map firstSeen = new IdentityHashMap<>(); + for (Object o : debug.context()) { + // Only dump a context object once. + if (!firstSeen.containsKey(o)) { + firstSeen.put(o, o); + if (DebugOptions.DumpOnError.getValue(options) || DebugOptions.Dump.getValue(options) != null) { + debug.dump(DebugContext.BASIC_LEVEL, o, "Exception: %s", e); + } else { + debug.log("Context obj %s", o); + } + } + } + } finally { + scope.updateFlags(this); + } + return null; + } + + @Override + public Collection dumpHandlers() { + return dumpHandlers; + } + + @Override + public Collection verifyHandlers() { + return verifyHandlers; + } +} --- /dev/null 2017-07-07 09:32:04.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java 2017-07-07 09:32:04.000000000 -0700 @@ -0,0 +1,2030 @@ +/* + * 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 org.graalvm.compiler.debug; + +import static java.util.FormattableFlags.LEFT_JUSTIFY; +import static java.util.FormattableFlags.UPPERCASE; +import static org.graalvm.compiler.debug.DebugOptions.Count; +import static org.graalvm.compiler.debug.DebugOptions.Counters; +import static org.graalvm.compiler.debug.DebugOptions.Dump; +import static org.graalvm.compiler.debug.DebugOptions.DumpOnError; +import static org.graalvm.compiler.debug.DebugOptions.DumpOnPhaseChange; +import static org.graalvm.compiler.debug.DebugOptions.ListMetrics; +import static org.graalvm.compiler.debug.DebugOptions.Log; +import static org.graalvm.compiler.debug.DebugOptions.MemUseTrackers; +import static org.graalvm.compiler.debug.DebugOptions.MethodFilter; +import static org.graalvm.compiler.debug.DebugOptions.Time; +import static org.graalvm.compiler.debug.DebugOptions.Timers; +import static org.graalvm.compiler.debug.DebugOptions.TrackMemUse; +import static org.graalvm.compiler.debug.DebugOptions.Verify; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.PrintStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Formatter; +import java.util.List; +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; + +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.EconomicSet; +import org.graalvm.util.Pair; + +import jdk.vm.ci.meta.JavaMethod; + +/** + * A facility for logging and dumping as well as a container for values associated with + * {@link MetricKey}s. + * + * A {@code DebugContext} object must only be used on the thread that created it. This means it + * needs to be passed around as a parameter. For convenience, it can be encapsulated in a widely + * used object that is in scope wherever a {@code DebugContext} is needed. However, care must be + * taken when such objects can be exposed to multiple threads (e.g., they are in a non-thread-local + * cache). + */ +public final class DebugContext implements AutoCloseable { + + public static final Description NO_DESCRIPTION = null; + public static final GlobalMetrics NO_GLOBAL_METRIC_VALUES = null; + public static final Iterable NO_CONFIG_CUSTOMIZERS = Collections.emptyList(); + + public static final PrintStream DEFAULT_LOG_STREAM = TTY.out; + + /** + * Contains the immutable parts of a debug context. This separation allows the immutable parts + * to be shared and reduces the overhead of initialization since most immutable fields are + * configured by parsing options. + */ + final Immutable immutable; + + /** + * Determines whether metrics are enabled. + */ + boolean metricsEnabled; + + DebugConfig currentConfig; + ScopeImpl currentScope; + CloseableCounter currentTimer; + CloseableCounter currentMemUseTracker; + Scope lastClosedScope; + Throwable lastExceptionThrown; + + /** + * Stores the {@link MetricKey} values. + */ + private long[] metricValues; + + /** + * Determines if dynamic scopes are enabled. + */ + public boolean areScopesEnabled() { + return immutable.scopesEnabled; + } + + /** + * The immutable configuration that can be shared between {@link DebugContext} objects. + */ + static final class Immutable { + + private static final Immutable[] CACHE = new Immutable[5]; + + /** + * The options from which this object was configured. + */ + final OptionValues options; + + /** + * Specifies if dynamic scopes are enabled. + */ + final boolean scopesEnabled; + + final boolean listMetrics; + + /** + * Names of unscoped counters. A counter is unscoped if this set is empty or contains the + * counter's name. + */ + final EconomicSet unscopedCounters; + + /** + * Names of unscoped timers. A timer is unscoped if this set is empty or contains the + * timer's name. + */ + final EconomicSet unscopedTimers; + + /** + * Names of unscoped memory usage trackers. A memory usage tracker is unscoped if this set + * is empty or contains the memory usage tracker's name. + */ + final EconomicSet unscopedMemUseTrackers; + + private static EconomicSet parseUnscopedMetricSpec(String spec, boolean unconditional, boolean accumulatedKey) { + EconomicSet res; + if (spec == null) { + if (!unconditional) { + res = null; + } else { + res = EconomicSet.create(); + } + } else { + res = EconomicSet.create(); + if (!spec.isEmpty()) { + if (!accumulatedKey) { + res.addAll(Arrays.asList(spec.split(","))); + } else { + for (String n : spec.split(",")) { + res.add(n + AccumulatedKey.ACCUMULATED_KEY_SUFFIX); + res.add(n + AccumulatedKey.FLAT_KEY_SUFFIX); + } + } + + } + } + return res; + } + + static Immutable create(OptionValues options) { + int i = 0; + while (i < CACHE.length) { + Immutable immutable = CACHE[i]; + if (immutable == null) { + break; + } + if (immutable.options == options) { + return immutable; + } + i++; + } + Immutable immutable = new Immutable(options); + if (i < CACHE.length) { + CACHE[i] = immutable; + } + return immutable; + } + + private static boolean isNotEmpty(OptionKey option, OptionValues options) { + return option.getValue(options) != null && !option.getValue(options).isEmpty(); + } + + private Immutable(OptionValues options) { + this.options = options; + this.unscopedCounters = parseUnscopedMetricSpec(Counters.getValue(options), "".equals(Count.getValue(options)), false); + this.unscopedTimers = parseUnscopedMetricSpec(Timers.getValue(options), "".equals(Time.getValue(options)), true); + this.unscopedMemUseTrackers = parseUnscopedMetricSpec(MemUseTrackers.getValue(options), "".equals(TrackMemUse.getValue(options)), true); + + this.scopesEnabled = DumpOnError.getValue(options) || + Dump.getValue(options) != null || + Log.getValue(options) != null || + isNotEmpty(DebugOptions.Count, options) || + isNotEmpty(DebugOptions.Time, options) || + isNotEmpty(DebugOptions.TrackMemUse, options) || + DumpOnPhaseChange.getValue(options) != null; + this.listMetrics = ListMetrics.getValue(options); + } + + private Immutable() { + this.options = new OptionValues(EconomicMap.create()); + this.unscopedCounters = null; + this.unscopedTimers = null; + this.unscopedMemUseTrackers = null; + this.scopesEnabled = false; + this.listMetrics = false; + } + + public boolean hasUnscopedMetrics() { + return unscopedCounters != null || unscopedTimers != null || unscopedMemUseTrackers != null; + } + } + + /** + * Gets the options this debug context was constructed with. + */ + public OptionValues getOptions() { + return immutable.options; + } + + static class Activated extends ThreadLocal { + } + + private static final Activated activated = new Activated(); + + /** + * An object used to undo the changes made by DebugContext#activate(). + */ + public static class Activation implements AutoCloseable { + private final DebugContext parent; + + Activation(DebugContext parent) { + this.parent = parent; + } + + @Override + public void close() { + activated.set(parent); + } + } + + /** + * Activates this object as the debug context {@linkplain DebugContext#forCurrentThread for the + * current thread}. This method should be used in a try-with-resources statement. + * + * @return an object that will deactivate the debug context for the current thread when + * {@link Activation#close()} is called on it + */ + public Activation activate() { + Activation res = new Activation(activated.get()); + activated.set(this); + return res; + } + + /** + * Shared object used to represent a disabled debug context. + */ + public static final DebugContext DISABLED = new DebugContext(NO_DESCRIPTION, NO_GLOBAL_METRIC_VALUES, DEFAULT_LOG_STREAM, new Immutable(), NO_CONFIG_CUSTOMIZERS); + + /** + * Gets the debug context for the current thread. This should only be used when there is no + * other reasonable means to get a hold of a debug context. + */ + public static DebugContext forCurrentThread() { + DebugContext current = activated.get(); + if (current == null) { + return DISABLED; + } + return current; + } + + private final GlobalMetrics globalMetrics; + + /** + * Describes the computation associated with a {@link DebugContext}. + */ + public static class Description { + /** + * The primary input to the computation. + */ + final Object compilable; + + /** + * A runtime based identifier that is most likely to be unique. + */ + final String identifier; + + public Description(Object compilable, String identifier) { + this.compilable = compilable; + this.identifier = identifier; + } + + @Override + public String toString() { + String compilableName = compilable instanceof JavaMethod ? ((JavaMethod) compilable).format("%H.%n(%p)%R") : String.valueOf(compilable); + return identifier + ":" + compilableName; + } + } + + private final Description description; + + /** + * Gets a description of the computation associated with this debug context. + * + * @return {@code null} if no description is available + */ + public Description getDescription() { + return description; + } + + /** + * Gets the global metrics associated with this debug context. + * + * @return {@code null} if no global metrics are available + */ + public GlobalMetrics getGlobalMetrics() { + return globalMetrics; + } + + /** + * Creates a {@link DebugContext} based on a given set of option values and {@code factory}. + */ + public static DebugContext create(OptionValues options, DebugHandlersFactory factory) { + return new DebugContext(NO_DESCRIPTION, NO_GLOBAL_METRIC_VALUES, DEFAULT_LOG_STREAM, Immutable.create(options), Collections.singletonList(factory)); + } + + /** + * Creates a {@link DebugContext} based on a given set of option values and {@code factories}. + * The {@link DebugHandlersFactory#LOADER} can be used for the latter. + */ + public static DebugContext create(OptionValues options, Iterable factories) { + return new DebugContext(NO_DESCRIPTION, NO_GLOBAL_METRIC_VALUES, DEFAULT_LOG_STREAM, Immutable.create(options), factories); + } + + /** + * Creates a {@link DebugContext}. + */ + public static DebugContext create(OptionValues options, Description description, GlobalMetrics globalMetrics, PrintStream logStream, Iterable factories) { + return new DebugContext(description, globalMetrics, logStream, Immutable.create(options), factories); + } + + private DebugContext(Description description, GlobalMetrics globalMetrics, PrintStream logStream, Immutable immutable, Iterable factories) { + this.immutable = immutable; + this.description = description; + this.globalMetrics = globalMetrics; + if (immutable.scopesEnabled) { + OptionValues options = immutable.options; + List dumpHandlers = new ArrayList<>(); + List verifyHandlers = new ArrayList<>(); + for (DebugHandlersFactory factory : factories) { + for (DebugHandler handler : factory.createHandlers(options)) { + if (handler instanceof DebugDumpHandler) { + dumpHandlers.add((DebugDumpHandler) handler); + } else { + assert handler instanceof DebugVerifyHandler; + verifyHandlers.add((DebugVerifyHandler) handler); + } + } + } + currentConfig = new DebugConfigImpl( + options, + Log.getValue(options), + Count.getValue(options), + TrackMemUse.getValue(options), + Time.getValue(options), + Dump.getValue(options), + Verify.getValue(options), + MethodFilter.getValue(options), + logStream, dumpHandlers, verifyHandlers); + currentScope = new ScopeImpl(this, Thread.currentThread()); + currentScope.updateFlags(currentConfig); + metricsEnabled = true; + } else { + metricsEnabled = immutable.hasUnscopedMetrics() || immutable.listMetrics; + } + } + + /** + * A special dump level that indicates the dumping machinery is enabled but no dumps will be + * produced except through other options. + */ + public static final int ENABLED_LEVEL = 0; + + /** + * Basic debug level. + * + * For HIR dumping, only ~5 graphs per method: after parsing, after inlining, after high tier, + * after mid tier, after low tier. + * + * LIR dumping: After LIR generation, after each pre-allocation, allocation and post allocation + * stage, and after code installation. + */ + public static final int BASIC_LEVEL = 1; + + /** + * Informational debug level. + * + * HIR dumping: One graph after each applied top-level phase. + * + * LIR dumping: After each applied phase. + */ + public static final int INFO_LEVEL = 2; + + /** + * Verbose debug level. + * + * HIR dumping: One graph after each phase (including sub phases). + * + * LIR dumping: After each phase including sub phases. + */ + public static final int VERBOSE_LEVEL = 3; + + /** + * Detailed debug level. + * + * HIR dumping: Graphs within phases where interesting for a phase, max ~5 per phase. + * + * LIR dumping: Dump CFG within phases where interesting. + */ + public static final int DETAILED_LEVEL = 4; + + /** + * Very detailed debug level. + * + * HIR dumping: Graphs per node granularity graph change (before/after change). + * + * LIR dumping: Intermediate CFGs of phases where interesting. + */ + public static final int VERY_DETAILED_LEVEL = 5; + + public boolean isDumpEnabled(int dumpLevel) { + return currentScope != null && currentScope.isDumpEnabled(dumpLevel); + } + + /** + * Determines if verification is enabled for any {@link JavaMethod} in the current scope. + * + * @see DebugContext#verify(Object, String) + */ + public boolean isVerifyEnabledForMethod() { + if (currentScope == null) { + return false; + } + if (currentConfig == null) { + return false; + } + return currentConfig.isVerifyEnabledForMethod(currentScope); + } + + /** + * Determines if verification is enabled in the current scope. + * + * @see DebugContext#verify(Object, String) + */ + public boolean isVerifyEnabled() { + return currentScope != null && currentScope.isVerifyEnabled(); + } + + public boolean isCountEnabled() { + return currentScope != null && currentScope.isCountEnabled(); + } + + public boolean isTimeEnabled() { + return currentScope != null && currentScope.isTimeEnabled(); + } + + public boolean isMemUseTrackingEnabled() { + return currentScope != null && currentScope.isMemUseTrackingEnabled(); + } + + public boolean isDumpEnabledForMethod() { + if (currentConfig == null) { + return false; + } + return currentConfig.isDumpEnabledForMethod(currentScope); + } + + public boolean isLogEnabledForMethod() { + if (currentScope == null) { + return false; + } + if (currentConfig == null) { + return false; + } + return currentConfig.isLogEnabledForMethod(currentScope); + } + + public boolean isLogEnabled() { + return currentScope != null && isLogEnabled(BASIC_LEVEL); + } + + public boolean isLogEnabled(int logLevel) { + return currentScope != null && currentScope.isLogEnabled(logLevel); + } + + /** + * Gets a string composed of the names in the current nesting of debug + * {@linkplain #scope(Object) scopes} separated by {@code '.'}. + */ + public String getCurrentScopeName() { + if (currentScope != null) { + return currentScope.getQualifiedName(); + } else { + return ""; + } + } + + /** + * Creates and enters a new debug scope which will be a child of the current debug scope. + *

+ * It is recommended to use the try-with-resource statement for managing entering and leaving + * debug scopes. For example: + * + *

+     * try (Scope s = Debug.scope("InliningGraph", inlineeGraph)) {
+     *     ...
+     * } catch (Throwable e) {
+     *     throw Debug.handle(e);
+     * }
+     * 
+ * + * The {@code name} argument is subject to the following type based conversion before having + * {@link Object#toString()} called on it: + * + *
+     *     Type          | Conversion
+     * ------------------+-----------------
+     *  java.lang.Class  | arg.getSimpleName()
+     *                   |
+     * 
+ * + * @param name the name of the new scope + * @param contextObjects an array of object to be appended to the {@linkplain #context() + * current} debug context + * @throws Throwable used to enforce a catch block. + * @return the scope entered by this method which will be exited when its {@link Scope#close()} + * method is called + */ + public DebugContext.Scope scope(Object name, Object[] contextObjects) throws Throwable { + if (currentScope != null) { + return enterScope(convertFormatArg(name).toString(), null, contextObjects); + } else { + return null; + } + } + + /** + * Similar to {@link #scope(Object, Object[])} but without context objects. Therefore the catch + * block can be omitted. + * + * @see #scope(Object, Object[]) + */ + public DebugContext.Scope scope(Object name) { + if (currentScope != null) { + return enterScope(convertFormatArg(name).toString(), null); + } else { + return null; + } + } + + private final Invariants invariants = Assertions.ENABLED ? new Invariants() : null; + + static StackTraceElement[] getStackTrace(Thread thread) { + return thread.getStackTrace(); + } + + /** + * Utility for enforcing {@link DebugContext} invariants via assertions. + */ + static class Invariants { + private final Thread thread; + private final StackTraceElement[] origin; + + Invariants() { + thread = Thread.currentThread(); + origin = getStackTrace(thread); + } + + boolean checkNoConcurrentAccess() { + Thread currentThread = Thread.currentThread(); + if (currentThread != thread) { + Formatter buf = new Formatter(); + buf.format("Thread local %s object was created on thread %s but is being accessed by thread %s. The most likely cause is " + + "that the object is being retrieved from a non-thread-local cache.", + DebugContext.class.getName(), thread, currentThread); + int debugContextConstructors = 0; + boolean addedHeader = false; + for (StackTraceElement e : origin) { + if (e.getMethodName().equals("") && e.getClassName().equals(DebugContext.class.getName())) { + debugContextConstructors++; + } else if (debugContextConstructors != 0) { + if (!addedHeader) { + addedHeader = true; + buf.format(" The object was instantiated here:"); + } + // Distinguish from assertion stack trace by using double indent and + // "in" instead of "at" prefix. + buf.format("%n\t\tin %s", e); + } + } + if (addedHeader) { + buf.format("%n"); + } + + throw new AssertionError(buf.toString()); + } + return true; + } + } + + boolean checkNoConcurrentAccess() { + assert invariants == null || invariants.checkNoConcurrentAccess(); + return true; + } + + private DebugContext.Scope enterScope(CharSequence name, DebugConfig sandboxConfig, Object... newContextObjects) { + assert checkNoConcurrentAccess(); + currentScope = currentScope.scope(name, sandboxConfig, newContextObjects); + return currentScope; + } + + /** + * @see #scope(Object, Object[]) + * @param context an object to be appended to the {@linkplain #context() current} debug context + */ + public DebugContext.Scope scope(Object name, Object context) throws Throwable { + if (currentScope != null) { + return enterScope(convertFormatArg(name).toString(), null, context); + } else { + return null; + } + } + + /** + * @see #scope(Object, Object[]) + * @param context1 first object to be appended to the {@linkplain #context() current} debug + * context + * @param context2 second object to be appended to the {@linkplain #context() current} debug + * context + */ + public DebugContext.Scope scope(Object name, Object context1, Object context2) throws Throwable { + if (currentScope != null) { + return enterScope(convertFormatArg(name).toString(), null, context1, context2); + } else { + return null; + } + } + + /** + * @see #scope(Object, Object[]) + * @param context1 first object to be appended to the {@linkplain #context() current} debug + * context + * @param context2 second object to be appended to the {@linkplain #context() current} debug + * context + * @param context3 third object to be appended to the {@linkplain #context() current} debug + * context + */ + public DebugContext.Scope scope(Object name, Object context1, Object context2, Object context3) throws Throwable { + if (currentScope != null) { + return enterScope(convertFormatArg(name).toString(), null, context1, context2, context3); + } else { + return null; + } + } + + /** + * Creates and enters a new debug scope which will be disjoint from the current debug scope. + *

+ * It is recommended to use the try-with-resource statement for managing entering and leaving + * debug scopes. For example: + * + *

+     * try (Scope s = Debug.sandbox("CompilingStub", null, stubGraph)) {
+     *     ...
+     * } catch (Throwable e) {
+     *     throw Debug.handle(e);
+     * }
+     * 
+ * + * @param name the name of the new scope + * @param config the debug configuration to use for the new scope or {@code null} to disable the + * scoping mechanism within the sandbox scope + * @param context objects to be appended to the {@linkplain #context() current} debug context + * @return the scope entered by this method which will be exited when its {@link Scope#close()} + * method is called + */ + public DebugContext.Scope sandbox(CharSequence name, DebugConfig config, Object... context) throws Throwable { + if (config == null) { + return disable(); + } + if (currentScope != null) { + return enterScope(name, config, context); + } else { + return null; + } + } + + class DisabledScope implements DebugContext.Scope { + final boolean savedMetricsEnabled; + final ScopeImpl savedScope; + final DebugConfig savedConfig; + + DisabledScope() { + this.savedMetricsEnabled = metricsEnabled; + this.savedScope = currentScope; + this.savedConfig = currentConfig; + metricsEnabled = false; + currentScope = null; + currentConfig = null; + } + + @Override + public String getQualifiedName() { + return ""; + } + + @Override + public Iterable getCurrentContext() { + return Collections.emptyList(); + } + + @Override + public void close() { + metricsEnabled = savedMetricsEnabled; + currentScope = savedScope; + currentConfig = savedConfig; + lastClosedScope = this; + } + } + + /** + * Disables all metrics and scope related functionality until {@code close()} is called on the + * returned object. + */ + public DebugContext.Scope disable() { + if (currentScope != null) { + return new DisabledScope(); + } else { + return null; + } + } + + public DebugContext.Scope forceLog() throws Throwable { + if (currentConfig != null) { + ArrayList context = new ArrayList<>(); + for (Object obj : context()) { + context.add(obj); + } + DebugConfigImpl config = new DebugConfigImpl(new OptionValues(currentConfig.getOptions(), DebugOptions.Log, ":1000")); + return sandbox("forceLog", config, context.toArray()); + } + return null; + } + + /** + * Opens a scope in which exception + * {@linkplain DebugConfig#interceptException(DebugContext, Throwable) interception} is + * disabled. The current state of interception is restored when {@link DebugCloseable#close()} + * is called on the returned object. + * + * This is particularly useful to suppress extraneous output in JUnit tests that are expected to + * throw an exception. + */ + public DebugCloseable disableIntercept() { + if (currentScope != null) { + return currentScope.disableIntercept(); + } + return null; + } + + /** + * Handles an exception in the context of the debug scope just exited. The just exited scope + * must have the current scope as its parent which will be the case if the try-with-resource + * pattern recommended by {@link #scope(Object)} and + * {@link #sandbox(CharSequence, DebugConfig, Object...)} is used + * + * @see #scope(Object, Object[]) + * @see #sandbox(CharSequence, DebugConfig, Object...) + */ + public RuntimeException handle(Throwable exception) { + if (currentScope != null) { + return currentScope.handle(exception); + } else { + if (exception instanceof Error) { + throw (Error) exception; + } + if (exception instanceof RuntimeException) { + throw (RuntimeException) exception; + } + throw new RuntimeException(exception); + } + } + + public void log(String msg) { + log(BASIC_LEVEL, msg); + } + + /** + * Prints a message to the current debug scope's logging stream if logging is enabled. + * + * @param msg the message to log + */ + public void log(int logLevel, String msg) { + if (currentScope != null) { + currentScope.log(logLevel, msg); + } + } + + public void log(String format, Object arg) { + log(BASIC_LEVEL, format, arg); + } + + /** + * Prints a message to the current debug scope's logging stream if logging is enabled. + * + * @param format a format string + * @param arg the argument referenced by the format specifiers in {@code format} + */ + public void log(int logLevel, String format, Object arg) { + if (currentScope != null) { + currentScope.log(logLevel, format, arg); + } + } + + public void log(String format, int arg) { + log(BASIC_LEVEL, format, arg); + } + + /** + * Prints a message to the current debug scope's logging stream if logging is enabled. + * + * @param format a format string + * @param arg the argument referenced by the format specifiers in {@code format} + */ + public void log(int logLevel, String format, int arg) { + if (currentScope != null) { + currentScope.log(logLevel, format, arg); + } + } + + public void log(String format, Object arg1, Object arg2) { + log(BASIC_LEVEL, format, arg1, arg2); + } + + /** + * @see #log(int, String, Object) + */ + public void log(int logLevel, String format, Object arg1, Object arg2) { + if (currentScope != null) { + currentScope.log(logLevel, format, arg1, arg2); + } + } + + public void log(String format, int arg1, Object arg2) { + log(BASIC_LEVEL, format, arg1, arg2); + } + + /** + * @see #log(int, String, Object) + */ + public void log(int logLevel, String format, int arg1, Object arg2) { + if (currentScope != null) { + currentScope.log(logLevel, format, arg1, arg2); + } + } + + public void log(String format, Object arg1, int arg2) { + log(BASIC_LEVEL, format, arg1, arg2); + } + + /** + * @see #log(int, String, Object) + */ + public void log(int logLevel, String format, Object arg1, int arg2) { + if (currentScope != null) { + currentScope.log(logLevel, format, arg1, arg2); + } + } + + public void log(String format, int arg1, int arg2) { + log(BASIC_LEVEL, format, arg1, arg2); + } + + /** + * @see #log(int, String, Object) + */ + public void log(int logLevel, String format, int arg1, int arg2) { + if (currentScope != null) { + currentScope.log(logLevel, format, arg1, arg2); + } + } + + public void log(String format, Object arg1, Object arg2, Object arg3) { + log(BASIC_LEVEL, format, arg1, arg2, arg3); + } + + /** + * @see #log(int, String, Object) + */ + public void log(int logLevel, String format, Object arg1, Object arg2, Object arg3) { + if (currentScope != null) { + currentScope.log(logLevel, format, arg1, arg2, arg3); + } + } + + public void log(String format, int arg1, int arg2, int arg3) { + log(BASIC_LEVEL, format, arg1, arg2, arg3); + } + + /** + * @see #log(int, String, Object) + */ + public void log(int logLevel, String format, int arg1, int arg2, int arg3) { + if (currentScope != null) { + currentScope.log(logLevel, format, arg1, arg2, arg3); + } + } + + public void log(String format, Object arg1, Object arg2, Object arg3, Object arg4) { + log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4); + } + + /** + * @see #log(int, String, Object) + */ + public void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4) { + if (currentScope != null) { + currentScope.log(logLevel, format, arg1, arg2, arg3, arg4); + } + } + + public void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) { + log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5); + } + + /** + * @see #log(int, String, Object) + */ + public void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) { + if (currentScope != null) { + currentScope.log(logLevel, format, arg1, arg2, arg3, arg4, arg5); + } + } + + public void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) { + log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6); + } + + /** + * @see #log(int, String, Object) + */ + public void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) { + if (currentScope != null) { + currentScope.log(logLevel, format, arg1, arg2, arg3, arg4, arg5, arg6); + } + } + + public void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7) { + log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7); + } + + public void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8) { + log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + } + + /** + * @see #log(int, String, Object) + */ + public void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7) { + if (currentScope != null) { + currentScope.log(logLevel, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7); + } + } + + public void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8) { + if (currentScope != null) { + currentScope.log(logLevel, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + } + } + + public void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9) { + log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); + } + + public void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9) { + if (currentScope != null) { + currentScope.log(logLevel, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); + } + } + + public void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10) { + log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); + } + + public void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10) { + if (currentScope != null) { + currentScope.log(logLevel, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); + } + } + + public void logv(String format, Object... args) { + logv(BASIC_LEVEL, format, args); + } + + /** + * Prints a message to the current debug scope's logging stream. This method must only be called + * if debugging scopes are {@linkplain DebugContext#areScopesEnabled() enabled} as it incurs + * allocation at the call site. If possible, call one of the other {@code log()} methods in this + * class that take a fixed number of parameters. + * + * @param format a format string + * @param args the arguments referenced by the format specifiers in {@code format} + */ + public void logv(int logLevel, String format, Object... args) { + if (currentScope == null) { + throw new InternalError("Use of Debug.logv() must be guarded by a test of Debug.isEnabled()"); + } + currentScope.log(logLevel, format, args); + } + + /** + * This override exists to catch cases when {@link #log(String, Object)} is called with one + * argument bound to a varargs method parameter. It will bind to this method instead of the + * single arg variant and produce a deprecation warning instead of silently wrapping the + * Object[] inside of another Object[]. + */ + @Deprecated + public void log(String format, Object[] args) { + assert false : "shouldn't use this"; + log(BASIC_LEVEL, format, args); + } + + /** + * This override exists to catch cases when {@link #log(int, String, Object)} is called with one + * argument bound to a varargs method parameter. It will bind to this method instead of the + * single arg variant and produce a deprecation warning instead of silently wrapping the + * Object[] inside of another Object[]. + */ + @Deprecated + public void log(int logLevel, String format, Object[] args) { + assert false : "shouldn't use this"; + logv(logLevel, format, args); + } + + /** + * Forces an unconditional dump. This method exists mainly for debugging. It can also be used to + * force a graph dump from IDEs that support invoking a Java method while at a breakpoint. + */ + public void forceDump(Object object, String format, Object... args) { + DebugConfig config = currentConfig; + Collection dumpHandlers; + boolean closeAfterDump; + if (config != null) { + dumpHandlers = config.dumpHandlers(); + closeAfterDump = false; + } else { + OptionValues options = getOptions(); + dumpHandlers = new ArrayList<>(); + for (DebugHandlersFactory factory : DebugHandlersFactory.LOADER) { + for (DebugHandler handler : factory.createHandlers(options)) { + if (handler instanceof DebugDumpHandler) { + dumpHandlers.add((DebugDumpHandler) handler); + } + } + } + closeAfterDump = true; + } + for (DebugDumpHandler dumpHandler : dumpHandlers) { + dumpHandler.dump(this, object, format, args); + if (closeAfterDump) { + dumpHandler.close(); + } + } + } + + public void dump(int dumpLevel, Object object, String msg) { + if (currentScope != null && currentScope.isDumpEnabled(dumpLevel)) { + currentScope.dump(dumpLevel, object, msg); + } + } + + public void dump(int dumpLevel, Object object, String format, Object arg) { + if (currentScope != null && currentScope.isDumpEnabled(dumpLevel)) { + currentScope.dump(dumpLevel, object, format, arg); + } + } + + public void dump(int dumpLevel, Object object, String format, Object arg1, Object arg2) { + if (currentScope != null && currentScope.isDumpEnabled(dumpLevel)) { + currentScope.dump(dumpLevel, object, format, arg1, arg2); + } + } + + public void dump(int dumpLevel, Object object, String format, Object arg1, Object arg2, Object arg3) { + if (currentScope != null && currentScope.isDumpEnabled(dumpLevel)) { + currentScope.dump(dumpLevel, object, format, arg1, arg2, arg3); + } + } + + /** + * This override exists to catch cases when {@link #dump(int, Object, String, Object)} is called + * with one argument bound to a varargs method parameter. It will bind to this method instead of + * the single arg variant and produce a deprecation warning instead of silently wrapping the + * Object[] inside of another Object[]. + */ + @Deprecated + public void dump(int dumpLevel, Object object, String format, Object[] args) { + assert false : "shouldn't use this"; + if (currentScope != null && currentScope.isDumpEnabled(dumpLevel)) { + currentScope.dump(dumpLevel, object, format, args); + } + } + + /** + * Calls all {@link DebugVerifyHandler}s in the current {@linkplain #getConfig() config} to + * perform verification on a given object. + * + * @param object object to verify + * @param message description of verification context + * + * @see DebugVerifyHandler#verify + */ + public void verify(Object object, String message) { + if (currentScope != null && currentScope.isVerifyEnabled()) { + currentScope.verify(object, message); + } + } + + /** + * Calls all {@link DebugVerifyHandler}s in the current {@linkplain #getConfig() config} to + * perform verification on a given object. + * + * @param object object to verify + * @param format a format string for the description of the verification context + * @param arg the argument referenced by the format specifiers in {@code format} + * + * @see DebugVerifyHandler#verify + */ + public void verify(Object object, String format, Object arg) { + if (currentScope != null && currentScope.isVerifyEnabled()) { + currentScope.verify(object, format, arg); + } + } + + /** + * This override exists to catch cases when {@link #verify(Object, String, Object)} is called + * with one argument bound to a varargs method parameter. It will bind to this method instead of + * the single arg variant and produce a deprecation warning instead of silently wrapping the + * Object[] inside of another Object[]. + */ + @Deprecated + public void verify(Object object, String format, Object[] args) { + assert false : "shouldn't use this"; + if (currentScope != null && currentScope.isVerifyEnabled()) { + currentScope.verify(object, format, args); + } + } + + /** + * Opens a new indentation level (by adding some spaces) based on the current indentation level. + * This should be used in a {@linkplain Indent try-with-resources} pattern. + * + * @return an object that reverts to the current indentation level when + * {@linkplain Indent#close() closed} or null if debugging is disabled + * @see #logAndIndent(int, String) + * @see #logAndIndent(int, String, Object) + */ + public Indent indent() { + if (currentScope != null) { + return currentScope.pushIndentLogger(); + } + return null; + } + + public Indent logAndIndent(String msg) { + return logAndIndent(BASIC_LEVEL, msg); + } + + /** + * A convenience function which combines {@link #log(String)} and {@link #indent()}. + * + * @param msg the message to log + * @return an object that reverts to the current indentation level when + * {@linkplain Indent#close() closed} or null if debugging is disabled + */ + public Indent logAndIndent(int logLevel, String msg) { + if (currentScope != null && isLogEnabled(logLevel)) { + return logvAndIndentInternal(logLevel, msg); + } + return null; + } + + public Indent logAndIndent(String format, Object arg) { + return logAndIndent(BASIC_LEVEL, format, arg); + } + + /** + * A convenience function which combines {@link #log(String, Object)} and {@link #indent()}. + * + * @param format a format string + * @param arg the argument referenced by the format specifiers in {@code format} + * @return an object that reverts to the current indentation level when + * {@linkplain Indent#close() closed} or null if debugging is disabled + */ + public Indent logAndIndent(int logLevel, String format, Object arg) { + if (currentScope != null && isLogEnabled(logLevel)) { + return logvAndIndentInternal(logLevel, format, arg); + } + return null; + } + + public Indent logAndIndent(String format, int arg) { + return logAndIndent(BASIC_LEVEL, format, arg); + } + + /** + * A convenience function which combines {@link #log(String, Object)} and {@link #indent()}. + * + * @param format a format string + * @param arg the argument referenced by the format specifiers in {@code format} + * @return an object that reverts to the current indentation level when + * {@linkplain Indent#close() closed} or null if debugging is disabled + */ + public Indent logAndIndent(int logLevel, String format, int arg) { + if (currentScope != null && isLogEnabled(logLevel)) { + return logvAndIndentInternal(logLevel, format, arg); + } + return null; + } + + public Indent logAndIndent(String format, int arg1, Object arg2) { + return logAndIndent(BASIC_LEVEL, format, arg1, arg2); + } + + /** + * @see #logAndIndent(int, String, Object) + */ + public Indent logAndIndent(int logLevel, String format, int arg1, Object arg2) { + if (currentScope != null && isLogEnabled(logLevel)) { + return logvAndIndentInternal(logLevel, format, arg1, arg2); + } + return null; + } + + public Indent logAndIndent(String format, Object arg1, int arg2) { + return logAndIndent(BASIC_LEVEL, format, arg1, arg2); + } + + /** + * @see #logAndIndent(int, String, Object) + */ + public Indent logAndIndent(int logLevel, String format, Object arg1, int arg2) { + if (currentScope != null && isLogEnabled(logLevel)) { + return logvAndIndentInternal(logLevel, format, arg1, arg2); + } + return null; + } + + public Indent logAndIndent(String format, int arg1, int arg2) { + return logAndIndent(BASIC_LEVEL, format, arg1, arg2); + } + + /** + * @see #logAndIndent(int, String, Object) + */ + public Indent logAndIndent(int logLevel, String format, int arg1, int arg2) { + if (currentScope != null && isLogEnabled(logLevel)) { + return logvAndIndentInternal(logLevel, format, arg1, arg2); + } + return null; + } + + public Indent logAndIndent(String format, Object arg1, Object arg2) { + return logAndIndent(BASIC_LEVEL, format, arg1, arg2); + } + + /** + * @see #logAndIndent(int, String, Object) + */ + public Indent logAndIndent(int logLevel, String format, Object arg1, Object arg2) { + if (currentScope != null && isLogEnabled(logLevel)) { + return logvAndIndentInternal(logLevel, format, arg1, arg2); + } + return null; + } + + public Indent logAndIndent(String format, Object arg1, Object arg2, Object arg3) { + return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3); + } + + /** + * @see #logAndIndent(int, String, Object) + */ + public Indent logAndIndent(int logLevel, String format, Object arg1, Object arg2, Object arg3) { + if (currentScope != null && isLogEnabled(logLevel)) { + return logvAndIndentInternal(logLevel, format, arg1, arg2, arg3); + } + return null; + } + + public Indent logAndIndent(String format, int arg1, int arg2, int arg3) { + return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3); + } + + /** + * @see #logAndIndent(int, String, Object) + */ + public Indent logAndIndent(int logLevel, String format, int arg1, int arg2, int arg3) { + if (currentScope != null && isLogEnabled(logLevel)) { + return logvAndIndentInternal(logLevel, format, arg1, arg2, arg3); + } + return null; + } + + public Indent logAndIndent(String format, Object arg1, int arg2, int arg3) { + return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3); + } + + /** + * @see #logAndIndent(int, String, Object) + */ + public Indent logAndIndent(int logLevel, String format, Object arg1, int arg2, int arg3) { + if (currentScope != null && isLogEnabled(logLevel)) { + return logvAndIndentInternal(logLevel, format, arg1, arg2, arg3); + } + return null; + } + + public Indent logAndIndent(String format, Object arg1, Object arg2, Object arg3, Object arg4) { + return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3, arg4); + } + + /** + * @see #logAndIndent(int, String, Object) + */ + public Indent logAndIndent(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4) { + if (currentScope != null && isLogEnabled(logLevel)) { + return logvAndIndentInternal(logLevel, format, arg1, arg2, arg3, arg4); + } + return null; + } + + public Indent logAndIndent(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) { + return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5); + } + + /** + * @see #logAndIndent(int, String, Object) + */ + public Indent logAndIndent(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) { + if (currentScope != null && isLogEnabled(logLevel)) { + return logvAndIndentInternal(logLevel, format, arg1, arg2, arg3, arg4, arg5); + } + return null; + } + + public Indent logAndIndent(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) { + return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6); + } + + /** + * @see #logAndIndent(int, String, Object) + */ + public Indent logAndIndent(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) { + if (currentScope != null && isLogEnabled(logLevel)) { + return logvAndIndentInternal(logLevel, format, arg1, arg2, arg3, arg4, arg5, arg6); + } + return null; + } + + /** + * A convenience function which combines {@link #logv(int, String, Object...)} and + * {@link #indent()}. + * + * @param format a format string + * @param args the arguments referenced by the format specifiers in {@code format} + * @return an object that reverts to the current indentation level when + * {@linkplain Indent#close() closed} or null if debugging is disabled + */ + public Indent logvAndIndent(int logLevel, String format, Object... args) { + if (currentScope != null) { + if (isLogEnabled(logLevel)) { + return logvAndIndentInternal(logLevel, format, args); + } + return null; + } + throw new InternalError("Use of Debug.logvAndIndent() must be guarded by a test of Debug.isEnabled()"); + } + + private Indent logvAndIndentInternal(int logLevel, String format, Object... args) { + assert currentScope != null && isLogEnabled(logLevel) : "must have checked Debug.isLogEnabled()"; + currentScope.log(logLevel, format, args); + return currentScope.pushIndentLogger(); + } + + /** + * This override exists to catch cases when {@link #logAndIndent(String, Object)} is called with + * one argument bound to a varargs method parameter. It will bind to this method instead of the + * single arg variant and produce a deprecation warning instead of silently wrapping the + * Object[] inside of another Object[]. + */ + @Deprecated + public void logAndIndent(String format, Object[] args) { + assert false : "shouldn't use this"; + logAndIndent(BASIC_LEVEL, format, args); + } + + /** + * This override exists to catch cases when {@link #logAndIndent(int, String, Object)} is called + * with one argument bound to a varargs method parameter. It will bind to this method instead of + * the single arg variant and produce a deprecation warning instead of silently wrapping the + * Object[] inside of another Object[]. + */ + @Deprecated + public void logAndIndent(int logLevel, String format, Object[] args) { + assert false : "shouldn't use this"; + logvAndIndent(logLevel, format, args); + } + + public Iterable context() { + if (currentScope != null) { + return currentScope.getCurrentContext(); + } else { + return Collections.emptyList(); + } + } + + @SuppressWarnings("unchecked") + public List contextSnapshot(Class clazz) { + if (currentScope != null) { + List result = new ArrayList<>(); + for (Object o : context()) { + if (clazz.isInstance(o)) { + result.add((T) o); + } + } + return result; + } else { + return Collections.emptyList(); + } + } + + /** + * Searches the current debug scope, bottom up, for a context object that is an instance of a + * given type. The first such object found is returned. + */ + @SuppressWarnings("unchecked") + public T contextLookup(Class clazz) { + if (currentScope != null) { + for (Object o : context()) { + if (clazz.isInstance(o)) { + return ((T) o); + } + } + } + return null; + } + + /** + * Searches the current debug scope, top down, for a context object that is an instance of a + * given type. The first such object found is returned. + */ + @SuppressWarnings("unchecked") + public T contextLookupTopdown(Class clazz) { + if (currentScope != null) { + T found = null; + for (Object o : context()) { + if (clazz.isInstance(o)) { + found = (T) o; + } + } + return found; + } + return null; + } + + /** + * Creates a {@linkplain MemUseTrackerKey memory use tracker}. + */ + public static MemUseTrackerKey memUseTracker(CharSequence name) { + return createMemUseTracker("%s", name, null); + } + + /** + * Creates a debug memory use tracker. Invoking this method is equivalent to: + * + *
+     * Debug.memUseTracker(format, arg, null)
+     * 
+ * + * except that the string formatting only happens if mem tracking is enabled. + * + * @see #counter(String, Object, Object) + */ + public static MemUseTrackerKey memUseTracker(String format, Object arg) { + return createMemUseTracker(format, arg, null); + } + + /** + * Creates a debug memory use tracker. Invoking this method is equivalent to: + * + *
+     * Debug.memUseTracker(String.format(format, arg1, arg2))
+     * 
+ * + * except that the string formatting only happens if memory use tracking is enabled. In + * addition, each argument is subject to the following type based conversion before being passed + * as an argument to {@link String#format(String, Object...)}: + * + *
+     *     Type          | Conversion
+     * ------------------+-----------------
+     *  java.lang.Class  | arg.getSimpleName()
+     *                   |
+     * 
+ * + * @see #memUseTracker(CharSequence) + */ + public static MemUseTrackerKey memUseTracker(String format, Object arg1, Object arg2) { + return createMemUseTracker(format, arg1, arg2); + } + + private static MemUseTrackerKey createMemUseTracker(String format, Object arg1, Object arg2) { + return new MemUseTrackerKeyImpl(format, arg1, arg2); + } + + /** + * Creates a {@linkplain CounterKey counter}. + */ + public static CounterKey counter(CharSequence name) { + return createCounter("%s", name, null); + } + + /** + * Gets a tally of the metric values in this context and a given tally. + * + * @param tally the tally to which the metrics should be added + * @return a tally of the metric values in this context and {@code tally}. This will be + * {@code tally} if this context has no metric values or {@code tally} is wide enough to + * hold all the metric values in this context otherwise it will be a new array. + */ + public long[] addValuesTo(long[] tally) { + if (metricValues == null) { + return tally; + } + if (tally == null) { + return metricValues.clone(); + } else if (metricValues.length >= tally.length) { + long[] newTally = metricValues.clone(); + for (int i = 0; i < tally.length; i++) { + newTally[i] += tally[i]; + } + return newTally; + } else { + for (int i = 0; i < metricValues.length; i++) { + tally[i] += metricValues[i]; + } + return tally; + } + } + + /** + * Creates and returns a sorted map from metric names to their values in {@code values}. + * + * @param values values for metrics in the {@link KeyRegistry}. + */ + public static EconomicMap convertValuesToKeyValueMap(long[] values) { + List keys = KeyRegistry.getKeys(); + Collections.sort(keys, MetricKey.NAME_COMPARATOR); + EconomicMap res = EconomicMap.create(keys.size()); + for (MetricKey key : keys) { + int index = ((AbstractKey) key).getIndex(); + if (index >= values.length) { + res.put(key, 0L); + } else { + res.put(key, values[index]); + } + } + return res; + } + + void setMetricValue(int keyIndex, long l) { + ensureMetricValuesSize(keyIndex); + metricValues[keyIndex] = l; + } + + long getMetricValue(int keyIndex) { + if (metricValues == null || metricValues.length <= keyIndex) { + return 0L; + } + return metricValues[keyIndex]; + } + + private void ensureMetricValuesSize(int index) { + if (metricValues == null) { + metricValues = new long[index + 1]; + } + if (metricValues.length <= index) { + metricValues = Arrays.copyOf(metricValues, index + 1); + } + } + + public static String applyFormattingFlagsAndWidth(String s, int flags, int width) { + if (flags == 0 && width < 0) { + return s; + } + StringBuilder sb = new StringBuilder(s); + + // apply width and justification + int len = sb.length(); + if (len < width) { + for (int i = 0; i < width - len; i++) { + if ((flags & LEFT_JUSTIFY) == LEFT_JUSTIFY) { + sb.append(' '); + } else { + sb.insert(0, ' '); + } + } + } + + String res = sb.toString(); + if ((flags & UPPERCASE) == UPPERCASE) { + res = res.toUpperCase(); + } + return res; + } + + /** + * Creates a debug counter. Invoking this method is equivalent to: + * + *
+     * Debug.counter(format, arg, null)
+     * 
+ * + * except that the string formatting only happens if count is enabled. + * + * @see #counter(String, Object, Object) + */ + public static CounterKey counter(String format, Object arg) { + return createCounter(format, arg, null); + } + + /** + * Creates a debug counter. Invoking this method is equivalent to: + * + *
+     * Debug.counter(String.format(format, arg1, arg2))
+     * 
+ * + * except that the string formatting only happens if count is enabled. In addition, each + * argument is subject to the following type based conversion before being passed as an argument + * to {@link String#format(String, Object...)}: + * + *
+     *     Type          | Conversion
+     * ------------------+-----------------
+     *  java.lang.Class  | arg.getSimpleName()
+     *                   |
+     * 
+ * + * @see #counter(CharSequence) + */ + public static CounterKey counter(String format, Object arg1, Object arg2) { + return createCounter(format, arg1, arg2); + } + + private static CounterKey createCounter(String format, Object arg1, Object arg2) { + return new CounterKeyImpl(format, arg1, arg2); + } + + public DebugConfig getConfig() { + return currentConfig; + } + + /** + * Creates a {@linkplain TimerKey timer}. + *

+ * A disabled timer has virtually no overhead. + */ + public static TimerKey timer(CharSequence name) { + return createTimer("%s", name, null); + } + + /** + * Creates a debug timer. Invoking this method is equivalent to: + * + *

+     * Debug.timer(format, arg, null)
+     * 
+ * + * except that the string formatting only happens if timing is enabled. + * + * @see #timer(String, Object, Object) + */ + public static TimerKey timer(String format, Object arg) { + return createTimer(format, arg, null); + } + + /** + * Creates a debug timer. Invoking this method is equivalent to: + * + *
+     * Debug.timer(String.format(format, arg1, arg2))
+     * 
+ * + * except that the string formatting only happens if timing is enabled. In addition, each + * argument is subject to the following type based conversion before being passed as an argument + * to {@link String#format(String, Object...)}: + * + *
+     *     Type          | Conversion
+     * ------------------+-----------------
+     *  java.lang.Class  | arg.getSimpleName()
+     *                   |
+     * 
+ * + * @see #timer(CharSequence) + */ + public static TimerKey timer(String format, Object arg1, Object arg2) { + return createTimer(format, arg1, arg2); + } + + /** + * There are paths where construction of formatted class names are common and the code below is + * surprisingly expensive, so compute it once and cache it. + */ + private static final ClassValue formattedClassName = new ClassValue() { + @Override + protected String computeValue(Class c) { + final String simpleName = c.getSimpleName(); + Class enclosingClass = c.getEnclosingClass(); + if (enclosingClass != null) { + String prefix = ""; + while (enclosingClass != null) { + prefix = enclosingClass.getSimpleName() + "_" + prefix; + enclosingClass = enclosingClass.getEnclosingClass(); + } + return prefix + simpleName; + } else { + return simpleName; + } + } + }; + + public static Object convertFormatArg(Object arg) { + if (arg instanceof Class) { + return formattedClassName.get((Class) arg); + } + return arg; + } + + static String formatDebugName(String format, Object arg1, Object arg2) { + return String.format(format, convertFormatArg(arg1), convertFormatArg(arg2)); + } + + private static TimerKey createTimer(String format, Object arg1, Object arg2) { + return new TimerKeyImpl(format, arg1, arg2); + } + + /** + * Represents a debug scope entered by {@link DebugContext#scope(Object)} or + * {@link DebugContext#sandbox(CharSequence, DebugConfig, Object...)}. Leaving the scope is + * achieved via {@link #close()}. + */ + public interface Scope extends AutoCloseable { + /** + * Gets the names of this scope and its ancestors separated by {@code '.'}. + */ + String getQualifiedName(); + + Iterable getCurrentContext(); + + @Override + void close(); + } + + boolean isTimerEnabled(TimerKeyImpl key) { + if (!metricsEnabled) { + // Pulling this common case out of `isTimerEnabledSlow` + // gives C1 a better chance to inline this method. + return false; + } + return isTimerEnabledSlow(key); + } + + private boolean isTimerEnabledSlow(AbstractKey key) { + if (currentScope != null && currentScope.isTimeEnabled()) { + return true; + } + if (immutable.listMetrics) { + key.ensureInitialized(); + } + assert checkNoConcurrentAccess(); + EconomicSet unscoped = immutable.unscopedTimers; + return unscoped != null && (unscoped.isEmpty() || unscoped.contains(key.getName())); + } + + /** + * Determines if a given timer is enabled in the current scope. + */ + boolean isCounterEnabled(CounterKeyImpl key) { + if (!metricsEnabled) { + // Pulling this common case out of `isCounterEnabledSlow` + // gives C1 a better chance to inline this method. + return false; + } + return isCounterEnabledSlow(key); + } + + private boolean isCounterEnabledSlow(AbstractKey key) { + if (currentScope != null && currentScope.isCountEnabled()) { + return true; + } + if (immutable.listMetrics) { + key.ensureInitialized(); + } + assert checkNoConcurrentAccess(); + EconomicSet unscoped = immutable.unscopedCounters; + return unscoped != null && (unscoped.isEmpty() || unscoped.contains(key.getName())); + } + + boolean isMemUseTrackerEnabled(MemUseTrackerKeyImpl key) { + if (!metricsEnabled) { + // Pulling this common case out of `isMemUseTrackerEnabledSlow` + // gives C1 a better chance to inline this method. + return false; + } + return isMemUseTrackerEnabledSlow(key); + } + + private boolean isMemUseTrackerEnabledSlow(AbstractKey key) { + if (currentScope != null && currentScope.isMemUseTrackingEnabled()) { + return true; + } + if (immutable.listMetrics) { + key.ensureInitialized(); + } + assert checkNoConcurrentAccess(); + EconomicSet unscoped = immutable.unscopedMemUseTrackers; + return unscoped != null && (unscoped.isEmpty() || unscoped.contains(key.getName())); + } + + public boolean areMetricsEnabled() { + return metricsEnabled; + } + + @Override + public void close() { + closeDumpHandlers(false); + if (description != null) { + printMetrics(description); + } + if (metricsEnabled && globalMetrics != null && metricValues != null) { + globalMetrics.add(this); + } + metricValues = null; + } + + public void closeDumpHandlers(boolean ignoreErrors) { + if (currentConfig != null) { + currentConfig.closeDumpHandlers(ignoreErrors); + } + } + + /** + * Records how many times a given method has been compiled. + */ + private static EconomicMap compilations; + + /** + * Maintains maximum buffer size used by {@link #printMetrics(Description)} to minimize buffer + * resizing during subsequent calls to this method. + */ + private static int metricsBufSize = 50_000; + + /** + * Flag that allows the first call to {@link #printMetrics(Description)} to delete the file that + * will be appended to. + */ + private static boolean metricsFileDeleteCheckPerformed; + + /** + * Prints metric values in this object to the file (if any) specified by + * {@link DebugOptions#MetricsFile}. + */ + public void printMetrics(Description desc) { + if (metricValues == null) { + return; + } + String metricsFile = DebugOptions.MetricsFile.getValue(getOptions()); + if (metricsFile != null) { + // Use identity to distinguish methods that have been redefined + // or loaded by different class loaders. + Object compilable = desc.compilable; + Integer identity = System.identityHashCode(compilable); + int compilationNr; + synchronized (PRINT_METRICS_LOCK) { + if (!metricsFileDeleteCheckPerformed) { + metricsFileDeleteCheckPerformed = true; + File file = new File(metricsFile); + if (file.exists()) { + // This can return false in case something like /dev/stdout + // is specified. If the file is unwriteable, the file open + // below will fail. + file.delete(); + } + } + if (compilations == null) { + compilationNr = 0; + compilations = EconomicMap.create(); + } else { + Integer value = compilations.get(identity); + compilationNr = value == null ? 0 : value + 1; + } + compilations.put(identity, compilationNr); + } + + // Release the lock while generating the content to reduce contention. + // This means `compilationNr` fields may show up out of order in the file. + ByteArrayOutputStream baos = new ByteArrayOutputStream(metricsBufSize); + PrintStream out = new PrintStream(baos); + if (metricsFile.endsWith(".csv") || metricsFile.endsWith(".CSV")) { + printMetricsCSV(out, compilable, identity, compilationNr, desc.identifier); + } else { + printMetrics(out, compilable, identity, compilationNr, desc.identifier); + } + + byte[] content = baos.toByteArray(); + Path path = Paths.get(metricsFile); + synchronized (PRINT_METRICS_LOCK) { + metricsBufSize = Math.max(metricsBufSize, content.length); + try { + Files.write(path, content, StandardOpenOption.CREATE, StandardOpenOption.APPEND); + } catch (IOException e) { + } + } + } + + } + + /** + * Lock to serialize writes to {@link DebugOptions#MetricsFile}. + */ + private static final Object PRINT_METRICS_LOCK = new Object(); + + /** + * Appends metrics in CSV format to {@code out} for a single method compilation. + * + * @param identity the identity hash code of {@code compilable} + * @param compilationNr where this compilation lies in the ordered sequence of all compilations + * identified by {@code identity} + * @param compilationId the runtime issued identifier for the compilation + */ + private void printMetricsCSV(PrintStream out, Object compilable, Integer identity, int compilationNr, String compilationId) { + String compilableName = compilable instanceof JavaMethod ? ((JavaMethod) compilable).format("%H.%n(%p)%R") : String.valueOf(compilable); + String csvFormat = CSVUtil.buildFormatString("%s", "%s", "%d", "%s"); + String format = String.format(csvFormat, CSVUtil.Escape.escapeArgs(compilableName, identity, compilationNr, compilationId)); + char sep = CSVUtil.SEPARATOR; + format += sep + "%s" + sep + "%s" + sep + "%s"; + for (MetricKey key : KeyRegistry.getKeys()) { + int index = ((AbstractKey) key).getIndex(); + if (index < metricValues.length) { + Pair valueAndUnit = key.toCSVFormat(metricValues[index]); + CSVUtil.Escape.println(out, format, CSVUtil.Escape.escape(key.getName()), valueAndUnit.getLeft(), valueAndUnit.getRight()); + } + } + } + + /** + * Appends metrics in a human readable format to {@code out} for a single method compilation. + * + * @param identity the identity hash code of {@code compilable} + * @param compilationNr where this compilation lies in the ordered sequence of all compilations + * identified by {@code identity} + * @param compilationId the runtime issued identifier for the compilation + */ + private void printMetrics(PrintStream out, Object compilable, Integer identity, int compilationNr, String compilationId) { + String compilableName = compilable instanceof JavaMethod ? ((JavaMethod) compilable).format("%H.%n(%p)%R") : String.valueOf(compilable); + int maxKeyWidth = compilableName.length(); + SortedMap res = new TreeMap<>(); + for (MetricKey key : KeyRegistry.getKeys()) { + int index = ((AbstractKey) key).getIndex(); + if (index < metricValues.length && metricValues[index] != 0) { + String name = key.getName(); + long value = metricValues[index]; + String valueString; + if (key instanceof TimerKey) { + // Report timers in ms + TimerKey timer = (TimerKey) key; + long ms = timer.getTimeUnit().toMillis(value); + if (ms == 0) { + continue; + } + valueString = ms + "ms"; + } else { + valueString = String.valueOf(value); + } + res.put(name, valueString); + maxKeyWidth = Math.max(maxKeyWidth, name.length()); + } + } + + String title = String.format("%s [id:%s compilation:%d compilation_id:%s]", compilableName, identity, compilationNr, compilationId); + out.println(new String(new char[title.length()]).replace('\0', '#')); + out.printf("%s%n", title); + out.println(new String(new char[title.length()]).replace('\0', '~')); + + for (Map.Entry e : res.entrySet()) { + out.printf("%-" + String.valueOf(maxKeyWidth) + "s = %20s%n", e.getKey(), e.getValue()); + } + out.println(); + } +} --- /dev/null 2017-07-07 09:32:05.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugHandler.java 2017-07-07 09:32:04.000000000 -0700 @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017, 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 org.graalvm.compiler.debug; + +/** + * This interface exists to unify {@link DebugDumpHandler} and {@link DebugVerifyHandler} for the + * sake of {@link DebugHandlersFactory#createHandlers}. + */ +public interface DebugHandler { +} --- /dev/null 2017-07-07 09:32:05.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugHandlersFactory.java 2017-07-07 09:32:05.000000000 -0700 @@ -0,0 +1,50 @@ +/* + * 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 org.graalvm.compiler.debug; + +import java.util.Iterator; +import java.util.List; + +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.serviceprovider.GraalServices; + +/** + * Factory for creating {@link DebugHandler}s. + */ +public interface DebugHandlersFactory { + + /** + * Creates {@link DebugHandler}s based on {@code options}. + */ + List createHandlers(OptionValues options); + + /** + * Loads {@link DebugHandlersFactory}s on demand via {@link GraalServices#load(Class)}. + */ + Iterable LOADER = new Iterable() { + @Override + public Iterator iterator() { + return GraalServices.load(DebugHandlersFactory.class).iterator(); + } + }; +} --- /dev/null 2017-07-07 09:32:05.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugOptions.java 2017-07-07 09:32:05.000000000 -0700 @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2017, 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 org.graalvm.compiler.debug; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionType; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicMap; + +/** + * Options that configure a {@link DebugContext} and related functionality. + */ +public class DebugOptions { + static class DeprecatedOptionKey extends OptionKey { + private final OptionKey replacement; + + DeprecatedOptionKey(OptionKey replacement) { + super(replacement.getDefaultValue()); + this.replacement = replacement; + } + + @Override + protected void onValueUpdate(EconomicMap, Object> values, T oldValue, T newValue) { + // Ideally we'd use TTY here but it may not yet be initialized. + System.err.printf("Warning: the %s option is deprecated - use %s instead%n", getName(), replacement.getName()); + replacement.update(values, newValue); + } + } + + // @formatter:off + @Option(help = "Comma separated names of timers that are enabled irrespective of the value for Time option. " + + "An empty value enables all timers unconditionally.", type = OptionType.Debug) + public static final OptionKey Timers = new OptionKey<>(null); + @Option(help = "Comma separated names of counters that are enabled irrespective of the value for Count option. " + + "An empty value enables all counters unconditionally.", type = OptionType.Debug) + public static final OptionKey Counters = new OptionKey<>(null); + @Option(help = "Comma separated names of memory usage trackers that are enabled irrespective of the value for TrackMemUse option. " + + "An empty value enables all memory usage trackers unconditionally.", type = OptionType.Debug) + public static final OptionKey MemUseTrackers = new OptionKey<>(null); + + @Option(help = "Pattern for scope(s) in which counting is enabled (see DebugFilter and Debug.counter). " + + "An empty value enables all counters unconditionally.", type = OptionType.Debug) + public static final OptionKey Count = new OptionKey<>(null); + @Option(help = "Pattern for scope(s) in which memory use tracking is enabled (see DebugFilter and Debug.counter). " + + "An empty value enables all memory use trackers unconditionally.", type = OptionType.Debug) + public static final OptionKey TrackMemUse = new OptionKey<>(null); + @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 OptionKey Time = new OptionKey<>(null); + + @Option(help = "Pattern for scope(s) in which verification is enabled (see DebugFilter and Debug.verify).", type = OptionType.Debug) + public static final OptionKey Verify = new OptionKey<>(Assertions.ENABLED ? "" : null); + @Option(help = "Pattern for scope(s) in which dumping is enabled (see DebugFilter and Debug.dump)", type = OptionType.Debug) + public static final OptionKey Dump = new OptionKey<>(null); + @Option(help = "Pattern for scope(s) in which logging is enabled (see DebugFilter and Debug.log)", type = OptionType.Debug) + public static final OptionKey Log = new OptionKey<>(null); + + @Option(help = "Pattern for filtering debug scope output based on method context (see MethodFilter)", type = OptionType.Debug) + public static final OptionKey MethodFilter = new OptionKey<>(null); + @Option(help = "Only check MethodFilter against the root method in the context if true, otherwise check all methods", type = OptionType.Debug) + public static final OptionKey MethodFilterRootOnly = new OptionKey<>(false); + @Option(help = "Dump a before and after graph if the named phase changes the graph.%n" + + "The argument is substring matched against the simple name of the phase class", type = OptionType.Debug) + public static final OptionKey DumpOnPhaseChange = new OptionKey<>(null); + + @Option(help = "Listst the console at VM shutdown the metric names available to the Timers, Counters and MemUseTrackers option. " + + "Note that this only lists the metrics that were initialized during the VM execution and so " + + "will not include metrics for compiler code that is not executed.", type = OptionType.Debug) + public static final OptionKey ListMetrics = new OptionKey<>(false); + @Option(help = "File to which metrics are dumped per compilation. A CSV format is used if the file ends with .csv " + + "otherwise a more human readable format is used. The fields in the CSV format are: " + + "compilable, compilable_identity, compilation_nr, compilation_id, metric_name, metric_value", type = OptionType.Debug) + public static final OptionKey MetricsFile = new OptionKey<>(null); + @Option(help = "File to which aggregated metrics are dumped at shutdown. A CSV format is used if the file ends with .csv " + + "otherwise a more human readable format is used. If not specified, metrics are dumped to the console.", type = OptionType.Debug) + public static final OptionKey AggregatedMetricsFile = new OptionKey<>(null); + + @Option(help = "Only report metrics for threads whose name matches the regular expression.", type = OptionType.Debug) + public static final OptionKey MetricsThreadFilter = new OptionKey<>(null); + @Option(help = "Enable debug output for stub code generation and snippet preparation.", type = OptionType.Debug) + public static final OptionKey DebugStubsAndSnippets = new OptionKey<>(false); + @Option(help = "Send Graal compiler IR to dump handlers on error.", type = OptionType.Debug) + public static final OptionKey DumpOnError = new OptionKey<>(false); + @Option(help = "Intercept also bailout exceptions", type = OptionType.Debug) + public static final OptionKey InterceptBailout = new OptionKey<>(false); + @Option(help = "Enable more verbose log output when available", type = OptionType.Debug) + public static final OptionKey LogVerbose = new OptionKey<>(false); + + @Option(help = "The directory where various Graal dump files are written.") + public static final OptionKey DumpPath = new OptionKey<>("dumps"); + @Option(help = "Print the name of each dump file path as it's created.") + public static final OptionKey ShowDumpFiles = new OptionKey<>(Assertions.ENABLED); + + @Option(help = "Enable dumping to the C1Visualizer. Enabling this option implies PrintBackendCFG.", type = OptionType.Debug) + public static final OptionKey PrintCFG = new OptionKey<>(false); + @Option(help = "Enable dumping LIR, register allocation and code generation info to the C1Visualizer.", type = OptionType.Debug) + public static final OptionKey PrintBackendCFG = new OptionKey<>(true); + + @Option(help = "Output probabilities for fixed nodes during binary graph dumping.", type = OptionType.Debug) + public static final OptionKey PrintGraphProbabilities = new OptionKey<>(false); + @Option(help = "Enable dumping to the IdealGraphVisualizer.", type = OptionType.Debug) + public static final OptionKey PrintGraph = new OptionKey<>(true); + @Option(help = "Dump graphs in binary format instead of XML format.", type = OptionType.Debug) + public static final OptionKey PrintBinaryGraphs = new OptionKey<>(true); + @Option(help = "Print graphs to files instead of sending them over the network.", type = OptionType.Debug) + public static final OptionKey PrintGraphFile = new OptionKey<>(false); + + @Option(help = "Host part of the address to which graphs are dumped.", type = OptionType.Debug) + public static final OptionKey PrintGraphHost = new OptionKey<>("127.0.0.1"); + @Option(help = "Port part of the address to which graphs are dumped in XML format (ignored if PrintBinaryGraphs=true).", type = OptionType.Debug) + public static final OptionKey PrintXmlGraphPort = new OptionKey<>(4444); + @Option(help = "Port part of the address to which graphs are dumped in binary format (ignored if PrintBinaryGraphs=false).", type = OptionType.Debug) + public static final OptionKey PrintBinaryGraphPort = new OptionKey<>(4445); + @Option(help = "Schedule graphs as they are dumped.", type = OptionType.Debug) + public static final OptionKey PrintGraphWithSchedule = new OptionKey<>(false); + + @Option(help = "Enable dumping Truffle ASTs to the IdealGraphVisualizer.", type = OptionType.Debug) + public static final OptionKey PrintTruffleTrees = new OptionKey<>(true); + + @Option(help = "Treat any exceptions during dumping as fatal.", type = OptionType.Debug) + public static final OptionKey DumpingErrorsAreFatal = new OptionKey<>(false); + + @Option(help = "Enable dumping canonical text from for graphs.", type = OptionType.Debug) + public static final OptionKey PrintCanonicalGraphStrings = new OptionKey<>(false); + @Option(help = "Choose format used when dumping canonical text for graphs: " + + "0 gives a scheduled graph (better for spotting changes involving the schedule)" + + "while 1 gives a CFG containing expressions rooted at fixed nodes (better for spotting small structure differences)", type = OptionType.Debug) + public static final OptionKey PrintCanonicalGraphStringFlavor = new OptionKey<>(0); + @Option(help = "Exclude virtual nodes when dumping canonical text for graphs.", type = OptionType.Debug) + public static final OptionKey CanonicalGraphStringsExcludeVirtuals = new OptionKey<>(true); + @Option(help = "Exclude virtual nodes when dumping canonical text for graphs.", type = OptionType.Debug) + public static final OptionKey CanonicalGraphStringsCheckConstants = new OptionKey<>(false); + @Option(help = "Attempts to remove object identity hashes when dumping canonical text for graphs.", type = OptionType.Debug) + public static final OptionKey CanonicalGraphStringsRemoveIdentities = new OptionKey<>(true); + + @Option(help = "Clear the debug metrics after bootstrap.", type = OptionType.Debug) + public static final OptionKey ClearMetricsAfterBootstrap = new OptionKey<>(false); + @Option(help = "Do not compile anything on bootstrap but just initialize the compiler.", type = OptionType.Debug) + public static final OptionKey BootstrapInitializeOnly = new OptionKey<>(false); + + // These will be removed at some point + @Option(help = "Deprecated - use PrintGraphHost instead.", type = OptionType.Debug) + static final OptionKey PrintIdealGraphAddress = new DebugOptions.DeprecatedOptionKey<>(PrintGraphHost); + @Option(help = "Deprecated - use PrintGraphWithSchedule instead.", type = OptionType.Debug) + static final OptionKey PrintIdealGraphSchedule = new DebugOptions.DeprecatedOptionKey<>(PrintGraphWithSchedule); + @Option(help = "Deprecated - use PrintGraph instead.", type = OptionType.Debug) + static final OptionKey PrintIdealGraph = new DebugOptions.DeprecatedOptionKey<>(PrintGraph); + @Option(help = "Deprecated - use PrintGraphFile instead.", type = OptionType.Debug) + static final OptionKey PrintIdealGraphFile = new DebugOptions.DeprecatedOptionKey<>(PrintGraphFile); + @Option(help = "Deprecated - use PrintXmlGraphPort instead.", type = OptionType.Debug) + static final OptionKey PrintIdealGraphPort = new DebugOptions.DeprecatedOptionKey<>(PrintXmlGraphPort); + // @formatter:on + + /** + * Gets the directory in which {@link DebugDumpHandler}s can generate output. This will be the + * directory specified by {@link #DumpPath} if it has been set otherwise it will be derived from + * the default value of {@link #DumpPath} and {@link UniquePathUtilities#getGlobalTimeStamp()}. + * + * This method will ensure the returned directory exists, printing a message to {@link TTY} if + * it creates it. + * + * @return a path as described above whose directories are guaranteed to exist + * @throws IOException if there was an error in {@link Files#createDirectories} + */ + public static Path getDumpDirectory(OptionValues options) throws IOException { + Path dumpDir; + if (DumpPath.hasBeenSet(options)) { + dumpDir = Paths.get(DumpPath.getValue(options)); + } else { + dumpDir = Paths.get(DumpPath.getValue(options), String.valueOf(UniquePathUtilities.getGlobalTimeStamp())); + } + if (!Files.exists(dumpDir)) { + synchronized (DebugConfigImpl.class) { + if (!Files.exists(dumpDir)) { + Files.createDirectories(dumpDir); + TTY.println("Dumping debug output in %s", dumpDir.toAbsolutePath().toString()); + } + } + } + return dumpDir; + } +} --- /dev/null 2017-07-07 09:32:06.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugValueMap.java 2017-07-07 09:32:05.000000000 -0700 @@ -0,0 +1,194 @@ +/* + * 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 org.graalvm.compiler.debug; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * A node in a tree of values. + */ +public class DebugValueMap { + + /** + * The top level maps for all threads. + */ + private static final List topLevelMaps = new ArrayList<>(); + + private long[] values; + private List children; + private String name; + + public DebugValueMap(String name) { + this.name = name; + } + + public void setCurrentValue(int index, long l) { + ensureSize(index); + values[index] = l; + } + + public long getCurrentValue(int index) { + ensureSize(index); + return values[index]; + } + + public void clearChildren() { + if (children != null) { + children.clear(); + } + } + + public void reset() { + if (values != null) { + Arrays.fill(values, 0L); + } + if (children != null) { + for (DebugValueMap child : children) { + child.reset(); + } + } + } + + private void ensureSize(int index) { + if (values == null) { + values = new long[index + 1]; + } + if (values.length <= index) { + values = Arrays.copyOf(values, index + 1); + } + } + + private int capacity() { + return (values == null) ? 0 : values.length; + } + + public void addChild(DebugValueMap map) { + if (children == null) { + children = new ArrayList<>(4); + } + children.add(map); + } + + public List getChildren() { + if (children == null) { + return Collections.emptyList(); + } else { + return Collections.unmodifiableList(children); + } + } + + public boolean hasChildren() { + return children != null && !children.isEmpty(); + } + + public String getName() { + return this.name; + } + + @Override + public String toString() { + return "DebugValueMap<" + getName() + ">"; + } + + public static synchronized void registerTopLevel(DebugValueMap map) { + topLevelMaps.add(map); + } + + public static synchronized List getTopLevelMaps() { + return topLevelMaps; + } + + /** + * The top level map for the current thread. + */ + private static final ThreadLocal topLevelMap = new ThreadLocal<>(); + + static DebugValueMap getTopLevelMap() { + DebugValueMap map = topLevelMap.get(); + if (map == null) { + map = new DebugValueMap(Thread.currentThread().getName()); + topLevelMap.set(map); + registerTopLevel(map); + } + return map; + } + + public void normalize() { + if (hasChildren()) { + Map occurred = new HashMap<>(); + for (DebugValueMap map : children) { + String mapName = map.getName(); + if (!occurred.containsKey(mapName)) { + occurred.put(mapName, map); + map.normalize(); + } else { + occurred.get(mapName).mergeWith(map); + occurred.get(mapName).normalize(); + } + } + + if (occurred.values().size() < children.size()) { + // At least one duplicate was found. + children.clear(); + for (DebugValueMap map : occurred.values()) { + addChild(map); + map.normalize(); + } + } + } + } + + private void mergeWith(DebugValueMap map) { + if (map.hasChildren()) { + if (hasChildren()) { + children.addAll(map.children); + } else { + children = map.children; + } + map.children = null; + } + + int size = Math.max(this.capacity(), map.capacity()); + ensureSize(size); + for (int i = 0; i < size; ++i) { + long curValue = getCurrentValue(i); + long otherValue = map.getCurrentValue(i); + setCurrentValue(i, curValue + otherValue); + } + } + + public void group() { + if (this.hasChildren()) { + List oldChildren = new ArrayList<>(this.children); + this.children.clear(); + for (DebugValueMap map : oldChildren) { + mergeWith(map); + } + } + } +} --- /dev/null 2017-07-07 09:32:06.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GlobalMetrics.java 2017-07-07 09:32:06.000000000 -0700 @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2017, 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 org.graalvm.compiler.debug; + +import java.io.IOException; +import java.io.PrintStream; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Collections; +import java.util.List; + +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.MapCursor; +import org.graalvm.util.Pair; + +/** + * Metric values that can be {@linkplain #add(DebugContext) updated} by multiple threads. + */ +public class GlobalMetrics { + long[] values; + + /** + * Adds the values in {@code debug} to the values in this object. + */ + public synchronized void add(DebugContext debug) { + values = debug.addValuesTo(values); + } + + /** + * Clears all values in this object. + */ + public void clear() { + values = null; + } + + /** + * Creates and returns a sorted map from metric names to their values in this object. + */ + public EconomicMap asKeyValueMap() { + List keys = KeyRegistry.getKeys(); + Collections.sort(keys, MetricKey.NAME_COMPARATOR); + EconomicMap res = EconomicMap.create(keys.size()); + long[] vals = values; + for (MetricKey key : keys) { + int index = ((AbstractKey) key).getIndex(); + if (vals == null || index >= vals.length) { + res.put(key, 0L); + } else { + res.put(key, vals[index]); + } + } + return res; + } + + /** + * Prints the values in the object to the file specified by + * {@link DebugOptions#AggregatedMetricsFile} if present otherwise to + * {@link DebugContext#DEFAULT_LOG_STREAM}. + */ + public void print(OptionValues options) { + long[] vals = values; + if (vals != null) { + EconomicMap map = asKeyValueMap(); + String metricsFile = DebugOptions.AggregatedMetricsFile.getValue(options); + boolean csv = metricsFile != null && (metricsFile.endsWith(".csv") || metricsFile.endsWith(".CSV")); + try (PrintStream p = metricsFile == null ? DebugContext.DEFAULT_LOG_STREAM : new PrintStream(Files.newOutputStream(Paths.get(metricsFile)))) { + if (!csv) { + if (!map.isEmpty()) { + p.println("++ Aggregated Metrics ++"); + } + } + String csvFormat = CSVUtil.buildFormatString("%s", "%s", "%s"); + MapCursor e = map.getEntries(); + while (e.advance()) { + MetricKey key = e.getKey(); + if (csv) { + Pair valueAndUnit = key.toCSVFormat(e.getValue()); + CSVUtil.Escape.println(p, csvFormat, key.getName(), valueAndUnit.getLeft(), valueAndUnit.getRight()); + } else { + p.println(key.getName() + "=" + key.toHumanReadableFormat(e.getValue())); + } + } + if (!csv) { + if (!map.isEmpty()) { + p.println("-- Aggregated Metrics --"); + } + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + if (DebugOptions.ListMetrics.getValue(options)) { + PrintStream p = System.out; + p.println("++ Metric Keys ++"); + List keys = KeyRegistry.getKeys(); + Collections.sort(keys, MetricKey.NAME_COMPARATOR); + for (MetricKey key : keys) { + String name = key.getDocName(); + if (name != null) { + String doc = key.getDoc(); + if (doc != null) { + p.println(name + ": " + doc); + } else { + p.println(name); + } + } + } + p.println("-- Metric Keys --"); + } + } +} --- /dev/null 2017-07-07 09:32:06.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/KeyRegistry.java 2017-07-07 09:32:06.000000000 -0700 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.debug; + +import java.util.ArrayList; +import java.util.List; + +import org.graalvm.util.EconomicMap; + +/** + * Registry for allocating a globally unique integer id to each {@link AbstractKey}. + */ +public class KeyRegistry { + + private static final EconomicMap keyMap = EconomicMap.create(); + private static final List keys = new ArrayList<>(); + + /** + * Ensures a given metric key is registered. + * + * @return the globally unique id for {@code value} + */ + static synchronized int register(AbstractKey key) { + String name = key.getName(); + if (!keyMap.containsKey(name)) { + keyMap.put(name, keys.size()); + keys.add(key); + } + return keyMap.get(name); + } + + /** + * Gets a copy of the registered keys. + * + * @return a list where {@code get(i).getIndex() == i} + */ + public static synchronized List getKeys() { + return new ArrayList<>(keys); + } +} --- /dev/null 2017-07-07 09:32:07.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MemUseTrackerKey.java 2017-07-07 09:32:06.000000000 -0700 @@ -0,0 +1,59 @@ +/* + * 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 org.graalvm.compiler.debug; + +import com.sun.management.ThreadMXBean; + +/** + * Tracks memory usage within a scope using {@link ThreadMXBean}. This facility should be employed + * using the try-with-resources pattern: + * + *
+ * try (DebugCloseable a = memUseTracker.start()) {
+ *     // the code to measure
+ * }
+ * 
+ */ +public interface MemUseTrackerKey extends MetricKey { + + /** + * Creates a point from which memory usage will be recorded if memory use tracking is + * {@linkplain DebugContext#isMemUseTrackingEnabled() enabled}. + * + * @return an object that must be closed once the activity has completed to add the memory used + * since this call to the total for this tracker + */ + DebugCloseable start(DebugContext debug); + + /** + * Gets the current value of this tracker. + */ + long getCurrentValue(DebugContext debug); + + @Override + MemUseTrackerKey doc(String string); + + static long getCurrentThreadAllocatedBytes() { + return Management.getCurrentThreadAllocatedBytes(); + } +} --- /dev/null 2017-07-07 09:32:07.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MemUseTrackerKeyImpl.java 2017-07-07 09:32:07.000000000 -0700 @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.debug; + +import static org.graalvm.compiler.debug.DebugCloseable.VOID_CLOSEABLE; + +import org.graalvm.util.Pair; + +class MemUseTrackerKeyImpl extends AccumulatedKey implements MemUseTrackerKey { + + MemUseTrackerKeyImpl(String format, Object arg1, Object arg2) { + super(new FlatMemUseTracker(format, arg1, arg2), format, arg1, arg2); + } + + @Override + public DebugCloseable start(DebugContext debug) { + if (debug.isMemUseTrackerEnabled(this)) { + CloseableCounter result = new MemUseCloseableCounterImpl(this, debug); + debug.currentMemUseTracker = result; + return result; + } + return VOID_CLOSEABLE; + } + + public static String valueToString(long value) { + return String.format("%d bytes", value); + } + + @Override + public String toHumanReadableFormat(long value) { + return valueToString(value); + } + + static final class FlatMemUseTracker extends AbstractKey implements MetricKey { + + FlatMemUseTracker(String nameFormat, Object nameArg1, Object nameArg2) { + super(nameFormat, nameArg1, nameArg2); + } + + @Override + protected String createName(String format, Object arg1, Object arg2) { + return super.createName(format, arg1, arg2) + FLAT_KEY_SUFFIX; + } + + @Override + public MetricKey doc(String doc) { + throw new IllegalArgumentException("Cannot set documentation for derived key " + getName()); + } + + @Override + public String getDocName() { + return null; + } + + @Override + public String toHumanReadableFormat(long value) { + return valueToString(value); + } + + @Override + public Pair toCSVFormat(long value) { + return Pair.create(String.valueOf(value), "bytes"); + } + } + + static final class MemUseCloseableCounterImpl extends CloseableCounter implements DebugCloseable { + + private final DebugContext debug; + + MemUseCloseableCounterImpl(AccumulatedKey counter, DebugContext debug) { + super(debug, debug.currentMemUseTracker, counter); + this.debug = debug; + } + + @Override + long getCounterValue() { + return MemUseTrackerKey.getCurrentThreadAllocatedBytes(); + } + + @Override + public void close() { + super.close(); + debug.currentMemUseTracker = parent; + } + } + + @Override + public Pair toCSVFormat(long value) { + return Pair.create(String.valueOf(value), "bytes"); + } + + @Override + public MemUseTrackerKey doc(String doc) { + setDoc(doc); + return this; + } +} --- /dev/null 2017-07-07 09:32:07.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MetricKey.java 2017-07-07 09:32:07.000000000 -0700 @@ -0,0 +1,87 @@ +/* + * 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 org.graalvm.compiler.debug; + +import java.util.Comparator; + +import org.graalvm.util.Pair; + +/** + * A key for a metric. + */ +public interface MetricKey { + + /** + * Converts a given value for this key to a string, scaling it to a more useful unit of + * measurement and appending a suffix indicating the unit where applicable. This representation + * is intended for human consumption. + */ + String toHumanReadableFormat(long value); + + /** + * Converts a given value for this key to a CSV format intended for automated data processing. + * + * @param value + * @return a pair where first is the {@code value} with any scaling conversion applied and + * second is the unit of measurement used for the first component (this will be the + * empty string for a simple counter) + */ + Pair toCSVFormat(long value); + + /** + * Gets the name of this key. + */ + String getName(); + + /** + * Comparator to sort keys by their names. + */ + Comparator NAME_COMPARATOR = new Comparator() { + + @Override + public int compare(MetricKey o1, MetricKey o2) { + return o1.getName().compareTo(o2.getName()); + } + + }; + + /** + * Sets the documentation for this key. + */ + MetricKey doc(String string); + + /** + * Gets the name to use when listing keys. Note that this may be different from + * {@link #getName()}. + * + * @return {@code null} if this key is derived from another key and so should not be listed + */ + String getDocName(); + + /** + * Gets the documentation for this key. + * + * @return {@code null} if this key has no documentation + */ + String getDoc(); +} --- /dev/null 2017-07-07 09:32:08.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/ScopeImpl.java 2017-07-07 09:32:07.000000000 -0700 @@ -0,0 +1,424 @@ +/* + * 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 org.graalvm.compiler.debug; + +import java.io.PrintStream; +import java.util.Iterator; + +import org.graalvm.compiler.debug.DebugContext.DisabledScope; + +import jdk.vm.ci.meta.JavaMethod; + +public final class ScopeImpl implements DebugContext.Scope { + + private final class IndentImpl implements Indent { + + private static final String INDENTATION_INCREMENT = " "; + + final String indent; + final IndentImpl parentIndent; + + IndentImpl(IndentImpl parentIndent) { + this.parentIndent = parentIndent; + this.indent = (parentIndent == null ? "" : parentIndent.indent + INDENTATION_INCREMENT); + } + + private boolean logScopeName() { + return logScopeName; + } + + private void printScopeName(StringBuilder str, boolean isCurrent) { + if (logScopeName) { + boolean parentPrinted = false; + if (parentIndent != null) { + parentPrinted = parentIndent.logScopeName(); + parentIndent.printScopeName(str, false); + } + /* + * Always print the current scope, scopes with context and the any scope whose + * parent didn't print. This ensure the first new scope always shows up. + */ + if (isCurrent || printContext(null) != 0 || !parentPrinted) { + str.append(indent).append("[thread:").append(Thread.currentThread().getId()).append("] scope: ").append(getQualifiedName()).append(System.lineSeparator()); + } + printContext(str); + logScopeName = false; + } + } + + /** + * Print or count the context objects for the current scope. + */ + private int printContext(StringBuilder str) { + int count = 0; + if (context != null && context.length > 0) { + // Include some context in the scope output + for (Object contextObj : context) { + if (contextObj instanceof JavaMethodContext || contextObj instanceof JavaMethod) { + if (str != null) { + str.append(indent).append("Context: ").append(contextObj).append(System.lineSeparator()); + } + count++; + } + } + } + return count; + } + + public void log(int logLevel, String msg, Object... args) { + if (isLogEnabled(logLevel)) { + StringBuilder str = new StringBuilder(); + printScopeName(str, true); + str.append(indent); + String result = args.length == 0 ? msg : String.format(msg, args); + String lineSep = System.lineSeparator(); + str.append(result.replace(lineSep, lineSep.concat(indent))); + str.append(lineSep); + output.append(str); + lastUsedIndent = this; + } + } + + IndentImpl indent() { + lastUsedIndent = new IndentImpl(this); + return lastUsedIndent; + } + + @Override + public void close() { + if (parentIndent != null) { + lastUsedIndent = parentIndent; + } + } + } + + private final DebugContext owner; + private final ScopeImpl parent; + private final boolean sandbox; + private IndentImpl lastUsedIndent; + private boolean logScopeName; + + private final Object[] context; + + private String qualifiedName; + private final String unqualifiedName; + + private static final char SCOPE_SEP = '.'; + + private boolean countEnabled; + private boolean timeEnabled; + private boolean memUseTrackingEnabled; + private boolean verifyEnabled; + + private int currentDumpLevel; + private int currentLogLevel; + + private PrintStream output; + private boolean interceptDisabled; + + static final Object[] EMPTY_CONTEXT = new Object[0]; + + ScopeImpl(DebugContext owner, Thread thread) { + this(owner, thread.getName(), null, false); + } + + ScopeImpl(DebugContext owner, String unqualifiedName, ScopeImpl parent, boolean sandbox, Object... context) { + this.owner = owner; + this.parent = parent; + this.sandbox = sandbox; + this.context = context; + this.unqualifiedName = unqualifiedName; + if (parent != null) { + logScopeName = !unqualifiedName.equals(""); + this.interceptDisabled = parent.interceptDisabled; + } else { + logScopeName = true; + } + + this.output = TTY.out; + assert context != null; + } + + @Override + public void close() { + owner.currentScope = parent; + owner.lastClosedScope = this; + } + + public boolean isDumpEnabled(int dumpLevel) { + assert dumpLevel >= 0; + return currentDumpLevel >= dumpLevel; + } + + public boolean isVerifyEnabled() { + return verifyEnabled; + } + + public boolean isLogEnabled(int logLevel) { + assert logLevel > 0; + return currentLogLevel >= logLevel; + } + + public boolean isCountEnabled() { + return countEnabled; + } + + public boolean isTimeEnabled() { + return timeEnabled; + } + + public boolean isMemUseTrackingEnabled() { + return memUseTrackingEnabled; + } + + public void log(int logLevel, String msg, Object... args) { + assert owner.checkNoConcurrentAccess(); + if (isLogEnabled(logLevel)) { + getLastUsedIndent().log(logLevel, msg, args); + } + } + + public void dump(int dumpLevel, Object object, String formatString, Object... args) { + assert isDumpEnabled(dumpLevel); + if (isDumpEnabled(dumpLevel)) { + DebugConfig config = getConfig(); + if (config != null) { + for (DebugDumpHandler dumpHandler : config.dumpHandlers()) { + dumpHandler.dump(owner, object, formatString, args); + } + } + } + } + + private DebugConfig getConfig() { + return owner.currentConfig; + } + + /** + * @see DebugContext#verify(Object, String) + */ + public void verify(Object object, String formatString, Object... args) { + if (isVerifyEnabled()) { + DebugConfig config = getConfig(); + if (config != null) { + String message = String.format(formatString, args); + for (DebugVerifyHandler handler : config.verifyHandlers()) { + handler.verify(owner, object, message); + } + } + } + } + + /** + * Creates and enters a new scope which is either a child of the current scope or a disjoint top + * level scope. + * + * @param name the name of the new scope + * @param sandboxConfig the configuration to use for a new top level scope, or null if the new + * scope should be a child scope + * @param newContextObjects objects to be appended to the debug context + * @return the new scope which will be exited when its {@link #close()} method is called + */ + public ScopeImpl scope(CharSequence name, DebugConfig sandboxConfig, Object... newContextObjects) { + ScopeImpl newScope = null; + if (sandboxConfig != null) { + newScope = new ScopeImpl(owner, name.toString(), this, true, newContextObjects); + } else { + newScope = this.createChild(name.toString(), newContextObjects); + } + newScope.updateFlags(owner.currentConfig); + return newScope; + } + + @SuppressWarnings({"unchecked", "unused"}) + private static RuntimeException silenceException(Class type, Throwable ex) throws E { + throw (E) ex; + } + + public RuntimeException handle(Throwable e) { + try { + if (owner.lastClosedScope instanceof ScopeImpl) { + ScopeImpl lastClosed = (ScopeImpl) owner.lastClosedScope; + assert lastClosed.parent == this : "DebugContext.handle() used without closing a scope opened by DebugContext.scope(...) or DebugContext.sandbox(...) " + + "or an exception occurred while opening a scope"; + if (e != owner.lastExceptionThrown) { + RuntimeException newException = null; + // Make the scope in which the exception was thrown + // the current scope again. + owner.currentScope = lastClosed; + + // When this try block exits, the above action will be undone + try (ScopeImpl s = lastClosed) { + newException = s.interceptException(e); + } + + // Checks that the action really is undone + assert owner.currentScope == this; + assert lastClosed == owner.lastClosedScope; + + if (newException == null) { + owner.lastExceptionThrown = e; + } else { + owner.lastExceptionThrown = newException; + throw newException; + } + } + } else if (owner.lastClosedScope == null) { + throw new AssertionError("DebugContext.handle() used without closing a scope opened by DebugContext.scope(...) or DebugContext.sandbox(...) " + + "or an exception occurred while opening a scope"); + } else { + assert owner.lastClosedScope instanceof DisabledScope : owner.lastClosedScope; + } + } catch (Throwable t) { + t.initCause(e); + throw t; + } + + if (e instanceof Error) { + throw (Error) e; + } + if (e instanceof RuntimeException) { + throw (RuntimeException) e; + } + throw silenceException(RuntimeException.class, e); + } + + void updateFlags(DebugConfig config) { + if (config == null) { + countEnabled = false; + memUseTrackingEnabled = false; + timeEnabled = false; + verifyEnabled = false; + currentDumpLevel = -1; + // Be pragmatic: provide a default log stream to prevent a crash if the stream is not + // set while logging + output = TTY.out; + } else { + countEnabled = config.isCountEnabled(this); + memUseTrackingEnabled = config.isMemUseTrackingEnabled(this); + timeEnabled = config.isTimeEnabled(this); + verifyEnabled = config.isVerifyEnabled(this); + output = config.output(); + currentDumpLevel = config.getDumpLevel(this); + currentLogLevel = config.getLogLevel(this); + } + } + + DebugCloseable disableIntercept() { + boolean previous = interceptDisabled; + interceptDisabled = true; + return new DebugCloseable() { + @Override + public void close() { + interceptDisabled = previous; + } + }; + } + + @SuppressWarnings("try") + private RuntimeException interceptException(final Throwable e) { + if (!interceptDisabled && owner.currentConfig != null) { + try (ScopeImpl s = scope("InterceptException", null, e)) { + return owner.currentConfig.interceptException(owner, e); + } catch (Throwable t) { + return new RuntimeException("Exception while intercepting exception", t); + } + } + return null; + } + + private ScopeImpl createChild(String newName, Object[] newContext) { + return new ScopeImpl(owner, newName, this, false, newContext); + } + + @Override + public Iterable getCurrentContext() { + final ScopeImpl scope = this; + return new Iterable() { + + @Override + public Iterator iterator() { + return new Iterator() { + + ScopeImpl currentScope = scope; + int objectIndex; + + @Override + public boolean hasNext() { + selectScope(); + return currentScope != null; + } + + private void selectScope() { + while (currentScope != null && currentScope.context.length <= objectIndex) { + currentScope = currentScope.sandbox ? null : currentScope.parent; + objectIndex = 0; + } + } + + @Override + public Object next() { + selectScope(); + if (currentScope != null) { + return currentScope.context[objectIndex++]; + } + throw new IllegalStateException("May only be called if there is a next element."); + } + + @Override + public void remove() { + throw new UnsupportedOperationException("This iterator is read only."); + } + }; + } + }; + } + + @Override + public String getQualifiedName() { + if (qualifiedName == null) { + if (parent == null) { + qualifiedName = unqualifiedName; + } else { + qualifiedName = parent.getQualifiedName() + SCOPE_SEP + unqualifiedName; + } + } + return qualifiedName; + } + + public Indent pushIndentLogger() { + lastUsedIndent = getLastUsedIndent().indent(); + return lastUsedIndent; + } + + public IndentImpl getLastUsedIndent() { + if (lastUsedIndent == null) { + if (parent != null) { + lastUsedIndent = new IndentImpl(parent.getLastUsedIndent()); + } else { + lastUsedIndent = new IndentImpl(null); + } + } + return lastUsedIndent; + } +} --- /dev/null 2017-07-07 09:32:08.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TimerKey.java 2017-07-07 09:32:08.000000000 -0700 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.debug; + +import java.util.concurrent.TimeUnit; + +/** + * A timer for some activity of interest. A timer should be deployed using the try-with-resources + * pattern: + * + *
+ * try (TimerCloseable a = timer.start()) {
+ *     // the code to time
+ * }
+ * 
+ */ +public interface TimerKey extends MetricKey { + + /** + * Starts this timer. + * + * @return an object that must be closed once the activity has completed to add the elapsed time + * since this call to the total for this timer + */ + DebugCloseable start(DebugContext debug); + + /** + * Gets the current value of this timer. + */ + long getCurrentValue(DebugContext debug); + + /** + * Gets the time unit of this timer. + */ + TimeUnit getTimeUnit(); + + @Override + TimerKey doc(String string); + + /** + * Gets the timer recording the amount time spent within a timed scope minus the time spent in + * any nested timed scopes. + * + * @return null if this timer does not support flat timing + */ + default TimerKey getFlat() { + return null; + } +} --- /dev/null 2017-07-07 09:32:08.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TimerKeyImpl.java 2017-07-07 09:32:08.000000000 -0700 @@ -0,0 +1,145 @@ +/* + * 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 org.graalvm.compiler.debug; + +import static org.graalvm.compiler.debug.DebugCloseable.VOID_CLOSEABLE; + +import java.util.concurrent.TimeUnit; + +import org.graalvm.util.Pair; + +final class TimerKeyImpl extends AccumulatedKey implements TimerKey { + static class FlatTimer extends AbstractKey implements TimerKey { + private TimerKeyImpl accm; + + FlatTimer(String nameFormat, Object nameArg1, Object nameArg2) { + super(nameFormat, nameArg1, nameArg2); + } + + @Override + protected String createName(String format, Object arg1, Object arg2) { + return super.createName(format, arg1, arg2) + FLAT_KEY_SUFFIX; + } + + @Override + public String toHumanReadableFormat(long value) { + return valueToString(value); + } + + @Override + public TimeUnit getTimeUnit() { + return accm.getTimeUnit(); + } + + @Override + public DebugCloseable start(DebugContext debug) { + return accm.start(debug); + } + + @Override + public Pair toCSVFormat(long value) { + return TimerKeyImpl.toCSVFormatHelper(value); + } + + @Override + public TimerKey doc(String doc) { + throw new IllegalArgumentException("Cannot set documentation for derived key " + getName()); + } + + @Override + public String getDocName() { + return null; + } + } + + TimerKeyImpl(String nameFormat, Object nameArg1, Object nameArg2) { + super(new FlatTimer(nameFormat, nameArg1, nameArg2), nameFormat, nameArg1, nameArg2); + ((FlatTimer) flat).accm = this; + } + + @Override + public DebugCloseable start(DebugContext debug) { + if (debug.isTimerEnabled(this)) { + Timer result = new Timer(this, debug); + debug.currentTimer = result; + return result; + } else { + return VOID_CLOSEABLE; + } + } + + public static String valueToString(long value) { + return String.format("%d.%d ms", value / 1000000, (value / 100000) % 10); + } + + @Override + public TimerKey getFlat() { + return (FlatTimer) flat; + } + + @Override + public String toHumanReadableFormat(long value) { + return valueToString(value); + } + + @Override + public TimeUnit getTimeUnit() { + return TimeUnit.NANOSECONDS; + } + + final class Timer extends CloseableCounter implements DebugCloseable { + final DebugContext debug; + + Timer(AccumulatedKey counter, DebugContext debug) { + super(debug, debug.currentTimer, counter); + this.debug = debug; + } + + @Override + public void close() { + super.close(); + debug.currentTimer = parent; + } + + @Override + protected long getCounterValue() { + return TimeSource.getTimeNS(); + } + + } + + @Override + public Pair toCSVFormat(long value) { + return toCSVFormatHelper(value); + } + + static Pair toCSVFormatHelper(long value) { + return Pair.create(Long.toString(value / 1000), "us"); + } + + @Override + public TimerKey doc(String doc) { + setDoc(doc); + return this; + } +} --- /dev/null 2017-07-07 09:32:09.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/UniquePathUtilities.java 2017-07-07 09:32:09.000000000 -0700 @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2016, 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 org.graalvm.compiler.debug; + +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; + +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionValues; + +public class UniquePathUtilities { + + private static final AtomicLong globalTimeStamp = new AtomicLong(); + /** + * This generates a per thread persistent id to aid mapping related dump files with each other. + */ + private static final ThreadLocal threadDumpId = new ThreadLocal<>(); + private static final AtomicInteger dumpId = new AtomicInteger(); + + static class PerThreadSequence { + final int threadID; + HashMap sequences = new HashMap<>(2); + + PerThreadSequence(int threadID) { + this.threadID = threadID; + } + + String generateID(String extension) { + Integer box = sequences.get(extension); + if (box == null) { + sequences.put(extension, 1); + return Integer.toString(threadID); + } else { + sequences.put(extension, box + 1); + return Integer.toString(threadID) + '-' + box; + } + } + } + + private static String getThreadDumpId(String extension) { + PerThreadSequence id = threadDumpId.get(); + if (id == null) { + id = new PerThreadSequence(dumpId.incrementAndGet()); + threadDumpId.set(id); + } + return id.generateID(extension); + } + + public static String formatExtension(String ext) { + if (ext == null || ext.length() == 0) { + return ""; + } + return "." + ext; + } + + public static long getGlobalTimeStamp() { + if (globalTimeStamp.get() == 0) { + globalTimeStamp.compareAndSet(0, System.currentTimeMillis()); + } + return globalTimeStamp.get(); + } + + /** + * Generates a {@link Path} using the format "%s-%d_%d%s" with the {@code baseNameOption}, a + * {@link #getGlobalTimeStamp() global timestamp} , {@link #getThreadDumpId a per thread unique + * id} and an optional {@code extension}. + * + * @return the output file path or null if the flag is null + */ + public static Path getPath(OptionValues options, OptionKey option, String extension) throws IOException { + return getPath(options, option, extension, true); + } + + /** + * Generate a {@link Path} using the format "%s-%d_%s" with the {@code baseNameOption}, a + * {@link #getGlobalTimeStamp() global timestamp} and an optional {@code extension} . + * + * @return the output file path or null if the flag is null + */ + public static Path getPathGlobal(OptionValues options, OptionKey baseNameOption, String extension) throws IOException { + return getPath(options, baseNameOption, extension, false); + } + + private static Path getPath(OptionValues options, OptionKey baseNameOption, String extension, boolean includeThreadId) throws IOException { + if (baseNameOption.getValue(options) == null) { + return null; + } + String ext = formatExtension(extension); + final String name = includeThreadId + ? String.format("%s-%d_%s%s", baseNameOption.getValue(options), getGlobalTimeStamp(), getThreadDumpId(ext), ext) + : String.format("%s-%d%s", baseNameOption.getValue(options), getGlobalTimeStamp(), ext); + Path result = Paths.get(name); + if (result.isAbsolute()) { + return result; + } + Path dumpDir = DebugOptions.getDumpDirectory(options); + return dumpDir.resolve(name).normalize(); + } +} --- /dev/null 2017-07-07 09:32:09.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopPartialUnrollPhase.java 2017-07-07 09:32:09.000000000 -0700 @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2012, 2016, 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 org.graalvm.compiler.loop.phases; + +import org.graalvm.compiler.graph.Graph; +import org.graalvm.compiler.loop.LoopEx; +import org.graalvm.compiler.loop.LoopPolicies; +import org.graalvm.compiler.loop.LoopsData; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.phases.common.CanonicalizerPhase; +import org.graalvm.compiler.phases.common.util.HashSetNodeEventListener; +import org.graalvm.compiler.phases.tiers.PhaseContext; + +public class LoopPartialUnrollPhase extends LoopPhase { + + private final CanonicalizerPhase canonicalizer; + + public LoopPartialUnrollPhase(LoopPolicies policies, CanonicalizerPhase canonicalizer) { + super(policies); + this.canonicalizer = canonicalizer; + } + + @Override + @SuppressWarnings("try") + protected void run(StructuredGraph graph, PhaseContext context) { + if (graph.hasLoops()) { + HashSetNodeEventListener listener = new HashSetNodeEventListener(); + try (Graph.NodeEventScope nes = graph.trackNodeEvents(listener)) { + boolean changed = true; + while (changed) { + LoopsData dataCounted = new LoopsData(graph); + dataCounted.detectedCountedLoops(); + changed = false; + for (LoopEx loop : dataCounted.countedLoops()) { + if (!LoopTransformations.isUnrollableLoop(loop)) { + continue; + } + if (getPolicies().shouldPartiallyUnroll(loop)) { + if (loop.loopBegin().isSimpleLoop()) { + // First perform the pre/post transformation and do the partial + // unroll when we come around again. + LoopTransformations.insertPrePostLoops(loop, graph); + changed = true; + } else { + changed |= LoopTransformations.partialUnroll(loop, graph); + } + } + } + dataCounted.deleteUnusedNodes(); + } + } + if (!listener.getNodes().isEmpty()) { + canonicalizer.applyIncremental(graph, context, listener.getNodes()); + listener.getNodes().clear(); + } + } + } + + @Override + public boolean checkContract() { + return false; + } +} --- /dev/null 2017-07-07 09:32:09.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.test/src/org/graalvm/compiler/loop/test/LoopPartialUnrollTest.java 2017-07-07 09:32:09.000000000 -0700 @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2017, 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 org.graalvm.compiler.loop.test; + +import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.graph.iterators.NodeIterable; +import org.graalvm.compiler.nodes.LoopBeginNode; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.junit.Ignore; +import org.junit.Test; + +public class LoopPartialUnrollTest extends GraalCompilerTest { + + @Override + protected boolean checkLowTierGraph(StructuredGraph graph) { + NodeIterable loops = graph.getNodes().filter(LoopBeginNode.class); + for (LoopBeginNode loop : loops) { + if (loop.isMainLoop()) { + return true; + } + } + return false; + } + + public static long testMultiplySnippet(int arg) { + long r = 1; + for (int i = 0; branchProbability(0.99, i < arg); i++) { + r *= i; + } + return r; + } + + @Test + public void testMultiply() { + test("testMultiplySnippet", 9); + } + + public static int testNestedSumSnippet(int d) { + int c = 0; + for (int i = 0; i < d; i++) { + for (int j = 0; branchProbability(0.99, j < i); j++) { + c += j & 0x3; + } + } + return c; + } + + @Test + public void testNestedSum() { + for (int i = 0; i < 1000; i++) { + test("testNestedSumSnippet", i); + } + } + + public static int testSumDownSnippet(int d) { + int c = 0; + for (int j = d; branchProbability(0.99, j > -4); j--) { + c += j & 0x3; + } + return c; + } + + @Test + public void testSumDown() { + test("testSumDownSnippet", 1); + for (int i = 0; i < 8; i++) { + test("testSumDownSnippet", i); + } + } + + @Ignore("Phis which reference the backedge value of other Phis aren't handled properly") + @Test + public void testLoopCarried() { + test("testLoopCarriedSnippet", 1, 2); + } + + public static int testLoopCarriedSnippet(int a, int b) { + int c = a; + int d = b; + for (int j = 0; j < a; j++) { + d = c; + c += 1; + } + return c + d; + } + + public static long init = Runtime.getRuntime().totalMemory(); + private int x; + private int z; + + public int[] testComplexSnippet(int d) { + x = 3; + int y = 5; + z = 7; + for (int i = 0; i < d; i++) { + for (int j = 0; branchProbability(0.99, j < i); j++) { + z += x; + } + y = x ^ z; + if ((i & 4) == 0) { + z--; + } else if ((i & 8) == 0) { + Runtime.getRuntime().totalMemory(); + } + } + return new int[]{x, y, z}; + } + + @Test + public void testComplex() { + for (int i = 0; i < 10; i++) { + test("testComplexSnippet", i); + } + test("testComplexSnippet", 10); + test("testComplexSnippet", 100); + test("testComplexSnippet", 1000); + } + +} --- /dev/null 2017-07-07 09:32:10.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraalDebugHandlersFactory.java 2017-07-07 09:32:10.000000000 -0700 @@ -0,0 +1,272 @@ +/* + * 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 org.graalvm.compiler.printer; + +import static org.graalvm.compiler.debug.DebugOptions.PrintBinaryGraphPort; +import static org.graalvm.compiler.debug.DebugOptions.PrintBinaryGraphs; +import static org.graalvm.compiler.debug.DebugOptions.PrintGraphHost; +import static org.graalvm.compiler.debug.DebugOptions.PrintXmlGraphPort; +import static org.graalvm.compiler.debug.DebugOptions.ShowDumpFiles; + +import java.io.IOException; +import java.io.InterruptedIOException; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.nio.channels.ClosedByInterruptException; +import java.nio.channels.FileChannel; +import java.nio.channels.SocketChannel; +import java.nio.file.FileAlreadyExistsException; +import java.nio.file.Files; +import java.nio.file.InvalidPathException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; +import org.graalvm.compiler.core.common.CompilationIdentifier; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DebugDumpHandler; +import org.graalvm.compiler.debug.DebugHandler; +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.debug.DebugOptions; +import org.graalvm.compiler.debug.TTY; +import org.graalvm.compiler.debug.UniquePathUtilities; +import org.graalvm.compiler.graph.Graph; +import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.nodeinfo.Verbosity; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.util.GraphUtil; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.serviceprovider.ServiceProvider; + +@ServiceProvider(DebugHandlersFactory.class) +public class GraalDebugHandlersFactory implements DebugHandlersFactory { + + private final SnippetReflectionProvider snippetReflection; + + public GraalDebugHandlersFactory() { + this.snippetReflection = null; + } + + public GraalDebugHandlersFactory(SnippetReflectionProvider snippetReflection) { + this.snippetReflection = snippetReflection; + } + + @Override + public List createHandlers(OptionValues options) { + List handlers = new ArrayList<>(); + if (DebugOptions.PrintGraphFile.getValue(options)) { + handlers.add(new GraphPrinterDumpHandler((graph) -> createFilePrinter(graph, options, snippetReflection))); + } else { + handlers.add(new GraphPrinterDumpHandler((graph) -> createNetworkPrinter(graph, options, snippetReflection))); + } + if (DebugOptions.PrintCanonicalGraphStrings.getValue(options)) { + handlers.add(new GraphPrinterDumpHandler((graph) -> createStringPrinter(snippetReflection))); + } + handlers.add(new NodeDumper()); + if (DebugOptions.PrintCFG.getValue(options) || DebugOptions.PrintBackendCFG.getValue(options)) { + if (DebugOptions.PrintBinaryGraphs.getValue(options) && DebugOptions.PrintCFG.getValue(options)) { + TTY.out.println("Complete C1Visualizer dumping slows down PrintBinaryGraphs: use -Dgraal.PrintCFG=false to disable it"); + } + handlers.add(new CFGPrinterObserver()); + } + handlers.add(new NoDeadCodeVerifyHandler()); + return handlers; + } + + private static class NodeDumper implements DebugDumpHandler { + @Override + public void dump(DebugContext debug, Object object, String format, Object... arguments) { + if (object instanceof Node) { + Node node = (Node) object; + String location = GraphUtil.approxSourceLocation(node); + String nodeName = node.toString(Verbosity.Debugger); + if (location != null) { + debug.log("Context obj %s (approx. location: %s)", nodeName, location); + } else { + debug.log("Context obj %s", nodeName); + } + } + } + } + + private static CanonicalStringGraphPrinter createStringPrinter(SnippetReflectionProvider snippetReflection) { + return new CanonicalStringGraphPrinter(snippetReflection); + } + + public static String sanitizedFileName(String name) { + try { + Paths.get(name); + return name; + } catch (InvalidPathException e) { + // fall through + } + StringBuilder buf = new StringBuilder(name.length()); + for (int i = 0; i < name.length(); i++) { + char c = name.charAt(i); + try { + Paths.get(String.valueOf(c)); + } catch (InvalidPathException e) { + buf.append('_'); + } + buf.append(c); + } + return buf.toString(); + } + + private static GraphPrinter createNetworkPrinter(Graph graph, OptionValues options, SnippetReflectionProvider snippetReflection) throws IOException { + String host = PrintGraphHost.getValue(options); + int port = PrintBinaryGraphs.getValue(options) ? PrintBinaryGraphPort.getValue(options) : PrintXmlGraphPort.getValue(options); + try { + GraphPrinter printer; + if (DebugOptions.PrintBinaryGraphs.getValue(options)) { + printer = new BinaryGraphPrinter(SocketChannel.open(new InetSocketAddress(host, port)), snippetReflection); + } else { + printer = new IdealGraphPrinter(new Socket(host, port).getOutputStream(), true, snippetReflection); + } + TTY.println("Connected to the IGV on %s:%d", host, port); + return printer; + } catch (ClosedByInterruptException | InterruptedIOException e) { + /* + * Interrupts should not count as errors because they may be caused by a cancelled Graal + * compilation. ClosedByInterruptException occurs if the SocketChannel could not be + * opened. InterruptedIOException occurs if new Socket(..) was interrupted. + */ + return null; + } catch (IOException e) { + if (!DebugOptions.PrintGraphFile.hasBeenSet(options)) { + return createFilePrinter(graph, options, snippetReflection); + } else { + throw new IOException(String.format("Could not connect to the IGV on %s:%d", host, port), e); + } + } + } + + private static final AtomicInteger unknownCompilationId = new AtomicInteger(); + + /** + * Creates a new file or directory for dumping based on a given graph and a file extension. + * + * @param graph a base path name is derived from {@code graph} + * @param extension a suffix which if non-null and non-empty added to the end of the returned + * path separated by a {@code "."} + * @param createDirectory specifies if this is a request to create a directory instead of a file + * @return the created directory or file + * @throws IOException if there was an error creating the directory or file + */ + static Path createDumpPath(OptionValues options, Graph graph, String extension, boolean createDirectory) throws IOException { + CompilationIdentifier compilationId = CompilationIdentifier.INVALID_COMPILATION_ID; + String id = null; + String label = null; + if (graph instanceof StructuredGraph) { + StructuredGraph sgraph = (StructuredGraph) graph; + label = getGraphName(sgraph); + compilationId = sgraph.compilationId(); + if (compilationId == CompilationIdentifier.INVALID_COMPILATION_ID) { + id = graph.getClass().getSimpleName() + "-" + sgraph.graphId(); + } else { + id = compilationId.toString(CompilationIdentifier.Verbosity.ID); + } + } else { + label = graph == null ? null : graph.name != null ? graph.name : graph.toString(); + id = "UnknownCompilation-" + unknownCompilationId.incrementAndGet(); + } + String ext = UniquePathUtilities.formatExtension(extension); + Path result = createUnique(DebugOptions.getDumpDirectory(options), id, label, ext, createDirectory); + if (ShowDumpFiles.getValue(options)) { + TTY.println("Dumping debug output to %s", result.toAbsolutePath().toString()); + } + return result; + } + + /** + * A maximum file name length supported by most file systems. There is no platform independent + * way to get this in Java. + */ + private static final int MAX_FILE_NAME_LENGTH = 255; + + private static final String ELLIPSIS = "..."; + + private static Path createUnique(Path dumpDir, String id, String label, String ext, boolean createDirectory) throws IOException { + String timestamp = ""; + for (;;) { + int fileNameLengthWithoutLabel = timestamp.length() + ext.length() + id.length() + "[]".length(); + int labelLengthLimit = MAX_FILE_NAME_LENGTH - fileNameLengthWithoutLabel; + String fileName; + if (labelLengthLimit < ELLIPSIS.length()) { + // This means `id` is very long + String suffix = timestamp + ext; + int idLengthLimit = Math.min(MAX_FILE_NAME_LENGTH - suffix.length(), id.length()); + fileName = id.substring(0, idLengthLimit) + suffix; + } else { + if (label == null) { + fileName = sanitizedFileName(id + timestamp + ext); + } else { + String adjustedLabel = label; + if (label.length() > labelLengthLimit) { + adjustedLabel = label.substring(0, labelLengthLimit - ELLIPSIS.length()) + ELLIPSIS; + } + fileName = sanitizedFileName(id + '[' + adjustedLabel + ']' + timestamp + ext); + } + } + Path result = dumpDir.resolve(fileName); + try { + if (createDirectory) { + return Files.createDirectory(result); + } else { + return Files.createFile(result); + } + } catch (FileAlreadyExistsException e) { + timestamp = "_" + Long.toString(System.currentTimeMillis()); + } + } + } + + private static String getGraphName(StructuredGraph graph) { + if (graph.name != null) { + return graph.name; + } else if (graph.method() != null) { + return graph.method().format("%h.%n(%p)").replace(" ", ""); + } else { + return graph.toString(); + } + } + + private static GraphPrinter createFilePrinter(Graph graph, OptionValues options, SnippetReflectionProvider snippetReflection) throws IOException { + Path path = createDumpPath(options, graph, PrintBinaryGraphs.getValue(options) ? "bgv" : "gv.xml", false); + try { + GraphPrinter printer; + if (DebugOptions.PrintBinaryGraphs.getValue(options)) { + printer = new BinaryGraphPrinter(FileChannel.open(path, StandardOpenOption.WRITE), snippetReflection); + } else { + printer = new IdealGraphPrinter(Files.newOutputStream(path), true, snippetReflection); + } + return printer; + } catch (IOException e) { + throw new IOException(String.format("Failed to open %s to dump IGV graphs", path), e); + } + } +} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTest.java 2017-07-07 09:32:10.000000000 -0700 +++ /dev/null 2017-07-07 09:32:10.000000000 -0700 @@ -1,371 +0,0 @@ -/* - * Copyright (c) 2015, 2016, 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 org.graalvm.compiler.core.test.debug; - -import java.io.PrintStream; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; -import java.util.ListIterator; -import java.util.Map; -import java.util.stream.Collectors; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.graalvm.compiler.core.common.util.Util; -import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCloseable; -import org.graalvm.compiler.debug.DebugConfig; -import org.graalvm.compiler.debug.DebugConfigScope; -import org.graalvm.compiler.debug.DebugCounter; -import org.graalvm.compiler.debug.DebugDumpHandler; -import org.graalvm.compiler.debug.DebugMethodMetrics; -import org.graalvm.compiler.debug.DebugTimer; -import org.graalvm.compiler.debug.DebugVerifyHandler; -import org.graalvm.compiler.debug.DelegatingDebugConfig; -import org.graalvm.compiler.debug.DelegatingDebugConfig.Feature; -import org.graalvm.compiler.debug.GraalDebugConfig; -import org.graalvm.compiler.debug.internal.DebugScope; -import org.graalvm.compiler.debug.internal.method.MethodMetricsImpl; -import org.graalvm.compiler.debug.internal.method.MethodMetricsImpl.CompilationData; -import org.graalvm.compiler.debug.internal.method.MethodMetricsInlineeScopeInfo; -import org.graalvm.compiler.debug.internal.method.MethodMetricsPrinter; -import org.graalvm.compiler.nodes.InvokeNode; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.calc.BinaryNode; -import org.graalvm.compiler.nodes.calc.FixedBinaryNode; -import org.graalvm.compiler.nodes.calc.MulNode; -import org.graalvm.compiler.nodes.calc.ShiftNode; -import org.graalvm.compiler.nodes.calc.SignedDivNode; -import org.graalvm.compiler.nodes.calc.SubNode; -import org.graalvm.compiler.options.OptionValues; -import org.graalvm.compiler.phases.BasePhase; -import org.graalvm.compiler.phases.Phase; -import org.graalvm.compiler.phases.PhaseSuite; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; -import org.graalvm.compiler.phases.common.ConvertDeoptimizeToGuardPhase; -import org.graalvm.compiler.phases.schedule.SchedulePhase; -import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy; -import org.graalvm.compiler.phases.tiers.HighTierContext; -import org.graalvm.compiler.phases.tiers.Suites; - -import jdk.vm.ci.meta.ResolvedJavaMethod; - -public abstract class MethodMetricsTest extends GraalCompilerTest { - static class TestApplication { - public static int m01(int x, int y) { - return x + y; - } - - public static int m02(int x, int y) { - return x * y; - } - - public static int m03(int x, int y) { - return x ^ y; - } - - public static int m04(int x, int y) { - return x >> y; - } - - public static int m05(int x, int y) { - return x >>> y; - } - - public static int m06(int x, int y) { - return x << y; - } - - public static int m07(int x, int y) { - return x > y ? 0 : 1; - } - - public static int m08(int x, int y) { - return x % y; - } - - public static int m09(int x, int y) { - return x / y; - } - - public static int m10(int x, int y) { - return x - y; - } - - } - - public static final Class[] testSignature = new Class[]{int.class, int.class}; - public static final Object[] testArgs = new Object[]{10, 10}; - - static class MethodMetricPhases { - static class CountingAddPhase extends Phase { - - // typically those global metrics would be static final, but we need new timers every - // invocation if we override the debugvaluefactory - private final DebugCounter globalCounter = Debug.counter("GlobalMetric"); - private final DebugTimer globalTimer = Debug.timer("GlobalTimer"); - - @Override - @SuppressWarnings("try") - protected void run(StructuredGraph graph) { - try (DebugCloseable d = globalTimer.start()) { - ResolvedJavaMethod method = graph.method(); - DebugMethodMetrics mm = Debug.methodMetrics(method); - mm.addToMetric(graph.getNodes().filter(InvokeNode.class).count(), "Invokes"); - mm.incrementMetric("PhaseRunsOnMethod"); - globalCounter.increment(); - } - } - } - - static class CountingShiftPhase extends Phase { - @Override - protected void run(StructuredGraph graph) { - Debug.methodMetrics(graph.method()).addToMetric(graph.getNodes().filter(ShiftNode.class).count(), "Shifts"); - } - } - - static class CountingMulPhase extends Phase { - @Override - protected void run(StructuredGraph graph) { - Debug.methodMetrics(graph.method()).addToMetric(graph.getNodes().filter(MulNode.class).count(), "Muls"); - } - } - - static class CountingSubPhase extends Phase { - @Override - protected void run(StructuredGraph graph) { - Debug.methodMetrics(graph.method()).addToMetric(graph.getNodes().filter(SubNode.class).count(), "Subs"); - } - } - - static class CountingDivPhase extends Phase { - @Override - protected void run(StructuredGraph graph) { - Debug.methodMetrics(graph.method()).addToMetric(graph.getNodes().filter(SignedDivNode.class).count(), "Divs"); - } - } - - static class CountingBinOpPhase extends Phase { - @Override - protected void run(StructuredGraph graph) { - Debug.methodMetrics(graph.method()).addToMetric(graph.getNodes().filter(x -> x instanceof BinaryNode || x instanceof FixedBinaryNode).count(), "BinOps"); - } - } - - static class ScopeTestPhase extends Phase { - // typically those global metrics would be static final, but we need new timers every - // invocation if we override the debugvaluefactory - private final DebugTimer timer = Debug.timer("GlobalTimer1"); - private final DebugTimer scopedTimer = Debug.timer("GlobalTimer2"); - private final DebugTimer scopedScopedTimer = Debug.timer("GlobalTimer3"); - private final DebugTimer scopedScopedScopeTimer = Debug.timer("GlobalTimer4"); - - private final DebugTimer timer1 = Debug.timer("GlobalTimer1_WithoutInlineEnhancement"); - private final DebugTimer scopedTimer1 = Debug.timer("GlobalTimer2_WithoutInlineEnhancement"); - private final DebugTimer scopedScopedTimer1 = Debug.timer("GlobalTimer3_WithoutInlineEnhancement"); - private final DebugTimer scopedScopedScopeTimer1 = Debug.timer("GlobalTimer4_WithoutInlineEnhancement"); - - @Override - @SuppressWarnings("try") - protected void run(StructuredGraph graph) { - // we are in an enhanced debug scope from graal compiler - // now we open multiple inlining scopes, record their time - try (DebugCloseable c1 = timer.start()) { - try (DebugCloseable c2 = scopedTimer.start()) { - try (DebugCloseable c3 = scopedScopedTimer.start()) { - // do sth unnecessary long allocating many inlinee scopes - for (int i = 0; i < 50; i++) { - try (Debug.Scope s1 = Debug.methodMetricsScope("InlineEnhancement1", MethodMetricsInlineeScopeInfo.create(graph.method()), false)) { - try (DebugCloseable c4 = scopedScopedScopeTimer.start()) { - new SchedulePhase(SchedulingStrategy.LATEST_OUT_OF_LOOPS).apply(graph); - // double scoped inlinee scopes should not make problems - // with the data - try (Debug.Scope s2 = Debug.methodMetricsScope("InlineEnhancement2", MethodMetricsInlineeScopeInfo.create(graph.method()), - false)) { - new SchedulePhase(SchedulingStrategy.LATEST_OUT_OF_LOOPS).apply(graph); - } - } - } - } - } - } - } - - // now lets try different counters without the inline enhancement - try (DebugCloseable c1 = timer1.start()) { - try (DebugCloseable c2 = scopedTimer1.start()) { - try (DebugCloseable c3 = scopedScopedTimer1.start()) { - // do sth unnecessary long allocating many inlinee scopes - for (int i = 0; i < 50; i++) { - try (DebugCloseable c4 = scopedScopedScopeTimer1.start()) { - new SchedulePhase(SchedulingStrategy.LATEST_OUT_OF_LOOPS).apply(graph); - new SchedulePhase(SchedulingStrategy.LATEST_OUT_OF_LOOPS).apply(graph); - } - } - } - } - } - } - - } - } - - static DebugConfig overrideGraalDebugConfig(PrintStream log, String methodFilter, String methodMeter) { - List dumpHandlers = new ArrayList<>(); - List verifyHandlers = new ArrayList<>(); - OptionValues options = getInitialOptions(); - GraalDebugConfig debugConfig = new GraalDebugConfig( - options, - GraalDebugConfig.Options.Log.getValue(options), - GraalDebugConfig.Options.Count.getValue(options), - GraalDebugConfig.Options.TrackMemUse.getValue(options), - GraalDebugConfig.Options.Time.getValue(options), - GraalDebugConfig.Options.Dump.getValue(options), - GraalDebugConfig.Options.Verify.getValue(options), - methodFilter, - methodMeter, - log, dumpHandlers, verifyHandlers); - return debugConfig; - } - - abstract Phase additionalPhase(); - - @Override - protected Suites createSuites(OptionValues options) { - Suites ret = super.createSuites(options); - ListIterator> iter = ret.getHighTier().findPhase(ConvertDeoptimizeToGuardPhase.class, true); - PhaseSuite.findNextPhase(iter, CanonicalizerPhase.class); - iter.add(additionalPhase()); - return ret; - } - - @Test - @SuppressWarnings("try") - public void test() throws Throwable { - try (DebugConfigScope s = Debug.setConfig(getConfig())) { - executeMethod(TestApplication.class.getMethod("m01", testSignature), null, testArgs); - executeMethod(TestApplication.class.getMethod("m02", testSignature), null, testArgs); - executeMethod(TestApplication.class.getMethod("m03", testSignature), null, testArgs); - executeMethod(TestApplication.class.getMethod("m04", testSignature), null, testArgs); - executeMethod(TestApplication.class.getMethod("m05", testSignature), null, testArgs); - executeMethod(TestApplication.class.getMethod("m06", testSignature), null, testArgs); - executeMethod(TestApplication.class.getMethod("m07", testSignature), null, testArgs); - executeMethod(TestApplication.class.getMethod("m08", testSignature), null, testArgs); - executeMethod(TestApplication.class.getMethod("m09", testSignature), null, testArgs); - executeMethod(TestApplication.class.getMethod("m10", testSignature), null, testArgs); - assertValues(); - } - } - - void executeMethod(Method m, Object receiver, Object... args) { - OptionValues options = new OptionValues(getInitialOptions(), MethodMetricsPrinter.Options.MethodMeterPrintAscii, true); - test(options, asResolvedJavaMethod(m), receiver, args); - } - - @Before - public void rememberScopeId() { - scopeIdBeforeAccess = DebugScope.getCurrentGlobalScopeId(); - } - - @After - public void clearMMCache() { - MethodMetricsImpl.clearMM(); - } - - abstract DebugConfig getConfig(); - - abstract void assertValues() throws Throwable; - - @SuppressWarnings("unchecked") - private static Map readMethodMetricsImplData() { - Map threadLocalMap = null; - for (Field f : MethodMetricsImpl.class.getDeclaredFields()) { - if (f.getName().equals("threadEntries")) { - Util.setAccessible(f, true); - Object map; - try { - map = ((ThreadLocal) f.get(null)).get(); - } catch (Throwable t) { - throw new RuntimeException(t); - } - threadLocalMap = (Map) map; - break; - } - } - return threadLocalMap; - } - - private long scopeIdBeforeAccess; - private long scopeIdAfterAccess; - - protected long readValFromCurrThread(ResolvedJavaMethod method, String metricName) { - - Map threadLocalMap = readMethodMetricsImplData(); - assert threadLocalMap != null; - CompilationData compilationData = threadLocalMap.get(method); - assert compilationData != null; - Map> compilations = compilationData.getCompilations(); - List> compilationEntries = new ArrayList<>(); - compilations.forEach((x, y) -> { - if (x >= scopeIdBeforeAccess && x <= scopeIdAfterAccess) { - compilationEntries.add(y); - } - }); - List> listView = compilationEntries.stream().filter(x -> x.size() > 0).collect(Collectors.toList()); - assert listView.size() <= 1 : "There must be at most one none empty compilation data point present:" + listView.size(); - /* - * NOTE: Using the pre-generation of compilation entries for a method has the disadvantage - * that during testing we have different points in time when we request the metric. First, - * properly, when we use it and then when we want to know the result, but when we check the - * result the debug context no longer holds a correct scope with the unique id, so we return - * the first compilation entry that is not empty. - */ - Map entries = listView.size() > 0 ? listView.get(0) : null; - Long res = entries != null ? entries.get(metricName) : null; - return res != null ? res : 0; - } - - @SuppressWarnings("try") - void assertValues(String metricName, long[] vals) { - scopeIdAfterAccess = DebugScope.getCurrentGlobalScopeId(); - try (DebugConfigScope s = Debug.setConfig(new DelegatingDebugConfig().enable(Feature.METHOD_METRICS))) { - Assert.assertEquals(vals[0], readValFromCurrThread(asResolvedJavaMethod(TestApplication.class.getMethod("m01", testSignature)), metricName)); - Assert.assertEquals(vals[1], readValFromCurrThread(asResolvedJavaMethod(TestApplication.class.getMethod("m02", testSignature)), metricName)); - Assert.assertEquals(vals[2], readValFromCurrThread(asResolvedJavaMethod(TestApplication.class.getMethod("m03", testSignature)), metricName)); - Assert.assertEquals(vals[3], readValFromCurrThread(asResolvedJavaMethod(TestApplication.class.getMethod("m04", testSignature)), metricName)); - Assert.assertEquals(vals[4], readValFromCurrThread(asResolvedJavaMethod(TestApplication.class.getMethod("m05", testSignature)), metricName)); - Assert.assertEquals(vals[5], readValFromCurrThread(asResolvedJavaMethod(TestApplication.class.getMethod("m06", testSignature)), metricName)); - Assert.assertEquals(vals[6], readValFromCurrThread(asResolvedJavaMethod(TestApplication.class.getMethod("m07", testSignature)), metricName)); - Assert.assertEquals(vals[7], readValFromCurrThread(asResolvedJavaMethod(TestApplication.class.getMethod("m08", testSignature)), metricName)); - Assert.assertEquals(vals[8], readValFromCurrThread(asResolvedJavaMethod(TestApplication.class.getMethod("m09", testSignature)), metricName)); - } catch (Throwable t) { - throw new RuntimeException(t); - } - } -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTest1.java 2017-07-07 09:32:10.000000000 -0700 +++ /dev/null 2017-07-07 09:32:10.000000000 -0700 @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2015, 2016, 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 org.graalvm.compiler.core.test.debug; - -import org.junit.Test; - -import org.graalvm.compiler.debug.DebugConfig; -import org.graalvm.compiler.phases.Phase; - -public class MethodMetricsTest1 extends MethodMetricsTest { - @Override - protected Phase additionalPhase() { - return new MethodMetricPhases.CountingAddPhase(); - } - - @Override - DebugConfig getConfig() { - return overrideGraalDebugConfig(System.out, "MethodMetricsTest$TestApplication.*", "CountingAddPhase"); - } - - @Override - void assertValues() throws Throwable { - assertValues("PhaseRunsOnMethod", new long[]{1, 1, 1, 1, 1, 1, 1, 1, 1, 1}); - } - - @Override - @Test - public void test() throws Throwable { - super.test(); - } -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTest2.java 2017-07-07 09:32:11.000000000 -0700 +++ /dev/null 2017-07-07 09:32:11.000000000 -0700 @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2015, 2016, 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 org.graalvm.compiler.core.test.debug; - -import org.junit.Test; - -import org.graalvm.compiler.debug.DebugConfig; -import org.graalvm.compiler.phases.Phase; - -public class MethodMetricsTest2 extends MethodMetricsTest { - - @Override - protected Phase additionalPhase() { - return new MethodMetricPhases.CountingShiftPhase(); - } - - @Override - DebugConfig getConfig() { - return overrideGraalDebugConfig(System.out, "MethodMetricsTest$TestApplication.*", "CountingShiftPhase"); - } - - @Override - void assertValues() throws Throwable { - assertValues("Shifts", new long[]{0, 0, 0, 1, 1, 1, 0, 0, 0, 0}); - } - - @Test - @Override - public void test() throws Throwable { - super.test(); - } -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTest3.java 2017-07-07 09:32:11.000000000 -0700 +++ /dev/null 2017-07-07 09:32:11.000000000 -0700 @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2015, 2016, 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 org.graalvm.compiler.core.test.debug; - -import org.junit.Test; - -import org.graalvm.compiler.debug.DebugConfig; -import org.graalvm.compiler.phases.Phase; - -public class MethodMetricsTest3 extends MethodMetricsTest { - - @Override - protected Phase additionalPhase() { - return new MethodMetricPhases.CountingMulPhase(); - } - - @Override - DebugConfig getConfig() { - return overrideGraalDebugConfig(System.out, "MethodMetricsTest$TestApplication.*", "CountingMulPhase"); - } - - @Override - void assertValues() throws Throwable { - assertValues("Muls", new long[]{0, 1, 0, 0, 0, 0, 0, 0, 0, 0}); - } - - @Override - @Test - public void test() throws Throwable { - super.test(); - } -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTest4.java 2017-07-07 09:32:11.000000000 -0700 +++ /dev/null 2017-07-07 09:32:11.000000000 -0700 @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2015, 2016, 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 org.graalvm.compiler.core.test.debug; - -import org.junit.Test; - -import org.graalvm.compiler.debug.DebugConfig; -import org.graalvm.compiler.phases.Phase; - -public class MethodMetricsTest4 extends MethodMetricsTest { - - @Override - protected Phase additionalPhase() { - return new MethodMetricPhases.CountingSubPhase(); - } - - @Override - DebugConfig getConfig() { - return overrideGraalDebugConfig(System.out, "MethodMetricsTest$TestApplication.*", "CountingSubPhase"); - } - - @Override - void assertValues() throws Throwable { - assertValues("Subs", new long[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 1}); - } - - @Override - @Test - public void test() throws Throwable { - super.test(); - } -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTest5.java 2017-07-07 09:32:12.000000000 -0700 +++ /dev/null 2017-07-07 09:32:12.000000000 -0700 @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2015, 2016, 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 org.graalvm.compiler.core.test.debug; - -import org.junit.Test; - -import org.graalvm.compiler.debug.DebugConfig; -import org.graalvm.compiler.phases.Phase; - -public class MethodMetricsTest5 extends MethodMetricsTest { - - @Override - protected Phase additionalPhase() { - return new MethodMetricPhases.CountingDivPhase(); - } - - @Override - DebugConfig getConfig() { - return overrideGraalDebugConfig(System.out, "MethodMetricsTest$TestApplication.*", "CountingDivPhase"); - } - - @Override - void assertValues() throws Throwable { - assertValues("Divs", new long[]{0, 0, 0, 0, 0, 0, 0, 0, 1, 0}); - } - - @Override - @Test - public void test() throws Throwable { - super.test(); - } - -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTest6.java 2017-07-07 09:32:12.000000000 -0700 +++ /dev/null 2017-07-07 09:32:12.000000000 -0700 @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2015, 2016, 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 org.graalvm.compiler.core.test.debug; - -import org.junit.Test; - -import org.graalvm.compiler.debug.DebugConfig; -import org.graalvm.compiler.phases.Phase; - -public class MethodMetricsTest6 extends MethodMetricsTest { - - @Override - protected Phase additionalPhase() { - return new MethodMetricPhases.CountingBinOpPhase(); - } - - @Override - DebugConfig getConfig() { - return overrideGraalDebugConfig(System.out, "MethodMetricsTest$TestApplication.*", "CountingBinOpPhase"); - } - - @Override - void assertValues() throws Throwable { - assertValues("BinOps", new long[]{1, 1, 1, 1, 1, 1, 0, 1, 1, 1}); - } - - @Override - @Test - public void test() throws Throwable { - super.test(); - } -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTestInterception01.java 2017-07-07 09:32:12.000000000 -0700 +++ /dev/null 2017-07-07 09:32:12.000000000 -0700 @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2015, 2016, 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 org.graalvm.compiler.core.test.debug; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugConfig; -import org.graalvm.compiler.debug.DebugCounter; -import org.graalvm.compiler.debug.DebugDumpHandler; -import org.graalvm.compiler.debug.DebugMemUseTracker; -import org.graalvm.compiler.debug.DebugMethodMetrics; -import org.graalvm.compiler.debug.DebugTimer; -import org.graalvm.compiler.debug.DebugValueFactory; -import org.graalvm.compiler.debug.DebugVerifyHandler; -import org.graalvm.compiler.debug.GraalDebugConfig; -import org.graalvm.compiler.debug.internal.CounterImpl; -import org.graalvm.compiler.debug.internal.MemUseTrackerImpl; -import org.graalvm.compiler.debug.internal.TimerImpl; -import org.graalvm.compiler.debug.internal.method.MethodMetricsImpl; -import org.graalvm.compiler.options.OptionValues; -import org.graalvm.compiler.phases.Phase; - -import jdk.vm.ci.meta.ResolvedJavaMethod; - -// intercepting metrics -public class MethodMetricsTestInterception01 extends MethodMetricsTest { - - @Override - protected Phase additionalPhase() { - return new MethodMetricPhases.CountingAddPhase(); - } - - @Override - DebugConfig getConfig() { - List dumpHandlers = new ArrayList<>(); - List verifyHandlers = new ArrayList<>(); - OptionValues options = getInitialOptions(); - GraalDebugConfig debugConfig = new GraalDebugConfig( - options, - GraalDebugConfig.Options.Log.getValue(options), - "CountingAddPhase", - GraalDebugConfig.Options.TrackMemUse.getValue(options), - "CountingAddPhase", - GraalDebugConfig.Options.Dump.getValue(options), - GraalDebugConfig.Options.Verify.getValue(options), - "MethodMetricsTest$TestApplication.*", - "CountingAddPhase", - System.out, dumpHandlers, verifyHandlers); - return debugConfig; - } - - private DebugValueFactory factory; - - @Test - @Override - @SuppressWarnings("try") - public void test() throws Throwable { - factory = Debug.getDebugValueFactory(); - Debug.setDebugValueFactory(new DebugValueFactory() { - @Override - public DebugTimer createTimer(String name, boolean conditional) { - return new TimerImpl(name, conditional, true); - } - - @Override - public DebugCounter createCounter(String name, boolean conditional) { - return CounterImpl.create(name, conditional, true); - } - - @Override - public DebugMethodMetrics createMethodMetrics(ResolvedJavaMethod method) { - return MethodMetricsImpl.getMethodMetrics(method); - } - - @Override - public DebugMemUseTracker createMemUseTracker(String name, boolean conditional) { - return new MemUseTrackerImpl(name, conditional, true); - } - }); - super.test(); - - } - - @Override - public void afterTest() { - super.afterTest(); - Debug.setDebugValueFactory(factory); - } - - @Override - @SuppressWarnings("try") - void assertValues() throws Throwable { - assertValues("GlobalMetric", new long[]{1, 1, 1, 1, 1, 1, 1, 1, 1, 1}); - } -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTestInterception02.java 2017-07-07 09:32:13.000000000 -0700 +++ /dev/null 2017-07-07 09:32:13.000000000 -0700 @@ -1,164 +0,0 @@ -/* - * Copyright (c) 2015, 2016, 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 org.graalvm.compiler.core.test.debug; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; - -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCloseable; -import org.graalvm.compiler.debug.DebugConfig; -import org.graalvm.compiler.debug.DebugCounter; -import org.graalvm.compiler.debug.DebugDumpHandler; -import org.graalvm.compiler.debug.DebugMemUseTracker; -import org.graalvm.compiler.debug.DebugMethodMetrics; -import org.graalvm.compiler.debug.DebugTimer; -import org.graalvm.compiler.debug.DebugValueFactory; -import org.graalvm.compiler.debug.DebugVerifyHandler; -import org.graalvm.compiler.debug.GraalDebugConfig; -import org.graalvm.compiler.debug.internal.method.MethodMetricsImpl; -import org.graalvm.compiler.options.OptionValues; -import org.graalvm.compiler.phases.Phase; - -import jdk.vm.ci.meta.ResolvedJavaMethod; - -// intercepting metrics -public class MethodMetricsTestInterception02 extends MethodMetricsTest { - - @Override - protected Phase additionalPhase() { - return new MethodMetricPhases.ScopeTestPhase(); - } - - private DebugValueFactory factory; - - public void setFactory() { - /* - * setting a custom debug value factory creating a constant timer for checking scope - * creation and inlining scopes with metric intercepting works - */ - factory = Debug.getDebugValueFactory(); - Debug.setDebugValueFactory(new DebugValueFactory() { - @Override - public DebugTimer createTimer(String name, boolean conditional) { - // can still use together with real timer - // TimerImpl realTimer = new TimerImpl(name, conditional, true); - return new DebugTimer() { - int runs = 0; - - // private DebugCloseable t; - - @Override - public DebugCloseable start() { - // t = realTimer.start(); - return new DebugCloseable() { - @Override - public void close() { - // t.close(); - runs++; - MethodMetricsImpl.addToCurrentScopeMethodMetrics(name, 1); - } - }; - } - - @Override - public void setConditional(boolean flag) { - - } - - @Override - public boolean isConditional() { - return false; - } - - @Override - public TimeUnit getTimeUnit() { - return TimeUnit.MILLISECONDS; - } - - @Override - public long getCurrentValue() { - return runs; - } - }; - } - - @Override - public DebugCounter createCounter(String name, boolean conditional) { - return factory.createCounter(name, conditional); - } - - @Override - public DebugMethodMetrics createMethodMetrics(ResolvedJavaMethod method) { - return factory.createMethodMetrics(method); - } - - @Override - public DebugMemUseTracker createMemUseTracker(String name, boolean conditional) { - return factory.createMemUseTracker(name, conditional); - } - }); - } - - @Test - @Override - public void test() throws Throwable { - setFactory(); - super.test(); - } - - @Override - public void afterTest() { - super.afterTest(); - Debug.setDebugValueFactory(factory); - } - - @Override - DebugConfig getConfig() { - List dumpHandlers = new ArrayList<>(); - List verifyHandlers = new ArrayList<>(); - OptionValues options = getInitialOptions(); - GraalDebugConfig debugConfig = new GraalDebugConfig( - options, - GraalDebugConfig.Options.Log.getValue(options), - ""/* unscoped meter */, - GraalDebugConfig.Options.TrackMemUse.getValue(options), - ""/* unscoped time */, - GraalDebugConfig.Options.Dump.getValue(options), - GraalDebugConfig.Options.Verify.getValue(options), - null /* no method filter */, - "" /* unscoped method metering */, - System.out, dumpHandlers, verifyHandlers); - return debugConfig; - } - - @Override - @SuppressWarnings("try") - void assertValues() throws Throwable { - assertValues("GlobalTimer4_WithoutInlineEnhancement", new long[]{50, 50, 50, 50, 50, 50, 50, 50, 50, 50}); - } - -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/VerifyMethodMetricsTest.java 2017-07-07 09:32:13.000000000 -0700 +++ /dev/null 2017-07-07 09:32:13.000000000 -0700 @@ -1,265 +0,0 @@ -/* - * Copyright (c) 2015, 2016, 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 org.graalvm.compiler.core.test.debug; - -import static org.graalvm.compiler.core.test.GraalCompilerTest.getInitialOptions; - -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; - -import org.graalvm.compiler.api.test.Graal; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugConfigScope; -import org.graalvm.compiler.debug.DebugMethodMetrics; -import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.java.GraphBuilderPhase; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; -import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; -import org.graalvm.compiler.phases.OptimisticOptimizations; -import org.graalvm.compiler.phases.Phase; -import org.graalvm.compiler.phases.PhaseSuite; -import org.graalvm.compiler.phases.VerifyPhase.VerificationError; -import org.graalvm.compiler.phases.tiers.HighTierContext; -import org.graalvm.compiler.phases.util.Providers; -import org.graalvm.compiler.phases.verify.VerifyDebugUsage; -import org.graalvm.compiler.runtime.RuntimeProvider; -import org.junit.Test; - -import jdk.vm.ci.meta.MetaAccessProvider; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -/** - * - * Tests to verify that the usage of method metrics does not generate compile time overhead through - * eager evaluation of arguments. - */ -public class VerifyMethodMetricsTest { - - private static class InvalidCCP_ToString01Inc extends Phase { - @Override - protected void run(StructuredGraph graph) { - DebugMethodMetrics m = Debug.methodMetrics(graph.method()); - for (Node n : graph.getNodes()) { - m.incrementMetric(n.toString()); - } - } - } - - private static class InvalidCCP_Concat01Inc extends Phase { - @Override - protected void run(StructuredGraph graph) { - DebugMethodMetrics m = Debug.methodMetrics(graph.method()); - for (Node n : graph.getNodes()) { - m.incrementMetric("a" + n.toString()); - } - } - } - - private static class InvalidCCP_ToString02Inc extends Phase { - @Override - protected void run(StructuredGraph graph) { - DebugMethodMetrics m = Debug.methodMetrics(graph.method()); - for (Node n : graph.getNodes()) { - m.incrementMetric("%s", n.toString()); - } - } - } - - private static class InvalidCCP_Concat02Inc extends Phase { - private final String s = this.getClass().toGenericString(); - - @Override - protected void run(StructuredGraph graph) { - DebugMethodMetrics m = Debug.methodMetrics(graph.method()); - for (Node n : graph.getNodes()) { - m.incrementMetric("%s%s", "a" + s, n); - } - } - } - - private static class ValidCCP_ToStringInc extends Phase { - @Override - protected void run(StructuredGraph graph) { - DebugMethodMetrics m = Debug.methodMetrics(graph.method()); - for (Node n : graph.getNodes()) { - m.addToMetric(1, "%s", n); - } - } - } - - private static class ValidCCP_ConcatInc extends Phase { - @Override - protected void run(StructuredGraph graph) { - DebugMethodMetrics m = Debug.methodMetrics(graph.method()); - for (Node n : graph.getNodes()) { - m.incrementMetric("%s%s", "a", n); - } - } - } - - private static class InvalidCCP_ToString01Add extends Phase { - @Override - protected void run(StructuredGraph graph) { - DebugMethodMetrics m = Debug.methodMetrics(graph.method()); - for (Node n : graph.getNodes()) { - m.addToMetric(1, n.toString()); - } - } - } - - private static class InvalidCCP_Concat01Add extends Phase { - @Override - protected void run(StructuredGraph graph) { - DebugMethodMetrics m = Debug.methodMetrics(graph.method()); - for (Node n : graph.getNodes()) { - m.addToMetric(1, "a" + n.toString()); - } - } - } - - private static class InvalidCCP_ToString02Add extends Phase { - @Override - protected void run(StructuredGraph graph) { - DebugMethodMetrics m = Debug.methodMetrics(graph.method()); - for (Node n : graph.getNodes()) { - m.addToMetric(1, "%s", n.toString()); - } - } - } - - private static class InvalidCCP_Concat02Add extends Phase { - private final String s = this.getClass().toGenericString(); - - @Override - protected void run(StructuredGraph graph) { - DebugMethodMetrics m = Debug.methodMetrics(graph.method()); - for (Node n : graph.getNodes()) { - m.addToMetric(1, "%s%s", "a" + s, n); - } - } - } - - private static class ValidCCP_ToStringAdd extends Phase { - @Override - protected void run(StructuredGraph graph) { - DebugMethodMetrics m = Debug.methodMetrics(graph.method()); - for (Node n : graph.getNodes()) { - m.addToMetric(1, "%s", n); - } - } - } - - private static class ValidCCP_ConcatAdd extends Phase { - @Override - protected void run(StructuredGraph graph) { - DebugMethodMetrics m = Debug.methodMetrics(graph.method()); - for (Node n : graph.getNodes()) { - m.addToMetric(1, "%s%s", "a", n); - } - } - } - - @Test(expected = VerificationError.class) - public void testLogInvalidToString01Add() { - testDebugUsageClass(InvalidCCP_ToString01Add.class); - } - - @Test(expected = VerificationError.class) - public void testLogInvalidConcat01Add() { - testDebugUsageClass(InvalidCCP_Concat01Add.class); - } - - @Test(expected = VerificationError.class) - public void testLogInvalidToString02Add() { - testDebugUsageClass(InvalidCCP_ToString02Add.class); - } - - @Test(expected = VerificationError.class) - public void testLogInvalidConcat02Add() { - testDebugUsageClass(InvalidCCP_Concat02Add.class); - } - - @Test - public void testLogValidToStringAdd() { - testDebugUsageClass(ValidCCP_ToStringAdd.class); - } - - @Test - public void testLogValidConcatAdd() { - testDebugUsageClass(ValidCCP_ConcatAdd.class); - } - - @Test(expected = VerificationError.class) - public void testLogInvalidToString01Inc() { - testDebugUsageClass(InvalidCCP_ToString01Inc.class); - } - - @Test(expected = VerificationError.class) - public void testLogInvalidConcat01Inc() { - testDebugUsageClass(InvalidCCP_Concat01Inc.class); - } - - @Test(expected = VerificationError.class) - public void testLogInvalidToString02Inc() { - testDebugUsageClass(InvalidCCP_ToString02Inc.class); - } - - @Test(expected = VerificationError.class) - public void testLogInvalidConcat02Inc() { - testDebugUsageClass(InvalidCCP_Concat02Inc.class); - } - - @Test - public void testLogValidToStringInc() { - testDebugUsageClass(ValidCCP_ToStringInc.class); - } - - @Test - public void testLogValidConcatInc() { - testDebugUsageClass(ValidCCP_ConcatInc.class); - } - - @SuppressWarnings("try") - private static void testDebugUsageClass(Class c) { - RuntimeProvider rt = Graal.getRequiredCapability(RuntimeProvider.class); - Providers providers = rt.getHostBackend().getProviders(); - MetaAccessProvider metaAccess = providers.getMetaAccess(); - PhaseSuite graphBuilderSuite = new PhaseSuite<>(); - Plugins plugins = new Plugins(new InvocationPlugins()); - GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true); - graphBuilderSuite.appendPhase(new GraphBuilderPhase(config)); - HighTierContext context = new HighTierContext(providers, graphBuilderSuite, OptimisticOptimizations.NONE); - for (Method m : c.getDeclaredMethods()) { - if (!Modifier.isNative(m.getModifiers()) && !Modifier.isAbstract(m.getModifiers())) { - ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m); - StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions()).method(method).build(); - graphBuilderSuite.apply(graph, context); - try (DebugConfigScope s = Debug.disableIntercept()) { - new VerifyDebugUsage().apply(graph, context); - } - } - } - } -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalDebugInitializationParticipant.java 2017-07-07 09:32:13.000000000 -0700 +++ /dev/null 2017-07-07 09:32:13.000000000 -0700 @@ -1,112 +0,0 @@ -/* - * 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 org.graalvm.compiler.core; - -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Params; -import org.graalvm.compiler.debug.DebugInitializationParticipant; -import org.graalvm.compiler.debug.GraalDebugConfig; -import org.graalvm.compiler.debug.TTY; -import org.graalvm.compiler.debug.internal.method.MethodMetricsPrinter; -import org.graalvm.compiler.options.OptionValues; -import org.graalvm.compiler.serviceprovider.ServiceProvider; - -/** - * A service provider that may modify the initialization of {@link Debug} based on the values - * specified for various {@link GraalDebugConfig} options. - */ -@ServiceProvider(DebugInitializationParticipant.class) -public class GraalDebugInitializationParticipant implements DebugInitializationParticipant { - - @Override - public void apply(Params params) { - OptionValues options = params.getOptions(); - if (GraalDebugConfig.areDebugScopePatternsEnabled(options)) { - params.enable = true; - } - if ("".equals(GraalDebugConfig.Options.Count.getValue(options))) { - params.enableUnscopedCounters = true; - } - if ("".equals(GraalDebugConfig.Options.MethodMeter.getValue(options))) { - params.enableUnscopedMethodMetrics = true; - // mm requires full debugging support - params.enable = true; - } - if ("".equals(GraalDebugConfig.Options.Time.getValue(options))) { - params.enableUnscopedTimers = true; - } - if ("".equals(GraalDebugConfig.Options.TrackMemUse.getValue(options))) { - params.enableUnscopedMemUseTrackers = true; - } - // unscoped counters/timers/mem use trackers/method metrics should respect method filter - // semantics - if (!params.enable && (params.enableUnscopedMemUseTrackers || params.enableUnscopedMethodMetrics || params.enableUnscopedCounters || params.enableUnscopedTimers) && - GraalDebugConfig.isNotEmpty(GraalDebugConfig.Options.MethodFilter, options)) { - params.enable = true; - params.enableMethodFilter = true; - } - - if (!params.enable && GraalDebugConfig.Options.DumpOnPhaseChange.getValue(options) != null) { - params.enable = true; - } - - if (!params.enableUnscopedMethodMetrics && GraalDebugConfig.Options.MethodMeter.getValue(options) != null) { - // mm requires full debugging support - params.enable = true; - } - - if (GraalDebugConfig.isGlobalMetricsInterceptedByMethodMetricsEnabled(options)) { - if (!params.enable) { - TTY.println("WARNING: MethodMeter is disabled but GlobalMetricsInterceptedByMethodMetrics is enabled. Ignoring MethodMeter and GlobalMetricsInterceptedByMethodMetrics."); - } else { - parseMethodMetricsDebugValueInterception(params, options); - } - } - if (GraalDebugConfig.isNotEmpty(GraalDebugConfig.Options.MethodMeter, options) || params.enableUnscopedMethodMetrics) { - if (!MethodMetricsPrinter.methodMetricsDumpingEnabled(options)) { - TTY.println("WARNING: MethodMeter is enabled but MethodMeter dumping is disabled. Output will not contain MethodMetrics."); - } - } - } - - private static void parseMethodMetricsDebugValueInterception(Params params, OptionValues options) { - String interceptionGroup = GraalDebugConfig.Options.GlobalMetricsInterceptedByMethodMetrics.getValue(options); - boolean intercepted = false; - if (interceptionGroup.contains("Timers")) { - params.interceptTime = true; - intercepted = true; - } - if (interceptionGroup.contains("Counters")) { - params.interceptCount = true; - intercepted = true; - } - if (interceptionGroup.contains("MemUseTrackers")) { - params.interceptMem = true; - intercepted = true; - } - - if (!intercepted) { - TTY.println("WARNING: Ignoring GlobalMetricsInterceptedByMethodMetrics as the supplied argument does not contain Timers/Counters/MemUseTrackers."); - } - } -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/DebugHistogramTest.java 2017-07-07 09:32:13.000000000 -0700 +++ /dev/null 2017-07-07 09:32:13.000000000 -0700 @@ -1,127 +0,0 @@ -/* - * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.debug.test; - -import java.io.ByteArrayOutputStream; -import java.io.PrintStream; - -import org.junit.Assert; -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugHistogram; -import org.graalvm.compiler.debug.internal.DebugHistogramAsciiPrinter; -import org.graalvm.compiler.debug.internal.DebugHistogramRPrinter; - -public class DebugHistogramTest { - - @Test - public void testEmptyHistogram() { - DebugHistogram histogram = Debug.createHistogram("TestHistogram"); - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - - new DebugHistogramAsciiPrinter(new PrintStream(outputStream)).print(histogram); - String line = outputStream.toString().split("\r?\n")[0]; - Assert.assertEquals("TestHistogram is empty.", line); - - outputStream.reset(); - new DebugHistogramRPrinter(new PrintStream(outputStream)).print(histogram); - Assert.assertEquals("", outputStream.toString()); - } - - @Test - public void testSingleEntryHistogram() { - DebugHistogram histogram = Debug.createHistogram("TestHistogram"); - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - histogram.add(new Integer(1)); - histogram.add(new Integer(1)); - new DebugHistogramAsciiPrinter(new PrintStream(outputStream)).print(histogram); - String[] lines = outputStream.toString().split("\r?\n"); - // @formatter:off - String[] expected = { - "TestHistogram has 1 unique elements and 2 total elements:", - "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------", - "| 1 | 2 | ==================================================================================================== |", - "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------" - }; - // @formatter:on - Assert.assertArrayEquals(expected, lines); - - outputStream.reset(); - new DebugHistogramRPrinter(new PrintStream(outputStream)).print(histogram); - lines = outputStream.toString().split("\r?\n"); - // @formatter:off - expected = new String[] { - "TestHistogram <- c(2);", - "names(TestHistogram) <- c(\"1\");" - }; - // @formatter:on - Assert.assertArrayEquals(expected, lines); - } - - @Test - public void testMultipleEntryHistogram() { - DebugHistogram histogram = Debug.createHistogram("TestHistogram"); - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - histogram.add(new Integer(1)); - histogram.add(new Integer(2)); - histogram.add(new Integer(2)); - new DebugHistogramAsciiPrinter(new PrintStream(outputStream)).print(histogram); - String[] lines = outputStream.toString().split("\r?\n"); - // @formatter:off - String[] expected = new String[] { - "TestHistogram has 2 unique elements and 3 total elements:", - "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------", - "| 2 | 2 | ==================================================================================================== |", - "| 1 | 1 | ================================================== |", - "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------" - }; - // @formatter:on - Assert.assertArrayEquals(expected, lines); - - outputStream.reset(); - new DebugHistogramRPrinter(new PrintStream(outputStream)).print(histogram); - lines = outputStream.toString().split("\r?\n"); - // @formatter:off - expected = new String[] { - "TestHistogram <- c(2, 1);", - "names(TestHistogram) <- c(\"2\", \"1\");" - }; - // @formatter:on - Assert.assertArrayEquals(expected, lines); - } - - @Test - public void testTooLongValueString() { - DebugHistogram histogram = Debug.createHistogram("TestHistogram"); - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - histogram.add("MyCustomValue"); - new DebugHistogramAsciiPrinter(new PrintStream(outputStream), Integer.MAX_VALUE, 10, 10, 1).print(histogram); - String[] lines = outputStream.toString().split("\r?\n"); - Assert.assertEquals(4, lines.length); - Assert.assertEquals("TestHistogram has 1 unique elements and 1 total elements:", lines[0]); - Assert.assertEquals("----------------------------------------", lines[1]); - Assert.assertEquals("| MyCusto... | 1 | ========== |", lines[2]); - Assert.assertEquals("----------------------------------------", lines[3]); - } -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/DebugTimerTest.java 2017-07-07 09:32:14.000000000 -0700 +++ /dev/null 2017-07-07 09:32:14.000000000 -0700 @@ -1,98 +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 org.graalvm.compiler.debug.test; - -import static org.junit.Assert.assertEquals; - -import java.lang.management.ThreadMXBean; - -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCloseable; -import org.graalvm.compiler.debug.DebugConfig; -import org.graalvm.compiler.debug.DebugConfigScope; -import org.graalvm.compiler.debug.DebugTimer; -import org.graalvm.compiler.debug.Management; -import org.graalvm.compiler.options.OptionValues; -import org.graalvm.util.EconomicMap; -import org.junit.Assume; -import org.junit.Before; -import org.junit.Test; - -@SuppressWarnings("try") -public class DebugTimerTest { - - private static final ThreadMXBean threadMXBean = Management.getThreadMXBean(); - - @Before - public void checkCapabilities() { - Assume.assumeTrue("skipping management interface test", threadMXBean.isCurrentThreadCpuTimeSupported()); - } - - /** - * Actively spins the current thread for at least a given number of milliseconds in such a way - * that timers for the current thread keep ticking over. - * - * @return the number of milliseconds actually spent spinning which is guaranteed to be >= - * {@code ms} - */ - private static long spin(long ms) { - long start = threadMXBean.getCurrentThreadCpuTime(); - do { - long durationMS = (threadMXBean.getCurrentThreadCpuTime() - start) / 1000; - if (durationMS >= ms) { - return durationMS; - } - } while (true); - } - - /** - * Asserts that a timer replied recursively without any other interleaving timers has the same - * flat and accumulated times. - */ - @Test - public void test2() { - OptionValues options = new OptionValues(EconomicMap.create()); - DebugConfig debugConfig = Debug.fixedConfig(options, 0, 0, false, false, true, false, false, null, null, System.out); - try (DebugConfigScope dcs = new DebugConfigScope(debugConfig); Debug.Scope s = Debug.scope("DebugTimerTest")) { - DebugTimer timerC = Debug.timer("TimerC"); - try (DebugCloseable c1 = timerC.start()) { - spin(50); - try (DebugCloseable c2 = timerC.start()) { - spin(50); - try (DebugCloseable c3 = timerC.start()) { - spin(50); - try (DebugCloseable c4 = timerC.start()) { - spin(50); - try (DebugCloseable c5 = timerC.start()) { - spin(50); - } - } - } - } - } - if (timerC.getFlat() != null) { - assertEquals(timerC.getFlat().getCurrentValue(), timerC.getCurrentValue()); - } - } - } -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Debug.java 2017-07-07 09:32:14.000000000 -0700 +++ /dev/null 2017-07-07 09:32:14.000000000 -0700 @@ -1,1786 +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 org.graalvm.compiler.debug; - -import static java.util.FormattableFlags.LEFT_JUSTIFY; -import static java.util.FormattableFlags.UPPERCASE; -import static org.graalvm.compiler.debug.DelegatingDebugConfig.Feature.INTERCEPT; -import static org.graalvm.compiler.debug.DelegatingDebugConfig.Feature.LOG_METHOD; - -import java.io.PrintStream; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.ConcurrentModificationException; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.Callable; -import java.util.concurrent.TimeUnit; - -import org.graalvm.compiler.debug.DelegatingDebugConfig.Level; -import org.graalvm.compiler.debug.internal.CounterImpl; -import org.graalvm.compiler.debug.internal.DebugHistogramImpl; -import org.graalvm.compiler.debug.internal.DebugScope; -import org.graalvm.compiler.debug.internal.MemUseTrackerImpl; -import org.graalvm.compiler.debug.internal.TimerImpl; -import org.graalvm.compiler.debug.internal.method.MethodMetricsImpl; -import org.graalvm.compiler.options.OptionValues; -import org.graalvm.compiler.options.OptionValuesAccess; -import org.graalvm.compiler.serviceprovider.GraalServices; - -import jdk.vm.ci.meta.ResolvedJavaMethod; - -/** - * Scope based debugging facility. - * - * This facility is {@linkplain #isEnabled() enabled} if any of the following hold when the - * {@link Debug} class is initialized: - *
    - *
  • assertions are enabled for the {@link Debug} class
  • - *
  • {@link Debug#params}{@code .enable} is {@code true}
  • - *
- */ -public class Debug { - - /** - * The option values available in this package. - */ - static final OptionValues DEBUG_OPTIONS = GraalServices.loadSingle(OptionValuesAccess.class, true).getOptions(); - - static final Params params = new Params(); - - static { - // Load the service providers that may want to modify any of the - // parameters encapsulated by the Initialization class below. - for (DebugInitializationParticipant p : GraalServices.load(DebugInitializationParticipant.class)) { - p.apply(params); - } - } - - /** - * The parameters for configuring the initialization of {@link Debug} class. - */ - public static final class Params { - public boolean enable; - public boolean enableMethodFilter; - public boolean enableUnscopedTimers; - public boolean enableUnscopedCounters; - public boolean enableUnscopedMethodMetrics; - public boolean enableUnscopedMemUseTrackers; - public boolean interceptCount; - public boolean interceptTime; - public boolean interceptMem; - - @SuppressWarnings("static-method") - public OptionValues getOptions() { - return DEBUG_OPTIONS; - } - } - - @SuppressWarnings("all") - private static boolean initialize() { - return Assertions.ENABLED || params.enable || GraalDebugConfig.Options.ForceDebugEnable.getValue(DEBUG_OPTIONS); - } - - private static final boolean ENABLED = initialize(); - - public static boolean isEnabled() { - return ENABLED; - } - - public static boolean isDumpEnabledForMethod() { - if (!ENABLED) { - return false; - } - DebugConfig config = DebugScope.getConfig(); - if (config == null) { - return false; - } - return config.isDumpEnabledForMethod(); - } - - /** - * A special dump level that indicates the dumping machinery is enabled but no dumps will be - * produced except through other options. - */ - public static final int ENABLED_LEVEL = 0; - - /** - * Basic debug level. - * - * For HIR dumping, only ~5 graphs per method: after parsing, after inlining, after high tier, - * after mid tier, after low tier. - * - * LIR dumping: After LIR generation, after each pre-allocation, allocation and post allocation - * stage, and after code installation. - */ - public static final int BASIC_LEVEL = 1; - - /** - * Informational debug level. - * - * HIR dumping: One graph after each applied top-level phase. - * - * LIR dumping: After each applied phase. - */ - public static final int INFO_LEVEL = 2; - - /** - * Verbose debug level. - * - * HIR dumping: One graph after each phase (including sub phases). - * - * LIR dumping: After each phase including sub phases. - */ - public static final int VERBOSE_LEVEL = 3; - - /** - * Detailed debug level. - * - * HIR dumping: Graphs within phases where interesting for a phase, max ~5 per phase. - * - * LIR dumping: Dump CFG within phases where interesting. - */ - public static final int DETAILED_LEVEL = 4; - - /** - * Very detailed debug level. - * - * HIR dumping: Graphs per node granularity graph change (before/after change). - * - * LIR dumping: Intermediate CFGs of phases where interesting. - */ - public static final int VERY_DETAILED_LEVEL = 5; - - public static boolean isDumpEnabled(int dumpLevel) { - return ENABLED && DebugScope.getInstance().isDumpEnabled(dumpLevel); - } - - /** - * Determines if verification is enabled in the current method, regardless of the - * {@linkplain Debug#currentScope() current debug scope}. - * - * @see Debug#verify(Object, String) - */ - public static boolean isVerifyEnabledForMethod() { - if (!ENABLED) { - return false; - } - DebugConfig config = DebugScope.getConfig(); - if (config == null) { - return false; - } - return config.isVerifyEnabledForMethod(); - } - - /** - * Determines if verification is enabled in the {@linkplain Debug#currentScope() current debug - * scope}. - * - * @see Debug#verify(Object, String) - */ - public static boolean isVerifyEnabled() { - return ENABLED && DebugScope.getInstance().isVerifyEnabled(); - } - - public static boolean isCountEnabled() { - return ENABLED && DebugScope.getInstance().isCountEnabled(); - } - - public static boolean isTimeEnabled() { - return ENABLED && DebugScope.getInstance().isTimeEnabled(); - } - - public static boolean isMemUseTrackingEnabled() { - return ENABLED && DebugScope.getInstance().isMemUseTrackingEnabled(); - } - - public static boolean isLogEnabledForMethod() { - if (!ENABLED) { - return false; - } - DebugConfig config = DebugScope.getConfig(); - if (config == null) { - return false; - } - return config.isLogEnabledForMethod(); - } - - public static boolean isLogEnabled() { - return isLogEnabled(BASIC_LEVEL); - } - - public static boolean isLogEnabled(int logLevel) { - return ENABLED && DebugScope.getInstance().isLogEnabled(logLevel); - } - - public static boolean isMethodMeterEnabled() { - return ENABLED && DebugScope.getInstance().isMethodMeterEnabled(); - } - - @SuppressWarnings("unused") - public static Runnable decorateDebugRoot(Runnable runnable, String name, DebugConfig config) { - return runnable; - } - - @SuppressWarnings("unused") - public static Callable decorateDebugRoot(Callable callable, String name, DebugConfig config) { - return callable; - } - - @SuppressWarnings("unused") - public static Runnable decorateScope(Runnable runnable, String name, Object... context) { - return runnable; - } - - @SuppressWarnings("unused") - public static Callable decorateScope(Callable callable, String name, Object... context) { - return callable; - } - - /** - * Gets a string composed of the names in the current nesting of debug - * {@linkplain #scope(Object) scopes} separated by {@code '.'}. - */ - public static String currentScope() { - if (ENABLED) { - return DebugScope.getInstance().getQualifiedName(); - } else { - return ""; - } - } - - /** - * Represents a debug scope entered by {@link Debug#scope(Object)} or - * {@link Debug#sandbox(CharSequence, DebugConfig, Object...)}. Leaving the scope is achieved - * via {@link #close()}. - */ - public interface Scope extends AutoCloseable { - @Override - void close(); - } - - /** - * Creates and enters a new debug scope which will be a child of the current debug scope. - *

- * It is recommended to use the try-with-resource statement for managing entering and leaving - * debug scopes. For example: - * - *

-     * try (Scope s = Debug.scope("InliningGraph", inlineeGraph)) {
-     *     ...
-     * } catch (Throwable e) {
-     *     throw Debug.handle(e);
-     * }
-     * 
- * - * The {@code name} argument is subject to the following type based conversion before having - * {@link Object#toString()} called on it: - * - *
-     *     Type          | Conversion
-     * ------------------+-----------------
-     *  java.lang.Class  | arg.getSimpleName()
-     *                   |
-     * 
- * - * @param name the name of the new scope - * @param contextObjects an array of object to be appended to the {@linkplain #context() - * current} debug context - * @throws Throwable used to enforce a catch block. - * @return the scope entered by this method which will be exited when its {@link Scope#close()} - * method is called - */ - public static Scope scope(Object name, Object[] contextObjects) throws Throwable { - if (ENABLED) { - return DebugScope.getInstance().scope(convertFormatArg(name).toString(), null, contextObjects); - } else { - return null; - } - } - - /** - * Similar to {@link #scope(Object, Object[])} but without context objects. Therefore the catch - * block can be omitted. - * - * @see #scope(Object, Object[]) - */ - public static Scope scope(Object name) { - if (ENABLED) { - return DebugScope.getInstance().scope(convertFormatArg(name).toString(), null); - } else { - return null; - } - } - - public static Scope methodMetricsScope(Object name, DebugScope.ExtraInfo metaInfo, boolean newId, Object... context) { - if (ENABLED) { - return DebugScope.getInstance().enhanceWithExtraInfo(convertFormatArg(name).toString(), metaInfo, newId, context); - } else { - return null; - } - } - - /** - * @see #scope(Object, Object[]) - * @param context an object to be appended to the {@linkplain #context() current} debug context - */ - public static Scope scope(Object name, Object context) throws Throwable { - if (ENABLED) { - return DebugScope.getInstance().scope(convertFormatArg(name).toString(), null, context); - } else { - return null; - } - } - - /** - * @see #scope(Object, Object[]) - * @param context1 first object to be appended to the {@linkplain #context() current} debug - * context - * @param context2 second object to be appended to the {@linkplain #context() current} debug - * context - */ - public static Scope scope(Object name, Object context1, Object context2) throws Throwable { - if (ENABLED) { - return DebugScope.getInstance().scope(convertFormatArg(name).toString(), null, context1, context2); - } else { - return null; - } - } - - /** - * @see #scope(Object, Object[]) - * @param context1 first object to be appended to the {@linkplain #context() current} debug - * context - * @param context2 second object to be appended to the {@linkplain #context() current} debug - * context - * @param context3 third object to be appended to the {@linkplain #context() current} debug - * context - */ - public static Scope scope(Object name, Object context1, Object context2, Object context3) throws Throwable { - if (ENABLED) { - return DebugScope.getInstance().scope(convertFormatArg(name).toString(), null, context1, context2, context3); - } else { - return null; - } - } - - /** - * Creates and enters a new debug scope which will be disjoint from the current debug scope. - *

- * It is recommended to use the try-with-resource statement for managing entering and leaving - * debug scopes. For example: - * - *

-     * try (Scope s = Debug.sandbox("CompilingStub", null, stubGraph)) {
-     *     ...
-     * } catch (Throwable e) {
-     *     throw Debug.handle(e);
-     * }
-     * 
- * - * @param name the name of the new scope - * @param config the debug configuration to use for the new scope - * @param context objects to be appended to the {@linkplain #context() current} debug context - * @return the scope entered by this method which will be exited when its {@link Scope#close()} - * method is called - */ - public static Scope sandbox(CharSequence name, DebugConfig config, Object... context) throws Throwable { - if (ENABLED) { - DebugConfig sandboxConfig = config == null ? silentConfig() : config; - return DebugScope.getInstance().scope(name, sandboxConfig, context); - } else { - return null; - } - } - - public static Scope forceLog() throws Throwable { - ArrayList context = new ArrayList<>(); - for (Object obj : context()) { - context.add(obj); - } - return Debug.sandbox("forceLog", new DelegatingDebugConfig().override(Level.LOG, Integer.MAX_VALUE).enable(LOG_METHOD), context.toArray()); - } - - /** - * Opens a scope in which exception {@linkplain DebugConfig#interceptException(Throwable) - * interception} is disabled. It is recommended to use the try-with-resource statement for - * managing entering and leaving such scopes: - * - *
-     * try (DebugConfigScope s = Debug.disableIntercept()) {
-     *     ...
-     * }
-     * 
- * - * This is particularly useful to suppress extraneous output in JUnit tests that are expected to - * throw an exception. - */ - public static DebugConfigScope disableIntercept() { - return Debug.setConfig(new DelegatingDebugConfig().disable(INTERCEPT)); - } - - /** - * Handles an exception in the context of the debug scope just exited. The just exited scope - * must have the current scope as its parent which will be the case if the try-with-resource - * pattern recommended by {@link #scope(Object)} and - * {@link #sandbox(CharSequence, DebugConfig, Object...)} is used - * - * @see #scope(Object, Object[]) - * @see #sandbox(CharSequence, DebugConfig, Object...) - */ - public static RuntimeException handle(Throwable exception) { - if (ENABLED) { - return DebugScope.getInstance().handle(exception); - } else { - if (exception instanceof Error) { - throw (Error) exception; - } - if (exception instanceof RuntimeException) { - throw (RuntimeException) exception; - } - throw new RuntimeException(exception); - } - } - - public static void log(String msg) { - log(BASIC_LEVEL, msg); - } - - /** - * Prints a message to the current debug scope's logging stream if logging is enabled. - * - * @param msg the message to log - */ - public static void log(int logLevel, String msg) { - if (ENABLED) { - DebugScope.getInstance().log(logLevel, msg); - } - } - - public static void log(String format, Object arg) { - log(BASIC_LEVEL, format, arg); - } - - /** - * Prints a message to the current debug scope's logging stream if logging is enabled. - * - * @param format a format string - * @param arg the argument referenced by the format specifiers in {@code format} - */ - public static void log(int logLevel, String format, Object arg) { - if (ENABLED) { - DebugScope.getInstance().log(logLevel, format, arg); - } - } - - public static void log(String format, int arg) { - log(BASIC_LEVEL, format, arg); - } - - /** - * Prints a message to the current debug scope's logging stream if logging is enabled. - * - * @param format a format string - * @param arg the argument referenced by the format specifiers in {@code format} - */ - public static void log(int logLevel, String format, int arg) { - if (ENABLED) { - DebugScope.getInstance().log(logLevel, format, arg); - } - } - - public static void log(String format, Object arg1, Object arg2) { - log(BASIC_LEVEL, format, arg1, arg2); - } - - /** - * @see #log(int, String, Object) - */ - public static void log(int logLevel, String format, Object arg1, Object arg2) { - if (ENABLED) { - DebugScope.getInstance().log(logLevel, format, arg1, arg2); - } - } - - public static void log(String format, int arg1, Object arg2) { - log(BASIC_LEVEL, format, arg1, arg2); - } - - /** - * @see #log(int, String, Object) - */ - public static void log(int logLevel, String format, int arg1, Object arg2) { - if (ENABLED) { - DebugScope.getInstance().log(logLevel, format, arg1, arg2); - } - } - - public static void log(String format, Object arg1, int arg2) { - log(BASIC_LEVEL, format, arg1, arg2); - } - - /** - * @see #log(int, String, Object) - */ - public static void log(int logLevel, String format, Object arg1, int arg2) { - if (ENABLED) { - DebugScope.getInstance().log(logLevel, format, arg1, arg2); - } - } - - public static void log(String format, int arg1, int arg2) { - log(BASIC_LEVEL, format, arg1, arg2); - } - - /** - * @see #log(int, String, Object) - */ - public static void log(int logLevel, String format, int arg1, int arg2) { - if (ENABLED) { - DebugScope.getInstance().log(logLevel, format, arg1, arg2); - } - } - - public static void log(String format, Object arg1, Object arg2, Object arg3) { - log(BASIC_LEVEL, format, arg1, arg2, arg3); - } - - /** - * @see #log(int, String, Object) - */ - public static void log(int logLevel, String format, Object arg1, Object arg2, Object arg3) { - if (ENABLED) { - DebugScope.getInstance().log(logLevel, format, arg1, arg2, arg3); - } - } - - public static void log(String format, int arg1, int arg2, int arg3) { - log(BASIC_LEVEL, format, arg1, arg2, arg3); - } - - /** - * @see #log(int, String, Object) - */ - public static void log(int logLevel, String format, int arg1, int arg2, int arg3) { - if (ENABLED) { - DebugScope.getInstance().log(logLevel, format, arg1, arg2, arg3); - } - } - - public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4) { - log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4); - } - - /** - * @see #log(int, String, Object) - */ - public static void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4) { - if (ENABLED) { - DebugScope.getInstance().log(logLevel, format, arg1, arg2, arg3, arg4); - } - } - - public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) { - log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5); - } - - /** - * @see #log(int, String, Object) - */ - public static void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) { - if (ENABLED) { - DebugScope.getInstance().log(logLevel, format, arg1, arg2, arg3, arg4, arg5); - } - } - - public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) { - log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6); - } - - /** - * @see #log(int, String, Object) - */ - public static void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) { - if (ENABLED) { - DebugScope.getInstance().log(logLevel, format, arg1, arg2, arg3, arg4, arg5, arg6); - } - } - - public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7) { - log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7); - } - - public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8) { - log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); - } - - /** - * @see #log(int, String, Object) - */ - public static void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7) { - if (ENABLED) { - DebugScope.getInstance().log(logLevel, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7); - } - } - - public static void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8) { - if (ENABLED) { - DebugScope.getInstance().log(logLevel, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); - } - } - - public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9) { - log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); - } - - public static void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9) { - if (ENABLED) { - DebugScope.getInstance().log(logLevel, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); - } - } - - public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10) { - log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); - } - - public static void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10) { - if (ENABLED) { - DebugScope.getInstance().log(logLevel, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); - } - } - - public static void logv(String format, Object... args) { - logv(BASIC_LEVEL, format, args); - } - - /** - * Prints a message to the current debug scope's logging stream. This method must only be called - * if debugging is {@linkplain Debug#isEnabled() enabled} as it incurs allocation at the call - * site. If possible, call one of the other {@code log()} methods in this class that take a - * fixed number of parameters. - * - * @param format a format string - * @param args the arguments referenced by the format specifiers in {@code format} - */ - public static void logv(int logLevel, String format, Object... args) { - if (!ENABLED) { - throw new InternalError("Use of Debug.logv() must be guarded by a test of Debug.isEnabled()"); - } - DebugScope.getInstance().log(logLevel, format, args); - } - - /** - * This override exists to catch cases when {@link #log(String, Object)} is called with one - * argument bound to a varargs method parameter. It will bind to this method instead of the - * single arg variant and produce a deprecation warning instead of silently wrapping the - * Object[] inside of another Object[]. - */ - @Deprecated - public static void log(String format, Object[] args) { - assert false : "shouldn't use this"; - log(BASIC_LEVEL, format, args); - } - - /** - * This override exists to catch cases when {@link #log(int, String, Object)} is called with one - * argument bound to a varargs method parameter. It will bind to this method instead of the - * single arg variant and produce a deprecation warning instead of silently wrapping the - * Object[] inside of another Object[]. - */ - @Deprecated - public static void log(int logLevel, String format, Object[] args) { - assert false : "shouldn't use this"; - logv(logLevel, format, args); - } - - /** - * Forces an unconditional dump. This method exists mainly for debugging. It can also be used to - * force a graph dump from IDEs that support invoking a Java method while at a breakpoint. - */ - public static void forceDump(Object object, String format, Object... args) { - DebugScope.forceDump(object, format, args); - } - - public static void dump(int dumpLevel, Object object, String msg) { - if (ENABLED && DebugScope.getInstance().isDumpEnabled(dumpLevel)) { - DebugScope.getInstance().dump(dumpLevel, object, msg); - } - } - - public static void dump(int dumpLevel, Object object, String format, Object arg) { - if (ENABLED && DebugScope.getInstance().isDumpEnabled(dumpLevel)) { - DebugScope.getInstance().dump(dumpLevel, object, format, arg); - } - } - - public static void dump(int dumpLevel, Object object, String format, Object arg1, Object arg2) { - if (ENABLED && DebugScope.getInstance().isDumpEnabled(dumpLevel)) { - DebugScope.getInstance().dump(dumpLevel, object, format, arg1, arg2); - } - } - - public static void dump(int dumpLevel, Object object, String format, Object arg1, Object arg2, Object arg3) { - if (ENABLED && DebugScope.getInstance().isDumpEnabled(dumpLevel)) { - DebugScope.getInstance().dump(dumpLevel, object, format, arg1, arg2, arg3); - } - } - - /** - * This override exists to catch cases when {@link #dump(int, Object, String, Object)} is called - * with one argument bound to a varargs method parameter. It will bind to this method instead of - * the single arg variant and produce a deprecation warning instead of silently wrapping the - * Object[] inside of another Object[]. - */ - @Deprecated - public static void dump(int dumpLevel, Object object, String format, Object[] args) { - assert false : "shouldn't use this"; - if (ENABLED && DebugScope.getInstance().isDumpEnabled(dumpLevel)) { - DebugScope.getInstance().dump(dumpLevel, object, format, args); - } - } - - /** - * Calls all {@link DebugVerifyHandler}s in the current {@linkplain DebugScope#getConfig() - * config} to perform verification on a given object. - * - * @param object object to verify - * @param message description of verification context - * - * @see DebugVerifyHandler#verify(java.lang.Object, java.lang.String, java.lang.Object...) - */ - public static void verify(Object object, String message) { - if (ENABLED && DebugScope.getInstance().isVerifyEnabled()) { - DebugScope.getInstance().verify(object, message); - } - } - - /** - * Calls all {@link DebugVerifyHandler}s in the current {@linkplain DebugScope#getConfig() - * config} to perform verification on a given object. - * - * @param object object to verify - * @param format a format string for the description of the verification context - * @param arg the argument referenced by the format specifiers in {@code format} - * - * @see DebugVerifyHandler#verify(java.lang.Object, java.lang.String, java.lang.Object...) - */ - public static void verify(Object object, String format, Object arg) { - if (ENABLED && DebugScope.getInstance().isVerifyEnabled()) { - DebugScope.getInstance().verify(object, format, arg); - } - } - - /** - * This override exists to catch cases when {@link #verify(Object, String, Object)} is called - * with one argument bound to a varargs method parameter. It will bind to this method instead of - * the single arg variant and produce a deprecation warning instead of silently wrapping the - * Object[] inside of another Object[]. - */ - @Deprecated - public static void verify(Object object, String format, Object[] args) { - assert false : "shouldn't use this"; - if (ENABLED && DebugScope.getInstance().isVerifyEnabled()) { - DebugScope.getInstance().verify(object, format, args); - } - } - - /** - * Opens a new indentation level (by adding some spaces) based on the current indentation level. - * This should be used in a {@linkplain Indent try-with-resources} pattern. - * - * @return an object that reverts to the current indentation level when - * {@linkplain Indent#close() closed} or null if debugging is disabled - * @see #logAndIndent(int, String) - * @see #logAndIndent(int, String, Object) - */ - public static Indent indent() { - if (ENABLED) { - DebugScope scope = DebugScope.getInstance(); - return scope.pushIndentLogger(); - } - return null; - } - - public static Indent logAndIndent(String msg) { - return logAndIndent(BASIC_LEVEL, msg); - } - - /** - * A convenience function which combines {@link #log(String)} and {@link #indent()}. - * - * @param msg the message to log - * @return an object that reverts to the current indentation level when - * {@linkplain Indent#close() closed} or null if debugging is disabled - */ - public static Indent logAndIndent(int logLevel, String msg) { - if (ENABLED && Debug.isLogEnabled(logLevel)) { - return logvAndIndentInternal(logLevel, msg); - } - return null; - } - - public static Indent logAndIndent(String format, Object arg) { - return logAndIndent(BASIC_LEVEL, format, arg); - } - - /** - * A convenience function which combines {@link #log(String, Object)} and {@link #indent()}. - * - * @param format a format string - * @param arg the argument referenced by the format specifiers in {@code format} - * @return an object that reverts to the current indentation level when - * {@linkplain Indent#close() closed} or null if debugging is disabled - */ - public static Indent logAndIndent(int logLevel, String format, Object arg) { - if (ENABLED && Debug.isLogEnabled(logLevel)) { - return logvAndIndentInternal(logLevel, format, arg); - } - return null; - } - - public static Indent logAndIndent(String format, int arg) { - return logAndIndent(BASIC_LEVEL, format, arg); - } - - /** - * A convenience function which combines {@link #log(String, Object)} and {@link #indent()}. - * - * @param format a format string - * @param arg the argument referenced by the format specifiers in {@code format} - * @return an object that reverts to the current indentation level when - * {@linkplain Indent#close() closed} or null if debugging is disabled - */ - public static Indent logAndIndent(int logLevel, String format, int arg) { - if (ENABLED && Debug.isLogEnabled(logLevel)) { - return logvAndIndentInternal(logLevel, format, arg); - } - return null; - } - - public static Indent logAndIndent(String format, int arg1, Object arg2) { - return logAndIndent(BASIC_LEVEL, format, arg1, arg2); - } - - /** - * @see #logAndIndent(int, String, Object) - */ - public static Indent logAndIndent(int logLevel, String format, int arg1, Object arg2) { - if (ENABLED && Debug.isLogEnabled(logLevel)) { - return logvAndIndentInternal(logLevel, format, arg1, arg2); - } - return null; - } - - public static Indent logAndIndent(String format, Object arg1, int arg2) { - return logAndIndent(BASIC_LEVEL, format, arg1, arg2); - } - - /** - * @see #logAndIndent(int, String, Object) - */ - public static Indent logAndIndent(int logLevel, String format, Object arg1, int arg2) { - if (ENABLED && Debug.isLogEnabled(logLevel)) { - return logvAndIndentInternal(logLevel, format, arg1, arg2); - } - return null; - } - - public static Indent logAndIndent(String format, int arg1, int arg2) { - return logAndIndent(BASIC_LEVEL, format, arg1, arg2); - } - - /** - * @see #logAndIndent(int, String, Object) - */ - public static Indent logAndIndent(int logLevel, String format, int arg1, int arg2) { - if (ENABLED && Debug.isLogEnabled(logLevel)) { - return logvAndIndentInternal(logLevel, format, arg1, arg2); - } - return null; - } - - public static Indent logAndIndent(String format, Object arg1, Object arg2) { - return logAndIndent(BASIC_LEVEL, format, arg1, arg2); - } - - /** - * @see #logAndIndent(int, String, Object) - */ - public static Indent logAndIndent(int logLevel, String format, Object arg1, Object arg2) { - if (ENABLED && Debug.isLogEnabled(logLevel)) { - return logvAndIndentInternal(logLevel, format, arg1, arg2); - } - return null; - } - - public static Indent logAndIndent(String format, Object arg1, Object arg2, Object arg3) { - return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3); - } - - /** - * @see #logAndIndent(int, String, Object) - */ - public static Indent logAndIndent(int logLevel, String format, Object arg1, Object arg2, Object arg3) { - if (ENABLED && Debug.isLogEnabled(logLevel)) { - return logvAndIndentInternal(logLevel, format, arg1, arg2, arg3); - } - return null; - } - - public static Indent logAndIndent(String format, int arg1, int arg2, int arg3) { - return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3); - } - - /** - * @see #logAndIndent(int, String, Object) - */ - public static Indent logAndIndent(int logLevel, String format, int arg1, int arg2, int arg3) { - if (ENABLED && Debug.isLogEnabled(logLevel)) { - return logvAndIndentInternal(logLevel, format, arg1, arg2, arg3); - } - return null; - } - - public static Indent logAndIndent(String format, Object arg1, int arg2, int arg3) { - return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3); - } - - /** - * @see #logAndIndent(int, String, Object) - */ - public static Indent logAndIndent(int logLevel, String format, Object arg1, int arg2, int arg3) { - if (ENABLED && Debug.isLogEnabled(logLevel)) { - return logvAndIndentInternal(logLevel, format, arg1, arg2, arg3); - } - return null; - } - - public static Indent logAndIndent(String format, Object arg1, Object arg2, Object arg3, Object arg4) { - return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3, arg4); - } - - /** - * @see #logAndIndent(int, String, Object) - */ - public static Indent logAndIndent(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4) { - if (ENABLED && Debug.isLogEnabled(logLevel)) { - return logvAndIndentInternal(logLevel, format, arg1, arg2, arg3, arg4); - } - return null; - } - - public static Indent logAndIndent(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) { - return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5); - } - - /** - * @see #logAndIndent(int, String, Object) - */ - public static Indent logAndIndent(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) { - if (ENABLED && Debug.isLogEnabled(logLevel)) { - return logvAndIndentInternal(logLevel, format, arg1, arg2, arg3, arg4, arg5); - } - return null; - } - - public static Indent logAndIndent(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) { - return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6); - } - - /** - * @see #logAndIndent(int, String, Object) - */ - public static Indent logAndIndent(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) { - if (ENABLED && Debug.isLogEnabled(logLevel)) { - return logvAndIndentInternal(logLevel, format, arg1, arg2, arg3, arg4, arg5, arg6); - } - return null; - } - - /** - * A convenience function which combines {@link #logv(int, String, Object...)} and - * {@link #indent()}. - * - * @param format a format string - * @param args the arguments referenced by the format specifiers in {@code format} - * @return an object that reverts to the current indentation level when - * {@linkplain Indent#close() closed} or null if debugging is disabled - */ - public static Indent logvAndIndent(int logLevel, String format, Object... args) { - if (ENABLED) { - if (Debug.isLogEnabled(logLevel)) { - return logvAndIndentInternal(logLevel, format, args); - } - return null; - } - throw new InternalError("Use of Debug.logvAndIndent() must be guarded by a test of Debug.isEnabled()"); - } - - private static Indent logvAndIndentInternal(int logLevel, String format, Object... args) { - assert ENABLED && Debug.isLogEnabled(logLevel) : "must have checked Debug.isLogEnabled()"; - DebugScope scope = DebugScope.getInstance(); - scope.log(logLevel, format, args); - return scope.pushIndentLogger(); - } - - /** - * This override exists to catch cases when {@link #logAndIndent(String, Object)} is called with - * one argument bound to a varargs method parameter. It will bind to this method instead of the - * single arg variant and produce a deprecation warning instead of silently wrapping the - * Object[] inside of another Object[]. - */ - @Deprecated - public static void logAndIndent(String format, Object[] args) { - assert false : "shouldn't use this"; - logAndIndent(BASIC_LEVEL, format, args); - } - - /** - * This override exists to catch cases when {@link #logAndIndent(int, String, Object)} is called - * with one argument bound to a varargs method parameter. It will bind to this method instead of - * the single arg variant and produce a deprecation warning instead of silently wrapping the - * Object[] inside of another Object[]. - */ - @Deprecated - public static void logAndIndent(int logLevel, String format, Object[] args) { - assert false : "shouldn't use this"; - logvAndIndent(logLevel, format, args); - } - - public static Iterable context() { - if (ENABLED) { - return DebugScope.getInstance().getCurrentContext(); - } else { - return Collections.emptyList(); - } - } - - @SuppressWarnings("unchecked") - public static List contextSnapshot(Class clazz) { - if (ENABLED) { - List result = new ArrayList<>(); - for (Object o : context()) { - if (clazz.isInstance(o)) { - result.add((T) o); - } - } - return result; - } else { - return Collections.emptyList(); - } - } - - /** - * Searches the current debug scope, bottom up, for a context object that is an instance of a - * given type. The first such object found is returned. - */ - @SuppressWarnings("unchecked") - public static T contextLookup(Class clazz) { - if (ENABLED) { - for (Object o : context()) { - if (clazz.isInstance(o)) { - return ((T) o); - } - } - } - return null; - } - - /** - * Creates a {@linkplain DebugMemUseTracker memory use tracker} that is enabled iff debugging is - * {@linkplain #isEnabled() enabled}. - *

- * A disabled tracker has virtually no overhead. - */ - public static DebugMemUseTracker memUseTracker(CharSequence name) { - if (!isUnconditionalMemUseTrackingEnabled && !ENABLED) { - return VOID_MEM_USE_TRACKER; - } - return createMemUseTracker("%s", name, null); - } - - /** - * Creates a debug memory use tracker. Invoking this method is equivalent to: - * - *

-     * Debug.memUseTracker(format, arg, null)
-     * 
- * - * except that the string formatting only happens if mem tracking is enabled. - * - * @see #counter(String, Object, Object) - */ - public static DebugMemUseTracker memUseTracker(String format, Object arg) { - if (!isUnconditionalMemUseTrackingEnabled && !ENABLED) { - return VOID_MEM_USE_TRACKER; - } - return createMemUseTracker(format, arg, null); - } - - /** - * Creates a debug memory use tracker. Invoking this method is equivalent to: - * - *
-     * Debug.memUseTracker(String.format(format, arg1, arg2))
-     * 
- * - * except that the string formatting only happens if memory use tracking is enabled. In - * addition, each argument is subject to the following type based conversion before being passed - * as an argument to {@link String#format(String, Object...)}: - * - *
-     *     Type          | Conversion
-     * ------------------+-----------------
-     *  java.lang.Class  | arg.getSimpleName()
-     *                   |
-     * 
- * - * @see #memUseTracker(CharSequence) - */ - public static DebugMemUseTracker memUseTracker(String format, Object arg1, Object arg2) { - if (!isUnconditionalMemUseTrackingEnabled && !ENABLED) { - return VOID_MEM_USE_TRACKER; - } - return createMemUseTracker(format, arg1, arg2); - } - - private static DebugMemUseTracker createMemUseTracker(String format, Object arg1, Object arg2) { - String name = formatDebugName(format, arg1, arg2); - return DebugValueFactory.createMemUseTracker(name, !isUnconditionalMemUseTrackingEnabled); - } - - /** - * Creates a {@linkplain DebugCounter counter} that is enabled iff debugging is - * {@linkplain #isEnabled() enabled} or the system property whose name is formed by adding - * {@value #ENABLE_COUNTER_PROPERTY_NAME_PREFIX} to {@code name} is - * {@linkplain Boolean#getBoolean(String) true}. If the latter condition is true, then the - * returned counter is {@linkplain DebugCounter#isConditional() unconditional} otherwise it is - * conditional. - *

- * A disabled counter has virtually no overhead. - */ - public static DebugCounter counter(CharSequence name) { - if (!areUnconditionalCountersEnabled() && !ENABLED) { - return VOID_COUNTER; - } - return createCounter("%s", name, null); - } - - /** - * Creates a {@link DebugMethodMetrics metric} that is enabled iff debugging is - * {@link #isEnabled() enabled}. - */ - public static DebugMethodMetrics methodMetrics(ResolvedJavaMethod method) { - if (isMethodMeterEnabled() && method != null) { - return MethodMetricsImpl.getMethodMetrics(method); - } - return VOID_MM; - } - - public static String applyFormattingFlagsAndWidth(String s, int flags, int width) { - if (flags == 0 && width < 0) { - return s; - } - StringBuilder sb = new StringBuilder(s); - - // apply width and justification - int len = sb.length(); - if (len < width) { - for (int i = 0; i < width - len; i++) { - if ((flags & LEFT_JUSTIFY) == LEFT_JUSTIFY) { - sb.append(' '); - } else { - sb.insert(0, ' '); - } - } - } - - String res = sb.toString(); - if ((flags & UPPERCASE) == UPPERCASE) { - res = res.toUpperCase(); - } - return res; - } - - /** - * Creates a debug counter. Invoking this method is equivalent to: - * - *

-     * Debug.counter(format, arg, null)
-     * 
- * - * except that the string formatting only happens if count is enabled. - * - * @see #counter(String, Object, Object) - */ - public static DebugCounter counter(String format, Object arg) { - if (!areUnconditionalCountersEnabled() && !ENABLED) { - return VOID_COUNTER; - } - return createCounter(format, arg, null); - } - - /** - * Creates a debug counter. Invoking this method is equivalent to: - * - *
-     * Debug.counter(String.format(format, arg1, arg2))
-     * 
- * - * except that the string formatting only happens if count is enabled. In addition, each - * argument is subject to the following type based conversion before being passed as an argument - * to {@link String#format(String, Object...)}: - * - *
-     *     Type          | Conversion
-     * ------------------+-----------------
-     *  java.lang.Class  | arg.getSimpleName()
-     *                   |
-     * 
- * - * @see #counter(CharSequence) - */ - public static DebugCounter counter(String format, Object arg1, Object arg2) { - if (!areUnconditionalCountersEnabled() && !ENABLED) { - return VOID_COUNTER; - } - return createCounter(format, arg1, arg2); - } - - private static DebugCounter createCounter(String format, Object arg1, Object arg2) { - String name = formatDebugName(format, arg1, arg2); - boolean conditional = enabledCounters == null || !findMatch(enabledCounters, enabledCountersSubstrings, name); - if (!ENABLED && conditional) { - return VOID_COUNTER; - } - return DebugValueFactory.createCounter(name, conditional); - } - - /** - * Changes the debug configuration for the current thread. - * - * @param config new configuration to use for the current thread - * @return an object that when {@linkplain DebugConfigScope#close() closed} will restore the - * debug configuration for the current thread to what it was before this method was - * called - */ - public static DebugConfigScope setConfig(DebugConfig config) { - if (ENABLED) { - return new DebugConfigScope(config); - } else { - return null; - } - } - - /** - * Creates an object for counting value frequencies. - */ - public static DebugHistogram createHistogram(String name) { - return new DebugHistogramImpl(name); - } - - public static DebugConfig silentConfig() { - return fixedConfig(new OptionValues(OptionValues.newOptionMap()), 0, 0, false, false, false, false, false, Collections. emptyList(), - Collections. emptyList(), null); - } - - public static DebugConfig fixedConfig(OptionValues options, final int logLevel, final int dumpLevel, final boolean isCountEnabled, final boolean isMemUseTrackingEnabled, - final boolean isTimerEnabled, - final boolean isVerifyEnabled, final boolean isMMEnabled, final Collection dumpHandlers, final Collection verifyHandlers, - final PrintStream output) { - return new DebugConfig() { - - @Override - public OptionValues getOptions() { - return options; - } - - @Override - public int getLogLevel() { - return logLevel; - } - - @Override - public boolean isLogEnabledForMethod() { - return logLevel > 0; - } - - @Override - public boolean isCountEnabled() { - return isCountEnabled; - } - - @Override - public boolean isMemUseTrackingEnabled() { - return isMemUseTrackingEnabled; - } - - @Override - public int getDumpLevel() { - return dumpLevel; - } - - @Override - public boolean isDumpEnabledForMethod() { - return dumpLevel > 0; - } - - @Override - public boolean isVerifyEnabled() { - return isVerifyEnabled; - } - - @Override - public boolean isVerifyEnabledForMethod() { - return isVerifyEnabled; - } - - @Override - public boolean isMethodMeterEnabled() { - return isMMEnabled; - } - - @Override - public boolean isTimeEnabled() { - return isTimerEnabled; - } - - @Override - public RuntimeException interceptException(Throwable e) { - return null; - } - - @Override - public Collection dumpHandlers() { - return dumpHandlers; - } - - @Override - public Collection verifyHandlers() { - return verifyHandlers; - } - - @Override - public PrintStream output() { - return output; - } - - @Override - public void addToContext(Object o) { - } - - @Override - public void removeFromContext(Object o) { - } - }; - } - - private static final DebugCounter VOID_COUNTER = new DebugCounter() { - - @Override - public void increment() { - } - - @Override - public void add(long value) { - } - - @Override - public void setConditional(boolean flag) { - throw new InternalError("Cannot make void counter conditional"); - } - - @Override - public boolean isConditional() { - return false; - } - - @Override - public long getCurrentValue() { - return 0L; - } - }; - - private static final DebugMethodMetrics VOID_MM = new DebugMethodMetrics() { - - @Override - public void addToMetric(long value, String metricName) { - } - - @Override - public void addToMetric(long value, String format, Object arg1) { - } - - @Override - public void addToMetric(long value, String format, Object arg1, Object arg2) { - } - - @Override - public void addToMetric(long value, String format, Object arg1, Object arg2, Object arg3) { - } - - @Override - public void incrementMetric(String metricName) { - } - - @Override - public void incrementMetric(String format, Object arg1) { - } - - @Override - public void incrementMetric(String format, Object arg1, Object arg2) { - } - - @Override - public void incrementMetric(String format, Object arg1, Object arg2, Object arg3) { - } - - @Override - public long getCurrentMetricValue(String metricName) { - return 0; - } - - @Override - public long getCurrentMetricValue(String format, Object arg1) { - return 0; - } - - @Override - public long getCurrentMetricValue(String format, Object arg1, Object arg2) { - return 0; - } - - @Override - public long getCurrentMetricValue(String format, Object arg1, Object arg2, Object arg3) { - return 0; - } - - @Override - public ResolvedJavaMethod getMethod() { - return null; - } - - }; - - private static final DebugMemUseTracker VOID_MEM_USE_TRACKER = new DebugMemUseTracker() { - - @Override - public DebugCloseable start() { - return DebugCloseable.VOID_CLOSEABLE; - } - - @Override - public long getCurrentValue() { - return 0; - } - }; - - /** - * @see #timer(CharSequence) - */ - public static final String ENABLE_TIMER_PROPERTY_NAME_PREFIX = "graaldebug.timer."; - - /** - * @see #counter(CharSequence) - */ - public static final String ENABLE_COUNTER_PROPERTY_NAME_PREFIX = "graaldebug.counter."; - - /** - * Set of unconditionally enabled counters. Possible values and their meanings: - *
    - *
  • {@code null}: no unconditionally enabled counters
  • - *
  • {@code isEmpty()}: all counters are unconditionally enabled
  • - *
  • {@code !isEmpty()}: use {@link #findMatch(Set, Set, String)} on this set and - * {@link #enabledCountersSubstrings} to determine which counters are unconditionally enabled - *
  • - *
- */ - private static final Set enabledCounters; - - /** - * Set of unconditionally enabled timers. Same interpretation of values as for - * {@link #enabledCounters}. - */ - private static final Set enabledTimers; - - private static final Set enabledCountersSubstrings = 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 counters = new HashSet<>(); - Set timers = new HashSet<>(); - parseCounterAndTimerSystemProperties(counters, timers, enabledCountersSubstrings, enabledTimersSubstrings); - counters = counters.isEmpty() && enabledCountersSubstrings.isEmpty() ? null : counters; - timers = timers.isEmpty() && enabledTimersSubstrings.isEmpty() ? null : timers; - if (counters == null && params.enableUnscopedCounters && !params.enableMethodFilter) { - counters = Collections.emptySet(); - } - if (timers == null && params.enableUnscopedTimers && !params.enableMethodFilter) { - timers = Collections.emptySet(); - } - enabledCounters = counters; - enabledTimers = timers; - isUnconditionalMemUseTrackingEnabled = params.enableUnscopedMemUseTrackers; - DebugValueFactory = initDebugValueFactory(); - } - - private static DebugValueFactory initDebugValueFactory() { - return new DebugValueFactory() { - - @Override - public DebugTimer createTimer(String name, boolean conditional) { - return new TimerImpl(name, conditional, params.interceptTime); - } - - @Override - public DebugCounter createCounter(String name, boolean conditional) { - return CounterImpl.create(name, conditional, params.interceptCount); - } - - @Override - public DebugMethodMetrics createMethodMetrics(ResolvedJavaMethod method) { - return MethodMetricsImpl.getMethodMetrics(method); - } - - @Override - public DebugMemUseTracker createMemUseTracker(String name, boolean conditional) { - return new MemUseTrackerImpl(name, conditional, params.interceptMem); - } - }; - } - - private static DebugValueFactory DebugValueFactory; - - public static void setDebugValueFactory(DebugValueFactory factory) { - Objects.requireNonNull(factory); - DebugValueFactory = factory; - } - - public static DebugValueFactory getDebugValueFactory() { - return DebugValueFactory; - } - - private static boolean findMatch(Set haystack, Set haystackSubstrings, String needle) { - if (haystack.isEmpty() && haystackSubstrings.isEmpty()) { - // Empty haystack means match all - return true; - } - if (haystack.contains(needle)) { - return true; - } - if (!haystackSubstrings.isEmpty()) { - for (String h : haystackSubstrings) { - if (needle.startsWith(h)) { - return true; - } - } - } - return false; - } - - public static boolean areUnconditionalTimersEnabled() { - return enabledTimers != null; - } - - public static boolean areUnconditionalCountersEnabled() { - return enabledCounters != null; - } - - public static boolean isMethodFilteringEnabled() { - return params.enableMethodFilter; - } - - public static boolean areUnconditionalMethodMetricsEnabled() { - // we do not collect mm substrings - return params.enableUnscopedMethodMetrics; - } - - protected static void parseCounterAndTimerSystemProperties(Set counters, Set timers, Set countersSubstrings, Set timersSubstrings) { - do { - try { - for (Map.Entry e : System.getProperties().entrySet()) { - String name = e.getKey().toString(); - if (name.startsWith(ENABLE_COUNTER_PROPERTY_NAME_PREFIX) && Boolean.parseBoolean(e.getValue().toString())) { - if (name.endsWith("*")) { - countersSubstrings.add(name.substring(ENABLE_COUNTER_PROPERTY_NAME_PREFIX.length(), name.length() - 1)); - } else { - counters.add(name.substring(ENABLE_COUNTER_PROPERTY_NAME_PREFIX.length())); - } - } - if (name.startsWith(ENABLE_TIMER_PROPERTY_NAME_PREFIX) && Boolean.parseBoolean(e.getValue().toString())) { - if (name.endsWith("*")) { - timersSubstrings.add(name.substring(ENABLE_TIMER_PROPERTY_NAME_PREFIX.length(), name.length() - 1)); - } else { - timers.add(name.substring(ENABLE_TIMER_PROPERTY_NAME_PREFIX.length())); - } - } - } - return; - } catch (ConcurrentModificationException e) { - // Iterating over the system properties may race with another thread that is - // updating the system properties. Simply try again in this case. - } - } while (true); - } - - /** - * Creates a {@linkplain DebugTimer timer} that is enabled iff debugging is - * {@linkplain #isEnabled() enabled} or the system property whose name is formed by adding - * {@value #ENABLE_TIMER_PROPERTY_NAME_PREFIX} to {@code name} is - * {@linkplain Boolean#getBoolean(String) true}. If the latter condition is true, then the - * returned timer is {@linkplain DebugCounter#isConditional() unconditional} otherwise it is - * conditional. - *

- * A disabled timer has virtually no overhead. - */ - public static DebugTimer timer(CharSequence name) { - if (!areUnconditionalTimersEnabled() && !ENABLED) { - return VOID_TIMER; - } - return createTimer("%s", name, null); - } - - /** - * Creates a debug timer. Invoking this method is equivalent to: - * - *

-     * Debug.timer(format, arg, null)
-     * 
- * - * except that the string formatting only happens if timing is enabled. - * - * @see #timer(String, Object, Object) - */ - public static DebugTimer timer(String format, Object arg) { - if (!areUnconditionalTimersEnabled() && !ENABLED) { - return VOID_TIMER; - } - return createTimer(format, arg, null); - } - - /** - * Creates a debug timer. Invoking this method is equivalent to: - * - *
-     * Debug.timer(String.format(format, arg1, arg2))
-     * 
- * - * except that the string formatting only happens if timing is enabled. In addition, each - * argument is subject to the following type based conversion before being passed as an argument - * to {@link String#format(String, Object...)}: - * - *
-     *     Type          | Conversion
-     * ------------------+-----------------
-     *  java.lang.Class  | arg.getSimpleName()
-     *                   |
-     * 
- * - * @see #timer(CharSequence) - */ - public static DebugTimer timer(String format, Object arg1, Object arg2) { - if (!areUnconditionalTimersEnabled() && !ENABLED) { - return VOID_TIMER; - } - return createTimer(format, arg1, arg2); - } - - /** - * There are paths where construction of formatted class names are common and the code below is - * surprisingly expensive, so compute it once and cache it. - */ - private static final ClassValue formattedClassName = new ClassValue() { - @Override - protected String computeValue(Class c) { - final String simpleName = c.getSimpleName(); - Class enclosingClass = c.getEnclosingClass(); - if (enclosingClass != null) { - String prefix = ""; - while (enclosingClass != null) { - prefix = enclosingClass.getSimpleName() + "_" + prefix; - enclosingClass = enclosingClass.getEnclosingClass(); - } - return prefix + simpleName; - } else { - return simpleName; - } - } - }; - - public static Object convertFormatArg(Object arg) { - if (arg instanceof Class) { - return formattedClassName.get((Class) arg); - } - return arg; - } - - private static String formatDebugName(String format, Object arg1, Object arg2) { - return String.format(format, convertFormatArg(arg1), convertFormatArg(arg2)); - } - - private static DebugTimer createTimer(String format, Object arg1, Object arg2) { - String name = formatDebugName(format, arg1, arg2); - boolean conditional = enabledTimers == null || !findMatch(enabledTimers, enabledTimersSubstrings, name); - if (!ENABLED && conditional) { - return VOID_TIMER; - } - return DebugValueFactory.createTimer(name, conditional); - } - - private static final DebugTimer VOID_TIMER = new DebugTimer() { - - @Override - public DebugCloseable start() { - return DebugCloseable.VOID_CLOSEABLE; - } - - @Override - public void setConditional(boolean flag) { - throw new InternalError("Cannot make void timer conditional"); - } - - @Override - public boolean isConditional() { - return false; - } - - @Override - public long getCurrentValue() { - return 0L; - } - - @Override - public TimeUnit getTimeUnit() { - return null; - } - }; -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfigCustomizer.java 2017-07-07 09:32:14.000000000 -0700 +++ /dev/null 2017-07-07 09:32:14.000000000 -0700 @@ -1,27 +0,0 @@ -/* - * 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 org.graalvm.compiler.debug; - -public interface DebugConfigCustomizer { - void customize(DebugConfig config); -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfigScope.java 2017-07-07 09:32:15.000000000 -0700 +++ /dev/null 2017-07-07 09:32:15.000000000 -0700 @@ -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 org.graalvm.compiler.debug; - -import org.graalvm.compiler.debug.internal.DebugScope; - -/** - * A utility for scoping a change to the current debug {@linkplain DebugScope#setConfig(DebugConfig) - * configuration}. For example: - * - *
- *     DebugConfig config = ...;
- *     try (DebugConfigScope s = new DebugConfigScope(config)) {
- *         // ...
- *     }
- * 
- */ -public class DebugConfigScope implements AutoCloseable { - - private final DebugConfig current; - - /** - * Sets the current debug {@linkplain DebugScope#setConfig(DebugConfig) configuration} to a - * given value and creates an object that when {@linkplain #close() closed} resets the - * configuration to the {@linkplain DebugScope#getConfig() current} configuration. - */ - public DebugConfigScope(DebugConfig config) { - this.current = DebugScope.getConfig(); - DebugScope.getInstance().setConfig(config); - } - - @Override - public void close() { - DebugScope.getInstance().setConfig(current); - } -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugCounter.java 2017-07-07 09:32:15.000000000 -0700 +++ /dev/null 2017-07-07 09:32:15.000000000 -0700 @@ -1,65 +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 org.graalvm.compiler.debug; - -/** - * A counter for some value of interest. - */ -public interface DebugCounter { - - /** - * Adds 1 to this counter if counting is {@link Debug#isCountEnabled() enabled} or this is an - * {@linkplain #isConditional() unconditional} counter. - */ - void increment(); - - /** - * Adds {@code value} to this counter if counting is {@link Debug#isCountEnabled() enabled} or - * this is an {@linkplain #isConditional() unconditional} counter. - */ - void add(long value); - - /** - * Sets a flag determining if this counter is only enabled if counting is - * {@link Debug#isCountEnabled() enabled}. - */ - void setConditional(boolean flag); - - /** - * Determines if this counter is only enabled if counting is {@link Debug#isCountEnabled() - * enabled}. - */ - boolean isConditional(); - - /** - * Gets the current value of this counter. - */ - long getCurrentValue(); - - /** - * Determines if this counter is enabled (either conditionally or unconditionally). - */ - default boolean isEnabled() { - return !isConditional() || Debug.isCountEnabled(); - } -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugEnvironment.java 2017-07-07 09:32:16.000000000 -0700 +++ /dev/null 2017-07-07 09:32:16.000000000 -0700 @@ -1,105 +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 org.graalvm.compiler.debug; - -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Count; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Dump; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Log; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.MethodFilter; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.MethodMeter; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Time; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.TrackMemUse; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Verify; - -import java.util.ArrayList; -import java.util.List; - -import org.graalvm.compiler.options.OptionValues; -import org.graalvm.compiler.debug.internal.DebugScope; -import org.graalvm.compiler.serviceprovider.GraalServices; - -import jdk.vm.ci.runtime.JVMCI; - -public class DebugEnvironment { - - /** - * Create a GraalDebugConfig if {@link Debug#isEnabled()} is true and one hasn't already been - * created. Additionally add {@code extraArgs} as capabilities to the {@link DebugDumpHandler}s - * associated with the current config. Capabilities can be added at any time. - * - * @return the current {@link GraalDebugConfig} or null if nothing was done - */ - public static GraalDebugConfig ensureInitialized(OptionValues options, Object... capabilities) { - return ensureInitializedHelper(options, false, capabilities); - } - - /** - * Create a new GraalDebugConfig if {@link Debug#isEnabled()} is true, even if one had already - * been created. Additionally add {@code extraArgs} as capabilities to the - * {@link DebugDumpHandler}s associated with the current config. Capabilities can be added at - * any time. - * - * @return the current {@link GraalDebugConfig} or null if nothing was done - */ - public static GraalDebugConfig forceInitialization(OptionValues options, Object... capabilities) { - return ensureInitializedHelper(options, true, capabilities); - } - - private static GraalDebugConfig ensureInitializedHelper(OptionValues options, boolean forceInit, Object... capabilities) { - if (!Debug.isEnabled()) { - return null; - } - GraalDebugConfig debugConfig = (GraalDebugConfig) DebugScope.getConfig(); - if (debugConfig == null || forceInit || options != debugConfig.getOptions()) { - // Initialize JVMCI before loading class Debug - JVMCI.initialize(); - List dumpHandlers = new ArrayList<>(); - List verifyHandlers = new ArrayList<>(); - debugConfig = new GraalDebugConfig( - options, - Log.getValue(options), - Count.getValue(options), - TrackMemUse.getValue(options), - Time.getValue(options), - Dump.getValue(options), - Verify.getValue(options), - MethodFilter.getValue(options), - MethodMeter.getValue(options), - TTY.out, dumpHandlers, verifyHandlers); - - for (DebugConfigCustomizer customizer : GraalServices.load(DebugConfigCustomizer.class)) { - customizer.customize(debugConfig); - } - - Debug.setConfig(debugConfig); - } - if (capabilities != null) { - for (Object o : capabilities) { - for (DebugDumpHandler handler : debugConfig.dumpHandlers()) { - handler.addCapability(o); - } - } - } - return debugConfig; - } -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugHistogram.java 2017-07-07 09:32:17.000000000 -0700 +++ /dev/null 2017-07-07 09:32:17.000000000 -0700 @@ -1,103 +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 org.graalvm.compiler.debug; - -import java.util.List; - -/** - * Facility for recording value frequencies. - */ -public interface DebugHistogram { - - /** - * Gets the name specified when this objected was {@linkplain Debug#createHistogram(String) - * created}. - */ - String getName(); - - /** - * Increments the count for a given value. - */ - void add(Object value); - - void add(Object value, long count); - - /** - * A value and a frequency. The ordering imposed by {@link #compareTo(CountedValue)} places - * values with higher frequencies first. - */ - class CountedValue implements Comparable { - - private long count; - private final Object value; - - public CountedValue(long count, Object value) { - this.count = count; - this.value = value; - } - - @Override - public int compareTo(CountedValue o) { - if (count < o.count) { - return 1; - } else if (count > o.count) { - return -1; - } - return 0; - } - - @Override - public String toString() { - return count + " -> " + value; - } - - public void inc() { - count++; - } - - public void add(long n) { - count += n; - } - - public long getCount() { - return count; - } - - public Object getValue() { - return value; - } - } - - /** - * Gets a list of the counted values, sorted in descending order of frequency. - */ - List getValues(); - - /** - * Interface for a service that can render a visualization of a histogram. - */ - public interface Printer { - - void print(DebugHistogram histogram); - } -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugInitializationParticipant.java 2017-07-07 09:32:17.000000000 -0700 +++ /dev/null 2017-07-07 09:32:17.000000000 -0700 @@ -1,36 +0,0 @@ -/* - * 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 org.graalvm.compiler.debug; - -import org.graalvm.compiler.debug.Debug.Params; - -/** - * Defines a service that can modify the {@linkplain Params parameters} for {@link Debug}. - */ -public interface DebugInitializationParticipant { - - /** - * Modifies the given {@link Debug} initialization parameters as necessary. - */ - void apply(Params params); -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugMethodMetrics.java 2017-07-07 09:32:17.000000000 -0700 +++ /dev/null 2017-07-07 09:32:17.000000000 -0700 @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2015, 2016, 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 org.graalvm.compiler.debug; - -import jdk.vm.ci.meta.ResolvedJavaMethod; - -/** - * A set of debug metrics for all compilations of a {@link ResolvedJavaMethod}. A method metrics - * object is a container for several metrics per compilation of a method {@code >}. Metrics are stored on a per-method per-compilation basis. - * - *
- * DebugMethodMetrics m = Debug.methodMetrics(method);
- * m.incrementMetric("MyPerCompilationmetric");
- * 
- * - * In contrast to global metrics like {@link DebugCounter}, {@link DebugTimer} or - * {@linkplain DebugMemUseTracker}, method compilation metrics are always associated with a - * {@link ResolvedJavaMethod}. - */ -public interface DebugMethodMetrics { - - /** - * Adds {@code value} to the metric for the current compilation associated with - * {@code metricName}. If the metric is yet undefined for the current compilation a new metric - * for the given name is defined and the value for it is set to {@code value}. - * - * @param metricName the name for the metric to be incremented - * @param value the value to add to the metric defined by name - */ - void addToMetric(long value, String metricName); - - /** - * @see #addToMetric(long, String) - */ - void addToMetric(long value, String format, Object arg1); - - /** - * @see #addToMetric(long, String) - */ - void addToMetric(long value, String format, Object arg1, Object arg2); - - /** - * @see #addToMetric(long, String) - */ - void addToMetric(long value, String format, Object arg1, Object arg2, Object arg3); - - /** - * Adds {@code 1} to the metric for the current compilation associated with {@code metricName}. - * If the metric is yet undefined for the current compilation a new metric for the given name is - * defined and the value for it is set to {@code value}. - * - * @param metricName the name for the metric to be incremented - */ - void incrementMetric(String metricName); - - /** - * @see #incrementMetric(String) - */ - void incrementMetric(String format, Object arg1); - - /** - * @see #incrementMetric(String) - */ - void incrementMetric(String format, Object arg1, Object arg2); - - /** - * @see #incrementMetric(String) - */ - void incrementMetric(String format, Object arg1, Object arg2, Object arg3); - - /** - * Gets the value of the metric for the current compilation associated with the - * {@code metricName} . If the metric is yet undefined for the current compilation {@code 0} is - * returned instead. - * - * @param metricName the name of the metric for which the value will be returned - * @return the value of the metric for the given compilation or {@code 0} if it is not defined - */ - long getCurrentMetricValue(String metricName); - - /** - * @see #getCurrentMetricValue(String) - */ - long getCurrentMetricValue(String format, Object arg1); - - /** - * @see #getCurrentMetricValue(String) - */ - long getCurrentMetricValue(String format, Object arg1, Object arg2); - - /** - * @see #getCurrentMetricValue(String) - */ - long getCurrentMetricValue(String format, Object arg1, Object arg2, Object arg3); - - /** - * Gets the {@link ResolvedJavaMethod} associated with this {@linkplain DebugMethodMetrics}. - * - * @return the {@link ResolvedJavaMethod} of the current method metric - */ - ResolvedJavaMethod getMethod(); - -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugTimer.java 2017-07-07 09:32:17.000000000 -0700 +++ /dev/null 2017-07-07 09:32:17.000000000 -0700 @@ -1,78 +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 org.graalvm.compiler.debug; - -import java.util.concurrent.TimeUnit; - -/** - * A timer for some activity of interest. A timer should be deployed using the try-with-resources - * pattern: - * - *
- * try (TimerCloseable a = timer.start()) {
- *     // the code to time
- * }
- * 
- */ -public interface DebugTimer { - - /** - * Starts this timer if timing is {@linkplain Debug#isTimeEnabled() enabled} or this is an - * {@linkplain #isConditional() unconditional} timer. - * - * @return an object that must be closed once the activity has completed to add the elapsed time - * since this call to the total for this timer - */ - DebugCloseable start(); - - /** - * Sets a flag determining if this timer is only enabled if timing is - * {@link Debug#isTimeEnabled() enabled}. - */ - void setConditional(boolean flag); - - /** - * Determines if this timer is only enabled if timing is {@link Debug#isTimeEnabled() enabled}. - */ - boolean isConditional(); - - /** - * Gets the current value of this timer. - */ - long getCurrentValue(); - - /** - * Gets the time unit of this timer. - */ - TimeUnit getTimeUnit(); - - /** - * Gets the timer recording the amount time spent within a timed scope minus the time spent in - * any nested timed scopes. - * - * @return null if this timer does not support flat timing - */ - default DebugTimer getFlat() { - return null; - } -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugValueFactory.java 2017-07-07 09:32:18.000000000 -0700 +++ /dev/null 2017-07-07 09:32:18.000000000 -0700 @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2015, 2016, 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 org.graalvm.compiler.debug; - -import jdk.vm.ci.meta.ResolvedJavaMethod; - -/** - * A factory for creating {@link DebugCounter}s, {@link DebugTimer}s, {@link DebugMemUseTracker}s - * and {@link DebugMethodMetrics}. - */ -public interface DebugValueFactory { - - DebugCounter createCounter(String name, boolean conditional); - - DebugTimer createTimer(String name, boolean conditional); - - DebugMemUseTracker createMemUseTracker(String name, boolean conditional); - - DebugMethodMetrics createMethodMetrics(ResolvedJavaMethod method); -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DelegatingDebugConfig.java 2017-07-07 09:32:18.000000000 -0700 +++ /dev/null 2017-07-07 09:32:18.000000000 -0700 @@ -1,264 +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 org.graalvm.compiler.debug; - -import java.io.PrintStream; -import java.util.Collection; -import java.util.EnumMap; -import java.util.Map; - -import org.graalvm.compiler.debug.internal.DebugScope; -import org.graalvm.compiler.options.OptionValues; - -public class DelegatingDebugConfig implements DebugConfig { - - protected final DebugConfig delegate; - - /** - * The features of a {@link DelegatingDebugConfig} that can be force - * {@linkplain DelegatingDebugConfig#enable(Feature) enabled}/ - * {@linkplain DelegatingDebugConfig#disable(Feature) disabled} or - * {@linkplain DelegatingDebugConfig#delegate(Feature) delegated}. - */ - public enum Feature { - /** - * @see Debug#isLogEnabledForMethod() - */ - LOG_METHOD, - /** - * @see Debug#isDumpEnabledForMethod() - */ - DUMP_METHOD, - /** - * @see Debug#isVerifyEnabled() - */ - VERIFY, - /** - * @see Debug#isVerifyEnabledForMethod() - */ - VERIFY_METHOD, - /** - * @see Debug#isCountEnabled() - */ - COUNT, - /** - * @see Debug#isMethodMeterEnabled() - */ - METHOD_METRICS, - /** - * @see Debug#isMemUseTrackingEnabled() - */ - TRACK_MEM_USE, - /** - * @see Debug#isTimeEnabled() - */ - TIME, - /** - * @see DebugConfig#interceptException(Throwable) - */ - INTERCEPT - } - - private final Map featureState = new EnumMap<>(Feature.class); - - /** - * The debug levels of a {@link DelegatingDebugConfig} than can be - * {@linkplain DelegatingDebugConfig#override(Level, int) overridden} or - * {@linkplain DelegatingDebugConfig#delegate(Level) delegated}. - */ - public enum Level { - LOG, - DUMP - } - - private final Map levelState = new EnumMap<>(Level.class); - - /** - * Creates a config that delegates to the {@link DebugScope#getConfig() current config}. - */ - public DelegatingDebugConfig() { - this(DebugScope.getConfig()); - } - - /** - * Creates a config that delegates to a given config. - */ - public DelegatingDebugConfig(DebugConfig delegate) { - this.delegate = delegate; - } - - public DelegatingDebugConfig enable(Feature feature) { - featureState.put(feature, Boolean.TRUE); - return this; - } - - public DelegatingDebugConfig disable(Feature feature) { - featureState.put(feature, Boolean.FALSE); - return this; - } - - public DelegatingDebugConfig override(Level level, int newLevel) { - levelState.put(level, newLevel); - return this; - } - - public DelegatingDebugConfig delegate(Feature feature) { - featureState.put(feature, null); - return this; - } - - public DelegatingDebugConfig delegate(Level level) { - levelState.put(level, null); - return this; - } - - @Override - public OptionValues getOptions() { - return delegate.getOptions(); - } - - @Override - public int getLogLevel() { - Integer ls = levelState.get(Level.LOG); - if (ls == null) { - return delegate.getLogLevel(); - } - return ls.intValue(); - } - - @Override - public boolean isLogEnabledForMethod() { - Boolean fs = featureState.get(Feature.LOG_METHOD); - if (fs == null) { - return delegate.isLogEnabledForMethod(); - } - return fs.booleanValue(); - } - - @Override - public boolean isCountEnabled() { - Boolean fs = featureState.get(Feature.COUNT); - if (fs == null) { - return delegate.isCountEnabled(); - } - return fs.booleanValue(); - } - - @Override - public boolean isMemUseTrackingEnabled() { - Boolean fs = featureState.get(Feature.TRACK_MEM_USE); - if (fs == null) { - return delegate.isMemUseTrackingEnabled(); - } - return fs.booleanValue(); - } - - @Override - public int getDumpLevel() { - Integer ls = levelState.get(Level.DUMP); - if (ls == null) { - return delegate.getDumpLevel(); - } - return ls.intValue(); - } - - @Override - public boolean isDumpEnabledForMethod() { - Boolean fs = featureState.get(Feature.DUMP_METHOD); - if (fs == null) { - return delegate.isDumpEnabledForMethod(); - } - return fs.booleanValue(); - } - - @Override - public boolean isVerifyEnabled() { - Boolean fs = featureState.get(Feature.VERIFY); - if (fs == null) { - return delegate.isVerifyEnabled(); - } - return fs.booleanValue(); - } - - @Override - public boolean isVerifyEnabledForMethod() { - Boolean fs = featureState.get(Feature.VERIFY_METHOD); - if (fs == null) { - return delegate.isVerifyEnabledForMethod(); - } - return fs.booleanValue(); - } - - @Override - public boolean isTimeEnabled() { - Boolean fs = featureState.get(Feature.TIME); - if (fs == null) { - return delegate.isTimeEnabled(); - } - return fs.booleanValue(); - } - - @Override - public boolean isMethodMeterEnabled() { - Boolean fs = featureState.get(Feature.METHOD_METRICS); - if (fs == null) { - return delegate.isMethodMeterEnabled(); - } - return fs.booleanValue(); - } - - @Override - public RuntimeException interceptException(Throwable e) { - Boolean fs = featureState.get(Feature.INTERCEPT); - if (fs == null || fs) { - return delegate.interceptException(e); - } - return null; - } - - @Override - public Collection dumpHandlers() { - return delegate.dumpHandlers(); - } - - @Override - public Collection verifyHandlers() { - return delegate.verifyHandlers(); - } - - @Override - public PrintStream output() { - return delegate.output(); - } - - @Override - public void addToContext(Object o) { - delegate.addToContext(o); - } - - @Override - public void removeFromContext(Object o) { - delegate.removeFromContext(o); - } - -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GraalDebugConfig.java 2017-07-07 09:32:18.000000000 -0700 +++ /dev/null 2017-07-07 09:32:18.000000000 -0700 @@ -1,452 +0,0 @@ -/* - * Copyright (c) 2012, 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 org.graalvm.compiler.debug; - -import java.io.PrintStream; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.IdentityHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.graalvm.compiler.options.Option; -import org.graalvm.compiler.options.OptionKey; -import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValues; -import org.graalvm.util.EconomicMap; - -import jdk.vm.ci.code.BailoutException; -import jdk.vm.ci.meta.JavaMethod; - -public class GraalDebugConfig implements DebugConfig { - - public static class Options { - // @formatter:off - @Option(help = "Pattern for scope(s) in which dumping is enabled (see DebugFilter and Debug.dump)", type = OptionType.Debug) - public static final OptionKey Dump = new OptionKey<>(null); - @Option(help = "Pattern for scope(s) in which counting is enabled (see DebugFilter and Debug.counter). " + - "An empty value enables all counters unconditionally.", type = OptionType.Debug) - public static final OptionKey Count = new OptionKey<>(null); - @Option(help = "Pattern for scope(s) in which verification is enabled (see DebugFilter and Debug.verify).", type = OptionType.Debug) - public static final OptionKey Verify = new OptionKey<>(Assertions.ENABLED ? "" : null); - @Option(help = "Pattern for scope(s) in which memory use tracking is enabled (see DebugFilter and Debug.counter). " + - "An empty value enables all memory use trackers unconditionally.", type = OptionType.Debug) - public static final OptionKey TrackMemUse = new OptionKey<>(null); - @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 OptionKey Time = new OptionKey<>(null); - @Option(help = "Pattern for scope(s) in which logging is enabled (see DebugFilter and Debug.log)", type = OptionType.Debug) - public static final OptionKey Log = new OptionKey<>(null); - @Option(help = "Pattern for filtering debug scope output based on method context (see MethodFilter)", type = OptionType.Debug) - public static final OptionKey MethodFilter = new OptionKey<>(null); - @Option(help = "Only check MethodFilter against the root method in the context if true, otherwise check all methods", type = OptionType.Debug) - public static final OptionKey MethodFilterRootOnly = new OptionKey<>(false); - @Option(help = "Dump a before and after graph if the named phase changes the graph.%n" + - "The argument is substring matched against the simple name of the phase class", type = OptionType.Debug) - public static final OptionKey DumpOnPhaseChange = new OptionKey<>(null); - - @Option(help = "How to print counters and timing values:%n" + - "Name - aggregate by unqualified name%n" + - "Partial - aggregate by partially qualified name (e.g., A.B.C.D.Counter and X.Y.Z.D.Counter will be merged to D.Counter)%n" + - "Complete - aggregate by qualified name%n" + - "Thread - aggregate by qualified name and thread", type = OptionType.Debug) - public static final OptionKey DebugValueSummary = new OptionKey<>("Name"); - @Option(help = "Print counters and timers in a human readable form.", type = OptionType.Debug) - public static final OptionKey DebugValueHumanReadable = new OptionKey<>(true); - @Option(help = "Omit reporting 0-value counters", type = OptionType.Debug) - public static final OptionKey SuppressZeroDebugValues = new OptionKey<>(true); - @Option(help = "Only report debug values for maps which match the regular expression.", type = OptionType.Debug) - public static final OptionKey DebugValueThreadFilter = new OptionKey<>(null); - @Option(help = "Write debug values into a file instead of the terminal. " + - "If DebugValueSummary is Thread, the thread name will be prepended.", type = OptionType.Debug) - public static final OptionKey DebugValueFile = new OptionKey<>(null); - @Option(help = "Enable debug output for stub code generation and snippet preparation.", type = OptionType.Debug) - public static final OptionKey DebugStubsAndSnippets = new OptionKey<>(false); - @Option(help = "Send Graal compiler IR to dump handlers on error.", type = OptionType.Debug) - public static final OptionKey DumpOnError = new OptionKey<>(false); - @Option(help = "Intercept also bailout exceptions", type = OptionType.Debug) - public static final OptionKey InterceptBailout = new OptionKey<>(false); - @Option(help = "Enable more verbose log output when available", type = OptionType.Debug) - public static final OptionKey LogVerbose = new OptionKey<>(false); - - @Option(help = "The directory where various Graal dump files are written.") - public static final OptionKey DumpPath = new OptionKey<>("."); - - @Option(help = "Enable dumping to the C1Visualizer. Enabling this option implies PrintBackendCFG.", type = OptionType.Debug) - public static final OptionKey PrintCFG = new OptionKey<>(false); - @Option(help = "Enable dumping LIR, register allocation and code generation info to the C1Visualizer.", type = OptionType.Debug) - public static final OptionKey PrintBackendCFG = new OptionKey<>(true); - @Option(help = "Base filename when dumping C1Visualizer output to files.", type = OptionType.Debug) - public static final OptionKey PrintCFGFileName = new OptionKey<>("compilations"); - - @Option(help = "Output probabilities for fixed nodes during binary graph dumping.", type = OptionType.Debug) - public static final OptionKey PrintGraphProbabilities = new OptionKey<>(false); - @Option(help = "Enable dumping to the IdealGraphVisualizer.", type = OptionType.Debug) - public static final OptionKey PrintGraph = new OptionKey<>(true); - @Option(help = "Dump graphs in binary format instead of XML format.", type = OptionType.Debug) - public static final OptionKey PrintBinaryGraphs = new OptionKey<>(true); - @Option(help = "Print graphs to files instead of sending them over the network.", type = OptionType.Debug) - public static final OptionKey PrintGraphFile = new OptionKey<>(false); - @Option(help = "Base filename when dumping graphs to files.", type = OptionType.Debug) - public static final OptionKey PrintGraphFileName = new OptionKey<>("runtime-graphs"); - - @Option(help = "Host part of the address to which graphs are dumped.", type = OptionType.Debug) - public static final OptionKey PrintGraphHost = new OptionKey<>("127.0.0.1"); - @Option(help = "Port part of the address to which graphs are dumped in XML format (ignored if PrintBinaryGraphs=true).", type = OptionType.Debug) - public static final OptionKey PrintXmlGraphPort = new OptionKey<>(4444); - @Option(help = "Port part of the address to which graphs are dumped in binary format (ignored if PrintBinaryGraphs=false).", type = OptionType.Debug) - public static final OptionKey PrintBinaryGraphPort = new OptionKey<>(4445); - @Option(help = "Schedule graphs as they are dumped.", type = OptionType.Debug) - public static final OptionKey PrintGraphWithSchedule = new OptionKey<>(false); - - @Option(help = "Enable dumping Truffle ASTs to the IdealGraphVisualizer.", type = OptionType.Debug) - public static final OptionKey PrintTruffleTrees = new OptionKey<>(true); - - @Option(help = "Treat any exceptions during dumping as fatal.", type = OptionType.Debug) - public static final OptionKey DumpingErrorsAreFatal = new OptionKey<>(false); - - @Option(help = "Enable dumping canonical text from for graphs.", type = OptionType.Debug) - public static final OptionKey PrintCanonicalGraphStrings = new OptionKey<>(false); - @Option(help = "Base directory when dumping graphs strings to files.", type = OptionType.Debug) - public static final OptionKey PrintCanonicalGraphStringsDirectory = new OptionKey<>("graph-strings"); - @Option(help = "Choose format used when dumping canonical text for graphs: " + - "0 gives a scheduled graph (better for spotting changes involving the schedule)" + - "while 1 gives a CFG containing expressions rooted at fixed nodes (better for spotting small structure differences)", type = OptionType.Debug) - public static final OptionKey PrintCanonicalGraphStringFlavor = new OptionKey<>(0); - @Option(help = "Exclude virtual nodes when dumping canonical text for graphs.", type = OptionType.Debug) - public static final OptionKey CanonicalGraphStringsExcludeVirtuals = new OptionKey<>(true); - @Option(help = "Exclude virtual nodes when dumping canonical text for graphs.", type = OptionType.Debug) - public static final OptionKey CanonicalGraphStringsCheckConstants = new OptionKey<>(false); - @Option(help = "Attempts to remove object identity hashes when dumping canonical text for graphs.", type = OptionType.Debug) - public static final OptionKey CanonicalGraphStringsRemoveIdentities = new OptionKey<>(true); - - @Option(help = "Enable per method metrics that are collected across all compilations of a method." + - "Pattern for scope(s) in which method metering is enabled (see DebugFilter and Debug.metric).", type = OptionType.Debug) - public static final OptionKey MethodMeter = new OptionKey<>(null); - @Option(help = "If a global metric (DebugTimer, DebugCounter or DebugMemUseTracker) is enabled in the same scope as a method metric, " + - "use the global metric to update the method metric for the current compilation. " + - "This option enables the re-use of global metrics on per-compilation basis. " + - "Whenever a value is added to a global metric, the value is also added to a MethodMetric under the same name " + - "as the global metric. " + - "This option incurs a small but constant overhead due to the context method lookup at each metric update. " + - "Format to specify GlobalMetric interception:(Timers|Counters|MemUseTrackers)(,Timers|,Counters|,MemUseTrackers)*", type = OptionType.Debug) - public static final OptionKey GlobalMetricsInterceptedByMethodMetrics = new OptionKey<>(null); - @Option(help = "Force-enable debug code paths", type = OptionType.Debug) - public static final OptionKey ForceDebugEnable = new OptionKey<>(false); - @Option(help = "Clear the debug metrics after bootstrap.", type = OptionType.Debug) - public static final OptionKey ClearMetricsAfterBootstrap = new OptionKey<>(false); - @Option(help = "Do not compile anything on bootstrap but just initialize the compiler.", type = OptionType.Debug) - public static final OptionKey BootstrapInitializeOnly = new OptionKey<>(false); - - // These - @Option(help = "Deprecated - use PrintGraphHost instead.", type = OptionType.Debug) - static final OptionKey PrintIdealGraphAddress = new DeprecatedOptionKey<>(PrintGraphHost); - @Option(help = "Deprecated - use PrintGraphWithSchedule instead.", type = OptionType.Debug) - static final OptionKey PrintIdealGraphSchedule = new DeprecatedOptionKey<>(PrintGraphWithSchedule); - @Option(help = "Deprecated - use PrintGraph instead.", type = OptionType.Debug) - static final OptionKey PrintIdealGraph = new DeprecatedOptionKey<>(PrintGraph); - @Option(help = "Deprecated - use PrintGraphFile instead.", type = OptionType.Debug) - static final OptionKey PrintIdealGraphFile = new DeprecatedOptionKey<>(PrintGraphFile); - @Option(help = "Deprecated - use PrintGraphFileName instead.", type = OptionType.Debug) - static final OptionKey PrintIdealGraphFileName = new DeprecatedOptionKey<>(PrintGraphFileName); - @Option(help = "Deprecated - use PrintXmlGraphPort instead.", type = OptionType.Debug) - static final OptionKey PrintIdealGraphPort = new DeprecatedOptionKey<>(PrintXmlGraphPort); - // @formatter:on - } - - static class DeprecatedOptionKey extends OptionKey { - private final OptionKey replacement; - - DeprecatedOptionKey(OptionKey replacement) { - super(replacement.getDefaultValue()); - this.replacement = replacement; - } - - @Override - protected void onValueUpdate(EconomicMap, Object> values, T oldValue, T newValue) { - // Ideally we'd use TTY here but it may not yet be initialized. - System.err.printf("Warning: the %s option is deprecated - use %s instead%n", getName(), replacement.getName()); - replacement.update(values, newValue); - } - } - - public static boolean isNotEmpty(OptionKey option, OptionValues options) { - return option.getValue(options) != null && !option.getValue(options).isEmpty(); - } - - public static boolean areDebugScopePatternsEnabled(OptionValues options) { - return Options.DumpOnError.getValue(options) || Options.Dump.getValue(options) != null || Options.Log.getValue(options) != null || areScopedGlobalMetricsEnabled(options); - } - - public static boolean isGlobalMetricsInterceptedByMethodMetricsEnabled(OptionValues options) { - return isNotEmpty(Options.GlobalMetricsInterceptedByMethodMetrics, options); - } - - /** - * Determines if any of {@link Options#Count}, {@link Options#Time} or - * {@link Options#TrackMemUse} has a non-null, non-empty value. - * - * @param options - */ - public static boolean areScopedGlobalMetricsEnabled(OptionValues options) { - return isNotEmpty(Options.Count, options) || isNotEmpty(Options.Time, options) || isNotEmpty(Options.TrackMemUse, options) || isNotEmpty(Options.MethodMeter, options); - } - - private final OptionValues options; - - private final DebugFilter countFilter; - private final DebugFilter logFilter; - private final DebugFilter methodMetricsFilter; - private final DebugFilter trackMemUseFilter; - private final DebugFilter timerFilter; - private final DebugFilter dumpFilter; - private final DebugFilter verifyFilter; - private final MethodFilter[] methodFilter; - private final List dumpHandlers; - private final List verifyHandlers; - private final PrintStream output; - - // Use an identity set to handle context objects that don't support hashCode(). - private final Set extraFilters = Collections.newSetFromMap(new IdentityHashMap<>()); - - public GraalDebugConfig(OptionValues options, String logFilter, String countFilter, String trackMemUseFilter, String timerFilter, String dumpFilter, String verifyFilter, String methodFilter, - String methodMetricsFilter, PrintStream output, List dumpHandlers, List verifyHandlers) { - this.options = options; - this.logFilter = DebugFilter.parse(logFilter); - this.countFilter = DebugFilter.parse(countFilter); - this.trackMemUseFilter = DebugFilter.parse(trackMemUseFilter); - this.timerFilter = DebugFilter.parse(timerFilter); - this.dumpFilter = DebugFilter.parse(dumpFilter); - this.verifyFilter = DebugFilter.parse(verifyFilter); - this.methodMetricsFilter = DebugFilter.parse(methodMetricsFilter); - if (methodFilter == null || methodFilter.isEmpty()) { - this.methodFilter = null; - } else { - this.methodFilter = org.graalvm.compiler.debug.MethodFilter.parse(methodFilter); - } - - this.dumpHandlers = dumpHandlers; - this.verifyHandlers = verifyHandlers; - this.output = output; - } - - @Override - public OptionValues getOptions() { - return options; - } - - @Override - public int getLogLevel() { - return getLevel(logFilter); - } - - @Override - public boolean isLogEnabledForMethod() { - return isEnabledForMethod(logFilter); - } - - @Override - public boolean isCountEnabled() { - return isEnabled(countFilter); - } - - @Override - public boolean isMemUseTrackingEnabled() { - return isEnabled(trackMemUseFilter); - } - - @Override - public int getDumpLevel() { - return getLevel(dumpFilter); - } - - @Override - public boolean isDumpEnabledForMethod() { - return isEnabledForMethod(dumpFilter); - } - - @Override - public boolean isVerifyEnabled() { - return isEnabled(verifyFilter); - } - - @Override - public boolean isVerifyEnabledForMethod() { - return isEnabledForMethod(verifyFilter); - } - - @Override - public boolean isMethodMeterEnabled() { - return isEnabled(methodMetricsFilter); - } - - @Override - public boolean isTimeEnabled() { - return isEnabled(timerFilter); - } - - @Override - public PrintStream output() { - return output; - } - - private boolean isEnabled(DebugFilter filter) { - return getLevel(filter) > 0; - } - - private int getLevel(DebugFilter filter) { - int level; - if (filter == null) { - level = 0; - } else { - level = filter.matchLevel(Debug.currentScope()); - } - if (level >= 0 && !checkMethodFilter()) { - level = -1; - } - return level; - } - - private boolean isEnabledForMethod(DebugFilter filter) { - return filter != null && checkMethodFilter(); - } - - /** - * Extracts a {@link JavaMethod} from an opaque debug context. - * - * @return the {@link JavaMethod} represented by {@code context} or null - */ - public static JavaMethod asJavaMethod(Object context) { - if (context instanceof JavaMethodContext) { - return ((JavaMethodContext) context).asJavaMethod(); - } - if (context instanceof JavaMethod) { - return (JavaMethod) context; - } - return null; - } - - private boolean checkMethodFilter() { - if (methodFilter == null && extraFilters.isEmpty()) { - return true; - } else { - JavaMethod lastMethod = null; - for (Object o : Debug.context()) { - if (extraFilters.contains(o)) { - return true; - } else if (methodFilter != null) { - JavaMethod method = asJavaMethod(o); - if (method != null) { - if (!Options.MethodFilterRootOnly.getValue(options)) { - if (org.graalvm.compiler.debug.MethodFilter.matches(methodFilter, method)) { - return true; - } - } else { - /* - * The context values operate as a stack so if we want MethodFilter to - * only apply to the root method we have to check only the last method - * seen. - */ - lastMethod = method; - } - } - } - } - if (lastMethod != null && org.graalvm.compiler.debug.MethodFilter.matches(methodFilter, lastMethod)) { - return true; - } - return false; - } - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("Debug config:"); - add(sb, "Log", logFilter); - add(sb, "Count", countFilter); - add(sb, "MethodMeter", methodMetricsFilter); - add(sb, "Time", timerFilter); - add(sb, "Dump", dumpFilter); - add(sb, "MethodFilter", methodFilter); - return sb.toString(); - } - - private static void add(StringBuilder sb, String name, Object filter) { - if (filter != null) { - sb.append(' '); - sb.append(name); - sb.append('='); - if (filter instanceof Object[]) { - sb.append(Arrays.toString((Object[]) filter)); - } else { - sb.append(String.valueOf(filter)); - } - } - } - - @Override - public RuntimeException interceptException(Throwable e) { - if (e instanceof BailoutException && !Options.InterceptBailout.getValue(options)) { - return null; - } - Debug.setConfig(Debug.fixedConfig(options, Debug.BASIC_LEVEL, Debug.BASIC_LEVEL, false, false, false, false, false, dumpHandlers, verifyHandlers, output)); - Debug.log("Exception occurred in scope: %s", Debug.currentScope()); - Map firstSeen = new IdentityHashMap<>(); - for (Object o : Debug.context()) { - // Only dump a context object once. - if (!firstSeen.containsKey(o)) { - firstSeen.put(o, o); - if (Options.DumpOnError.getValue(options) || Options.Dump.getValue(options) != null) { - Debug.dump(Debug.BASIC_LEVEL, o, "Exception: %s", e); - } else { - Debug.log("Context obj %s", o); - } - } - } - return null; - } - - @Override - public Collection dumpHandlers() { - return dumpHandlers; - } - - @Override - public Collection verifyHandlers() { - return verifyHandlers; - } - - @Override - public void addToContext(Object o) { - extraFilters.add(o); - } - - @Override - public void removeFromContext(Object o) { - extraFilters.remove(o); - } - -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TopLevelDebugConfig.java 2017-07-07 09:32:19.000000000 -0700 +++ /dev/null 2017-07-07 09:32:19.000000000 -0700 @@ -1,31 +0,0 @@ -/* - * 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 org.graalvm.compiler.debug; - -/** - * A marker class for a scoped debug configuration covering a compilation region. Useful for - * programmatically enabling debug config features. - * - */ -public class TopLevelDebugConfig extends DelegatingDebugConfig { -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/AccumulatedDebugValue.java 2017-07-07 09:32:19.000000000 -0700 +++ /dev/null 2017-07-07 09:32:19.000000000 -0700 @@ -1,32 +0,0 @@ -/* - * 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 org.graalvm.compiler.debug.internal; - -public abstract class AccumulatedDebugValue extends DebugValue { - protected final DebugValue flat; - - public AccumulatedDebugValue(String name, boolean conditional, DebugValue flat) { - super(name + "_Accm", conditional); - this.flat = flat; - } -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/CloseableCounterImpl.java 2017-07-07 09:32:19.000000000 -0700 +++ /dev/null 2017-07-07 09:32:19.000000000 -0700 @@ -1,93 +0,0 @@ -/* - * 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 org.graalvm.compiler.debug.internal; - -import org.graalvm.compiler.debug.DebugCloseable; - -/** - * A helper class for DebugValues that can nest and need to split out accumulated and flat values - * for some kind of counter-like measurement. - */ -abstract class CloseableCounterImpl implements DebugCloseable { - - protected final CloseableCounterImpl parent; - protected final AccumulatedDebugValue counter; - protected final long start; - protected long nestedAmountToSubtract; - - CloseableCounterImpl(CloseableCounterImpl parent, AccumulatedDebugValue counter) { - this.parent = parent; - this.start = getCounterValue(); - this.counter = counter; - } - - /** - * A hook for subclasses. Lets them perform custom operations with the value since the last - * invocation of {@link CloseableCounterImpl#close()} of this accumulated - * {@link CloseableCounterImpl#counter}. - * - * @param difference since the last invocation of this counter flat - */ - protected void interceptDifferenceAccm(long difference) { - // hook for subclasses - } - - /** - * A hook for subclasses. Lets them perform custom operations with the value since the last - * invocation of {@link CloseableCounterImpl#close()} of this flat - * {@link CloseableCounterImpl#counter}. - * - * @param difference since the last invocation of this counter flat - */ - protected void interceptDifferenceFlat(long difference) { - // hook for subclasses - } - - @Override - public void close() { - long end = getCounterValue(); - long difference = end - start; - if (parent != null) { - if (!counter.getName().equals(parent.counter.getName())) { - parent.nestedAmountToSubtract += difference; - // Look for our counter in an outer scope and fix up - // the adjustment to the flat count - CloseableCounterImpl ancestor = parent.parent; - while (ancestor != null) { - if (ancestor.counter.getName().equals(counter.getName())) { - ancestor.nestedAmountToSubtract -= difference; - break; - } - ancestor = ancestor.parent; - } - } - } - long flatAmount = difference - nestedAmountToSubtract; - counter.addToCurrentValue(difference); - counter.flat.addToCurrentValue(flatAmount); - interceptDifferenceAccm(difference); - interceptDifferenceFlat(flatAmount); - } - - abstract long getCounterValue(); -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/CounterImpl.java 2017-07-07 09:32:20.000000000 -0700 +++ /dev/null 2017-07-07 09:32:20.000000000 -0700 @@ -1,96 +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 org.graalvm.compiler.debug.internal; - -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; -import org.graalvm.compiler.debug.internal.method.MethodMetricsImpl; - -public abstract class CounterImpl extends DebugValue implements DebugCounter { - - public CounterImpl(String name, boolean conditional) { - super(name, conditional); - if (isEnabled()) { - // Allows for zero counters to be shown - getCurrentValue(); - } - } - - @Override - public void increment() { - add(1); - } - - @Override - public String rawUnit() { - return ""; - } - - @Override - public String toRawString(long value) { - return Long.toString(value); - } - - @Override - public String toString(long value) { - return Long.toString(value); - } - - private static final class InterceptingCounterImpl extends CounterImpl { - - private InterceptingCounterImpl(String name, boolean conditional) { - super(name, conditional); - } - - @Override - public void add(long value) { - if (isEnabled()) { - if (Debug.isMethodMeterEnabled()) { - MethodMetricsImpl.addToCurrentScopeMethodMetrics(getName(), value); - } - super.addToCurrentValue(value); - } - } - } - - private static final class PlainCounterImpl extends CounterImpl { - - private PlainCounterImpl(String name, boolean conditional) { - super(name, conditional); - } - - @Override - public void add(long value) { - if (isEnabled()) { - super.addToCurrentValue(value); - } - } - } - - public static DebugCounter create(String name, boolean conditional, boolean intercepting) { - if (intercepting) { - return new InterceptingCounterImpl(name, conditional); - } - return new PlainCounterImpl(name, conditional); - } -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugHistogramAsciiPrinter.java 2017-07-07 09:32:20.000000000 -0700 +++ /dev/null 2017-07-07 09:32:20.000000000 -0700 @@ -1,105 +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 org.graalvm.compiler.debug.internal; - -import java.io.PrintStream; -import java.util.Arrays; -import java.util.List; - -import org.graalvm.compiler.debug.DebugHistogram; -import org.graalvm.compiler.debug.DebugHistogram.CountedValue; -import org.graalvm.compiler.debug.DebugHistogram.Printer; - -/** - * Renders a textual representation of a histogram to a given print stream. - */ -public class DebugHistogramAsciiPrinter implements Printer { - - public static final int NumberSize = 10; - public static final int DefaultNameSize = 50; - public static final int DefaultBarSize = 100; - public static final int DefaultScale = 1; - - private final PrintStream os; - private final int limit; - private final int nameSize; - private final int barSize; - private final int scale; - - public DebugHistogramAsciiPrinter(PrintStream os) { - this(os, Integer.MAX_VALUE, DefaultNameSize, DefaultBarSize, DefaultScale); - } - - /** - * @param os where to print - * @param limit limits printing to the {@code limit} most frequent values - * @param nameSize the width of the value names column - * @param barSize the width of the value frequency column - * @param scale a factor by which every result is divided - */ - public DebugHistogramAsciiPrinter(PrintStream os, int limit, int nameSize, int barSize, int scale) { - this.os = os; - this.limit = limit; - this.nameSize = nameSize; - this.barSize = barSize; - this.scale = scale; - } - - @Override - public void print(DebugHistogram histogram) { - List list = histogram.getValues(); - if (list.isEmpty()) { - os.printf("%s is empty.%n", histogram.getName()); - return; - } - - // Sum up the total number of elements. - long total = list.stream().mapToLong(CountedValue::getCount).sum(); - - // Print header. - os.printf("%s has %d unique elements and %d total elements:%n", histogram.getName(), list.size(), total / scale); - - long max = list.get(0).getCount() / scale; - final int lineSize = nameSize + NumberSize + barSize + 10; - printLine(os, '-', lineSize); - String formatString = "| %-" + nameSize + "s | %-" + NumberSize + "d | %-" + barSize + "s |\n"; - for (int i = 0; i < list.size() && i < limit; ++i) { - CountedValue cv = list.get(i); - long value = cv.getCount() / scale; - char[] bar = new char[(int) (((double) value / (double) max) * barSize)]; - Arrays.fill(bar, '='); - String objectString = String.valueOf(cv.getValue()); - if (objectString.length() > nameSize) { - objectString = objectString.substring(0, nameSize - 3) + "..."; - } - os.printf(formatString, objectString, value, new String(bar)); - } - printLine(os, '-', lineSize); - } - - private static void printLine(PrintStream printStream, char c, int lineSize) { - char[] charArr = new char[lineSize]; - Arrays.fill(charArr, c); - printStream.printf("%s%n", new String(charArr)); - } -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugHistogramImpl.java 2017-07-07 09:32:20.000000000 -0700 +++ /dev/null 2017-07-07 09:32:20.000000000 -0700 @@ -1,72 +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 org.graalvm.compiler.debug.internal; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; - -import org.graalvm.compiler.debug.DebugHistogram; - -public class DebugHistogramImpl implements DebugHistogram { - - private final String name; - private HashMap map = new HashMap<>(); - - public DebugHistogramImpl(String name) { - this.name = name; - } - - @Override - public void add(Object value) { - CountedValue cv = map.get(value); - if (cv == null) { - map.put(value, new CountedValue(1, value)); - } else { - cv.inc(); - } - } - - @Override - public void add(Object value, long count) { - CountedValue cv = map.get(value); - if (cv == null) { - map.put(value, new CountedValue(count, value)); - } else { - cv.add(count); - } - } - - @Override - public String getName() { - return name; - } - - @Override - public List getValues() { - ArrayList res = new ArrayList<>(map.values()); - Collections.sort(res); - return res; - } -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugHistogramRPrinter.java 2017-07-07 09:32:20.000000000 -0700 +++ /dev/null 2017-07-07 09:32:20.000000000 -0700 @@ -1,82 +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 org.graalvm.compiler.debug.internal; - -import java.io.PrintStream; -import java.util.List; - -import org.graalvm.compiler.debug.DebugHistogram; -import org.graalvm.compiler.debug.DebugHistogram.CountedValue; -import org.graalvm.compiler.debug.DebugHistogram.Printer; - -/** - * Renders a histogram as an R script to a given print stream. The R script emitted for a histogram - * is a simple set of statements for defining a vector of named objects. - */ -public class DebugHistogramRPrinter implements Printer { - - private PrintStream os; - private int limit; - - public DebugHistogramRPrinter(PrintStream os) { - this(os, Integer.MAX_VALUE); - } - - /** - * @param os where to print - * @param limit limits printing to the {@code limit} most frequent values - */ - public DebugHistogramRPrinter(PrintStream os, int limit) { - this.os = os; - this.limit = limit; - } - - @Override - public void print(DebugHistogram histogram) { - List list = histogram.getValues(); - if (list.isEmpty()) { - return; - } - - String var = histogram.getName().replace('-', '.').replace(' ', '_'); - os.print(var + " <- c("); - for (int i = 0; i < list.size() && i < limit; ++i) { - CountedValue cv = list.get(i); - if (i != 0) { - os.print(", "); - } - os.print(cv.getCount()); - } - os.println(");"); - - os.print("names(" + var + ") <- c("); - for (int i = 0; i < list.size() && i < limit; ++i) { - CountedValue cv = list.get(i); - if (i != 0) { - os.print(", "); - } - os.print("\"" + cv.getValue() + "\""); - } - os.println(");"); - } -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugScope.java 2017-07-07 09:32:21.000000000 -0700 +++ /dev/null 2017-07-07 09:32:21.000000000 -0700 @@ -1,579 +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 org.graalvm.compiler.debug.internal; - -import java.io.PrintStream; -import java.util.Iterator; -import java.util.concurrent.Callable; -import java.util.concurrent.atomic.AtomicLong; - -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugConfig; -import org.graalvm.compiler.debug.DebugDumpHandler; -import org.graalvm.compiler.debug.DebugVerifyHandler; -import org.graalvm.compiler.debug.DelegatingDebugConfig; -import org.graalvm.compiler.debug.Indent; -import org.graalvm.compiler.debug.JavaMethodContext; -import org.graalvm.compiler.debug.TTY; -import org.graalvm.compiler.debug.TopLevelDebugConfig; - -import jdk.vm.ci.meta.JavaMethod; - -public final class DebugScope implements Debug.Scope { - - private final class IndentImpl implements Indent { - - private static final String INDENTATION_INCREMENT = " "; - - final String indent; - final IndentImpl parentIndent; - - IndentImpl(IndentImpl parentIndent) { - this.parentIndent = parentIndent; - this.indent = (parentIndent == null ? "" : parentIndent.indent + INDENTATION_INCREMENT); - } - - private boolean logScopeName() { - return logScopeName; - } - - private void printScopeName(StringBuilder str, boolean isCurrent) { - if (logScopeName) { - boolean parentPrinted = false; - if (parentIndent != null) { - parentPrinted = parentIndent.logScopeName(); - parentIndent.printScopeName(str, false); - } - /* - * Always print the current scope, scopes with context and the any scope whose - * parent didn't print. This ensure the first new scope always shows up. - */ - if (isCurrent || printContext(null) != 0 || !parentPrinted) { - str.append(indent).append("[thread:").append(Thread.currentThread().getId()).append("] scope: ").append(getQualifiedName()).append(System.lineSeparator()); - } - printContext(str); - logScopeName = false; - } - } - - /** - * Print or count the context objects for the current scope. - */ - private int printContext(StringBuilder str) { - int count = 0; - if (context != null && context.length > 0) { - // Include some context in the scope output - for (Object contextObj : context) { - if (contextObj instanceof JavaMethodContext || contextObj instanceof JavaMethod) { - if (str != null) { - str.append(indent).append("Context: ").append(contextObj).append(System.lineSeparator()); - } - count++; - } - } - } - return count; - } - - public void log(int logLevel, String msg, Object... args) { - if (isLogEnabled(logLevel)) { - StringBuilder str = new StringBuilder(); - printScopeName(str, true); - str.append(indent); - String result = args.length == 0 ? msg : String.format(msg, args); - String lineSep = System.lineSeparator(); - str.append(result.replace(lineSep, lineSep.concat(indent))); - str.append(lineSep); - output.append(str); - lastUsedIndent = this; - } - } - - IndentImpl indent() { - lastUsedIndent = new IndentImpl(this); - return lastUsedIndent; - } - - @Override - public void close() { - if (parentIndent != null) { - lastUsedIndent = parentIndent; - } - } - } - - /** - * Interface for an additional information object per scope. The information object will be - * given to child scopes, but can be explicitly set with - * {@link DebugScope#enhanceWithExtraInfo(CharSequence, ExtraInfo, boolean, Object...)} - */ - public interface ExtraInfo { - - } - - private static final ThreadLocal instanceTL = new ThreadLocal<>(); - private static final ThreadLocal lastClosedTL = new ThreadLocal<>(); - private static final ThreadLocal configTL = new ThreadLocal<>(); - private static final ThreadLocal lastExceptionThrownTL = new ThreadLocal<>(); - - private final DebugScope parent; - private final DebugConfig parentConfig; - private final boolean sandbox; - private IndentImpl lastUsedIndent; - private boolean logScopeName; - - private final Object[] context; - - private DebugValueMap valueMap; - - private String qualifiedName; - private final String unqualifiedName; - - private final ExtraInfo extraInfo; - - private static final AtomicLong uniqueScopeId = new AtomicLong(); - private final long scopeId; - - private static final char SCOPE_SEP = '.'; - - private boolean countEnabled; - private boolean timeEnabled; - private boolean memUseTrackingEnabled; - private boolean verifyEnabled; - private boolean methodMetricsEnabled; - - private int currentDumpLevel; - private int currentLogLevel; - - private PrintStream output; - - public static long getCurrentGlobalScopeId() { - return uniqueScopeId.get(); - } - - public static DebugScope getInstance() { - DebugScope result = instanceTL.get(); - if (result == null) { - DebugScope topLevelDebugScope = new DebugScope(Thread.currentThread()); - instanceTL.set(topLevelDebugScope); - return topLevelDebugScope; - } else { - return result; - } - } - - public static DebugConfig getConfig() { - return configTL.get(); - } - - static final Object[] EMPTY_CONTEXT = new Object[0]; - - private DebugScope(Thread thread) { - this(thread.getName(), null, uniqueScopeId.incrementAndGet(), null, false); - computeValueMap(thread.getName()); - DebugValueMap.registerTopLevel(getValueMap()); - } - - private DebugScope(String unqualifiedName, DebugScope parent, long scopeId, ExtraInfo metaInfo, boolean sandbox, Object... context) { - this.parent = parent; - this.sandbox = sandbox; - this.parentConfig = getConfig(); - this.context = context; - this.scopeId = scopeId; - this.unqualifiedName = unqualifiedName; - this.extraInfo = metaInfo; - if (parent != null) { - logScopeName = !unqualifiedName.equals(""); - } else { - logScopeName = true; - } - - this.output = TTY.out; - assert context != null; - } - - private void computeValueMap(String name) { - if (parent != null) { - for (DebugValueMap child : parent.getValueMap().getChildren()) { - if (child.getName().equals(name)) { - this.valueMap = child; - return; - } - } - this.valueMap = new DebugValueMap(name); - parent.getValueMap().addChild(this.valueMap); - } else { - this.valueMap = new DebugValueMap(name); - } - } - - @Override - public void close() { - instanceTL.set(parent); - configTL.set(parentConfig); - lastClosedTL.set(this); - } - - public boolean isDumpEnabled(int dumpLevel) { - assert dumpLevel >= 0; - return currentDumpLevel >= dumpLevel; - } - - /** - * Enable dumping at the new {@code dumpLevel} for the remainder of enclosing scopes. This only - * works if a {@link TopLevelDebugConfig} was installed at a higher scope. - * - * @param dumpLevel - */ - public static void setDumpLevel(int dumpLevel) { - TopLevelDebugConfig config = fetchTopLevelDebugConfig("setDebugLevel"); - if (config != null) { - config.override(DelegatingDebugConfig.Level.DUMP, dumpLevel); - recursiveUpdateFlags(); - } - } - - /** - * Enable logging at the new {@code logLevel} for the remainder of enclosing scopes. This only - * works if a {@link TopLevelDebugConfig} was installed at a higher scope. - * - * @param logLevel - */ - public static void setLogLevel(int logLevel) { - TopLevelDebugConfig config = fetchTopLevelDebugConfig("setLogLevel"); - if (config != null) { - config.override(DelegatingDebugConfig.Level.LOG, logLevel); - config.delegate(DelegatingDebugConfig.Feature.LOG_METHOD); - recursiveUpdateFlags(); - } - } - - private static void recursiveUpdateFlags() { - DebugScope c = DebugScope.getInstance(); - while (c != null) { - c.updateFlags(); - c = c.parent; - } - } - - private static TopLevelDebugConfig fetchTopLevelDebugConfig(String msg) { - DebugConfig config = getConfig(); - if (config instanceof TopLevelDebugConfig) { - return (TopLevelDebugConfig) config; - } else { - if (config == null) { - TTY.println("DebugScope.%s ignored because debugging is disabled", msg); - } else { - TTY.println("DebugScope.%s ignored because top level delegate config missing", msg); - } - return null; - } - } - - public boolean isVerifyEnabled() { - return verifyEnabled; - } - - public boolean isLogEnabled(int logLevel) { - assert logLevel > 0; - return currentLogLevel >= logLevel; - } - - public boolean isCountEnabled() { - return countEnabled; - } - - public boolean isTimeEnabled() { - return timeEnabled; - } - - public boolean isMethodMeterEnabled() { - return methodMetricsEnabled; - } - - public boolean isMemUseTrackingEnabled() { - return memUseTrackingEnabled; - } - - public void log(int logLevel, String msg, Object... args) { - if (isLogEnabled(logLevel)) { - getLastUsedIndent().log(logLevel, msg, args); - } - } - - public ExtraInfo getExtraInfo() { - return extraInfo; - } - - public long scopeId() { - return scopeId; - } - - public void dump(int dumpLevel, Object object, String formatString, Object... args) { - if (isDumpEnabled(dumpLevel)) { - DebugConfig config = getConfig(); - if (config != null) { - for (DebugDumpHandler dumpHandler : config.dumpHandlers()) { - dumpHandler.dump(object, formatString, args); - } - } - } - } - - /** - * This method exists mainly to allow a debugger (e.g., Eclipse) to force dump a graph. - */ - public static void forceDump(Object object, String format, Object... args) { - DebugConfig config = getConfig(); - if (config != null) { - for (DebugDumpHandler dumpHandler : config.dumpHandlers()) { - dumpHandler.dump(object, format, args); - } - } else { - TTY.println("Forced dump ignored because debugging is disabled - use -Dgraal.ForceDebugEnable=true"); - } - } - - /** - * @see Debug#verify(Object, String) - */ - public void verify(Object object, String formatString, Object... args) { - if (isVerifyEnabled()) { - DebugConfig config = getConfig(); - if (config != null) { - for (DebugVerifyHandler handler : config.verifyHandlers()) { - handler.verify(object, formatString, args); - } - } - } - } - - /** - * Creates and enters a new debug scope which is either a child of the current scope or a - * disjoint top level scope. - * - * @param name the name of the new scope - * @param sandboxConfig the configuration to use for a new top level scope, or null if the new - * scope should be a child scope - * @param newContextObjects objects to be appended to the debug context - * @return the new scope which will be exited when its {@link #close()} method is called - */ - public DebugScope scope(CharSequence name, DebugConfig sandboxConfig, Object... newContextObjects) { - DebugScope newScope = null; - if (sandboxConfig != null) { - newScope = new DebugScope(name.toString(), this, uniqueScopeId.incrementAndGet(), null, true, newContextObjects); - configTL.set(sandboxConfig); - } else { - newScope = this.createChild(name.toString(), this.extraInfo, newContextObjects); - } - instanceTL.set(newScope); - newScope.updateFlags(); - return newScope; - } - - public DebugScope enhanceWithExtraInfo(CharSequence name, ExtraInfo newInfo, boolean newId, Object... newContext) { - DebugScope newScope = createChild(name.toString(), newInfo, newId ? uniqueScopeId.incrementAndGet() : this.scopeId, newContext); - instanceTL.set(newScope); - newScope.updateFlags(); - return newScope; - } - - public RuntimeException handle(Throwable e) { - DebugScope lastClosed = lastClosedTL.get(); - try { - assert lastClosed.parent == this : "Debug.handle() used with no matching Debug.scope(...) or Debug.sandbox(...) " + - "or an exception occurred while opening a scope"; - if (e != lastExceptionThrownTL.get()) { - RuntimeException newException = null; - instanceTL.set(lastClosed); - try (DebugScope s = lastClosed) { - newException = s.interceptException(e); - } - assert instanceTL.get() == this; - assert lastClosed == lastClosedTL.get(); - if (newException == null) { - lastExceptionThrownTL.set(e); - } else { - lastExceptionThrownTL.set(newException); - throw newException; - } - } - } catch (Throwable t) { - t.initCause(e); - throw t; - } - if (e instanceof Error) { - throw (Error) e; - } - if (e instanceof RuntimeException) { - throw (RuntimeException) e; - } - throw new RuntimeException(e); - } - - private void updateFlags() { - DebugConfig config = getConfig(); - if (config == null) { - countEnabled = false; - memUseTrackingEnabled = false; - timeEnabled = false; - verifyEnabled = false; - currentDumpLevel = -1; - methodMetricsEnabled = false; - // Be pragmatic: provide a default log stream to prevent a crash if the stream is not - // set while logging - output = TTY.out; - } else { - countEnabled = config.isCountEnabled(); - memUseTrackingEnabled = config.isMemUseTrackingEnabled(); - timeEnabled = config.isTimeEnabled(); - verifyEnabled = config.isVerifyEnabled(); - output = config.output(); - currentDumpLevel = config.getDumpLevel(); - currentLogLevel = config.getLogLevel(); - methodMetricsEnabled = config.isMethodMeterEnabled(); - } - } - - @SuppressWarnings("try") - private RuntimeException interceptException(final Throwable e) { - final DebugConfig config = getConfig(); - if (config != null) { - try (DebugScope s = scope("InterceptException", null, e)) { - return config.interceptException(e); - } catch (Throwable t) { - return new RuntimeException("Exception while intercepting exception", t); - } - } - return null; - } - - private DebugValueMap getValueMap() { - if (valueMap == null) { - computeValueMap(unqualifiedName); - } - return valueMap; - } - - long getCurrentValue(int index) { - return getValueMap().getCurrentValue(index); - } - - void setCurrentValue(int index, long l) { - getValueMap().setCurrentValue(index, l); - } - - private DebugScope createChild(String newName, ExtraInfo newInfo, Object[] newContext) { - return new DebugScope(newName, this, this.scopeId, newInfo, false, newContext); - } - - private DebugScope createChild(String newName, ExtraInfo newInfo, long newId, Object[] newContext) { - return new DebugScope(newName, this, newId, newInfo, false, newContext); - } - - public Iterable getCurrentContext() { - final DebugScope scope = this; - return new Iterable() { - - @Override - public Iterator iterator() { - return new Iterator() { - - DebugScope currentScope = scope; - int objectIndex; - - @Override - public boolean hasNext() { - selectScope(); - return currentScope != null; - } - - private void selectScope() { - while (currentScope != null && currentScope.context.length <= objectIndex) { - currentScope = currentScope.sandbox ? null : currentScope.parent; - objectIndex = 0; - } - } - - @Override - public Object next() { - selectScope(); - if (currentScope != null) { - return currentScope.context[objectIndex++]; - } - throw new IllegalStateException("May only be called if there is a next element."); - } - - @Override - public void remove() { - throw new UnsupportedOperationException("This iterator is read only."); - } - }; - } - }; - } - - public static T call(Callable callable) { - try { - return callable.call(); - } catch (Exception e) { - if (e instanceof RuntimeException) { - throw (RuntimeException) e; - } else { - throw new RuntimeException(e); - } - } - } - - public void setConfig(DebugConfig newConfig) { - configTL.set(newConfig); - updateFlags(); - } - - public String getQualifiedName() { - if (qualifiedName == null) { - if (parent == null) { - qualifiedName = unqualifiedName; - } else { - qualifiedName = parent.getQualifiedName() + SCOPE_SEP + unqualifiedName; - } - } - return qualifiedName; - } - - public Indent pushIndentLogger() { - lastUsedIndent = getLastUsedIndent().indent(); - return lastUsedIndent; - } - - public IndentImpl getLastUsedIndent() { - if (lastUsedIndent == null) { - if (parent != null) { - lastUsedIndent = new IndentImpl(parent.getLastUsedIndent()); - } else { - lastUsedIndent = new IndentImpl(null); - } - } - return lastUsedIndent; - } -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugValue.java 2017-07-07 09:32:21.000000000 -0700 +++ /dev/null 2017-07-07 09:32:21.000000000 -0700 @@ -1,105 +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 org.graalvm.compiler.debug.internal; - -/** - * A name and index for a value managed in a thread local value map. All access to the value is made - * via a {@link DebugValue} instance. - */ -public abstract class DebugValue implements Comparable { - - private final String name; - private int index; - private boolean conditional; - - protected DebugValue(String name, boolean conditional) { - this.name = name; - this.index = -1; - this.conditional = conditional; - } - - public long getCurrentValue() { - ensureInitialized(); - return DebugScope.getInstance().getCurrentValue(index); - } - - protected void setCurrentValue(long l) { - ensureInitialized(); - DebugScope.getInstance().setCurrentValue(index, l); - } - - public void setConditional(boolean flag) { - conditional = flag; - } - - public boolean isConditional() { - return conditional; - } - - private void ensureInitialized() { - if (index == -1) { - index = KeyRegistry.register(this); - } - } - - protected void addToCurrentValue(long value) { - setCurrentValue(getCurrentValue() + value); - } - - /** - * Gets the globally unique index for the value represented by this object. - */ - public int getIndex() { - ensureInitialized(); - return index; - } - - /** - * Gets the globally unique name for the value represented by this object. - */ - public String getName() { - return name; - } - - @Override - public int compareTo(DebugValue o) { - return name.compareTo(o.name); - } - - @Override - public String toString() { - return name + "@" + index; - } - - public abstract String toString(long value); - - /** - * The raw unit of the value (e.g. 'us', 'ms'). Use {@code ""} if there is no unit. - */ - public abstract String rawUnit(); - - /** - * The raw value. - */ - public abstract String toRawString(long value); -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugValueMap.java 2017-07-07 09:32:21.000000000 -0700 +++ /dev/null 2017-07-07 09:32:21.000000000 -0700 @@ -1,176 +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 org.graalvm.compiler.debug.internal; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * A node in a tree of {@link DebugValue}s. - */ -public class DebugValueMap { - - private static final List topLevelMaps = new ArrayList<>(); - - private long[] values; - private List children; - private String name; - - public DebugValueMap(String name) { - this.name = name; - } - - public void setCurrentValue(int index, long l) { - ensureSize(index); - values[index] = l; - } - - public long getCurrentValue(int index) { - ensureSize(index); - return values[index]; - } - - public void clearChildren() { - if (children != null) { - children.clear(); - } - } - - public void reset() { - if (values != null) { - Arrays.fill(values, 0L); - } - if (children != null) { - for (DebugValueMap child : children) { - child.reset(); - } - } - } - - private void ensureSize(int index) { - if (values == null) { - values = new long[index + 1]; - } - if (values.length <= index) { - values = Arrays.copyOf(values, index + 1); - } - } - - private int capacity() { - return (values == null) ? 0 : values.length; - } - - public void addChild(DebugValueMap map) { - if (children == null) { - children = new ArrayList<>(4); - } - children.add(map); - } - - public List getChildren() { - if (children == null) { - return Collections.emptyList(); - } else { - return Collections.unmodifiableList(children); - } - } - - public boolean hasChildren() { - return children != null && !children.isEmpty(); - } - - public String getName() { - return this.name; - } - - @Override - public String toString() { - return "DebugValueMap<" + getName() + ">"; - } - - public static synchronized void registerTopLevel(DebugValueMap map) { - topLevelMaps.add(map); - } - - public static synchronized List getTopLevelMaps() { - return topLevelMaps; - } - - public void normalize() { - if (hasChildren()) { - Map occurred = new HashMap<>(); - for (DebugValueMap map : children) { - String mapName = map.getName(); - if (!occurred.containsKey(mapName)) { - occurred.put(mapName, map); - map.normalize(); - } else { - occurred.get(mapName).mergeWith(map); - occurred.get(mapName).normalize(); - } - } - - if (occurred.values().size() < children.size()) { - // At least one duplicate was found. - children.clear(); - for (DebugValueMap map : occurred.values()) { - addChild(map); - map.normalize(); - } - } - } - } - - private void mergeWith(DebugValueMap map) { - if (map.hasChildren()) { - if (hasChildren()) { - children.addAll(map.children); - } else { - children = map.children; - } - map.children = null; - } - - int size = Math.max(this.capacity(), map.capacity()); - ensureSize(size); - for (int i = 0; i < size; ++i) { - long curValue = getCurrentValue(i); - long otherValue = map.getCurrentValue(i); - setCurrentValue(i, curValue + otherValue); - } - } - - public void group() { - if (this.hasChildren()) { - List oldChildren = new ArrayList<>(this.children); - this.children.clear(); - for (DebugValueMap map : oldChildren) { - mergeWith(map); - } - } - } -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugValuesPrinter.java 2017-07-07 09:32:22.000000000 -0700 +++ /dev/null 2017-07-07 09:32:22.000000000 -0700 @@ -1,293 +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 org.graalvm.compiler.debug.internal; - -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.DebugValueFile; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.DebugValueHumanReadable; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.DebugValueSummary; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.DebugValueThreadFilter; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.SuppressZeroDebugValues; - -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.PrintStream; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.regex.Pattern; - -import org.graalvm.compiler.debug.CSVUtil; -import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.debug.LogStream; -import org.graalvm.compiler.debug.TTY; -import org.graalvm.compiler.debug.internal.method.MethodMetricsImpl; -import org.graalvm.compiler.debug.internal.method.MethodMetricsPrinter; -import org.graalvm.compiler.options.OptionValues; -import org.graalvm.util.CollectionsUtil; - -/** - * Facility for printing the {@linkplain KeyRegistry#getDebugValues() values} collected across all - * {@link DebugValueMap#getTopLevelMaps() threads}. - */ -public class DebugValuesPrinter { - private static final String COMPUTER_READABLE_FMT = CSVUtil.buildFormatString("%s", "%s", "%s", "%s"); - private static final char SCOPE_DELIMITER = '.'; - private final MethodMetricsPrinter mmPrinter; - - public DebugValuesPrinter() { - this(null); - } - - public DebugValuesPrinter(MethodMetricsPrinter mmPrinter) { - this.mmPrinter = mmPrinter; - } - - public void printDebugValues(OptionValues options) throws GraalError { - TTY.println(); - TTY.println(""); - List topLevelMaps = DebugValueMap.getTopLevelMaps(); - List debugValues = KeyRegistry.getDebugValues(); - if (debugValues.size() > 0) { - try { - ArrayList sortedValues = new ArrayList<>(debugValues); - Collections.sort(sortedValues); - - String summary = DebugValueSummary.getValue(options); - if (summary == null) { - summary = "Complete"; - } - if (DebugValueThreadFilter.getValue(options) != null && topLevelMaps.size() != 0) { - topLevelMaps = CollectionsUtil.filterToList(topLevelMaps, map -> Pattern.compile(DebugValueThreadFilter.getValue(options)).matcher(map.getName()).find()); - if (topLevelMaps.size() == 0) { - TTY.println("Warning: DebugValueThreadFilter=%s eliminated all maps so nothing will be printed", DebugValueThreadFilter.getValue(options)); - } - } - switch (summary) { - case "Name": { - LogStream log = getLogStream(options); - printSummary(options, log, topLevelMaps, sortedValues); - break; - } - case "Partial": { - DebugValueMap globalMap = new DebugValueMap("Global"); - for (DebugValueMap map : topLevelMaps) { - flattenChildren(map, globalMap); - } - globalMap.normalize(); - LogStream log = getLogStream(options); - printMap(options, log, new DebugValueScope(null, globalMap), sortedValues); - break; - } - case "Complete": { - DebugValueMap globalMap = new DebugValueMap("Global"); - for (DebugValueMap map : topLevelMaps) { - globalMap.addChild(map); - } - globalMap.group(); - globalMap.normalize(); - LogStream log = getLogStream(options); - printMap(options, log, new DebugValueScope(null, globalMap), sortedValues); - break; - } - case "Thread": - for (DebugValueMap map : topLevelMaps) { - TTY.println("Showing the results for thread: " + map.getName()); - map.group(); - map.normalize(); - LogStream log = getLogStream(options, map.getName().replace(' ', '_')); - printMap(options, log, new DebugValueScope(null, map), sortedValues); - } - break; - default: - throw new GraalError("Unknown summary type: %s", summary); - } - for (DebugValueMap topLevelMap : topLevelMaps) { - topLevelMap.reset(); - } - } catch (Throwable e) { - // Don't want this to change the exit status of the VM - PrintStream err = System.err; - err.println("Error while printing debug values:"); - e.printStackTrace(); - } - } - if (mmPrinter != null) { - mmPrinter.printMethodMetrics(MethodMetricsImpl.collectedMetrics()); - } - TTY.println(""); - } - - private static LogStream getLogStream(OptionValues options) { - return getLogStream(options, null); - } - - private static LogStream getLogStream(OptionValues options, String prefix) { - String debugValueFile = DebugValueFile.getValue(options); - if (debugValueFile != null) { - try { - final String fileName; - if (prefix != null) { - fileName = prefix + '-' + debugValueFile; - } else { - fileName = debugValueFile; - } - LogStream logStream = new LogStream(new FileOutputStream(fileName)); - TTY.println("Writing debug values to '%s'", fileName); - return logStream; - } catch (FileNotFoundException e) { - TTY.println("Warning: Could not open debug value log file: %s (defaulting to TTY)", e.getMessage()); - } - } - return TTY.out(); - } - - private void flattenChildren(DebugValueMap map, DebugValueMap globalMap) { - globalMap.addChild(map); - for (DebugValueMap child : map.getChildren()) { - flattenChildren(child, globalMap); - } - map.clearChildren(); - } - - private void printSummary(OptionValues options, LogStream log, List topLevelMaps, List debugValues) { - DebugValueMap result = new DebugValueMap("Summary"); - for (int i = debugValues.size() - 1; i >= 0; i--) { - DebugValue debugValue = debugValues.get(i); - int index = debugValue.getIndex(); - long total = collectTotal(topLevelMaps, index); - result.setCurrentValue(index, total); - } - printMap(options, log, new DebugValueScope(null, result), debugValues); - } - - private long collectTotal(List maps, int index) { - long total = 0; - for (int i = 0; i < maps.size(); i++) { - DebugValueMap map = maps.get(i); - total += map.getCurrentValue(index); - total += collectTotal(map.getChildren(), index); - } - return total; - } - - /** - * Tracks the scope when printing a {@link DebugValueMap}, allowing "empty" scopes to be - * omitted. An empty scope is one in which there are no (nested) non-zero debug values. - */ - static class DebugValueScope { - - final DebugValueScope parent; - final int level; - final DebugValueMap map; - private boolean printed; - - DebugValueScope(DebugValueScope parent, DebugValueMap map) { - this.parent = parent; - this.map = map; - this.level = parent == null ? 0 : parent.level + 1; - } - - public void print(LogStream log) { - if (!printed) { - printed = true; - if (parent != null) { - parent.print(log); - } - printIndent(log, level); - log.printf("%s%n", map.getName()); - } - } - - public String toRawString() { - return toRaw(new StringBuilder()).toString(); - } - - private StringBuilder toRaw(StringBuilder stringBuilder) { - final StringBuilder sb = (parent == null) ? stringBuilder : parent.toRaw(stringBuilder).append(SCOPE_DELIMITER); - return sb.append(map.getName()); - } - - } - - private void printMap(OptionValues options, LogStream log, DebugValueScope scope, List debugValues) { - if (DebugValueHumanReadable.getValue(options)) { - printMapHumanReadable(options, log, scope, debugValues); - } else { - printMapComputerReadable(options, log, scope, debugValues); - } - } - - private void printMapComputerReadable(OptionValues options, LogStream log, DebugValueScope scope, List debugValues) { - - for (DebugValue value : debugValues) { - long l = scope.map.getCurrentValue(value.getIndex()); - if (l != 0 || !SuppressZeroDebugValues.getValue(options)) { - CSVUtil.Escape.println(log, COMPUTER_READABLE_FMT, scope.toRawString(), value.getName(), value.toRawString(l), value.rawUnit()); - } - } - - List children = scope.map.getChildren(); - for (int i = 0; i < children.size(); i++) { - DebugValueMap child = children.get(i); - printMapComputerReadable(options, log, new DebugValueScope(scope, child), debugValues); - } - } - - private void printMapHumanReadable(OptionValues options, LogStream log, DebugValueScope scope, List debugValues) { - - for (DebugValue value : debugValues) { - long l = scope.map.getCurrentValue(value.getIndex()); - if (l != 0 || !SuppressZeroDebugValues.getValue(options)) { - scope.print(log); - printIndent(log, scope.level + 1); - log.println(value.getName() + "=" + value.toString(l)); - } - } - - List children = scope.map.getChildren(); - for (int i = 0; i < children.size(); i++) { - DebugValueMap child = children.get(i); - printMapHumanReadable(options, log, new DebugValueScope(scope, child), debugValues); - } - } - - private static void printIndent(LogStream log, int level) { - for (int i = 0; i < level; ++i) { - log.print(" "); - } - log.print("|-> "); - } - - public void clearDebugValues() { - List topLevelMaps = DebugValueMap.getTopLevelMaps(); - List debugValues = KeyRegistry.getDebugValues(); - if (debugValues.size() > 0) { - for (DebugValueMap map : topLevelMaps) { - map.reset(); - } - } - if (mmPrinter != null) { - MethodMetricsImpl.clearMM(); - } - } -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/KeyRegistry.java 2017-07-07 09:32:22.000000000 -0700 +++ /dev/null 2017-07-07 09:32:22.000000000 -0700 @@ -1,61 +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 org.graalvm.compiler.debug.internal; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Registry for allocating a globally unique integer id to each {@link DebugValue}. - */ -public class KeyRegistry { - - private static final Map keyMap = new HashMap<>(); - private static final List debugValues = new ArrayList<>(); - - /** - * Ensures a given debug value is registered. - * - * @return the globally unique id for {@code value} - */ - public static synchronized int register(DebugValue value) { - String name = value.getName(); - if (!keyMap.containsKey(name)) { - keyMap.put(name, debugValues.size()); - debugValues.add(value); - } - return keyMap.get(name); - } - - /** - * Gets a immutable view of the registered debug values. - * - * @return a list where {@code get(i).getIndex() == i} - */ - public static synchronized List getDebugValues() { - return Collections.unmodifiableList(debugValues); - } -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/MemUseTrackerImpl.java 2017-07-07 09:32:22.000000000 -0700 +++ /dev/null 2017-07-07 09:32:22.000000000 -0700 @@ -1,145 +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 org.graalvm.compiler.debug.internal; - -import static org.graalvm.compiler.debug.DebugCloseable.VOID_CLOSEABLE; - -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCloseable; -import org.graalvm.compiler.debug.DebugMemUseTracker; -import org.graalvm.compiler.debug.Management; -import org.graalvm.compiler.debug.internal.method.MethodMetricsImpl; - -public class MemUseTrackerImpl extends AccumulatedDebugValue implements DebugMemUseTracker { - private final boolean intercepting; - - public static long getCurrentThreadAllocatedBytes() { - return Management.getCurrentThreadAllocatedBytes(); - } - - /** - * Records the most recent active tracker. - */ - private static final ThreadLocal currentTracker = new ThreadLocal<>(); - - public MemUseTrackerImpl(String name, boolean conditional, boolean intercepting) { - super(name, conditional, new DebugValue(name + "_Flat", conditional) { - - @Override - public String toString(long value) { - return valueToString(value); - } - - @Override - public String rawUnit() { - return "B"; - } - - @Override - public String toRawString(long value) { - return Long.toString(value); - } - }); - this.intercepting = intercepting; - } - - @Override - public DebugCloseable start() { - if (!isConditional() || Debug.isMemUseTrackingEnabled()) { - CloseableCounterImpl result = intercepting ? new MemUseInterceptingCloseableCounterImpl(this) : new MemUseCloseableCounterImpl(this); - currentTracker.set(result); - return result; - } else { - return VOID_CLOSEABLE; - } - } - - public static String valueToString(long value) { - return String.format("%d bytes", value); - } - - @Override - public String toString(long value) { - return valueToString(value); - } - - private static final class MemUseCloseableCounterImpl extends CloseableCounterImpl implements DebugCloseable { - - private MemUseCloseableCounterImpl(AccumulatedDebugValue counter) { - super(currentTracker.get(), counter); - } - - @Override - long getCounterValue() { - return getCurrentThreadAllocatedBytes(); - } - - @Override - public void close() { - super.close(); - currentTracker.set(parent); - } - } - - private static final class MemUseInterceptingCloseableCounterImpl extends CloseableCounterImpl implements DebugCloseable { - - private MemUseInterceptingCloseableCounterImpl(AccumulatedDebugValue counter) { - super(currentTracker.get(), counter); - } - - @Override - long getCounterValue() { - return getCurrentThreadAllocatedBytes(); - } - - @Override - public void close() { - super.close(); - currentTracker.set(parent); - } - - @Override - protected void interceptDifferenceAccm(long difference) { - if (Debug.isMethodMeterEnabled()) { - MethodMetricsImpl.addToCurrentScopeMethodMetrics(counter.getName(), difference); - } - } - - @Override - protected void interceptDifferenceFlat(long difference) { - if (Debug.isMethodMeterEnabled()) { - MethodMetricsImpl.addToCurrentScopeMethodMetrics(counter.flat.getName(), difference); - } - } - } - - @Override - public String rawUnit() { - return "B"; - } - - @Override - public String toRawString(long value) { - return Long.toString(value); - } -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/TimerImpl.java 2017-07-07 09:32:23.000000000 -0700 +++ /dev/null 2017-07-07 09:32:23.000000000 -0700 @@ -1,178 +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 org.graalvm.compiler.debug.internal; - -import static org.graalvm.compiler.debug.DebugCloseable.VOID_CLOSEABLE; - -import java.util.concurrent.TimeUnit; - -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCloseable; -import org.graalvm.compiler.debug.DebugTimer; -import org.graalvm.compiler.debug.TimeSource; -import org.graalvm.compiler.debug.internal.method.MethodMetricsImpl; - -public final class TimerImpl extends AccumulatedDebugValue implements DebugTimer { - private final boolean intercepting; - - /** - * Records the most recent active timer. - */ - private static final ThreadLocal currentTimer = new ThreadLocal<>(); - - static class FlatTimer extends DebugValue implements DebugTimer { - private TimerImpl accm; - - FlatTimer(String name, boolean conditional) { - super(name + "_Flat", conditional); - } - - @Override - public String toString(long value) { - return valueToString(value); - } - - @Override - public TimeUnit getTimeUnit() { - return accm.getTimeUnit(); - } - - @Override - public DebugCloseable start() { - return accm.start(); - } - - @Override - public String rawUnit() { - return "us"; - } - - @Override - public String toRawString(long value) { - return valueToRawString(value); - } - } - - public TimerImpl(String name, boolean conditional, boolean intercepting) { - super(name, conditional, new FlatTimer(name, conditional)); - ((FlatTimer) flat).accm = this; - this.intercepting = intercepting; - } - - @Override - public DebugCloseable start() { - if (!isConditional() || Debug.isTimeEnabled()) { - AbstractTimer result = intercepting ? new InterceptingTimer(this) : new Timer(this); - currentTimer.set(result); - return result; - } else { - return VOID_CLOSEABLE; - } - } - - public static String valueToString(long value) { - return String.format("%d.%d ms", value / 1000000, (value / 100000) % 10); - } - - @Override - public DebugTimer getFlat() { - return (FlatTimer) flat; - } - - @Override - public String toString(long value) { - return valueToString(value); - } - - @Override - public TimeUnit getTimeUnit() { - return TimeUnit.NANOSECONDS; - } - - private abstract class AbstractTimer extends CloseableCounterImpl implements DebugCloseable { - - private AbstractTimer(AccumulatedDebugValue counter) { - super(currentTimer.get(), counter); - } - - @Override - public void close() { - super.close(); - currentTimer.set(parent); - } - } - - private final class Timer extends AbstractTimer { - - private Timer(TimerImpl timer) { - super(timer); - } - - @Override - protected long getCounterValue() { - return TimeSource.getTimeNS(); - } - - } - - private final class InterceptingTimer extends AbstractTimer { - - private InterceptingTimer(TimerImpl timer) { - super(timer); - } - - @Override - protected long getCounterValue() { - return TimeSource.getTimeNS(); - } - - @Override - protected void interceptDifferenceAccm(long difference) { - if (Debug.isMethodMeterEnabled()) { - MethodMetricsImpl.addToCurrentScopeMethodMetrics(counter.getName(), difference); - } - } - - @Override - protected void interceptDifferenceFlat(long difference) { - if (Debug.isMethodMeterEnabled()) { - MethodMetricsImpl.addToCurrentScopeMethodMetrics(counter.flat.getName(), difference); - } - } - } - - @Override - public String rawUnit() { - return "us"; - } - - @Override - public String toRawString(long value) { - return valueToRawString(value); - } - - public static String valueToRawString(long value) { - return Long.toString(value / 1000); - } - -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsImpl.java 2017-07-07 09:32:23.000000000 -0700 +++ /dev/null 2017-07-07 09:32:23.000000000 -0700 @@ -1,444 +0,0 @@ -/* - * Copyright (c) 2015, 2016, 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 org.graalvm.compiler.debug.internal.method; - -import java.io.PrintStream; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -import org.graalvm.compiler.debug.CSVUtil; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; -import org.graalvm.compiler.debug.DebugMethodMetrics; -import org.graalvm.compiler.debug.GraalDebugConfig; -import org.graalvm.compiler.debug.internal.DebugScope; - -import jdk.vm.ci.meta.ResolvedJavaMethod; - -public class MethodMetricsImpl implements DebugMethodMetrics { - - /** - * A list capturing all method metrics data of all the compiler threads. Every thread registers - * a reference to its thread local map of compilation metrics in this list. During metrics - * dumping this list is globally locked and all method entries across all threads are merged to - * a result. - */ - private static final List> threadMaps = new ArrayList<>(); - /** - * Every compiler thread carries its own map of metric data for each method and compilation it - * compiles. This data is stored in {@link ThreadLocal} maps for each compiler thread that are - * merged before metrics are reported. Storing compilation data thread locally reduces the - * locking on access of a method metric object to one point for each thread, the first access - * where the thread local is initialized. - */ - private static final ThreadLocal> threadEntries = new ThreadLocal<>(); - /** - * The lowest debug scope id that should be used during metric dumping. When a bootstrap is run - * all compilations during bootstrap are also collected if the associated debug filters match. - * Data collected during bootstrap should normally not be included in metrics for application - * compilation, thus every compilation lower than this index is ignored during metric dumping. - */ - private static long lowestCompilationDebugScopeId; - - public static class CompilationData { - /** - * A mapping of graph ids (unique ids used for the caching) to compilations. - */ - private final Map> compilations; - /** - * A pointer to a {@code MethodMetricsImpl} object. This reference is created once for every - * compilation of a method (and once for each thread, i.e. if method a is compiled by 8 - * compiler threads there will be 8 metrics objects for the given method, one local to every - * thread, this avoids synchronizing on the metrics object on every access) accessing method - * metrics for a given method. - */ - private final MethodMetricsImpl metrics; - - CompilationData(ResolvedJavaMethod method) { - compilations = new HashMap<>(8); - metrics = new MethodMetricsImpl(method); - } - - public Map> getCompilations() { - return compilations; - } - } - - private static void addThreadCompilationData(Map threadMap) { - synchronized (threadMaps) { - threadMaps.add(threadMap); - } - } - - /** - * A reference to the {@link ResolvedJavaMethod} method object. This object's identity is used - * to store metrics for each compilation. - */ - private final ResolvedJavaMethod method; - /** - * A list of all recorded compilations. This is generated during metric dumping when all thread - * local metrics are merged into one final method metrics object that is than reported - */ - private List>> collected; - /** - * A pointer to the current compilation data for the {@link MethodMetricsImpl#method} method - * which allows to avoid synchronizing over the compilation data. This reference changes for - * each compilation of the given method. It is set on the first access of this - * {@link MethodMetricsImpl} object during the call to - * {@link MethodMetricsImpl#getMethodMetrics(ResolvedJavaMethod)}. - */ - private Map currentCompilation; - - MethodMetricsImpl(ResolvedJavaMethod method) { - this.method = method; - } - - private static void clearData() { - lowestCompilationDebugScopeId = DebugScope.getCurrentGlobalScopeId(); - } - - @Override - public void addToMetric(long value, String metricName) { - if (!Debug.isMethodMeterEnabled() || value == 0) { - return; - } - assert metricName != null; - Long valueStored = currentCompilation.get(metricName); - currentCompilation.put(metricName, valueStored == null ? value : value + valueStored); - } - - @Override - public long getCurrentMetricValue(String metricName) { - assert metricName != null; - Long valueStored = currentCompilation.get(metricName); - return valueStored == null ? 0 : valueStored; - } - - @Override - public void addToMetric(long value, String format, Object arg1) { - addToMetric(value, String.format(format, arg1)); - } - - @Override - public void addToMetric(long value, String format, Object arg1, Object arg2) { - addToMetric(value, String.format(format, arg1, arg2)); - } - - @Override - public void addToMetric(long value, String format, Object arg1, Object arg2, Object arg3) { - addToMetric(value, String.format(format, arg1, arg2, arg3)); - } - - @Override - public void incrementMetric(String metricName) { - addToMetric(1, metricName); - } - - @Override - public void incrementMetric(String format, Object arg1) { - incrementMetric(String.format(format, arg1)); - } - - @Override - public void incrementMetric(String format, Object arg1, Object arg2) { - incrementMetric(String.format(format, arg1, arg2)); - } - - @Override - public void incrementMetric(String format, Object arg1, Object arg2, Object arg3) { - incrementMetric(String.format(format, arg1, arg2, arg3)); - } - - @Override - public long getCurrentMetricValue(String format, Object arg1) { - return getCurrentMetricValue(String.format(format, arg1)); - } - - @Override - public long getCurrentMetricValue(String format, Object arg1, Object arg2) { - return getCurrentMetricValue(String.format(format, arg1, arg2)); - } - - @Override - public long getCurrentMetricValue(String format, Object arg1, Object arg2, Object arg3) { - return getCurrentMetricValue(String.format(format, arg1, arg2, arg3)); - } - - @Override - public ResolvedJavaMethod getMethod() { - return method; - } - - public static DebugMethodMetrics getMethodMetrics(ResolvedJavaMethod method) { - assert method != null; - Map threadCache = threadEntries.get(); - if (threadCache == null) { - // this branch will only be executed once for each compiler thread on the first request - // of a method metric - threadCache = new HashMap<>(GraalDebugConfig.Options.MethodFilter.getValue(DebugScope.getConfig().getOptions()) == null ? 128 : 16); - threadEntries.set(threadCache); - addThreadCompilationData(threadCache); - } - - CompilationData recorded = threadCache.get(method); - if (recorded == null) { - recorded = new CompilationData(method); - threadCache.put(method, recorded); - } - // pre-generate the current compilation map to avoid doing it later every time we add to a - // metric or read a current metric's value - long compilationId = DebugScope.getInstance().scopeId(); - Map currentCompilation = recorded.compilations.get(compilationId); - if (currentCompilation == null) { - // this map is generated for every distinct compilation of a unique method - currentCompilation = new HashMap<>(32); - recorded.compilations.put(compilationId, currentCompilation); - // we remember a reference to the current compilation to avoid the expensive lookup - recorded.metrics.currentCompilation = currentCompilation; - } - - return recorded.metrics; - } - - public void dumpASCII(PrintStream p) { - // we need to lock the threadmap as a concurrent call to #collectedMetrics can change the - // content of this#collected - synchronized (threadMaps) { - String methodName = method.toString(); - int maxLen = methodName.length(); - int entrySum = 0; - // get the longest entry - for (Map> compilationThreadTable : collected) { - for (Map.Entry> compilationEntry : compilationThreadTable.entrySet()) { - Map table = compilationEntry.getValue(); - if (table != null) { - for (Map.Entry entry : table.entrySet()) { - maxLen = Math.max(maxLen, entry.getKey().length()); - entrySum += entry.getValue(); - } - } - } - } - if (entrySum == 0) { - // nothing to report - return; - } - maxLen += 23; - for (int j = 0; j < maxLen; j++) { - p.print("#"); - } - p.println(); - p.println(methodName); - for (int j = 0; j < maxLen; j++) { - p.print("~"); - } - p.println(); - for (Map> compilationThreadTable : collected) { - for (Map.Entry> compilationEntry : compilationThreadTable.entrySet()) { - Map table = compilationEntry.getValue(); - if (table != null) { - if (table.values().stream().filter(x -> x > 0).count() == 0) { - continue; - } - Set> entries = table.entrySet(); - for (Map.Entry entry : entries.stream().sorted((x, y) -> x.getKey().compareTo(y.getKey())).collect(Collectors.toList())) { - long value = entry.getValue(); - // report timers in ms and memory in mb - if ((entry.getKey().endsWith("Accm") || entry.getKey().endsWith("Flat")) && - !entry.getKey().toLowerCase().contains("mem")) { - value = value / 1000000; - } - if (value == 0) { - continue; - } - p.print(String.format("%-" + String.valueOf(maxLen - 23) + "s = %20d", entry.getKey(), value)); - p.println(); - } - for (int j = 0; j < maxLen; j++) { - p.print("~"); - } - p.println(); - } - } - } - for (int j = 0; j < maxLen; j++) { - p.print("#"); - } - p.println(); - } - } - - private static final String FMT = CSVUtil.buildFormatString("%s", "%s", "%d", "%d", "%s", "%d"); - - public void dumpCSV(PrintStream p) { - // we need to lock the threadmap as a concurrent call to #collectedMetrics can change - // the content of this#collected - synchronized (threadMaps) { - String methodName = method.format("%H.%n(%p)%R"); - /* - * NOTE: the caching mechanism works by caching compilation data based on the identity - * of the resolved java method object. The identity is based on the metaspace address of - * the resolved java method object. If the class was loaded by different class loaders - * or e.g. loaded - unloaded - loaded the identity will be different. Therefore we also - * need to include the identity in the reporting of the data as it is an additional - * dimension to . - */ - String methodIdentity = String.valueOf(System.identityHashCode(method)); - int nrOfCompilations = 0; - for (Map> compilationThreadTable : collected) { - for (Map.Entry> compilationEntry : compilationThreadTable.entrySet()) { - Map table = compilationEntry.getValue(); - if (table != null) { - Set> entries = table.entrySet(); - for (Map.Entry entry : entries.stream().sorted((x, y) -> x.getKey().compareTo(y.getKey())).collect(Collectors.toList())) { - CSVUtil.Escape.println(p, FMT, methodName, methodIdentity, nrOfCompilations, compilationEntry.getKey(), entry.getKey(), entry.getValue()); - } - nrOfCompilations++; - } - } - } - } - } - - public static Collection collectedMetrics() { - synchronized (threadMaps) { - // imprecise excluding all compilations that follow, we simply do not report them - final long lastId = DebugScope.getCurrentGlobalScopeId(); - List finalMetrics = new ArrayList<>(); - Set methods = new HashSet<>(); - - // gather all methods we found - threadMaps.forEach(x -> { - // snapshot the current compilations to only capture all methods compiled until now - HashMap snapShot = new HashMap<>(x); - snapShot.keySet().forEach(y -> methods.add(y)); - }); - - // for each method gather all metrics we want to report - for (ResolvedJavaMethod method : methods) { - MethodMetricsImpl impl = new MethodMetricsImpl(method); - impl.collected = new ArrayList<>(); - for (Map threadMap : threadMaps) { - CompilationData threadMethodData = threadMap.get(method); - - // not every method is necessarily compiled by all threads - if (threadMethodData != null) { - Map> snapshot = new HashMap<>(threadMethodData.compilations); - for (Map.Entry> entry : snapshot.entrySet()) { - if (entry.getKey() < lowestCompilationDebugScopeId || entry.getKey() > lastId) { - entry.setValue(null); - } - } - impl.collected.add(snapshot); - } - } - finalMetrics.add(impl); - } - - return finalMetrics; - } - } - - public static void clearMM() { - clearData(); - } - - private static final String INLINEE_PREFIX = "INLINING_SCOPE_"; - private static final boolean TRACK_INLINED_SCOPES = false; - - public static void recordInlinee(ResolvedJavaMethod root, ResolvedJavaMethod caller, ResolvedJavaMethod inlinee) { - if (TRACK_INLINED_SCOPES) { - Debug.methodMetrics(root).addToMetric(1, "INLINED_METHOD_root: caller:%s inlinee:%s", caller, inlinee); - } - } - - private static final boolean COUNT_CACHE = false; - private static final String HIT_MSG = "InterceptionCache_Hit"; - private static final String MISS_MSG = "InterceptionCache_Miss"; - private static final DebugCounter cacheHit = Debug.counter(HIT_MSG); - private static final DebugCounter cacheMiss = Debug.counter(MISS_MSG); - /** - * To avoid the lookup of a method metrics through the - * {@link MethodMetricsImpl#getMethodMetrics(ResolvedJavaMethod)} method on every global metric - * interception we thread-locally cache the last (through metric interception) - * {@link MethodMetricsImpl} object. This avoids additional map lookups and replaces them with a - * {@link DebugScope#scopeId()} call and a numerical comparison in a cache hit case. - */ - private static final ThreadLocal interceptionCache = new ThreadLocal<>(); - private static final ThreadLocal interceptionMetrics = new ThreadLocal<>(); - - public static void addToCurrentScopeMethodMetrics(String metricName, long value) { - if (COUNT_CACHE) { - if (metricName.equals(HIT_MSG) || metricName.equals(MISS_MSG)) { - return; - } - } - final DebugScope currScope = DebugScope.getInstance(); - final DebugScope.ExtraInfo metaInfo = currScope.getExtraInfo(); - final long currScopeId = currScope.scopeId(); - if (metaInfo instanceof MethodMetricsRootScopeInfo) { - ResolvedJavaMethod rootMethod = ((MethodMetricsRootScopeInfo) metaInfo).getRootMethod(); - if (metaInfo instanceof MethodMetricsInlineeScopeInfo) { - /* - * if we make use of a method filter(s) together with interception we get a problem - * with inlined methods and their scopes. Inlining will put the inlinee(s) on the - * debug scope context thus Debug.areMethodMetricsEnabled() will yield true if an - * inlinee matches a method filter. Thus we must make sure the root is defined as - * this means the root matched a method filter and therefore the inlinee can be - * safely recorded. - */ - if (TRACK_INLINED_SCOPES) { - if (threadEntries.get().get(rootMethod) != null) { - Debug.methodMetrics(rootMethod).addToMetric(value, "%s%s", INLINEE_PREFIX, metricName); - } - } - } else { - // when unboxing the thread local on access it must not be null - Long cachedId = interceptionCache.get(); - if (cachedId != null && cachedId == currScopeId) { - interceptionMetrics.get().addToMetric(value, metricName); - if (COUNT_CACHE) { - cacheHit.increment(); - } - } else { - // avoid the lookup over Debug.methodMetrics - final MethodMetricsImpl impl = (MethodMetricsImpl) getMethodMetrics(rootMethod); - impl.addToMetric(value, metricName); - // cache for next access - interceptionCache.set(currScopeId); - interceptionMetrics.set(impl); - if (COUNT_CACHE) { - cacheMiss.increment(); - } - } - } - } - } - -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsInlineeScopeInfo.java 2017-07-07 09:32:23.000000000 -0700 +++ /dev/null 2017-07-07 09:32:23.000000000 -0700 @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2015, 2016, 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 org.graalvm.compiler.debug.internal.method; - -import org.graalvm.compiler.debug.GraalDebugConfig; -import org.graalvm.compiler.debug.internal.DebugScope; -import org.graalvm.compiler.debug.internal.DebugScope.ExtraInfo; -import org.graalvm.compiler.options.OptionValues; - -import jdk.vm.ci.meta.ResolvedJavaMethod; - -public class MethodMetricsInlineeScopeInfo extends MethodMetricsRootScopeInfo { - - MethodMetricsInlineeScopeInfo(ResolvedJavaMethod rootMethod) { - super(rootMethod); - } - - public static MethodMetricsInlineeScopeInfo create(ResolvedJavaMethod rootMethod, OptionValues options) { - if (GraalDebugConfig.isGlobalMetricsInterceptedByMethodMetricsEnabled(options)) { - return new MethodMetricsInlineeScopeInfo(rootMethod); - } - return null; - } - - public static MethodMetricsInlineeScopeInfo create(OptionValues options) { - if (GraalDebugConfig.isGlobalMetricsInterceptedByMethodMetricsEnabled(options)) { - ExtraInfo rootInfo = DebugScope.getInstance().getExtraInfo(); - if (rootInfo instanceof MethodMetricsRootScopeInfo) { - return new MethodMetricsInlineeScopeInfo(((MethodMetricsRootScopeInfo) rootInfo).getRootMethod()); - } - } - return null; - } - -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsPrinter.java 2017-07-07 09:32:24.000000000 -0700 +++ /dev/null 2017-07-07 09:32:24.000000000 -0700 @@ -1,143 +0,0 @@ -/* - * Copyright (c) 2015, 2016, 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 org.graalvm.compiler.debug.internal.method; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.io.PrintStream; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; - -import org.graalvm.compiler.debug.DebugMethodMetrics; -import org.graalvm.compiler.debug.TTY; -import org.graalvm.compiler.debug.internal.DebugScope; -import org.graalvm.compiler.options.Option; -import org.graalvm.compiler.options.OptionKey; -import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValues; - -/** - * Interface for printing a collection of method metrics (e.g. during shutdown). - */ -public interface MethodMetricsPrinter { - - class Options { - // @formatter:off - @Option(help = "Dump method metrics to stdout on shutdown.", type = OptionType.Debug) - public static final OptionKey MethodMeterPrintAscii = new OptionKey<>(false); - @Option(help = "Dump method metrics to the given file in CSV format on shutdown.", type = OptionType.Debug) - public static final OptionKey MethodMeterFile = new OptionKey<>(null); - // @formatter:on - } - - static boolean methodMetricsDumpingEnabled(OptionValues options) { - return MethodMetricsPrinter.Options.MethodMeterPrintAscii.getValue(options) || MethodMetricsPrinter.Options.MethodMeterFile.getValue(options) != null; - } - - /** - * Prints the metrics to a destination specified by the implementor of this interface. - * - * @param metrics the set of collected method metrics during execution as defined by - * {@link DebugMethodMetrics}. - */ - void printMethodMetrics(Collection metrics); - - class MethodMetricsASCIIPrinter implements MethodMetricsPrinter { - private final OutputStream out; - - public MethodMetricsASCIIPrinter(OutputStream out) { - this.out = out; - } - - @Override - public void printMethodMetrics(Collection metrics) { - PrintStream p = new PrintStream(out); - for (DebugMethodMetrics m : metrics) { - ((MethodMetricsImpl) m).dumpASCII(p); - p.println(); - } - } - - } - - class MethodMetricsCompositePrinter implements MethodMetricsPrinter { - private final List printers; - - public MethodMetricsCompositePrinter(MethodMetricsPrinter... p) { - printers = Arrays.asList(p); - } - - public void registerPrinter(MethodMetricsPrinter printer) { - printers.add(printer); - } - - public void unregisterPrinter(MethodMetricsPrinter printer) { - printers.remove(printer); - } - - @Override - public void printMethodMetrics(Collection metrics) { - for (MethodMetricsPrinter p : printers) { - p.printMethodMetrics(metrics); - } - } - - } - - class MethodMetricsCSVFilePrinter implements MethodMetricsPrinter { - private FileOutputStream fw; - - public MethodMetricsCSVFilePrinter() { - try { - fw = new FileOutputStream(new File(Options.MethodMeterFile.getValue(DebugScope.getConfig().getOptions()))); - } catch (IOException e) { - TTY.println("Cannot create file %s for method metrics dumping:%s", Options.MethodMeterFile.getValue(DebugScope.getConfig().getOptions()), e); - throw new Error(e); - } - } - - @Override - public void printMethodMetrics(Collection metrics) { - // mm printing creates simple (R-parsable) csv files in long data format - if (fw != null && metrics != null) { - try (PrintStream p = new PrintStream(fw)) { - for (DebugMethodMetrics m : metrics) { - if (m instanceof MethodMetricsImpl) { - ((MethodMetricsImpl) m).dumpCSV(p); - p.println(); - } - } - } - try { - fw.close(); - } catch (IOException e) { - throw new Error(e); - } - } - } - - } -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsRootScopeInfo.java 2017-07-07 09:32:24.000000000 -0700 +++ /dev/null 2017-07-07 09:32:24.000000000 -0700 @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2015, 2016, 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 org.graalvm.compiler.debug.internal.method; - -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.internal.DebugScope; -import org.graalvm.compiler.debug.internal.DebugScope.ExtraInfo; - -import jdk.vm.ci.meta.ResolvedJavaMethod; - -public class MethodMetricsRootScopeInfo implements ExtraInfo { - protected final ResolvedJavaMethod rootMethod; - - MethodMetricsRootScopeInfo(ResolvedJavaMethod rootMethod) { - this.rootMethod = rootMethod; - } - - public ResolvedJavaMethod getRootMethod() { - return rootMethod; - } - - public static MethodMetricsRootScopeInfo create(ResolvedJavaMethod rootMethod) { - return new MethodMetricsRootScopeInfo(rootMethod); - } - - /** - * Creates and returns a {@link org.graalvm.compiler.debug.Debug.Scope scope} iff there is no - * existing {@linkplain org.graalvm.compiler.debug.internal.DebugScope.ExtraInfo extraInfo} - * object of type {@link MethodMetricsRootScopeInfo} present in the current {@link DebugScope - * scope}. - * - * @param method - * @return a new {@link org.graalvm.compiler.debug.Debug.Scope scope} or {@code null} iff there - * is already an existing one on the scope - */ - public static Debug.Scope createRootScopeIfAbsent(ResolvedJavaMethod method) { - if (Debug.isEnabled()) { - /* - * if the current compilation is not triggered from JVMCI we need a valid context root - * method for method metrics - */ - return DebugScope.getInstance().getExtraInfo() instanceof MethodMetricsRootScopeInfo ? null - : Debug.methodMetricsScope("GraalCompilerRoot", MethodMetricsRootScopeInfo.create(method), true); - } else { - return null; - } - } - -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/FingerprintUtil.java 2017-07-07 09:32:24.000000000 -0700 +++ /dev/null 2017-07-07 09:32:24.000000000 -0700 @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2016, 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 org.graalvm.compiler.hotspot; - -import java.lang.reflect.Method; - -import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; - -/** - * Reflective wrapper around the fingerprint generation functionality in JDK9. - */ -public class FingerprintUtil { - private static Method getFingerprint; - static { - try { - getFingerprint = HotSpotResolvedObjectType.class.getMethod("getFingerprint"); - } catch (Exception e) { - } - } - - public static long getFingerprint(HotSpotResolvedObjectType type) { - if (getFingerprint != null) { - try { - return ((Long) getFingerprint.invoke(type)).longValue(); - } catch (Exception e) { - } - } - return 0; - } -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/UniquePathUtilities.java 2017-07-07 09:32:25.000000000 -0700 +++ /dev/null 2017-07-07 09:32:25.000000000 -0700 @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2016, 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 org.graalvm.compiler.options; - -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.HashMap; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; - -public class UniquePathUtilities { - - private static final AtomicLong globalTimeStamp = new AtomicLong(); - /** - * This generates a per thread persistent id to aid mapping related dump files with each other. - */ - private static final ThreadLocal threadDumpId = new ThreadLocal<>(); - private static final AtomicInteger dumpId = new AtomicInteger(); - - static class PerThreadSequence { - final int threadID; - HashMap sequences = new HashMap<>(2); - - PerThreadSequence(int threadID) { - this.threadID = threadID; - } - - String generateID(String extension) { - Integer box = sequences.get(extension); - if (box == null) { - sequences.put(extension, 1); - return Integer.toString(threadID); - } else { - sequences.put(extension, box + 1); - return Integer.toString(threadID) + '-' + box; - } - } - } - - private static String getThreadDumpId(String extension) { - PerThreadSequence id = threadDumpId.get(); - if (id == null) { - id = new PerThreadSequence(dumpId.incrementAndGet()); - threadDumpId.set(id); - } - return id.generateID(extension); - } - - private static String formatExtension(String ext) { - if (ext == null || ext.length() == 0) { - return ""; - } - return "." + ext; - } - - public static long getGlobalTimeStamp() { - if (globalTimeStamp.get() == 0) { - globalTimeStamp.compareAndSet(0, System.currentTimeMillis()); - } - return globalTimeStamp.get(); - } - - /** - * Generates a {@link Path} using the format "%s-%d_%d%s" with the {@link OptionKey#getValue - * base filename}, a {@link #globalTimeStamp global timestamp} , {@link #getThreadDumpId a per - * thread unique id} and an optional {@code extension}. - * - * @return the output file path or null if the flag is null - */ - public static Path getPath(OptionValues options, OptionKey option, OptionKey defaultDirectory, String extension) { - return getPath(options, option, defaultDirectory, extension, true); - } - - /** - * Generate a {@link Path} using the format "%s-%d_%s" with the {@link OptionKey#getValue base - * filename}, a {@link #globalTimeStamp global timestamp} and an optional {@code extension} . - * - * @return the output file path or null if the flag is null - */ - public static Path getPathGlobal(OptionValues options, OptionKey option, OptionKey defaultDirectory, String extension) { - return getPath(options, option, defaultDirectory, extension, false); - } - - private static Path getPath(OptionValues options, OptionKey option, OptionKey defaultDirectory, String extension, boolean includeThreadId) { - if (option.getValue(options) == null) { - return null; - } - String ext = formatExtension(extension); - final String name = includeThreadId - ? String.format("%s-%d_%s%s", option.getValue(options), getGlobalTimeStamp(), getThreadDumpId(ext), ext) - : String.format("%s-%d%s", option.getValue(options), getGlobalTimeStamp(), ext); - Path result = Paths.get(name); - if (result.isAbsolute() || defaultDirectory == null) { - return result; - } - return Paths.get(defaultDirectory.getValue(options), name).normalize(); - } -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraalDebugConfigCustomizer.java 2017-07-07 09:32:25.000000000 -0700 +++ /dev/null 2017-07-07 09:32:25.000000000 -0700 @@ -1,159 +0,0 @@ -/* - * 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 org.graalvm.compiler.printer; - -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.DumpPath; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.PrintBinaryGraphPort; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.PrintBinaryGraphs; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.PrintCanonicalGraphStringsDirectory; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.PrintGraphHost; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.PrintGraphFileName; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.PrintXmlGraphPort; - -import java.io.IOException; -import java.io.InterruptedIOException; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.nio.channels.ClosedByInterruptException; -import java.nio.channels.FileChannel; -import java.nio.channels.SocketChannel; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.StandardOpenOption; - -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugConfig; -import org.graalvm.compiler.debug.DebugConfigCustomizer; -import org.graalvm.compiler.debug.DebugDumpHandler; -import org.graalvm.compiler.debug.GraalDebugConfig.Options; -import org.graalvm.compiler.debug.TTY; -import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.nodeinfo.Verbosity; -import org.graalvm.compiler.nodes.util.GraphUtil; -import org.graalvm.compiler.options.OptionValues; -import org.graalvm.compiler.options.UniquePathUtilities; -import org.graalvm.compiler.serviceprovider.ServiceProvider; - -@ServiceProvider(DebugConfigCustomizer.class) -public class GraalDebugConfigCustomizer implements DebugConfigCustomizer { - - @Override - public void customize(DebugConfig config) { - OptionValues options = config.getOptions(); - if (Options.PrintGraphFile.getValue(options)) { - config.dumpHandlers().add(new GraphPrinterDumpHandler(() -> createFilePrinter(options))); - } else { - config.dumpHandlers().add(new GraphPrinterDumpHandler(() -> createNetworkPrinter(options))); - } - if (Options.PrintCanonicalGraphStrings.getValue(options)) { - config.dumpHandlers().add(new GraphPrinterDumpHandler(() -> createStringPrinter(options))); - } - config.dumpHandlers().add(new NodeDumper()); - if (Options.PrintCFG.getValue(options) || Options.PrintBackendCFG.getValue(options)) { - if (Options.PrintBinaryGraphs.getValue(options) && Options.PrintCFG.getValue(options)) { - TTY.out.println("Complete C1Visualizer dumping slows down PrintBinaryGraphs: use -Dgraal.PrintCFG=false to disable it"); - } - config.dumpHandlers().add(new CFGPrinterObserver(Options.PrintCFG.getValue(options))); - } - config.verifyHandlers().add(new NoDeadCodeVerifyHandler()); - } - - private static class NodeDumper implements DebugDumpHandler { - @Override - public void dump(Object object, String format, Object... arguments) { - if (object instanceof Node) { - String location = GraphUtil.approxSourceLocation((Node) object); - String node = ((Node) object).toString(Verbosity.Debugger); - if (location != null) { - Debug.log("Context obj %s (approx. location: %s)", node, location); - } else { - Debug.log("Context obj %s", node); - } - } - } - - @Override - public void close() { - } - - @Override - public void addCapability(Object capability) { - } - } - - private static CanonicalStringGraphPrinter createStringPrinter(OptionValues options) { - // Construct the path to the directory. - Path path = UniquePathUtilities.getPath(options, PrintCanonicalGraphStringsDirectory, Options.DumpPath, ""); - return new CanonicalStringGraphPrinter(path); - } - - private static GraphPrinter createNetworkPrinter(OptionValues options) throws IOException { - String host = PrintGraphHost.getValue(options); - int port = PrintBinaryGraphs.getValue(options) ? PrintBinaryGraphPort.getValue(options) : PrintXmlGraphPort.getValue(options); - try { - GraphPrinter printer; - if (Options.PrintBinaryGraphs.getValue(options)) { - printer = new BinaryGraphPrinter(SocketChannel.open(new InetSocketAddress(host, port))); - } else { - printer = new IdealGraphPrinter(new Socket(host, port).getOutputStream(), true); - } - TTY.println("Connected to the IGV on %s:%d", host, port); - return printer; - } catch (ClosedByInterruptException | InterruptedIOException e) { - /* - * Interrupts should not count as errors because they may be caused by a cancelled Graal - * compilation. ClosedByInterruptException occurs if the SocketChannel could not be - * opened. InterruptedIOException occurs if new Socket(..) was interrupted. - */ - return null; - } catch (IOException e) { - if (!Options.PrintGraphFile.hasBeenSet(options)) { - TTY.println(String.format("Could not connect to the IGV on %s:%d - falling back to file dumping...", host, port)); - return createFilePrinter(options); - } else { - throw new IOException(String.format("Could not connect to the IGV on %s:%d", host, port), e); - } - } - } - - private static Path getFilePrinterPath(OptionValues options) { - // Construct the path to the file. - return UniquePathUtilities.getPath(options, PrintGraphFileName, DumpPath, PrintBinaryGraphs.getValue(options) ? "bgv" : "gv.xml"); - } - - private static GraphPrinter createFilePrinter(OptionValues options) throws IOException { - Path path = getFilePrinterPath(options); - try { - GraphPrinter printer; - if (Options.PrintBinaryGraphs.getValue(options)) { - printer = new BinaryGraphPrinter(FileChannel.open(path, StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW)); - } else { - printer = new IdealGraphPrinter(Files.newOutputStream(path), true); - } - TTY.println("Dumping IGV graphs to %s", path.toAbsolutePath().toString()); - return printer; - } catch (IOException e) { - throw new IOException(String.format("Failed to open %s to dump IGV graphs", path), e); - } - } -}