OpenJDK / portola / portola
changeset 54113:84f10bbf993f
8218074: Update Graal
Reviewed-by: kvn
line wrap: on
line diff
--- a/make/CompileJavaModules.gmk Tue Mar 12 12:12:01 2019 -0700 +++ b/make/CompileJavaModules.gmk Tue Mar 12 19:17:42 2019 +0100 @@ -461,6 +461,7 @@ org.graalvm.compiler.debug.test \ org.graalvm.compiler.graph.test \ org.graalvm.compiler.hotspot.amd64.test \ + org.graalvm.compiler.hotspot.jdk9.test \ org.graalvm.compiler.hotspot.lir.test \ org.graalvm.compiler.hotspot.sparc.test \ org.graalvm.compiler.hotspot.test \
--- a/make/test/JtregGraalUnit.gmk Tue Mar 12 12:12:01 2019 -0700 +++ b/make/test/JtregGraalUnit.gmk Tue Mar 12 19:17:42 2019 +0100 @@ -92,6 +92,7 @@ $(SRC_DIR)/org.graalvm.compiler.debug.test/src \ $(SRC_DIR)/org.graalvm.compiler.graph.test/src \ $(SRC_DIR)/org.graalvm.compiler.hotspot.amd64.test/src \ + $(SRC_DIR)/org.graalvm.compiler.hotspot.jdk9.test/src \ $(SRC_DIR)/org.graalvm.compiler.hotspot.lir.test/src \ $(SRC_DIR)/org.graalvm.compiler.hotspot.sparc.test/src \ $(SRC_DIR)/org.graalvm.compiler.hotspot.test/src \
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Linker.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Linker.java Tue Mar 12 19:17:42 2019 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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,6 +29,10 @@ import java.io.File; import java.io.InputStream; import java.io.InputStreamReader; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; import java.util.stream.Stream; final class Linker { @@ -46,9 +50,12 @@ return libraryFileName; } + private static Stream<String> getLines(InputStream stream) { + return new BufferedReader(new InputStreamReader(stream)).lines(); + } + private static String getString(InputStream stream) { - BufferedReader br = new BufferedReader(new InputStreamReader(stream)); - Stream<String> lines = br.lines(); + Stream<String> lines = getLines(stream); StringBuilder sb = new StringBuilder(); lines.iterator().forEachRemaining(e -> sb.append(e)); return sb.toString(); @@ -150,9 +157,18 @@ } /** - * Search for Visual Studio link.exe Search Order is: VS2013, VS2015, VS2012. + * Search for Visual Studio link.exe Search Order is: VS2017+, VS2013, VS2015, VS2012. */ - private static String getWindowsLinkPath() { + private static String getWindowsLinkPath() throws Exception { + try { + Path vc141NewerLinker = getVC141AndNewerLinker(); + if (vc141NewerLinker != null) { + return vc141NewerLinker.toString(); + } + } catch (Exception e) { + e.printStackTrace(); + } + String link = "\\VC\\bin\\amd64\\link.exe"; /** @@ -183,10 +199,46 @@ return null; } + private static Path getVC141AndNewerLinker() throws Exception { + String programFilesX86 = System.getenv("ProgramFiles(x86)"); + if (programFilesX86 == null) { + throw new InternalError("Could not read the ProgramFiles(x86) environment variable"); + } + Path vswhere = Paths.get(programFilesX86 + "\\Microsoft Visual Studio\\Installer\\vswhere.exe"); + if (!Files.exists(vswhere)) { + return null; + } + + ProcessBuilder processBuilder = new ProcessBuilder(vswhere.toString(), "-requires", + "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", "-property", "installationPath", "-latest"); + processBuilder.redirectOutput(ProcessBuilder.Redirect.PIPE); + processBuilder.redirectError(ProcessBuilder.Redirect.PIPE); + Process process = processBuilder.start(); + final int exitCode = process.waitFor(); + if (exitCode != 0) { + String errorMessage = getString(process.getErrorStream()); + if (errorMessage.isEmpty()) { + errorMessage = getString(process.getInputStream()); + } + throw new InternalError(errorMessage); + } + + String installationPath = getLines(process.getInputStream()).findFirst().orElseThrow(() -> new InternalError("Unexpected empty output from vswhere")); + Path vcToolsVersionFilePath = Paths.get(installationPath, "VC\\Auxiliary\\Build\\Microsoft.VCToolsVersion.default.txt"); + List<String> vcToolsVersionFileLines = Files.readAllLines(vcToolsVersionFilePath); + if (vcToolsVersionFileLines.isEmpty()) { + throw new InternalError(vcToolsVersionFilePath.toString() + " is empty"); + } + String vcToolsVersion = vcToolsVersionFileLines.get(0); + Path linkPath = Paths.get(installationPath, "VC\\Tools\\MSVC", vcToolsVersion, "bin\\Hostx64\\x64\\link.exe"); + if (!Files.exists(linkPath)) { + throw new InternalError("Linker at path " + linkPath.toString() + " does not exist"); + } + + return linkPath; + } + // @formatter:off (workaround for Eclipse formatting bug) - /** - * Visual Studio supported versions Search Order is: VS2013, VS2015, VS2012. - */ enum VSVERSIONS { VS2013("VS120COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\bin\\amd64\\link.exe"), VS2015("VS140COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\bin\\amd64\\link.exe"),
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java Tue Mar 12 19:17:42 2019 +0100 @@ -166,7 +166,7 @@ printer.printInfo(classesToCompile.size() + " classes found"); } - OptionValues graalOptions = HotSpotGraalOptionValues.HOTSPOT_OPTIONS; + OptionValues graalOptions = HotSpotGraalOptionValues.defaultOptions(); // Setting -Dgraal.TieredAOT overrides --compile-for-tiered if (!TieredAOT.hasBeenSet(graalOptions)) { graalOptions = new OptionValues(graalOptions, TieredAOT, options.tiered);
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSearch.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSearch.java Tue Mar 12 19:17:42 2019 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, 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 @@ -30,6 +30,7 @@ import java.util.ArrayList; import java.util.List; import java.util.function.BiConsumer; +import java.io.File; public final class ClassSearch { private final List<SourceProvider> providers = new ArrayList<>(); @@ -106,7 +107,7 @@ public static List<SearchFor> makeList(String type, String argument) { List<SearchFor> list = new ArrayList<>(); - String[] elements = argument.split(":"); + String[] elements = argument.split(File.pathSeparator); for (String element : elements) { list.add(new SearchFor(element, type)); }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java Tue Mar 12 19:17:42 2019 +0100 @@ -880,15 +880,15 @@ protected void tbnz(Register reg, int uimm6, int imm16, int pos) { assert reg.getRegisterCategory().equals(CPU); assert NumUtil.isUnsignedNbit(6, uimm6); - assert NumUtil.isSignedNbit(18, imm16); - assert (imm16 & 3) == 0; + assert NumUtil.isSignedNbit(16, imm16) : String.format("Offset value must fit in 16 bits signed: 0x%x", imm16); + assert (imm16 & 3) == 0 : String.format("Lower two bits must be zero: 0x%x", imm16 & 3); // size bit is overloaded as top bit of uimm6 bit index int size = (((uimm6 >> 5) & 1) == 0 ? 32 : 64); // remaining 5 bits are encoded lower down - int uimm5 = uimm6 >> 1; - int offset = (imm16 & NumUtil.getNbitNumberInt(16)) >> 2; + int uimm5 = uimm6 & 0x1F; + int imm14 = (imm16 & NumUtil.getNbitNumberInt(16)) >> 2; InstructionType type = generalFromSize(size); - int encoding = type.encoding | TBNZ.encoding | (uimm5 << 19) | (offset << 5) | rd(reg); + int encoding = type.encoding | TBNZ.encoding | (uimm5 << 19) | (imm14 << 5) | rd(reg); if (pos == -1) { emitInt(encoding); } else { @@ -907,15 +907,15 @@ protected void tbz(Register reg, int uimm6, int imm16, int pos) { assert reg.getRegisterCategory().equals(CPU); assert NumUtil.isUnsignedNbit(6, uimm6); - assert NumUtil.isSignedNbit(18, imm16); - assert (imm16 & 3) == 0; + assert NumUtil.isSignedNbit(16, imm16) : String.format("Offset value must fit in 16 bits signed: 0x%x", imm16); + assert (imm16 & 3) == 0 : String.format("Lower two bits must be zero: 0x%x", imm16 & 3); // size bit is overloaded as top bit of uimm6 bit index int size = (((uimm6 >> 5) & 1) == 0 ? 32 : 64); // remaining 5 bits are encoded lower down - int uimm5 = uimm6 >> 1; - int offset = (imm16 & NumUtil.getNbitNumberInt(16)) >> 2; + int uimm5 = uimm6 & 0x1F; + int imm14 = (imm16 & NumUtil.getNbitNumberInt(16)) >> 2; InstructionType type = generalFromSize(size); - int encoding = type.encoding | TBZ.encoding | (uimm5 << 19) | (offset << 5) | rd(reg); + int encoding = type.encoding | TBZ.encoding | (uimm5 << 19) | (imm14 << 5) | rd(reg); if (pos == -1) { emitInt(encoding); } else {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java Tue Mar 12 19:17:42 2019 +0100 @@ -33,6 +33,9 @@ import static org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.AddressGenerationPlan.WorkPlan.ADD_TO_BASE; import static org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.AddressGenerationPlan.WorkPlan.ADD_TO_INDEX; import static org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.AddressGenerationPlan.WorkPlan.NO_WORK; + +import org.graalvm.compiler.asm.BranchTargetOutOfBoundsException; + import static jdk.vm.ci.aarch64.AArch64.CPU; import static jdk.vm.ci.aarch64.AArch64.r8; import static jdk.vm.ci.aarch64.AArch64.r9; @@ -1452,7 +1455,7 @@ * * @param cmp general purpose register. May not be null, zero-register or stackpointer. * @param uimm6 Unsigned 6-bit bit index. - * @param label Can only handle 21-bit word-aligned offsets for now. May be unbound. Non null. + * @param label Can only handle 16-bit word-aligned offsets for now. May be unbound. Non null. */ public void tbnz(Register cmp, int uimm6, Label label) { assert NumUtil.isUnsignedNbit(6, uimm6); @@ -1472,7 +1475,7 @@ * * @param cmp general purpose register. May not be null, zero-register or stackpointer. * @param uimm6 Unsigned 6-bit bit index. - * @param label Can only handle 21-bit word-aligned offsets for now. May be unbound. Non null. + * @param label Can only handle 16-bit word-aligned offsets for now. May be unbound. Non null. */ public void tbz(Register cmp, int uimm6, Label label) { assert NumUtil.isUnsignedNbit(6, uimm6); @@ -1681,6 +1684,9 @@ int sizeEncoding = information & NumUtil.getNbitNumberInt(6); int regEncoding = information >>> 6; Register reg = AArch64.cpuRegisters.get(regEncoding); + if (!NumUtil.isSignedNbit(16, branchOffset)) { + throw new BranchTargetOutOfBoundsException(true, "Branch target %d out of bounds", branchOffset); + } switch (type) { case BRANCH_BIT_NONZERO: super.tbnz(reg, sizeEncoding, branchOffset, branch);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java Tue Mar 12 19:17:42 2019 +0100 @@ -683,7 +683,7 @@ emitImmediate(asm, size, imm); int nextInsnPos = asm.position(); if (annotateImm && asm.codePatchingAnnotationConsumer != null) { - asm.codePatchingAnnotationConsumer.accept(new ImmediateOperandAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos)); + asm.codePatchingAnnotationConsumer.accept(new OperandDataAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos)); } } @@ -700,7 +700,7 @@ emitImmediate(asm, size, imm); int nextInsnPos = asm.position(); if (annotateImm && asm.codePatchingAnnotationConsumer != null) { - asm.codePatchingAnnotationConsumer.accept(new ImmediateOperandAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos)); + asm.codePatchingAnnotationConsumer.accept(new OperandDataAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos)); } } } @@ -2023,7 +2023,7 @@ emitInt(imm32); int nextInsnPos = position(); if (annotateImm && codePatchingAnnotationConsumer != null) { - codePatchingAnnotationConsumer.accept(new ImmediateOperandAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos)); + codePatchingAnnotationConsumer.accept(new OperandDataAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos)); } } @@ -2201,10 +2201,11 @@ } public final void movswl(Register dst, AMD64Address src) { - prefix(src, dst); - emitByte(0x0F); - emitByte(0xBF); - emitOperandHelper(dst, src, 0); + AMD64RMOp.MOVSX.emit(this, DWORD, dst, src); + } + + public final void movswq(Register dst, AMD64Address src) { + AMD64RMOp.MOVSX.emit(this, QWORD, dst, src); } public final void movw(AMD64Address dst, int imm16) { @@ -2222,6 +2223,13 @@ emitOperandHelper(src, dst, 0); } + public final void movw(Register dst, AMD64Address src) { + emitByte(0x66); + prefix(src, dst); + emitByte(0x8B); + emitOperandHelper(dst, src, 0); + } + public final void movzbl(Register dst, AMD64Address src) { prefix(src, dst); emitByte(0x0F); @@ -2237,11 +2245,16 @@ AMD64RMOp.MOVZXB.emit(this, QWORD, dst, src); } + public final void movzbq(Register dst, AMD64Address src) { + AMD64RMOp.MOVZXB.emit(this, QWORD, dst, src); + } + public final void movzwl(Register dst, AMD64Address src) { - prefix(src, dst); - emitByte(0x0F); - emitByte(0xB7); - emitOperandHelper(dst, src, 0); + AMD64RMOp.MOVZX.emit(this, DWORD, dst, src); + } + + public final void movzwq(Register dst, AMD64Address src) { + AMD64RMOp.MOVZX.emit(this, QWORD, dst, src); } public final void negl(Register dst) { @@ -2557,16 +2570,63 @@ emitModRM(dst, src); } - // Insn: VPMOVZXBW xmm1, xmm2/m64 - - public final void pmovzxbw(Register dst, AMD64Address src) { + private void pmovSZx(Register dst, AMD64Address src, int op) { assert supports(CPUFeature.SSE4_1); assert inRC(XMM, dst); simdPrefix(dst, Register.None, src, PD, P_0F38, false); - emitByte(0x30); + emitByte(op); emitOperandHelper(dst, src, 0); } + public final void pmovsxbw(Register dst, AMD64Address src) { + pmovSZx(dst, src, 0x20); + } + + public final void pmovsxbd(Register dst, AMD64Address src) { + pmovSZx(dst, src, 0x21); + } + + public final void pmovsxbq(Register dst, AMD64Address src) { + pmovSZx(dst, src, 0x22); + } + + public final void pmovsxwd(Register dst, AMD64Address src) { + pmovSZx(dst, src, 0x23); + } + + public final void pmovsxwq(Register dst, AMD64Address src) { + pmovSZx(dst, src, 0x24); + } + + public final void pmovsxdq(Register dst, AMD64Address src) { + pmovSZx(dst, src, 0x25); + } + + // Insn: VPMOVZXBW xmm1, xmm2/m64 + public final void pmovzxbw(Register dst, AMD64Address src) { + pmovSZx(dst, src, 0x30); + } + + public final void pmovzxbd(Register dst, AMD64Address src) { + pmovSZx(dst, src, 0x31); + } + + public final void pmovzxbq(Register dst, AMD64Address src) { + pmovSZx(dst, src, 0x32); + } + + public final void pmovzxwd(Register dst, AMD64Address src) { + pmovSZx(dst, src, 0x33); + } + + public final void pmovzxwq(Register dst, AMD64Address src) { + pmovSZx(dst, src, 0x34); + } + + public final void pmovzxdq(Register dst, AMD64Address src) { + pmovSZx(dst, src, 0x35); + } + public final void pmovzxbw(Register dst, Register src) { assert supports(CPUFeature.SSE4_1); assert inRC(XMM, dst) && inRC(XMM, src); @@ -2881,6 +2941,10 @@ XOR.rmOp.emit(this, DWORD, dst, src); } + public final void xorq(Register dst, Register src) { + XOR.rmOp.emit(this, QWORD, dst, src); + } + public final void xorpd(Register dst, Register src) { SSEOp.XOR.emit(this, PD, dst, src); } @@ -3045,7 +3109,7 @@ emitLong(imm64); int nextInsnPos = position(); if (annotateImm && codePatchingAnnotationConsumer != null) { - codePatchingAnnotationConsumer.accept(new ImmediateOperandAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos)); + codePatchingAnnotationConsumer.accept(new OperandDataAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos)); } } @@ -3189,6 +3253,19 @@ emitModRM(5, dst); } + public final void sarq(Register dst, int imm8) { + assert isShiftCount(imm8 >> 1) : "illegal shift count"; + prefixq(dst); + if (imm8 == 1) { + emitByte(0xD1); + emitModRM(7, dst); + } else { + emitByte(0xC1); + emitModRM(7, dst); + emitByte(imm8); + } + } + public final void sbbq(Register dst, Register src) { SBB.rmOp.emit(this, QWORD, dst, src); }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64BaseAssembler.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64BaseAssembler.java Tue Mar 12 19:17:42 2019 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 @@ -210,7 +210,7 @@ } } - public abstract static class OperandDataAnnotation extends CodeAnnotation { + public static class OperandDataAnnotation extends CodeAnnotation { /** * The position (bytes from the beginning of the method) of the operand. */ @@ -239,30 +239,10 @@ } } - /** - * Annotation that stores additional information about the displacement of a - * {@link Assembler#getPlaceholder placeholder address} that needs patching. - */ - protected static class AddressDisplacementAnnotation extends OperandDataAnnotation { - AddressDisplacementAnnotation(int instructionPosition, int operandPosition, int operandSize, int nextInstructionPosition) { - super(instructionPosition, operandPosition, operandSize, nextInstructionPosition); - } - } - - /** - * Annotation that stores additional information about the immediate operand, e.g., of a call - * instruction, that needs patching. - */ - protected static class ImmediateOperandAnnotation extends OperandDataAnnotation { - ImmediateOperandAnnotation(int instructionPosition, int operandPosition, int operandSize, int nextInstructionPosition) { - super(instructionPosition, operandPosition, operandSize, nextInstructionPosition); - } - } - protected void annotatePatchingImmediate(int operandOffset, int operandSize) { if (codePatchingAnnotationConsumer != null) { int pos = position(); - codePatchingAnnotationConsumer.accept(new ImmediateOperandAnnotation(pos, pos + operandOffset, operandSize, pos + operandOffset + operandSize)); + codePatchingAnnotationConsumer.accept(new OperandDataAnnotation(pos, pos + operandOffset, operandSize, pos + operandOffset + operandSize)); } } @@ -581,7 +561,7 @@ assert index.equals(Register.None) : "cannot use RIP relative addressing with index register"; emitByte(0x05 | regenc); if (codePatchingAnnotationConsumer != null && addr.instructionStartPosition >= 0) { - codePatchingAnnotationConsumer.accept(new AddressDisplacementAnnotation(addr.instructionStartPosition, position(), 4, position() + 4 + additionalInstructionSize)); + codePatchingAnnotationConsumer.accept(new OperandDataAnnotation(addr.instructionStartPosition, position(), 4, position() + 4 + additionalInstructionSize)); } emitInt(disp); } else if (base.isValid()) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCAssembler.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCAssembler.java Tue Mar 12 19:17:42 2019 +0100 @@ -136,9 +136,9 @@ import java.util.Map; import org.graalvm.compiler.asm.Assembler; +import org.graalvm.compiler.asm.BranchTargetOutOfBoundsException; import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.core.common.NumUtil; -import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.debug.GraalError; import jdk.vm.ci.code.Register; @@ -1281,7 +1281,7 @@ public int setDisp(int inst, int d) { assert this.match(inst); if (!isValidDisp(d)) { - throw new PermanentBailoutException("Too large displacement 0x%x in field %s in instruction %s", d, this.disp, this); + throw new BranchTargetOutOfBoundsException(true, "Too large displacement 0x%x in field %s in instruction %s", d, this.disp, this); } return this.disp.setBits(inst, d); }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.test/src/org/graalvm/compiler/asm/test/AssemblerTest.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.test/src/org/graalvm/compiler/asm/test/AssemblerTest.java Tue Mar 12 19:17:42 2019 +0100 @@ -32,6 +32,7 @@ import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.code.DisassemblerProvider; import org.graalvm.compiler.core.common.CompilationIdentifier; +import org.graalvm.compiler.core.gen.LIRGenerationProvider; import org.graalvm.compiler.core.target.Backend; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.StructuredGraph; @@ -90,7 +91,7 @@ RegisterConfig registerConfig = codeCache.getRegisterConfig(); CompilationIdentifier compilationId = backend.getCompilationIdentifier(method); StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(method).compilationId(compilationId).build(); - CallingConvention cc = backend.newLIRGenerationResult(compilationId, null, null, graph, null).getCallingConvention(); + CallingConvention cc = ((LIRGenerationProvider) backend).newLIRGenerationResult(compilationId, null, null, graph, null).getCallingConvention(); CompilationResult compResult = new CompilationResult(graph.compilationId()); byte[] targetCode = test.generateCode(compResult, codeCache.getTarget(), registerConfig, cc);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/BranchTargetOutOfBoundsException.java Tue Mar 12 19:17:42 2019 +0100 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2018, 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.asm; + +import org.graalvm.compiler.core.common.GraalBailoutException; + +@SuppressWarnings("serial") +public class BranchTargetOutOfBoundsException extends GraalBailoutException { + + public BranchTargetOutOfBoundsException(boolean permanent, String format, Object... args) { + super(permanent, format, args); + } + + public BranchTargetOutOfBoundsException(String format, Object... args) { + super(format, args); + } + + public BranchTargetOutOfBoundsException(Throwable cause, String format, Object... args) { + super(cause, format, args); + } + +}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java Tue Mar 12 19:17:42 2019 +0100 @@ -55,6 +55,7 @@ import jdk.vm.ci.meta.InvokeTarget; import jdk.vm.ci.meta.ResolvedJavaField; import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.SpeculationLog; /** * Represents the output from compiling a method, including the compiled machine code, associated @@ -221,6 +222,11 @@ private ResolvedJavaMethod[] methods; /** + * The {@link SpeculationLog} log used during compilation. + */ + private SpeculationLog speculationLog; + + /** * The list of fields that were accessed from the bytecodes. */ private ResolvedJavaField[] fields; @@ -373,6 +379,21 @@ } /** + * Sets the {@link SpeculationLog} log used during compilation. + */ + public void setSpeculationLog(SpeculationLog speculationLog) { + checkOpen(); + this.speculationLog = speculationLog; + } + + /** + * Gets the {@link SpeculationLog} log, if any, used during compilation. + */ + public SpeculationLog getSpeculationLog() { + return speculationLog; + } + + /** * Sets the fields that were referenced from the bytecodes that were used as input to the * compilation. * @@ -615,7 +636,7 @@ /** * @return the code annotations or {@code null} if there are none */ - public List<CodeAnnotation> getAnnotations() { + public List<CodeAnnotation> getCodeAnnotations() { if (annotations == null) { return Collections.emptyList(); } @@ -706,7 +727,8 @@ * Clears the information in this object pertaining to generating code. That is, the * {@linkplain #getMarks() marks}, {@linkplain #getInfopoints() infopoints}, * {@linkplain #getExceptionHandlers() exception handlers}, {@linkplain #getDataPatches() data - * patches} and {@linkplain #getAnnotations() annotations} recorded in this object are cleared. + * patches} and {@linkplain #getCodeAnnotations() annotations} recorded in this object are + * cleared. */ public void resetForEmittingCode() { checkOpen(); @@ -721,6 +743,14 @@ } } + public void clearInfopoints() { + infopoints.clear(); + } + + public void clearExceptionHandlers() { + exceptionHandlers.clear(); + } + private void checkOpen() { if (closed) { throw new IllegalStateException();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/HexCodeFileDisassemblerProvider.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/HexCodeFileDisassemblerProvider.java Tue Mar 12 19:17:42 2019 +0100 @@ -78,7 +78,7 @@ long start = installedCode == null ? 0L : installedCode.getStart(); HexCodeFile hcf = new HexCodeFile(code, start, target.arch.getName(), target.wordSize * 8); if (compResult != null) { - HexCodeFile.addAnnotations(hcf, compResult.getAnnotations()); + HexCodeFile.addAnnotations(hcf, compResult.getCodeAnnotations()); addExceptionHandlersComment(compResult, hcf); Register fp = regConfig.getFrameRegister(); RefMapFormatter slotFormatter = new DefaultRefMapFormatter(target.wordSize, fp, 0);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64CbzTest.java Tue Mar 12 19:17:42 2019 +0100 @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, Arm Limited. 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.aarch64.test; + +import org.graalvm.compiler.lir.LIRInstruction; +import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow; +import org.junit.Test; + +import java.util.function.Predicate; + +public class AArch64CbzTest extends AArch64MatchRuleTest { + private static final Predicate<LIRInstruction> predicate = op -> (op instanceof AArch64ControlFlow.CompareBranchZeroOp); + + public static int equalsTo(int x) { + if (x == 0) { + return 1; + } else { + return x - 1; + } + } + + public static int notEqualsTo(int x) { + if (x != 0) { + return x + 2; + } else { + return 3; + } + } + + public static String isNull(String s) { + if (s == null) { + return "abc"; + } else { + return s + "abc"; + } + } + + public static String isNotNull(String s) { + if (s != null) { + return s + "abc"; + } else { + return "abc"; + } + } + + public static String objectEqualsNull(String s1, String s2) { + if (s1.equals(null)) { + return s1 + "abc"; + } else { + return s2 + "abd"; + } + } + + public static String objectEquals(String s1, String s2) { + if (s1.equals(s2)) { + return s1 + "abc"; + } else { + return s2 + "abd"; + } + } + + @Test + public void testEqualsTo() { + test("equalsTo", 0); + test("equalsTo", 1); + checkLIR("equalsTo", predicate, 1); + } + + @Test + public void testNotEqualsTo() { + test("notEqualsTo", 0); + test("notEqualsTo", 1); + checkLIR("notEqualsTo", predicate, 1); + } + + @Test + public void testIsNull() { + test("isNull", new Object[]{null}); + test("isNull", "abc"); + checkLIR("isNull", predicate, 1); + } + + @Test + public void testIsNotNull() { + test("isNotNull", new Object[]{null}); + test("isNotNull", "abc"); + checkLIR("isNotNull", predicate, 1); + } + + @Test + public void testObjectEqualsNull() { + test("objectEqualsNull", "ab", "ac"); + test("objectEqualsNull", "abc", "abc"); + checkLIR("objectEqualsNull", predicate, 1); + } + + @Test + public void testObjectEquals() { + test("objectEquals", "ab", "ac"); + test("objectEquals", "abc", "abc"); + checkLIR("objectEquals", predicate, 0); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64MembarOpTest.java Tue Mar 12 19:17:42 2019 +0100 @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, Arm Limited. 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.aarch64.test; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assume.assumeTrue; + +import java.util.ArrayList; +import java.util.List; + +import jdk.internal.vm.compiler.collections.Pair; +import org.graalvm.compiler.asm.aarch64.AArch64Assembler.BarrierKind; +import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; +import org.graalvm.compiler.code.CompilationResult; +import org.graalvm.compiler.core.gen.LIRGenerationProvider; +import org.graalvm.compiler.core.test.backend.BackendTest; +import org.graalvm.compiler.lir.aarch64.AArch64Move.MembarOp; +import org.graalvm.compiler.lir.asm.CompilationResultBuilder; +import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; +import org.graalvm.compiler.lir.gen.LIRGenerationResult; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.junit.Before; +import org.junit.Test; + +import jdk.vm.ci.aarch64.AArch64; +import jdk.vm.ci.code.MemoryBarriers; +import jdk.vm.ci.runtime.JVMCI; +import jdk.vm.ci.runtime.JVMCIBackend; + +public class AArch64MembarOpTest extends BackendTest { + + private final JVMCIBackend providers; + private final CompilationResultBuilder crb; + + public AArch64MembarOpTest() { + this.providers = JVMCI.getRuntime().getHostJVMCIBackend(); + + final StructuredGraph graph = parseEager("stub", StructuredGraph.AllowAssumptions.YES); + LIRGenerationResult lirGenRes = getLIRGenerationResult(graph); + CompilationResult compResult = new CompilationResult(graph.compilationId()); + this.crb = ((LIRGenerationProvider) getBackend()).newCompilationResultBuilder(lirGenRes, lirGenRes.getFrameMap(), compResult, CompilationResultBuilderFactory.Default); + } + + public void stub() { + } + + @Before + public void checkAArch64() { + assumeTrue("skipping AArch64 specific test", JVMCI.getRuntime().getHostJVMCIBackend().getTarget().arch instanceof AArch64); + } + + @Test + public void runNormalMembarTests() { + List<Pair<Integer, BarrierKind>> cases = new ArrayList<>(); + cases.add(Pair.create(MemoryBarriers.LOAD_LOAD, BarrierKind.LOAD_LOAD)); + cases.add(Pair.create(MemoryBarriers.LOAD_STORE, BarrierKind.LOAD_LOAD)); + cases.add(Pair.create(MemoryBarriers.LOAD_LOAD | MemoryBarriers.LOAD_STORE, BarrierKind.LOAD_LOAD)); + cases.add(Pair.create(MemoryBarriers.STORE_LOAD, BarrierKind.ANY_ANY)); + cases.add(Pair.create(MemoryBarriers.STORE_LOAD | MemoryBarriers.LOAD_LOAD, BarrierKind.ANY_ANY)); + cases.add(Pair.create(MemoryBarriers.STORE_LOAD | MemoryBarriers.LOAD_STORE, BarrierKind.ANY_ANY)); + cases.add(Pair.create(MemoryBarriers.STORE_LOAD | MemoryBarriers.LOAD_LOAD | MemoryBarriers.LOAD_STORE, BarrierKind.ANY_ANY)); + cases.add(Pair.create(MemoryBarriers.STORE_STORE, BarrierKind.STORE_STORE)); + cases.add(Pair.create(MemoryBarriers.STORE_STORE | MemoryBarriers.LOAD_LOAD, BarrierKind.ANY_ANY)); + cases.add(Pair.create(MemoryBarriers.STORE_STORE | MemoryBarriers.LOAD_STORE, BarrierKind.ANY_ANY)); + cases.add(Pair.create(MemoryBarriers.STORE_STORE | MemoryBarriers.LOAD_LOAD | MemoryBarriers.LOAD_STORE, BarrierKind.ANY_ANY)); + cases.add(Pair.create(MemoryBarriers.STORE_STORE | MemoryBarriers.STORE_LOAD, BarrierKind.ANY_ANY)); + cases.add(Pair.create(MemoryBarriers.STORE_STORE | MemoryBarriers.STORE_LOAD | MemoryBarriers.LOAD_LOAD, BarrierKind.ANY_ANY)); + cases.add(Pair.create(MemoryBarriers.STORE_STORE | MemoryBarriers.STORE_LOAD | MemoryBarriers.LOAD_STORE, BarrierKind.ANY_ANY)); + cases.add(Pair.create(MemoryBarriers.STORE_STORE | MemoryBarriers.STORE_LOAD | MemoryBarriers.LOAD_STORE | MemoryBarriers.LOAD_LOAD, BarrierKind.ANY_ANY)); + + for (Pair<Integer, BarrierKind> c : cases) { + assertArrayEquals(new MembarOpActual(c.getLeft()).emit(new AArch64MacroAssembler(providers.getTarget())), + new MembarOpExpected(c.getRight()).emit(new AArch64MacroAssembler(providers.getTarget()))); + } + } + + @Test(expected = AssertionError.class) + public void runExceptionalTests() { + new MembarOpActual(16).emit(new AArch64MacroAssembler(providers.getTarget())); + } + + private class MembarOpActual { + private MembarOp op; + + MembarOpActual(int barriers) { + op = new MembarOp(barriers); + } + + byte[] emit(AArch64MacroAssembler masm) { + op.emitCode(crb, masm); + return masm.close(false); + } + } + + private class MembarOpExpected { + private BarrierKind barrierKind; + + MembarOpExpected(BarrierKind barrierKind) { + this.barrierKind = barrierKind; + } + + byte[] emit(AArch64MacroAssembler masm) { + masm.dmb(barrierKind); + return masm.close(false); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64TestBitAndBranchTest.java Tue Mar 12 19:17:42 2019 +0100 @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2018, 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.aarch64.test; + +import static org.junit.Assume.assumeTrue; + +import java.util.function.Predicate; + +import org.graalvm.compiler.api.directives.GraalDirectives; +import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; +import org.graalvm.compiler.lir.LIR; +import org.graalvm.compiler.lir.LIRInstruction; +import org.graalvm.compiler.lir.LIRInstructionClass; +import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow; +import org.graalvm.compiler.lir.aarch64.AArch64LIRInstruction; +import org.graalvm.compiler.lir.asm.CompilationResultBuilder; +import org.graalvm.compiler.lir.gen.LIRGenerationResult; +import org.graalvm.compiler.lir.gen.LIRGeneratorTool; +import org.graalvm.compiler.lir.jtt.LIRTest; +import org.graalvm.compiler.lir.jtt.LIRTestSpecification; +import org.graalvm.compiler.lir.phases.LIRPhase; +import org.graalvm.compiler.lir.phases.LIRSuites; +import org.graalvm.compiler.lir.phases.PreAllocationOptimizationPhase.PreAllocationOptimizationContext; +import org.graalvm.compiler.options.OptionValues; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import jdk.vm.ci.aarch64.AArch64; +import jdk.vm.ci.code.TargetDescription; +import jdk.vm.ci.meta.Value; + +public class AArch64TestBitAndBranchTest extends LIRTest { + private static final Predicate<LIRInstruction> checkForBitTestAndBranchOp = op -> (op instanceof AArch64ControlFlow.BitTestAndBranchOp); + private LIR lir; + + @Before + public void checkAArch64() { + assumeTrue("skipping AArch64 specific test", getTarget().arch instanceof AArch64); + } + + public static long testBit42Snippet(long a, long b, long c) { + if ((a & (1 << 42)) == 0) { + return b; + } else { + return c; + } + } + + @Test + public void testBit42() { + test("testBit42Snippet", 1L << 42L, Long.MAX_VALUE, Long.MIN_VALUE); + test("testBit42Snippet", ~(1L << 42L), Long.MAX_VALUE, Long.MIN_VALUE); + checkLIR("testBit42Snippet", checkForBitTestAndBranchOp, 1); + } + + private static final LargeOpSpec largeOpSingleNop = new LargeOpSpec((1 << 14 - 2), 2); + + /** + * Tests the graceful case, where the estimation for + * {@link CompilationResultBuilder#labelWithinRange(LIRInstruction, org.graalvm.compiler.asm.Label, int)} + * holds. + */ + public static int testBitTestAndBranchSingleSnippet(int a) { + int res; + if (a % 2 == 0) { + res = fillOps(largeOpSingleNop, 1); + } else { + res = fillOps(largeOpSingleNop, 2); + } + return GraalDirectives.opaque(res); + } + + @Test + public void testBitTestAndBranchSingle() { + runTest("testBitTestAndBranchSingleSnippet", 1); + checkLIR("testBitTestAndBranchSingleSnippet", checkForBitTestAndBranchOp, 1); + } + + private static final LargeOpSpec largeOpFourNop = new LargeOpSpec((1 << 14 - 2), 8); + + /** + * Tests the case, where the estimation for + * {@link CompilationResultBuilder#labelWithinRange(LIRInstruction, org.graalvm.compiler.asm.Label, int)} + * does not hold and the code generation must be redone with large branches. + */ + public static int testBitTestAndBranchFourSnippet(int a) { + int res; + if (a % 2 == 0) { + res = fillOps(largeOpFourNop, 1); + } else { + res = fillOps(largeOpFourNop, 2); + } + return GraalDirectives.opaque(res); + } + + @Test + public void testBitTestAndBranchFour() { + runTest("testBitTestAndBranchFourSnippet", 1); + checkLIR("testBitTestAndBranchFourSnippet", checkForBitTestAndBranchOp, 1); + } + + private static class LargeOpSpec extends LIRTestSpecification { + private final int n; + private final int nopCount; + + LargeOpSpec(int n, int nopCount) { + super(); + this.n = n; + this.nopCount = nopCount; + } + + @Override + public void generate(LIRGeneratorTool gen, Value a) { + for (int i = 0; i < n; i++) { + gen.append(new NoOp(nopCount)); + } + setResult(a); + } + } + + public static class NoOp extends AArch64LIRInstruction { + private static final LIRInstructionClass<NoOp> TYPE = LIRInstructionClass.create(NoOp.class); + private final int nopCount; + + public NoOp(int nopCount) { + super(TYPE); + this.nopCount = nopCount; + } + + @Override + protected void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { + for (int i = 0; i < nopCount; i++) { + masm.nop(); + } + } + } + + @LIRIntrinsic + public static int fillOps(@SuppressWarnings("unused") LargeOpSpec s, int a) { + return a; + } + + @Override + protected LIRSuites createLIRSuites(OptionValues options) { + LIRSuites suites = super.createLIRSuites(options); + suites.getPreAllocationOptimizationStage().appendPhase(new CheckPhase()); + return suites; + } + + public class CheckPhase extends LIRPhase<PreAllocationOptimizationContext> { + @Override + protected void run(TargetDescription target, LIRGenerationResult lirGenRes, PreAllocationOptimizationContext context) { + lir = lirGenRes.getLIR(); + } + } + + protected void checkLIR(String methodName, Predicate<LIRInstruction> predicate, int expected) { + compile(getResolvedJavaMethod(methodName), null); + int actualOpNum = 0; + for (LIRInstruction ins : lir.getLIRforBlock(lir.codeEmittingOrder()[0])) { + if (predicate.test(ins)) { + actualOpNum++; + } + } + Assert.assertEquals(expected, actualOpNum); + } +}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java Tue Mar 12 19:17:42 2019 +0100 @@ -485,26 +485,6 @@ } @Override - public Value emitMathLog(Value input, boolean base10) { - throw GraalError.unimplemented(); - } - - @Override - public Value emitMathCos(Value input) { - throw GraalError.unimplemented(); - } - - @Override - public Value emitMathSin(Value input) { - throw GraalError.unimplemented(); - } - - @Override - public Value emitMathTan(Value input) { - throw GraalError.unimplemented(); - } - - @Override public void emitCompareOp(AArch64Kind cmpKind, Variable left, Value right) { throw GraalError.unimplemented(); }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRGenerator.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRGenerator.java Tue Mar 12 19:17:42 2019 +0100 @@ -52,6 +52,7 @@ import org.graalvm.compiler.lir.aarch64.AArch64Compare; import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow; import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.BranchOp; +import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.CompareBranchZeroOp; import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.CondMoveOp; import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.CondSetOp; import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.StrategySwitchOp; @@ -257,6 +258,27 @@ @Override public void emitCompareBranch(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability) { + if (cond == Condition.EQ) { + // emit cbz instruction for IsNullNode. + assert !LIRValueUtil.isNullConstant(left) : "emitNullCheckBranch()'s null input should be in right."; + if (LIRValueUtil.isNullConstant(right)) { + append(new CompareBranchZeroOp(asAllocatable(left), trueDestination, falseDestination, trueDestinationProbability)); + return; + } + + // emit cbz instruction for IntegerEquals when any of the inputs is zero. + AArch64Kind kind = (AArch64Kind) cmpKind; + if (kind.isInteger()) { + if (isIntConstant(left, 0)) { + append(new CompareBranchZeroOp(asAllocatable(right), trueDestination, falseDestination, trueDestinationProbability)); + return; + } else if (isIntConstant(right, 0)) { + append(new CompareBranchZeroOp(asAllocatable(left), trueDestination, falseDestination, trueDestinationProbability)); + return; + } + } + } + boolean mirrored = emitCompare(cmpKind, left, right, cond, unorderedIsTrue); Condition finalCondition = mirrored ? cond.mirror() : cond; boolean finalUnorderedIsTrue = mirrored ? !unorderedIsTrue : unorderedIsTrue;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java Tue Mar 12 19:17:42 2019 +0100 @@ -37,11 +37,14 @@ import org.graalvm.compiler.core.match.MatchRule; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.lir.LIRFrameState; +import org.graalvm.compiler.lir.LabelRef; import org.graalvm.compiler.lir.Variable; import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticOp; +import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.DeoptimizingNode; +import org.graalvm.compiler.nodes.IfNode; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.AddNode; @@ -178,6 +181,28 @@ return builder -> getArithmeticLIRGenerator().emitMSub(operand(a), operand(b), operand(c)); } + /** + * ((x & (1 << n)) == 0) -> tbz/tbnz n label. + */ + @MatchRule("(If (IntegerTest value Constant=a))") + public ComplexMatchResult testBitAndBranch(IfNode root, ValueNode value, ConstantNode a) { + if (value.getStackKind().isNumericInteger()) { + long constant = a.asJavaConstant().asLong(); + if (Long.bitCount(constant) == 1) { + int bitToTest = Long.numberOfTrailingZeros(constant); + return builder -> { + LabelRef trueDestination = getLIRBlock(root.trueSuccessor()); + LabelRef falseDestination = getLIRBlock(root.falseSuccessor()); + AllocatableValue src = moveSp(gen.asAllocatable(operand(value))); + double trueDestinationProbability = root.getTrueSuccessorProbability(); + gen.append(new AArch64ControlFlow.BitTestAndBranchOp(trueDestination, falseDestination, src, trueDestinationProbability, bitToTest)); + return null; + }; + } + } + return null; + } + @Override public AArch64LIRGenerator getLIRGeneratorTool() { return (AArch64LIRGenerator) gen;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java Tue Mar 12 19:17:42 2019 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2019, 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 @@ -80,13 +80,6 @@ import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant; import static org.graalvm.compiler.lir.amd64.AMD64Arithmetic.DREM; import static org.graalvm.compiler.lir.amd64.AMD64Arithmetic.FREM; -import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicBinaryOp.BinaryIntrinsicOpcode.POW; -import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp.UnaryIntrinsicOpcode.COS; -import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp.UnaryIntrinsicOpcode.EXP; -import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp.UnaryIntrinsicOpcode.LOG; -import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp.UnaryIntrinsicOpcode.LOG10; -import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp.UnaryIntrinsicOpcode.SIN; -import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp.UnaryIntrinsicOpcode.TAN; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp; @@ -116,8 +109,13 @@ import org.graalvm.compiler.lir.amd64.AMD64Binary; import org.graalvm.compiler.lir.amd64.AMD64BinaryConsumer; import org.graalvm.compiler.lir.amd64.AMD64ClearRegisterOp; -import org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicBinaryOp; -import org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp; +import org.graalvm.compiler.lir.amd64.AMD64MathCosOp; +import org.graalvm.compiler.lir.amd64.AMD64MathExpOp; +import org.graalvm.compiler.lir.amd64.AMD64MathLog10Op; +import org.graalvm.compiler.lir.amd64.AMD64MathLogOp; +import org.graalvm.compiler.lir.amd64.AMD64MathPowOp; +import org.graalvm.compiler.lir.amd64.AMD64MathSinOp; +import org.graalvm.compiler.lir.amd64.AMD64MathTanOp; import org.graalvm.compiler.lir.amd64.AMD64Move; import org.graalvm.compiler.lir.amd64.AMD64MulDivOp; import org.graalvm.compiler.lir.amd64.AMD64ShiftOp; @@ -127,7 +125,6 @@ import org.graalvm.compiler.lir.amd64.vector.AMD64VectorBinary.AVXBinaryOp; import org.graalvm.compiler.lir.amd64.vector.AMD64VectorUnary; import org.graalvm.compiler.lir.gen.ArithmeticLIRGenerator; -import org.graalvm.compiler.lir.gen.LIRGenerator; import jdk.vm.ci.amd64.AMD64; import jdk.vm.ci.amd64.AMD64.CPUFeature; @@ -152,41 +149,11 @@ private static final RegisterValue RCX_I = AMD64.rcx.asValue(LIRKind.value(AMD64Kind.DWORD)); - public AMD64ArithmeticLIRGenerator(AllocatableValue nullRegisterValue, Maths maths) { + public AMD64ArithmeticLIRGenerator(AllocatableValue nullRegisterValue) { this.nullRegisterValue = nullRegisterValue; - this.maths = maths == null ? new Maths() { - } : maths; } private final AllocatableValue nullRegisterValue; - private final Maths maths; - - /** - * Interface for emitting LIR for selected {@link Math} routines. A {@code null} return value - * for any method in this interface means the caller must emit the LIR itself. - */ - public interface Maths { - - @SuppressWarnings("unused") - default Variable emitLog(LIRGenerator gen, Value input, boolean base10) { - return null; - } - - @SuppressWarnings("unused") - default Variable emitCos(LIRGenerator gen, Value input) { - return null; - } - - @SuppressWarnings("unused") - default Variable emitSin(LIRGenerator gen, Value input) { - return null; - } - - @SuppressWarnings("unused") - default Variable emitTan(LIRGenerator gen, Value input) { - return null; - } - } @Override public Variable emitNegate(Value inputVal) { @@ -781,6 +748,7 @@ } } + @Override public Variable emitRor(Value a, Value b) { switch ((AMD64Kind) a.getPlatformKind()) { case DWORD: @@ -1103,65 +1071,36 @@ @Override public Value emitMathLog(Value input, boolean base10) { - LIRGenerator gen = getLIRGen(); - Variable result = maths.emitLog(gen, input, base10); - if (result == null) { - result = gen.newVariable(LIRKind.combine(input)); - AllocatableValue stackSlot = gen.getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(AMD64Kind.QWORD)); - gen.append(new AMD64MathIntrinsicUnaryOp(getAMD64LIRGen(), base10 ? LOG10 : LOG, result, asAllocatable(input), stackSlot)); + if (base10) { + return new AMD64MathLog10Op().emitLIRWrapper(getLIRGen(), input); + } else { + return new AMD64MathLogOp().emitLIRWrapper(getLIRGen(), input); } - return result; } @Override public Value emitMathCos(Value input) { - LIRGenerator gen = getLIRGen(); - Variable result = maths.emitCos(gen, input); - if (result == null) { - result = gen.newVariable(LIRKind.combine(input)); - AllocatableValue stackSlot = gen.getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(AMD64Kind.QWORD)); - gen.append(new AMD64MathIntrinsicUnaryOp(getAMD64LIRGen(), COS, result, asAllocatable(input), stackSlot)); - } - return result; + return new AMD64MathCosOp().emitLIRWrapper(getLIRGen(), input); } @Override public Value emitMathSin(Value input) { - LIRGenerator gen = getLIRGen(); - Variable result = maths.emitSin(gen, input); - if (result == null) { - result = gen.newVariable(LIRKind.combine(input)); - AllocatableValue stackSlot = gen.getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(AMD64Kind.QWORD)); - gen.append(new AMD64MathIntrinsicUnaryOp(getAMD64LIRGen(), SIN, result, asAllocatable(input), stackSlot)); - } - return result; + return new AMD64MathSinOp().emitLIRWrapper(getLIRGen(), input); } @Override public Value emitMathTan(Value input) { - LIRGenerator gen = getLIRGen(); - Variable result = maths.emitTan(gen, input); - if (result == null) { - result = gen.newVariable(LIRKind.combine(input)); - AllocatableValue stackSlot = gen.getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(AMD64Kind.QWORD)); - gen.append(new AMD64MathIntrinsicUnaryOp(getAMD64LIRGen(), TAN, result, asAllocatable(input), stackSlot)); - } - return result; + return new AMD64MathTanOp().emitLIRWrapper(getLIRGen(), input); } @Override public Value emitMathExp(Value input) { - Variable result = getLIRGen().newVariable(LIRKind.combine(input)); - AllocatableValue stackSlot = getLIRGen().getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(AMD64Kind.QWORD)); - getLIRGen().append(new AMD64MathIntrinsicUnaryOp(getAMD64LIRGen(), EXP, result, asAllocatable(input), stackSlot)); - return result; + return new AMD64MathExpOp().emitLIRWrapper(getLIRGen(), input); } @Override - public Value emitMathPow(Value input1, Value input2) { - Variable result = getLIRGen().newVariable(LIRKind.combine(input1)); - getLIRGen().append(new AMD64MathIntrinsicBinaryOp(getAMD64LIRGen(), POW, result, asAllocatable(input1), asAllocatable(input2))); - return result; + public Value emitMathPow(Value x, Value y) { + return new AMD64MathPowOp().emitLIRWrapper(getLIRGen(), x, y); } protected AMD64LIRGenerator getAMD64LIRGen() {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java Tue Mar 12 19:17:42 2019 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2019, 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 @@ -41,6 +41,8 @@ import static org.graalvm.compiler.lir.LIRValueUtil.isIntConstant; import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant; +import java.util.Optional; + import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp; @@ -81,6 +83,7 @@ import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.ReturnOp; import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.StrategySwitchOp; import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.TableSwitchOp; +import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.HashTableSwitchOp; import org.graalvm.compiler.lir.amd64.AMD64LFenceOp; import org.graalvm.compiler.lir.amd64.AMD64Move; import org.graalvm.compiler.lir.amd64.AMD64Move.CompareAndSwapOp; @@ -93,6 +96,7 @@ import org.graalvm.compiler.lir.amd64.AMD64ZapStackOp; import org.graalvm.compiler.lir.gen.LIRGenerationResult; import org.graalvm.compiler.lir.gen.LIRGenerator; +import org.graalvm.compiler.lir.hashing.Hasher; import org.graalvm.compiler.phases.util.Providers; import jdk.vm.ci.amd64.AMD64; @@ -545,7 +549,14 @@ @Override public Variable emitArrayEquals(JavaKind kind, Value array1, Value array2, Value length, int constantLength, boolean directPointers) { Variable result = newVariable(LIRKind.value(AMD64Kind.DWORD)); - append(new AMD64ArrayEqualsOp(this, kind, result, array1, array2, asAllocatable(length), constantLength, directPointers, getMaxVectorSize())); + append(new AMD64ArrayEqualsOp(this, kind, kind, result, array1, array2, asAllocatable(length), constantLength, directPointers, getMaxVectorSize())); + return result; + } + + @Override + public Variable emitArrayEquals(JavaKind kind1, JavaKind kind2, Value array1, Value array2, Value length, int constantLength, boolean directPointers) { + Variable result = newVariable(LIRKind.value(AMD64Kind.DWORD)); + append(new AMD64ArrayEqualsOp(this, kind1, kind2, result, array1, array2, asAllocatable(length), constantLength, directPointers, getMaxVectorSize())); return result; } @@ -635,6 +646,19 @@ } @Override + protected Optional<Hasher> hasherFor(JavaConstant[] keyConstants, double minDensity) { + return Hasher.forKeys(keyConstants, minDensity); + } + + @Override + protected void emitHashTableSwitch(Hasher hasher, JavaConstant[] keys, LabelRef defaultTarget, LabelRef[] targets, Value value) { + Value index = hasher.hash(value, arithmeticLIRGen); + Variable scratch = newVariable(LIRKind.value(target().arch.getWordKind())); + Variable entryScratch = newVariable(LIRKind.value(target().arch.getWordKind())); + append(new HashTableSwitchOp(keys, defaultTarget, targets, value, index, scratch, entryScratch)); + } + + @Override public void emitPause() { append(new AMD64PauseOp()); }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java Tue Mar 12 19:17:42 2019 +0100 @@ -83,8 +83,8 @@ @Option(help = "", type = OptionType.Debug) public static final OptionKey<String> EscapeAnalyzeOnly = new OptionKey<>(null); - @Option(help = "", type = OptionType.Expert) - public static final OptionKey<Integer> MaximumEscapeAnalysisArrayLength = new OptionKey<>(32); + @Option(help = "The maximum length of an array that will be escape analyzed.", type = OptionType.Expert) + public static final OptionKey<Integer> MaximumEscapeAnalysisArrayLength = new OptionKey<>(128); @Option(help = "", type = OptionType.Debug) public static final OptionKey<Boolean> PEAInliningHints = new OptionKey<>(false); @@ -142,7 +142,7 @@ public static final OptionKey<Boolean> VerifyPhases = new OptionKey<>(false); // Debug settings: - @Option(help = "", type = OptionType.Debug) + @Option(help = "Start tracing compiled GC barriers after N garbage collections (disabled if N <= 0).", type = OptionType.Debug) public static final OptionKey<Integer> GCDebugStartCycle = new OptionKey<>(-1); @Option(help = "Perform platform dependent validation of the Java heap at returns", type = OptionType.Debug) @@ -206,9 +206,6 @@ @Option(help = "Generate position independent code", type = OptionType.Expert) public static final OptionKey<Boolean> GeneratePIC = new OptionKey<>(false); - @Option(help = "", type = OptionType.Expert) - public static final OptionKey<Boolean> CallArrayCopy = new OptionKey<>(true); - // Runtime settings @Option(help = "", type = OptionType.Expert) public static final OptionKey<Boolean> SupportJsrBytecodes = new OptionKey<>(true);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/SpeculativeExecutionAttacksMitigations.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/SpeculativeExecutionAttacksMitigations.java Tue Mar 12 19:17:42 2019 +0100 @@ -37,9 +37,9 @@ public static class Options { // @formatter:off - @Option(help = "Select a strategy to mitigate speculative execution attacks (e.g., SPECTRE)", type = OptionType.User) + @Option(help = "file:doc-files/MitigateSpeculativeExecutionAttacksHelp.txt") public static final EnumOptionKey<SpeculativeExecutionAttacksMitigations> MitigateSpeculativeExecutionAttacks = new EnumOptionKey<>(None); - @Option(help = "Use index masking after bounds check to mitigate speculative execution attacks", type = OptionType.User) + @Option(help = "Use index masking after bounds check to mitigate speculative execution attacks.", type = OptionType.User) public static final OptionKey<Boolean> UseIndexMasking = new OptionKey<>(false); // @formatter:on }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractBlockBase.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractBlockBase.java Tue Mar 12 19:17:42 2019 +0100 @@ -24,6 +24,8 @@ package org.graalvm.compiler.core.common.cfg; +import java.util.Comparator; + public abstract class AbstractBlockBase<T extends AbstractBlockBase<T>> { protected int id; @@ -171,4 +173,13 @@ public int hashCode() { return id; } + + public static class BlockIdComparator implements Comparator<AbstractBlockBase<?>> { + @Override + public int compare(AbstractBlockBase<?> o1, AbstractBlockBase<?> o2) { + return Integer.compare(o1.getId(), o2.getId()); + } + } + + public static final BlockIdComparator BLOCK_ID_COMPARATOR = new BlockIdComparator(); }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/CFGVerifier.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/CFGVerifier.java Tue Mar 12 19:17:42 2019 +0100 @@ -121,7 +121,7 @@ } } - for (T block : loop.getExits()) { + for (T block : loop.getLoopExits()) { assert block.getId() >= loop.getHeader().getId(); Loop<?> blockLoop = block.getLoop();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/Loop.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/Loop.java Tue Mar 12 19:17:42 2019 +0100 @@ -25,19 +25,28 @@ package org.graalvm.compiler.core.common.cfg; +import static org.graalvm.compiler.core.common.cfg.AbstractBlockBase.BLOCK_ID_COMPARATOR; + import java.util.ArrayList; +import java.util.Collections; import java.util.List; public abstract class Loop<T extends AbstractBlockBase<T>> { private final Loop<T> parent; - private final List<Loop<T>> children; + private final ArrayList<Loop<T>> children; private final int depth; private final int index; private final T header; - private final List<T> blocks; - private final List<T> exits; + private final ArrayList<T> blocks; + private final ArrayList<T> exits; + /** + * Natural exits, ignoring LoopExitNodes. + * + * @see #getNaturalExits() + */ + private final ArrayList<T> naturalExits; protected Loop(Loop<T> parent, int index, T header) { this.parent = parent; @@ -51,6 +60,7 @@ this.blocks = new ArrayList<>(); this.children = new ArrayList<>(); this.exits = new ArrayList<>(); + this.naturalExits = new ArrayList<>(); } public abstract long numBackedges(); @@ -84,12 +94,87 @@ return blocks; } - public List<T> getExits() { + /** + * Returns the loop exits. + * + * This might be a conservative set: before framestate assignment it matches the LoopExitNodes + * even if earlier blocks could be considered as exits. After framestate assignments, this is + * the same as {@link #getNaturalExits()}. + * + * <p> + * LoopExitNodes are inserted in the control-flow during parsing and are natural exits: they are + * the earliest block at which we are guaranteed to have exited the loop. However, after some + * transformations of the graph, the natural exit might go up but the LoopExitNodes are not + * updated. + * </p> + * + * <p> + * For example in: + * + * <pre> + * for (int i = 0; i < N; i++) { + * if (c) { + * // Block 1 + * if (dummy) { + * // ... + * } else { + * // ... + * } + * if (b) { + * continue; + * } else { + * // Block 2 + * // LoopExitNode + * break; + * } + * } + * } + * </pre> + * + * After parsing, the natural exits match the LoopExitNode: Block 2 is a natural exit and has a + * LoopExitNode. If the {@code b} condition gets canonicalized to {@code false}, the natural + * exit moves to Block 1 while the LoopExitNode remains in Block 2. In such a scenario, + * {@code getLoopExits()} will contain block 2 while {@link #getNaturalExits()} will contain + * block 1. + * + * + * @see #getNaturalExits() + */ + public List<T> getLoopExits() { return exits; } - public void addExit(T t) { - exits.add(t); + public boolean isLoopExit(T block) { + assert isSorted(exits); + return Collections.binarySearch(exits, block, BLOCK_ID_COMPARATOR) >= 0; + } + + /** + * Returns the natural exit points: these are the earliest block that are guaranteed to never + * reach a back-edge. + * + * This can not be used in the context of preserving or using loop-closed form. + * + * @see #getLoopExits() + */ + public ArrayList<T> getNaturalExits() { + return naturalExits; + } + + public boolean isNaturalExit(T block) { + assert isSorted(naturalExits); + return Collections.binarySearch(naturalExits, block, BLOCK_ID_COMPARATOR) >= 0; + } + + private static <T extends AbstractBlockBase<T>> boolean isSorted(List<T> list) { + int lastId = Integer.MIN_VALUE; + for (AbstractBlockBase<?> block : list) { + if (block.getId() < lastId) { + return false; + } + lastId = block.getId(); + } + return true; } /** @@ -115,4 +200,9 @@ public int hashCode() { return index + depth * 31; } + + @Override + public boolean equals(Object obj) { + return super.equals(obj); + } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/doc-files/MitigateSpeculativeExecutionAttacksHelp.txt Tue Mar 12 19:17:42 2019 +0100 @@ -0,0 +1,9 @@ +Select a strategy to mitigate speculative execution attacks (e.g., SPECTRE). +The accepted values are: + None - No mitigations are used in JIT compiled code. + AllTargets - All branches are protected against speculative attacks. + This has a significant performance impact. + GuardTargets - Only branches that preserve Java memory safety are protected. + This has less performance impact than AllTargets. + NonDeoptGuardTargets - GuardTargets except that branches which deoptimize are not + protected since they can not be executed repeatedly.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/AbstractObjectStamp.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/AbstractObjectStamp.java Tue Mar 12 19:17:42 2019 +0100 @@ -48,6 +48,13 @@ this.exactType = exactType; } + @Override + public void accept(Visitor v) { + super.accept(v); + v.visitObject(type); + v.visitBoolean(exactType); + } + protected abstract AbstractObjectStamp copyWith(ResolvedJavaType newType, boolean newExactType, boolean newNonNull, boolean newAlwaysNull); @Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/AbstractPointerStamp.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/AbstractPointerStamp.java Tue Mar 12 19:17:42 2019 +0100 @@ -36,6 +36,12 @@ private final boolean nonNull; private final boolean alwaysNull; + @Override + public void accept(Visitor v) { + v.visitBoolean(nonNull); + v.visitBoolean(alwaysNull); + } + protected AbstractPointerStamp(boolean nonNull, boolean alwaysNull) { this.nonNull = nonNull; this.alwaysNull = alwaysNull;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IllegalStamp.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IllegalStamp.java Tue Mar 12 19:17:42 2019 +0100 @@ -46,6 +46,10 @@ } @Override + public void accept(Visitor v) { + } + + @Override public JavaKind getStackKind() { return JavaKind.Illegal; }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ObjectStamp.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ObjectStamp.java Tue Mar 12 19:17:42 2019 +0100 @@ -31,6 +31,7 @@ import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.MemoryAccessProvider; import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.meta.UnresolvedJavaType; public class ObjectStamp extends AbstractObjectStamp { @@ -92,4 +93,48 @@ return null; } } + + /** + * Convert an ObjectStamp into a representation that can be resolved symbolically into the + * original stamp. + */ + @Override + public SymbolicJVMCIReference<ObjectStamp> makeSymbolic() { + if (type() == null) { + return null; + } + return new SymbolicObjectStamp(this); + } + + static class SymbolicObjectStamp implements SymbolicJVMCIReference<ObjectStamp> { + UnresolvedJavaType type; + private boolean exactType; + private boolean nonNull; + private boolean alwaysNull; + + SymbolicObjectStamp(ObjectStamp stamp) { + if (stamp.type() != null) { + type = UnresolvedJavaType.create(stamp.type().getName()); + } + exactType = stamp.isExactType(); + nonNull = stamp.nonNull(); + alwaysNull = stamp.alwaysNull(); + } + + @Override + public ObjectStamp resolve(ResolvedJavaType accessingClass) { + return new ObjectStamp(type != null ? type.resolve(accessingClass) : null, exactType, nonNull, alwaysNull); + } + + @Override + public String toString() { + return "SymbolicObjectStamp{" + + "declaringType=" + type + + ", exactType=" + exactType + + ", nonNull=" + nonNull + + ", alwaysNull=" + alwaysNull + + '}'; + } + } + }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/PrimitiveStamp.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/PrimitiveStamp.java Tue Mar 12 19:17:42 2019 +0100 @@ -39,6 +39,11 @@ this.bits = bits; } + @Override + public void accept(Visitor v) { + v.visitInt(bits); + } + /** * The width in bits of the value described by this stamp. */
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/Stamp.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/Stamp.java Tue Mar 12 19:17:42 2019 +0100 @@ -26,6 +26,7 @@ import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.spi.LIRKindTool; +import org.graalvm.compiler.serviceprovider.SpeculationReasonGroup.SpeculationContextObject; import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.JavaKind; @@ -36,7 +37,7 @@ /** * A stamp is the basis for a type system. */ -public abstract class Stamp { +public abstract class Stamp implements SpeculationContextObject { protected Stamp() { } @@ -185,4 +186,15 @@ } return false; } + + /** + * Convert a Stamp into a representation that can be resolved symbolically into the original + * stamp. If this stamp contains no references to JVMCI types then simply return null. + */ + public SymbolicJVMCIReference<? extends Stamp> makeSymbolic() { + return null; + } + + @Override + public abstract String toString(); }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/StampPair.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/StampPair.java Tue Mar 12 19:17:42 2019 +0100 @@ -24,6 +24,8 @@ package org.graalvm.compiler.core.common.type; +import java.util.Objects; + /** * A pair of stamp with one being the stamp that can be trusted and the other one being a guess that * needs a dynamic check to be used. @@ -63,4 +65,22 @@ return trustedStamp + " (unchecked=" + uncheckedStamp + ")"; } } + + @Override + public int hashCode() { + return trustedStamp.hashCode() + 11 + (uncheckedStamp != null ? uncheckedStamp.hashCode() : 0); + + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (obj instanceof StampPair) { + StampPair other = (StampPair) obj; + return trustedStamp.equals(other.trustedStamp) && Objects.equals(uncheckedStamp, other.uncheckedStamp); + } + return false; + } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/SymbolicJVMCIReference.java Tue Mar 12 19:17:42 2019 +0100 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2018, 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.common.type; + +import jdk.vm.ci.meta.ResolvedJavaType; + +/** + * This interface represents an object which contains a symbolic reference to a JVMCI type or method + * that can be converted back into the original object by looking up types relative to an + * {@code accessingClass}. + */ +public interface SymbolicJVMCIReference<T> { + T resolve(ResolvedJavaType accessingClass); +}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/VoidStamp.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/VoidStamp.java Tue Mar 12 19:17:42 2019 +0100 @@ -43,6 +43,10 @@ } @Override + public void accept(Visitor v) { + } + + @Override public Stamp unrestricted() { return this; }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/UnsignedLong.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/UnsignedLong.java Tue Mar 12 19:17:42 2019 +0100 @@ -43,6 +43,10 @@ return Long.compareUnsigned(value, unsignedValue) < 0; } + public boolean isGreaterThan(long unsignedValue) { + return Long.compareUnsigned(value, unsignedValue) > 0; + } + public boolean isLessOrEqualTo(long unsignedValue) { return Long.compareUnsigned(value, unsignedValue) <= 0; }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java Tue Mar 12 19:17:42 2019 +0100 @@ -157,6 +157,10 @@ if (className.equals("org.graalvm.compiler.serviceprovider.GraalServices$Lazy")) { return false; } + } else { + if (className.equals("jdk.vm.ci.services.JVMCIClassLoaderFactory")) { + return false; + } } return true; }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java Tue Mar 12 19:17:42 2019 +0100 @@ -33,7 +33,7 @@ import org.graalvm.compiler.phases.OptimisticOptimizations.Optimization; 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.loop.phases.ConvertDeoptimizeToGuardPhase; import org.graalvm.compiler.phases.common.IterativeConditionalEliminationPhase; import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.schedule.SchedulePhase;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CountedLoopTest2.java Tue Mar 12 19:17:42 2019 +0100 @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2018, 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.api.directives.GraalDirectives; +import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.graph.iterators.FilteredNodeIterable; +import org.graalvm.compiler.loop.LoopEx; +import org.graalvm.compiler.loop.LoopsData; +import org.graalvm.compiler.nodes.DeoptimizingNode; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.junit.Assert; +import org.junit.Test; + +public class CountedLoopTest2 extends GraalCompilerTest { + public static float countedDeoptLoop0(int n) { + float v = 0; + for (int i = 0; i < n; i++) { + v += 2.1f * i; + GraalDirectives.controlFlowAnchor(); + } + GraalDirectives.deoptimizeAndInvalidate(); + return v; + } + + @Test + public void test0() { + test("countedDeoptLoop0"); + } + + public static float countedDeoptLoop1(int n) { + float v = 0; + for (int i = 0; i < n; i++) { + v += 2.1f * i; + GraalDirectives.controlFlowAnchor(); + } + if (v > 0) { + if (v / 55 < 3) { + v -= 2; + GraalDirectives.controlFlowAnchor(); + } else { + v += 6; + GraalDirectives.controlFlowAnchor(); + } + } else { + v += 1; + GraalDirectives.controlFlowAnchor(); + } + GraalDirectives.deoptimizeAndInvalidate(); + return v; + } + + @Test + public void test1() { + test("countedDeoptLoop1"); + } + + public static float countedDeoptLoop2(int n, float init) { + float v = init; + if (v > 0) { + if (v / 55 < 3) { + for (int i = 0; i < n; i++) { + v += 2.1f * i; + GraalDirectives.controlFlowAnchor(); + } + } else { + for (int i = 0; i < n; i++) { + v += 1.1f * i; + GraalDirectives.controlFlowAnchor(); + } + } + } else { + for (int i = 0; i < n; i++) { + v += -0.1f * i; + GraalDirectives.controlFlowAnchor(); + } + } + GraalDirectives.deoptimizeAndInvalidate(); + return v; + } + + @Test + public void test2() { + test("countedDeoptLoop2", 3); + } + + private void test(String methodName) { + test(methodName, 1); + } + + private void test(String methodName, int nLoops) { + StructuredGraph graph = parseEager(methodName, AllowAssumptions.YES); + LoopsData loops = new LoopsData(graph); + Assert.assertEquals(nLoops, loops.loops().size()); + for (LoopEx loop : loops.loops()) { + Assert.assertTrue(loop.detectCounted()); + } + + StructuredGraph finalGraph = getFinalGraph(methodName); + loops = new LoopsData(finalGraph); + Assert.assertEquals(nLoops, loops.loops().size()); + FilteredNodeIterable<Node> nonStartDeopts = finalGraph.getNodes().filter(n -> { + return n instanceof DeoptimizingNode.DeoptBefore && ((DeoptimizingNode.DeoptBefore) n).stateBefore().bci > 0; + }); + Assert.assertTrue(nonStartDeopts.isNotEmpty()); + } +}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DumpPathTest.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DumpPathTest.java Tue Mar 12 19:17:42 2019 +0100 @@ -31,6 +31,7 @@ import jdk.internal.vm.compiler.collections.EconomicMap; import org.graalvm.compiler.debug.DebugOptions; +import org.graalvm.compiler.debug.DebugOptions.PrintGraphTarget; import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionValues; import org.junit.Test; @@ -52,7 +53,7 @@ String[] extensions = new String[]{".cfg", ".bgv", ".graph-strings"}; EconomicMap<OptionKey<?>, Object> overrides = OptionValues.newOptionMap(); overrides.put(DebugOptions.DumpPath, dumpDirectoryPath.toString()); - overrides.put(DebugOptions.PrintGraphFile, true); + overrides.put(DebugOptions.PrintGraph, PrintGraphTarget.File); overrides.put(DebugOptions.PrintCanonicalGraphStrings, true); overrides.put(DebugOptions.Dump, "*");
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java Tue Mar 12 19:17:42 2019 +0100 @@ -111,7 +111,7 @@ 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.loop.phases.ConvertDeoptimizeToGuardPhase; import org.graalvm.compiler.phases.common.inlining.InliningPhase; import org.graalvm.compiler.phases.common.inlining.info.InlineInfo; import org.graalvm.compiler.phases.common.inlining.policy.GreedyInliningPolicy; @@ -899,11 +899,21 @@ return actual; } + private static final List<Class<?>> C2_OMIT_STACK_TRACE_IN_FAST_THROW_EXCEPTIONS = Arrays.asList( + ArithmeticException.class, + ArrayIndexOutOfBoundsException.class, + ArrayStoreException.class, + ClassCastException.class, + NullPointerException.class); + protected void assertEquals(Result expect, Result actual) { if (expect.exception != null) { Assert.assertTrue("expected " + expect.exception, actual.exception != null); Assert.assertEquals("Exception class", expect.exception.getClass(), actual.exception.getClass()); - Assert.assertEquals("Exception message", expect.exception.getMessage(), actual.exception.getMessage()); + // C2 can optimize out the stack trace and message in some cases + if (expect.exception.getMessage() != null || !C2_OMIT_STACK_TRACE_IN_FAST_THROW_EXCEPTIONS.contains(expect.exception.getClass())) { + Assert.assertEquals("Exception message", expect.exception.getMessage(), actual.exception.getMessage()); + } } else { if (actual.exception != null) { throw new AssertionError("expected " + expect.returnValue + " but got an exception", actual.exception);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphEncoderTest.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphEncoderTest.java Tue Mar 12 19:17:42 2019 +0100 @@ -30,16 +30,15 @@ import java.util.List; import java.util.Map; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -import org.junit.Test; - import org.graalvm.compiler.nodes.EncodedGraph; import org.graalvm.compiler.nodes.GraphEncoder; 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; + +import jdk.vm.ci.meta.ResolvedJavaMethod; public class GraphEncoderTest extends GraalCompilerTest { @@ -80,7 +79,7 @@ for (StructuredGraph originalGraph : originalGraphs) { EncodedGraph encodedGraph = new EncodedGraph(encoder.getEncoding(), startOffsets.get(originalGraph), encoder.getObjects(), encoder.getNodeClasses(), originalGraph); - GraphEncoder.verifyEncoding(originalGraph, encodedGraph, getTarget().arch); + encoder.verifyEncoding(originalGraph, encodedGraph); } } }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardPrioritiesTest.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardPrioritiesTest.java Tue Mar 12 19:17:42 2019 +0100 @@ -35,6 +35,7 @@ import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.graph.iterators.NodeIterable; +import org.graalvm.compiler.loop.phases.ConvertDeoptimizeToGuardPhase; import org.graalvm.compiler.nodes.GuardNode; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.StructuredGraph; @@ -42,7 +43,6 @@ import org.graalvm.compiler.nodes.calc.IsNullNode; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.phases.common.CanonicalizerPhase; -import org.graalvm.compiler.phases.common.ConvertDeoptimizeToGuardPhase; import org.graalvm.compiler.phases.common.FloatingReadPhase; import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.schedule.SchedulePhase;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IntegerDivRemConstantTest.java Tue Mar 12 19:17:42 2019 +0100 @@ -0,0 +1,293 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, Arm Limited and 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.junit.Test; + +public class IntegerDivRemConstantTest extends GraalCompilerTest { + public static int intDivPositiveConstant(int val) { + return val / 5; + } + + @Test + public void testIntDivPositiveConstant() { + test("intDivPositiveConstant", -10); + test("intDivPositiveConstant", 0); + test("intDivPositiveConstant", 4256); + test("intDivPositiveConstant", Integer.MAX_VALUE); + test("intDivPositiveConstant", Integer.MIN_VALUE); + } + + public static int intDivIntegerMax(int val) { + return val / Integer.MAX_VALUE; + } + + @Test + public void testIntDivIntegerMax() { + test("intDivIntegerMax", -10); + test("intDivIntegerMax", 0); + test("intDivIntegerMax", 4256); + test("intDivIntegerMax", Integer.MAX_VALUE); + test("intDivIntegerMax", Integer.MIN_VALUE); + } + + public static int intDivNegativeConstant(int val) { + return val / -1234; + } + + @Test + public void testIntDivNegativeConstant() { + test("intDivNegativeConstant", -123); + test("intDivNegativeConstant", 0); + test("intDivNegativeConstant", 123); + test("intDivNegativeConstant", Integer.MAX_VALUE); + test("intDivNegativeConstant", Integer.MIN_VALUE); + } + + public static int intDivIntegerMinOdd(int val) { + return val / (Integer.MIN_VALUE + 1); + } + + @Test + public void testIntDivIntegerMinOdd() { + test("intDivIntegerMinOdd", -123); + test("intDivIntegerMinOdd", 0); + test("intDivIntegerMinOdd", 123); + test("intDivIntegerMinOdd", Integer.MAX_VALUE); + test("intDivIntegerMinOdd", Integer.MIN_VALUE); + } + + public static long longDivPositiveConstant(long val) { + return val / 35170432; + } + + @Test + public void testLongDivPositiveConstant() { + test("longDivPositiveConstant", -1234L); + test("longDivPositiveConstant", 0L); + test("longDivPositiveConstant", 214423L); + test("longDivPositiveConstant", Long.MAX_VALUE); + test("longDivPositiveConstant", Long.MIN_VALUE); + } + + public static long longDivLongMax(long val) { + return val / Long.MAX_VALUE; + } + + @Test + public void testLongDivLongMax() { + test("longDivLongMax", -1234L); + test("longDivLongMax", 0L); + test("longDivLongMax", 214423L); + test("longDivLongMax", Long.MAX_VALUE); + test("longDivLongMax", Long.MIN_VALUE); + } + + public static long longDivNegativeConstant(long val) { + return val / -413; + } + + @Test + public void testLongDivNegativeConstant() { + test("longDivNegativeConstant", -43L); + test("longDivNegativeConstant", 0L); + test("longDivNegativeConstant", 147065L); + test("longDivNegativeConstant", Long.MAX_VALUE); + test("longDivNegativeConstant", Long.MIN_VALUE); + } + + public static long longDivLongMinOdd(long val) { + return val / (Long.MIN_VALUE + 1); + } + + @Test + public void testLongDivLongMinOdd() { + test("longDivLongMinOdd", -1234L); + test("longDivLongMinOdd", 0L); + test("longDivLongMinOdd", 214423L); + test("longDivLongMinOdd", Long.MAX_VALUE); + test("longDivLongMinOdd", Long.MIN_VALUE); + } + + public static int intRemPositiveConstant(int val) { + return val % 139968; + } + + @Test + public void testIntRemPositiveConstant() { + test("intRemPositiveConstant", -10); + test("intRemPositiveConstant", 0); + test("intRemPositiveConstant", 4256); + test("intRemPositiveConstant", Integer.MAX_VALUE); + test("intRemPositiveConstant", Integer.MIN_VALUE); + } + + public static int intRemNegativeConstant(int val) { + return val % -139968; + } + + @Test + public void testIntRemNegativeConstant() { + test("intRemNegativeConstant", -10); + test("intRemNegativeConstant", 0); + test("intRemNegativeConstant", 4256); + test("intRemNegativeConstant", Integer.MAX_VALUE); + test("intRemNegativeConstant", Integer.MIN_VALUE); + } + + @SuppressWarnings("divzero") + public static int intRemZero(int val) { + return val % 0; + } + + @Test + public void testIntRemZero() { + test("intRemZero", -10); + test("intRemZero", 0); + test("intRemZero", 4256); + test("intRemZero", Integer.MAX_VALUE); + test("intRemZero", Integer.MIN_VALUE); + } + + public static int intRemMax(int val) { + return val % Integer.MAX_VALUE; + } + + @Test + public void testIntRemMax() { + test("intRemMax", -10); + test("intRemMax", 0); + test("intRemMax", 4256); + test("intRemMax", Integer.MAX_VALUE); + test("intRemMax", Integer.MIN_VALUE); + } + + public static int intRemMin(int val) { + return val % Integer.MIN_VALUE; + } + + @Test + public void testIntRemMin() { + test("intRemMin", -10); + test("intRemMin", 0); + test("intRemMin", 4256); + test("intRemMin", Integer.MAX_VALUE); + test("intRemMin", Integer.MIN_VALUE); + } + + public static long longRemPositiveConstant(long val) { + return val % 35170432; + } + + public static int intRemPowerOf2(int val) { + return val % 4; + } + + @Test + public void testIntRemPowerOf2() { + test("intRemPowerOf2", -10); + test("intRemPowerOf2", 0); + test("intRemPowerOf2", 4256); + test("intRemPowerOf2", Integer.MAX_VALUE); + test("intRemPowerOf2", Integer.MIN_VALUE); + } + + @Test + public void testLongRemPositiveConstant() { + test("longRemPositiveConstant", -1234L); + test("longRemPositiveConstant", 0L); + test("longRemPositiveConstant", 214423L); + test("longRemPositiveConstant", Long.MAX_VALUE); + test("longRemPositiveConstant", Long.MIN_VALUE); + } + + public static long longRemNegativeConstant(long val) { + return val % -413; + } + + @Test + public void testLongRemNegativeConstant() { + test("longRemNegativeConstant", -43L); + test("longRemNegativeConstant", 0L); + test("longRemNegativeConstant", 147065L); + test("longRemNegativeConstant", Long.MAX_VALUE); + test("longRemNegativeConstant", Long.MIN_VALUE); + } + + @SuppressWarnings("divzero") + public static long longRemZero(long val) { + return val % 0; + } + + @Test + public void testLongRemZero() { + test("longRemZero", -43L); + test("longRemZero", 0L); + test("longRemZero", 147065L); + test("longRemZero", Long.MAX_VALUE); + test("longRemZero", Long.MIN_VALUE); + } + + public static long longRemMax(long val) { + return val % Long.MAX_VALUE; + } + + @Test + public void testLongRemMax() { + test("longRemMax", -43L); + test("longRemMax", 0L); + test("longRemMax", 147065L); + test("longRemMax", Long.MAX_VALUE); + test("longRemMax", Long.MIN_VALUE); + } + + public static long longRemMin(long val) { + return val % Long.MIN_VALUE; + } + + @Test + public void testLongRemMin() { + test("longRemMin", -43L); + test("longRemMin", 0L); + test("longRemMin", 147065L); + test("longRemMin", Long.MAX_VALUE); + test("longRemMin", Long.MIN_VALUE); + } + + public static long longRemPowerOf2(long val) { + return val % 4L; + } + + @Test + public void testLongRemPowerOf2() { + test("longRemPowerOf2", -43L); + test("longRemPowerOf2", 0L); + test("longRemPowerOf2", 147065L); + test("longRemPowerOf2", Long.MAX_VALUE); + test("longRemPowerOf2", Long.MIN_VALUE); + } +}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryScheduleTest.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryScheduleTest.java Tue Mar 12 19:17:42 2019 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2019, 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
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NestedLoopTest.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NestedLoopTest.java Tue Mar 12 19:17:42 2019 +0100 @@ -161,9 +161,9 @@ Assert.assertTrue(containsDirect(innerMostLoop, d, cfg)); Assert.assertTrue(contains(rootLoop, d, cfg)); Assert.assertTrue(contains(nestedLoop, d, cfg)); - Assert.assertEquals(rootExits, rootLoop.getExits().size()); - Assert.assertEquals(nestedExits, nestedLoop.getExits().size()); - Assert.assertEquals(innerExits, innerMostLoop.getExits().size()); + Assert.assertEquals(rootExits, rootLoop.getLoopExits().size()); + Assert.assertEquals(nestedExits, nestedLoop.getLoopExits().size()); + Assert.assertEquals(innerExits, innerMostLoop.getLoopExits().size()); debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SwitchCanonicalizerTest.java Tue Mar 12 19:17:42 2019 +0100 @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2019, 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.extended.IntegerSwitchNode; +import org.graalvm.compiler.phases.common.CanonicalizerPhase; +import org.junit.Test; + +public class SwitchCanonicalizerTest extends GraalCompilerTest { + + public int divByPowerOf2(int n) { + switch (n / 8) { + case Integer.MAX_VALUE / 8 + 1: + return hashCode(); + default: + return 1; + } + } + + @Test + public void testDivByPowerOf2() { + shouldFoldSwitch("divByPowerOf2"); + } + + public int divByNonPowerOf2(int n) { + switch (n / 7) { + case Integer.MAX_VALUE / 7 + 1: + return hashCode(); + default: + return 1; + } + } + + @Test + public void testDivByNonPowerOf2() { + shouldFoldSwitch("divByNonPowerOf2"); + } + + public int remByPowerOf2(int n) { + switch (n % 8) { + case 9: + return hashCode(); + default: + return 1; + } + } + + @Test + public void testRemByPowerOf2() { + shouldFoldSwitch("remByPowerOf2"); + } + + public int remByPowerOf2PositiveX(int n) { + int n0 = n > 0 ? 8 : 9; + switch (n0 % 8) { + case 9: + return hashCode(); + default: + return 1; + } + } + + @Test + public void testRemByPowerOf2PositiveX() { + shouldFoldSwitch("remByPowerOf2PositiveX"); + } + + public int remByPowerOf2NegativeX(int n) { + int n0 = n > 0 ? -8 : -9; + switch (n0 % 8) { + case 9: + return hashCode(); + default: + return 1; + } + } + + @Test + public void testRemByPowerOf2NegativeX() { + shouldFoldSwitch("remByPowerOf2NegativeX"); + } + + public int remByNonPowerOf2(int n) { + switch (n % 7) { + case 9: + return hashCode(); + default: + return 1; + } + } + + @Test + public void testRemByNonPowerOf2() { + shouldFoldSwitch("remByNonPowerOf2"); + } + + private void shouldFoldSwitch(String methodName) { + StructuredGraph graph = parseForCompile(getResolvedJavaMethod(methodName)); + new CanonicalizerPhase().apply(graph, getDefaultHighTierContext()); + assertFalse(graph.hasNode(IntegerSwitchNode.TYPE)); + } + +}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyCallerSensitiveMethods.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyCallerSensitiveMethods.java Tue Mar 12 19:17:42 2019 +0100 @@ -24,7 +24,7 @@ package org.graalvm.compiler.core.test; -import static org.graalvm.compiler.serviceprovider.GraalServices.Java8OrEarlier; +import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.Java8OrEarlier; import java.lang.annotation.Annotation;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyDebugUsage.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyDebugUsage.java Tue Mar 12 19:17:42 2019 +0100 @@ -150,7 +150,8 @@ "org.graalvm.compiler.truffle.compiler.TruffleCompilerImpl.compilePEGraph", "org.graalvm.compiler.core.test.VerifyDebugUsageTest$ValidDumpUsagePhase.run", "org.graalvm.compiler.core.test.VerifyDebugUsageTest$InvalidConcatDumpUsagePhase.run", - "org.graalvm.compiler.core.test.VerifyDebugUsageTest$InvalidDumpUsagePhase.run")); + "org.graalvm.compiler.core.test.VerifyDebugUsageTest$InvalidDumpUsagePhase.run", + "org.graalvm.compiler.hotspot.SymbolicSnippetEncoder.verifySnippetEncodeDecode")); /** * The set of methods allowed to call a {@code Debug.dump(...)} method with the {@code level} @@ -165,7 +166,8 @@ "org.graalvm.compiler.core.GraalCompiler.emitFrontEnd", "org.graalvm.compiler.phases.BasePhase.dumpAfter", "org.graalvm.compiler.replacements.ReplacementsImpl$GraphMaker.makeGraph", - "org.graalvm.compiler.replacements.SnippetTemplate.instantiate")); + "org.graalvm.compiler.replacements.SnippetTemplate.instantiate", + "org.graalvm.compiler.hotspot.SymbolicSnippetEncoder.verifySnippetEncodeDecode")); private void verifyParameters(StructuredGraph callerGraph, MethodCallTargetNode debugCallTarget, List<? extends ValueNode> args, ResolvedJavaType stringType, int startArgIdx, int varArgsIndex) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/BackendTest.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/BackendTest.java Tue Mar 12 19:17:42 2019 +0100 @@ -25,6 +25,7 @@ package org.graalvm.compiler.core.test.backend; import org.graalvm.compiler.core.GraalCompiler; +import org.graalvm.compiler.core.gen.LIRCompilerBackend; import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.lir.gen.LIRGenerationResult; @@ -52,7 +53,7 @@ throw debug.handle(e); } - LIRGenerationResult lirGen = GraalCompiler.emitLIR(getBackend(), graph, null, null, createLIRSuites(graph.getOptions())); + LIRGenerationResult lirGen = LIRCompilerBackend.emitLIR(getBackend(), graph, null, null, createLIRSuites(graph.getOptions())); return lirGen; }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/RethrowDeoptMaterializeTest.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/RethrowDeoptMaterializeTest.java Tue Mar 12 19:17:42 2019 +0100 @@ -46,7 +46,7 @@ @SuppressWarnings("sync-override") @Override public final Throwable fillInStackTrace() { - return null; + return this; } }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java Tue Mar 12 19:17:42 2019 +0100 @@ -293,7 +293,7 @@ @SuppressWarnings("sync-override") @Override public final Throwable fillInStackTrace() { - return null; + return this; } }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java Tue Mar 12 19:17:42 2019 +0100 @@ -24,42 +24,18 @@ package org.graalvm.compiler.core; -import java.util.Collection; -import java.util.List; - -import jdk.internal.vm.compiler.collections.EconomicSet; import org.graalvm.compiler.code.CompilationResult; -import org.graalvm.compiler.core.LIRGenerationPhase.LIRGenerationContext; -import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.core.common.RetryableBailoutException; -import org.graalvm.compiler.core.common.alloc.ComputeBlockOrder; -import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; -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.CounterKey; import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.debug.DebugContext; -import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.MethodFilter; 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; import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; -import org.graalvm.compiler.lir.framemap.FrameMap; -import org.graalvm.compiler.lir.framemap.FrameMapBuilder; -import org.graalvm.compiler.lir.gen.LIRGenerationResult; -import org.graalvm.compiler.lir.gen.LIRGeneratorTool; -import org.graalvm.compiler.lir.phases.AllocationPhase.AllocationContext; import org.graalvm.compiler.lir.phases.LIRSuites; -import org.graalvm.compiler.lir.phases.PostAllocationOptimizationPhase.PostAllocationOptimizationContext; -import org.graalvm.compiler.lir.phases.PreAllocationOptimizationPhase.PreAllocationOptimizationContext; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; -import org.graalvm.compiler.nodes.cfg.Block; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; @@ -70,17 +46,8 @@ import org.graalvm.compiler.phases.tiers.TargetProvider; import org.graalvm.compiler.phases.util.Providers; -import jdk.vm.ci.code.RegisterConfig; -import jdk.vm.ci.code.TargetDescription; -import jdk.vm.ci.code.site.ConstantReference; -import jdk.vm.ci.code.site.DataPatch; -import jdk.vm.ci.meta.Assumptions; -import jdk.vm.ci.meta.JavaConstant; -import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ProfilingInfo; -import jdk.vm.ci.meta.ResolvedJavaField; import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.meta.VMConstant; /** * Static methods for orchestrating the compilation of a {@linkplain StructuredGraph graph}. @@ -89,9 +56,6 @@ 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}. @@ -178,7 +142,7 @@ assert !r.graph.isFrozen(); 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); + r.backend.emitBackEnd(r.graph, null, r.installedCodeOwner, r.compilationResult, r.factory, null, r.lirSuites); if (r.verifySourcePositions) { assert r.graph.verifySourcePositions(true); } @@ -275,85 +239,6 @@ } } - @SuppressWarnings("try") - public static <T extends CompilationResult> void emitBackEnd(StructuredGraph graph, Object stub, ResolvedJavaMethod installedCodeOwner, Backend backend, T compilationResult, - CompilationResultBuilderFactory factory, RegisterConfig registerConfig, LIRSuites lirSuites) { - 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 (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); - } - } catch (Throwable e) { - throw debug.handle(e); - } finally { - graph.checkCancellation(); - } - } - - @SuppressWarnings("try") - public static LIRGenerationResult emitLIR(Backend backend, StructuredGraph graph, Object stub, RegisterConfig registerConfig, LIRSuites lirSuites) { - String registerPressure = GraalOptions.RegisterPressure.getValue(graph.getOptions()); - String[] allocationRestrictedTo = registerPressure == null ? null : registerPressure.split(","); - try { - return emitLIR0(backend, graph, stub, registerConfig, lirSuites, allocationRestrictedTo); - } catch (OutOfRegistersException e) { - if (allocationRestrictedTo != null) { - allocationRestrictedTo = null; - return emitLIR0(backend, graph, stub, registerConfig, lirSuites, allocationRestrictedTo); - } - /* If the re-execution fails we convert the exception into a "hard" failure */ - throw new GraalError(e); - } finally { - graph.checkCancellation(); - } - } - - @SuppressWarnings("try") - private static LIRGenerationResult emitLIR0(Backend backend, StructuredGraph graph, Object stub, RegisterConfig registerConfig, LIRSuites lirSuites, - String[] allocationRestrictedTo) { - 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(); - Block startBlock = schedule.getCFG().getStartBlock(); - assert startBlock != null; - assert startBlock.getPredecessorCount() == 0; - - AbstractBlockBase<?>[] codeEmittingOrder = ComputeBlockOrder.computeCodeEmittingOrder(blocks.length, startBlock); - AbstractBlockBase<?>[] linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blocks.length, startBlock); - 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); - LIRGeneratorTool lirGen = backend.newLIRGenerator(lirGenRes); - NodeLIRBuilderTool nodeLirGen = backend.newNodeLIRBuilder(graph, lirGen); - - // LIR generation - LIRGenerationContext context = new LIRGenerationContext(lirGen, nodeLirGen, graph, schedule); - new LIRGenerationPhase().apply(backend.getTarget(), lirGenRes, context); - - try (DebugContext.Scope s = debug.scope("LIRStages", nodeLirGen, lirGenRes, lir)) { - // Dump LIR along with HIR (the LIR is looked up from context) - 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); - } - } catch (Throwable e) { - throw debug.handle(e); - } finally { - graph.checkCancellation(); - } - } - protected static <T extends CompilationResult> String getCompilationUnitName(StructuredGraph graph, T compilationResult) { if (compilationResult != null && compilationResult.getName() != null) { return compilationResult.getName(); @@ -364,70 +249,4 @@ } return method.format("%H.%n(%p)"); } - - 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(DebugContext.BASIC_LEVEL, lirGenRes.getLIR(), "After PreAllocationOptimizationStage"); - - AllocationContext allocContext = new AllocationContext(lirGen.getSpillMoveFactory(), registerAllocationConfig); - lirSuites.getAllocationStage().apply(target, lirGenRes, allocContext); - debug.dump(DebugContext.BASIC_LEVEL, lirGenRes.getLIR(), "After AllocationStage"); - - PostAllocationOptimizationContext postAllocOptContext = new PostAllocationOptimizationContext(lirGen); - lirSuites.getPostAllocationOptimizationStage().apply(target, lirGenRes, postAllocOptContext); - debug.dump(DebugContext.BASIC_LEVEL, lirGenRes.getLIR(), "After PostAllocationOptimizationStage"); - - return lirGenRes; - } - - @SuppressWarnings("try") - public static void emitCode(Backend backend, Assumptions assumptions, ResolvedJavaMethod rootMethod, Collection<ResolvedJavaMethod> inlinedMethods, EconomicSet<ResolvedJavaField> accessedFields, - int bytecodeSize, LIRGenerationResult lirGenRes, - CompilationResult compilationResult, ResolvedJavaMethod installedCodeOwner, CompilationResultBuilderFactory factory) { - 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); - if (assumptions != null && !assumptions.isEmpty()) { - compilationResult.setAssumptions(assumptions.toArray()); - } - if (rootMethod != null) { - compilationResult.setMethods(rootMethod, inlinedMethods); - compilationResult.setFields(accessedFields); - compilationResult.setBytecodeSize(bytecodeSize); - } - crb.finish(); - if (debug.isCountEnabled()) { - List<DataPatch> ldp = compilationResult.getDataPatches(); - JavaKind[] kindValues = JavaKind.values(); - CounterKey[] dms = new CounterKey[kindValues.length]; - for (int i = 0; i < dms.length; i++) { - dms[i] = DebugContext.counter("DataPatches-%s", kindValues[i]); - } - - for (DataPatch dp : ldp) { - JavaKind kind = JavaKind.Illegal; - if (dp.reference instanceof ConstantReference) { - VMConstant constant = ((ConstantReference) dp.reference).getConstant(); - if (constant instanceof JavaConstant) { - kind = ((JavaConstant) constant).getJavaKind(); - } - } - dms[kind.ordinal()].add(debug, 1); - } - - 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(DebugContext.BASIC_LEVEL, compilationResult, "After code generation"); - } - } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/LIRCompilerBackend.java Tue Mar 12 19:17:42 2019 +0100 @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2017, 2018, 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.gen; + +import java.util.Collection; +import java.util.List; + +import jdk.internal.vm.compiler.collections.EconomicSet; +import org.graalvm.compiler.code.CompilationResult; +import org.graalvm.compiler.core.LIRGenerationPhase; +import org.graalvm.compiler.core.LIRGenerationPhase.LIRGenerationContext; +import org.graalvm.compiler.core.common.GraalOptions; +import org.graalvm.compiler.core.common.alloc.ComputeBlockOrder; +import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; +import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.target.Backend; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugCloseable; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.GraalError; +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; +import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; +import org.graalvm.compiler.lir.framemap.FrameMap; +import org.graalvm.compiler.lir.gen.LIRGenerationResult; +import org.graalvm.compiler.lir.gen.LIRGeneratorTool; +import org.graalvm.compiler.lir.phases.AllocationPhase.AllocationContext; +import org.graalvm.compiler.lir.phases.LIRSuites; +import org.graalvm.compiler.lir.phases.PostAllocationOptimizationPhase.PostAllocationOptimizationContext; +import org.graalvm.compiler.lir.phases.PreAllocationOptimizationPhase.PreAllocationOptimizationContext; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; +import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; + +import jdk.vm.ci.code.RegisterConfig; +import jdk.vm.ci.code.TargetDescription; +import jdk.vm.ci.code.site.ConstantReference; +import jdk.vm.ci.code.site.DataPatch; +import jdk.vm.ci.meta.Assumptions; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.ResolvedJavaField; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.SpeculationLog; +import jdk.vm.ci.meta.VMConstant; + +public class LIRCompilerBackend { + 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."); + + @SuppressWarnings("try") + public static <T extends CompilationResult> void emitBackEnd(StructuredGraph graph, Object stub, ResolvedJavaMethod installedCodeOwner, Backend backend, T compilationResult, + CompilationResultBuilderFactory factory, RegisterConfig registerConfig, LIRSuites lirSuites) { + 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 (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(), + graph.getSpeculationLog(), + bytecodeSize, + lirGen, + compilationResult, + installedCodeOwner, + factory); + } catch (Throwable e) { + throw debug.handle(e); + } + } catch (Throwable e) { + throw debug.handle(e); + } finally { + graph.checkCancellation(); + } + } + + @SuppressWarnings("try") + public static LIRGenerationResult emitLIR(Backend backend, StructuredGraph graph, Object stub, RegisterConfig registerConfig, LIRSuites lirSuites) { + String registerPressure = GraalOptions.RegisterPressure.getValue(graph.getOptions()); + String[] allocationRestrictedTo = registerPressure == null ? null : registerPressure.split(","); + try { + return emitLIR0(backend, graph, stub, registerConfig, lirSuites, allocationRestrictedTo); + } catch (OutOfRegistersException e) { + if (allocationRestrictedTo != null) { + allocationRestrictedTo = null; + return emitLIR0(backend, graph, stub, registerConfig, lirSuites, allocationRestrictedTo); + } + /* If the re-execution fails we convert the exception into a "hard" failure */ + throw new GraalError(e); + } finally { + graph.checkCancellation(); + } + } + + @SuppressWarnings("try") + private static LIRGenerationResult emitLIR0(Backend backend, StructuredGraph graph, Object stub, RegisterConfig registerConfig, LIRSuites lirSuites, + String[] allocationRestrictedTo) { + 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(); + Block startBlock = schedule.getCFG().getStartBlock(); + assert startBlock != null; + assert startBlock.getPredecessorCount() == 0; + + AbstractBlockBase<?>[] codeEmittingOrder = ComputeBlockOrder.computeCodeEmittingOrder(blocks.length, startBlock); + AbstractBlockBase<?>[] linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blocks.length, startBlock); + LIR lir = new LIR(schedule.getCFG(), linearScanOrder, codeEmittingOrder, graph.getOptions(), graph.getDebug()); + + LIRGenerationProvider lirBackend = (LIRGenerationProvider) backend; + LIRGenerationResult lirGenRes = lirBackend.newLIRGenerationResult(graph.compilationId(), lir, registerConfig, graph, stub); + LIRGeneratorTool lirGen = lirBackend.newLIRGenerator(lirGenRes); + NodeLIRBuilderTool nodeLirGen = lirBackend.newNodeLIRBuilder(graph, lirGen); + + // LIR generation + LIRGenerationContext context = new LIRGenerationContext(lirGen, nodeLirGen, graph, schedule); + new LIRGenerationPhase().apply(backend.getTarget(), lirGenRes, context); + + try (DebugContext.Scope s = debug.scope("LIRStages", nodeLirGen, lirGenRes, lir)) { + // Dump LIR along with HIR (the LIR is looked up from context) + 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); + } + } catch (Throwable e) { + throw debug.handle(e); + } finally { + graph.checkCancellation(); + } + } + + private 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(DebugContext.BASIC_LEVEL, lirGenRes.getLIR(), "After PreAllocationOptimizationStage"); + + AllocationContext allocContext = new AllocationContext(lirGen.getSpillMoveFactory(), registerAllocationConfig); + lirSuites.getAllocationStage().apply(target, lirGenRes, allocContext); + debug.dump(DebugContext.BASIC_LEVEL, lirGenRes.getLIR(), "After AllocationStage"); + + PostAllocationOptimizationContext postAllocOptContext = new PostAllocationOptimizationContext(lirGen); + lirSuites.getPostAllocationOptimizationStage().apply(target, lirGenRes, postAllocOptContext); + debug.dump(DebugContext.BASIC_LEVEL, lirGenRes.getLIR(), "After PostAllocationOptimizationStage"); + + return lirGenRes; + } + + @SuppressWarnings("try") + public static void emitCode(Backend backend, + Assumptions assumptions, + ResolvedJavaMethod rootMethod, + Collection<ResolvedJavaMethod> inlinedMethods, + EconomicSet<ResolvedJavaField> accessedFields, + SpeculationLog speculationLog, + int bytecodeSize, + LIRGenerationResult lirGenRes, + CompilationResult compilationResult, + ResolvedJavaMethod installedCodeOwner, + CompilationResultBuilderFactory factory) { + DebugContext debug = lirGenRes.getLIR().getDebug(); + try (DebugCloseable a = EmitCode.start(debug)) { + LIRGenerationProvider lirBackend = (LIRGenerationProvider) backend; + + FrameMap frameMap = lirGenRes.getFrameMap(); + CompilationResultBuilder crb = lirBackend.newCompilationResultBuilder(lirGenRes, frameMap, compilationResult, factory); + lirBackend.emitCode(crb, lirGenRes.getLIR(), installedCodeOwner); + if (assumptions != null && !assumptions.isEmpty()) { + compilationResult.setAssumptions(assumptions.toArray()); + } + if (rootMethod != null) { + compilationResult.setMethods(rootMethod, inlinedMethods); + compilationResult.setFields(accessedFields); + compilationResult.setBytecodeSize(bytecodeSize); + } + if (speculationLog != null) { + compilationResult.setSpeculationLog(speculationLog); + } + crb.finish(); + if (debug.isCountEnabled()) { + List<DataPatch> ldp = compilationResult.getDataPatches(); + JavaKind[] kindValues = JavaKind.values(); + CounterKey[] dms = new CounterKey[kindValues.length]; + for (int i = 0; i < dms.length; i++) { + dms[i] = DebugContext.counter("DataPatches-%s", kindValues[i]); + } + + for (DataPatch dp : ldp) { + JavaKind kind = JavaKind.Illegal; + if (dp.reference instanceof ConstantReference) { + VMConstant constant = ((ConstantReference) dp.reference).getConstant(); + if (constant instanceof JavaConstant) { + kind = ((JavaConstant) constant).getJavaKind(); + } + } + dms[kind.ordinal()].add(debug, 1); + } + + 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(DebugContext.BASIC_LEVEL, compilationResult, "After code generation"); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/LIRGenerationProvider.java Tue Mar 12 19:17:42 2019 +0100 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2017, 2018, 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.gen; + +import org.graalvm.compiler.code.CompilationResult; +import org.graalvm.compiler.core.common.CompilationIdentifier; +import org.graalvm.compiler.lir.LIR; +import org.graalvm.compiler.lir.asm.CompilationResultBuilder; +import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; +import org.graalvm.compiler.lir.framemap.FrameMap; +import org.graalvm.compiler.lir.gen.LIRGenerationResult; +import org.graalvm.compiler.lir.gen.LIRGeneratorTool; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; + +import jdk.vm.ci.code.RegisterConfig; +import jdk.vm.ci.meta.ResolvedJavaMethod; + +/** + * Provides compiler backend-specific generation helpers for the {@link LIRCompilerBackend}. + */ +public interface LIRGenerationProvider { + LIRGeneratorTool newLIRGenerator(LIRGenerationResult lirGenRes); + + LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, RegisterConfig registerConfig, StructuredGraph graph, + Object stub); + + NodeLIRBuilderTool newNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen); + + /** + * Creates the object used to fill in the details of a given compilation result. + */ + CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenResult, FrameMap frameMap, CompilationResult compilationResult, + CompilationResultBuilderFactory factory); + + /** + * Emits the code for a given graph. + * + * @param installedCodeOwner the method the compiled code will be associated with once + * installed. This argument can be null. + */ + void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner); +}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java Tue Mar 12 19:17:42 2019 +0100 @@ -768,4 +768,13 @@ public LIRGeneratorTool getLIRGeneratorTool() { return gen; } + + @Override + public void emitReadExceptionObject(ValueNode node) { + LIRGeneratorTool lirGenTool = getLIRGeneratorTool(); + Value returnRegister = lirGenTool.getRegisterConfig().getReturnRegister(node.getStackKind()).asValue( + LIRKind.fromJavaKind(lirGenTool.target().arch, node.getStackKind())); + lirGenTool.emitIncomingValues(new Value[]{returnRegister}); + setResult(node, lirGenTool.emitMove(returnRegister)); + } }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/HighTier.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/HighTier.java Tue Mar 12 19:17:42 2019 +0100 @@ -47,7 +47,7 @@ import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.CanonicalizerPhase; -import org.graalvm.compiler.phases.common.ConvertDeoptimizeToGuardPhase; +import org.graalvm.compiler.loop.phases.ConvertDeoptimizeToGuardPhase; import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; import org.graalvm.compiler.phases.common.IncrementalCanonicalizerPhase; import org.graalvm.compiler.phases.common.IterativeConditionalEliminationPhase;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/LowTier.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/LowTier.java Tue Mar 12 19:17:42 2019 +0100 @@ -39,6 +39,7 @@ import org.graalvm.compiler.phases.common.ExpandLogicPhase; import org.graalvm.compiler.phases.common.FixReadsPhase; import org.graalvm.compiler.phases.common.LoweringPhase; +import org.graalvm.compiler.phases.common.OptimizeDivPhase; import org.graalvm.compiler.phases.common.ProfileCompiledMethodsPhase; import org.graalvm.compiler.phases.common.PropagateDeoptimizeProbabilityPhase; import org.graalvm.compiler.phases.common.UseTrappingNullChecksPhase; @@ -72,6 +73,8 @@ appendPhase(new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.LOW_TIER)); + appendPhase(new OptimizeDivPhase()); + appendPhase(new ExpandLogicPhase()); appendPhase(new FixReadsPhase(true, new SchedulePhase(GraalOptions.StressTestEarlyReads.getValue(options) ? SchedulingStrategy.EARLIEST : SchedulingStrategy.LATEST_OUT_OF_LOOPS)));
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java Tue Mar 12 19:17:42 2019 +0100 @@ -26,24 +26,17 @@ import java.util.ArrayList; -import jdk.internal.vm.compiler.collections.EconomicSet; -import org.graalvm.compiler.asm.Assembler; import org.graalvm.compiler.code.CompilationResult; 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.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; +import org.graalvm.compiler.core.gen.LIRCompilerBackend; 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; -import org.graalvm.compiler.lir.framemap.FrameMap; -import org.graalvm.compiler.lir.framemap.FrameMapBuilder; -import org.graalvm.compiler.lir.gen.LIRGenerationResult; -import org.graalvm.compiler.lir.gen.LIRGeneratorTool; +import org.graalvm.compiler.lir.phases.LIRSuites; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.SuitesProvider; import org.graalvm.compiler.phases.tiers.TargetProvider; @@ -54,7 +47,6 @@ import jdk.vm.ci.code.CompilationRequest; import jdk.vm.ci.code.CompiledCode; import jdk.vm.ci.code.InstalledCode; -import jdk.vm.ci.code.Register; import jdk.vm.ci.code.RegisterConfig; import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.code.ValueKindFactory; @@ -62,7 +54,6 @@ import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.meta.SpeculationLog; /** * Represents a compiler backend for Graal. @@ -117,12 +108,6 @@ } /** - * The given registerConfig is optional, in case null is passed the default RegisterConfig from - * the CodeCacheProvider will be used. - */ - public abstract FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig); - - /** * Creates a new configuration for register allocation. * * @param allocationRestrictedTo if not {@code null}, register allocation will be restricted to @@ -130,26 +115,6 @@ */ public abstract RegisterAllocationConfig newRegisterAllocationConfig(RegisterConfig registerConfig, String[] allocationRestrictedTo); - public abstract FrameMap newFrameMap(RegisterConfig registerConfig); - - public abstract LIRGeneratorTool newLIRGenerator(LIRGenerationResult lirGenRes); - - public abstract LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, FrameMapBuilder frameMapBuilder, StructuredGraph graph, - Object stub); - - public abstract NodeLIRBuilderTool newNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen); - - /** - * Creates the assembler used to emit the machine code. - */ - protected abstract Assembler createAssembler(FrameMap frameMap); - - /** - * Creates the object used to fill in the details of a given compilation result. - */ - public abstract CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenResult, FrameMap frameMap, CompilationResult compilationResult, - CompilationResultBuilderFactory factory); - /** * Turns a Graal {@link CompilationResult} into a {@link CompiledCode} object that can be passed * to the VM for code installation. @@ -158,21 +123,28 @@ /** * @see #createInstalledCode(DebugContext, ResolvedJavaMethod, CompilationRequest, - * CompilationResult, SpeculationLog, InstalledCode, boolean, Object[]) + * CompilationResult, InstalledCode, boolean, Object[]) */ - public InstalledCode createInstalledCode(DebugContext debug, ResolvedJavaMethod method, CompilationResult compilationResult, - SpeculationLog speculationLog, InstalledCode predefinedInstalledCode, boolean isDefault) { - return createInstalledCode(debug, method, null, compilationResult, speculationLog, predefinedInstalledCode, isDefault, null); + public InstalledCode createInstalledCode(DebugContext debug, + ResolvedJavaMethod method, + CompilationResult compilationResult, + InstalledCode predefinedInstalledCode, + boolean isDefault) { + return createInstalledCode(debug, method, null, compilationResult, predefinedInstalledCode, isDefault, null); } /** * @see #createInstalledCode(DebugContext, ResolvedJavaMethod, CompilationRequest, - * CompilationResult, SpeculationLog, InstalledCode, boolean, Object[]) + * CompilationResult, InstalledCode, boolean, Object[]) */ @SuppressWarnings("try") - public InstalledCode createInstalledCode(DebugContext debug, ResolvedJavaMethod method, CompilationRequest compilationRequest, CompilationResult compilationResult, - SpeculationLog speculationLog, InstalledCode predefinedInstalledCode, boolean isDefault) { - return createInstalledCode(debug, method, compilationRequest, compilationResult, speculationLog, predefinedInstalledCode, isDefault, null); + public InstalledCode createInstalledCode(DebugContext debug, + ResolvedJavaMethod method, + CompilationRequest compilationRequest, + CompilationResult compilationResult, + InstalledCode predefinedInstalledCode, + boolean isDefault) { + return createInstalledCode(debug, method, compilationRequest, compilationResult, predefinedInstalledCode, isDefault, null); } /** @@ -185,7 +157,6 @@ * @param predefinedInstalledCode a pre-allocated {@link InstalledCode} object to use as a * reference to the installed code. If {@code null}, a new {@link InstalledCode} * object will be created. - * @param speculationLog the speculation log to be used * @param isDefault specifies if the installed code should be made the default implementation of * {@code compRequest.getMethod()}. The default implementation for a method is the * code executed for standard calls to the method. This argument is ignored if @@ -198,8 +169,13 @@ * {@link InstalledCode} object */ @SuppressWarnings("try") - public InstalledCode createInstalledCode(DebugContext debug, ResolvedJavaMethod method, CompilationRequest compilationRequest, CompilationResult compilationResult, - SpeculationLog speculationLog, InstalledCode predefinedInstalledCode, boolean isDefault, Object[] context) { + public InstalledCode createInstalledCode(DebugContext debug, + ResolvedJavaMethod method, + CompilationRequest compilationRequest, + CompilationResult compilationResult, + InstalledCode predefinedInstalledCode, + boolean isDefault, + Object[] context) { Object[] debugContext = context != null ? context : new Object[]{getProviders().getCodeCache(), method, compilationResult}; CodeInstallationTask[] tasks; synchronized (this) { @@ -215,7 +191,7 @@ try { preCodeInstallationTasks(tasks, compilationResult); CompiledCode compiledCode = createCompiledCode(method, compilationRequest, compilationResult, isDefault, debug.getOptions()); - installedCode = getProviders().getCodeCache().installCode(method, compiledCode, predefinedInstalledCode, speculationLog, isDefault); + installedCode = getProviders().getCodeCache().installCode(method, compiledCode, predefinedInstalledCode, compilationResult.getSpeculationLog(), isDefault); assert predefinedInstalledCode == null || installedCode == predefinedInstalledCode; } catch (Throwable t) { failCodeInstallationTasks(tasks, t); @@ -259,12 +235,15 @@ * @param method the method compiled to produce {@code compiledCode} or {@code null} if the * input to {@code compResult} was not a {@link ResolvedJavaMethod} * @param compilationRequest the request or {@code null} - * @param compilationResult the code to be compiled + * @param compilationResult the compiled code * @return a reference to the compiled and ready-to-run installed code * @throws BailoutException if the code installation failed */ - public InstalledCode addInstalledCode(DebugContext debug, ResolvedJavaMethod method, CompilationRequest compilationRequest, CompilationResult compilationResult) { - return createInstalledCode(debug, method, compilationRequest, compilationResult, null, null, false); + public InstalledCode addInstalledCode(DebugContext debug, + ResolvedJavaMethod method, + CompilationRequest compilationRequest, + CompilationResult compilationResult) { + return createInstalledCode(debug, method, compilationRequest, compilationResult, null, false); } /** @@ -273,30 +252,16 @@ * * @param method the method compiled to produce {@code compiledCode} or {@code null} if the * input to {@code compResult} was not a {@link ResolvedJavaMethod} - * @param compilationResult the code to be compiled + * @param compilationResult the compiled code * @return a reference to the compiled and ready-to-run installed code * @throws BailoutException if the code installation failed */ public InstalledCode createDefaultInstalledCode(DebugContext debug, ResolvedJavaMethod method, CompilationResult compilationResult) { - return createInstalledCode(debug, method, compilationResult, null, null, true); + System.out.println(compilationResult.getSpeculationLog()); + return createInstalledCode(debug, method, compilationResult, null, true); } /** - * Emits the code for a given graph. - * - * @param installedCodeOwner the method the compiled code will be associated with once - * installed. This argument can be null. - */ - public abstract void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner); - - /** - * Translates a set of registers from the callee's perspective to the caller's perspective. This - * is needed for architectures where input/output registers are renamed during a call (e.g. - * register windows on SPARC). Registers which are not visible by the caller are removed. - */ - public abstract EconomicSet<Register> translateToCallerRegisters(EconomicSet<Register> calleeRegisters); - - /** * Gets the compilation id for a given {@link ResolvedJavaMethod}. Returns * {@code CompilationIdentifier#INVALID_COMPILATION_ID} in case there is no such id. * @@ -306,6 +271,15 @@ return CompilationIdentifier.INVALID_COMPILATION_ID; } + public void emitBackEnd(StructuredGraph graph, + Object stub, + ResolvedJavaMethod installedCodeOwner, + CompilationResult compilationResult, + CompilationResultBuilderFactory factory, + RegisterConfig config, LIRSuites lirSuites) { + LIRCompilerBackend.emitBackEnd(graph, stub, installedCodeOwner, this, compilationResult, factory, config, lirSuites); + } + /** * Encapsulates custom tasks done before and after code installation. */
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java Tue Mar 12 19:17:42 2019 +0100 @@ -450,11 +450,11 @@ } } - public Path getDumpPath(String extension, boolean directory) { + public Path getDumpPath(String extension, boolean createMissingDirectory) { try { String id = description == null ? null : description.identifier; String label = description == null ? null : description.getLabel(); - Path result = PathUtilities.createUnique(immutable.options, DumpPath, id, label, extension, directory); + Path result = PathUtilities.createUnique(immutable.options, DumpPath, id, label, extension, createMissingDirectory); if (ShowDumpFiles.getValue(immutable.options)) { TTY.println("Dumping debug output to %s", result.toAbsolutePath().toString()); } @@ -807,8 +807,9 @@ return true; } return !currentScope.isTopLevel(); + } else { + return false; } - return immutable.scopesEnabled && currentScope == null; } class DisabledScope implements DebugContext.Scope {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugOptions.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugOptions.java Tue Mar 12 19:17:42 2019 +0100 @@ -30,6 +30,7 @@ import java.nio.file.Paths; import jdk.internal.vm.compiler.collections.EconomicMap; +import org.graalvm.compiler.options.EnumOptionKey; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; @@ -40,20 +41,28 @@ * Options that configure a {@link DebugContext} and related functionality. */ public class DebugOptions { - static class DeprecatedOptionKey<T> extends OptionKey<T> { - private final OptionKey<T> replacement; - DeprecatedOptionKey(OptionKey<T> replacement) { - super(replacement.getDefaultValue()); - this.replacement = replacement; - } + /** + * Values for the {@link DebugOptions#PrintGraph} option denoting where graphs dumped as a + * result of the {@link DebugOptions#Dump} option are sent. + */ + public enum PrintGraphTarget { + /** + * Dump graphs to files. + */ + File, - @Override - protected void onValueUpdate(EconomicMap<OptionKey<?>, 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); - } + /** + * Dump graphs to the network. The network destination is specified by the + * {@link DebugOptions#PrintGraphHost} and {@link DebugOptions#PrintGraphPort} options. If a + * network connection cannot be opened, dumping falls back to {@link #File} dumping. + */ + Network, + + /** + * Do not dump graphs. + */ + Disable; } // @formatter:off @@ -118,7 +127,7 @@ public static final OptionKey<Boolean> LogVerbose = new OptionKey<>(false); @Option(help = "The directory where various Graal dump files are written.") - public static final OptionKey<String> DumpPath = new OptionKey<>("dumps"); + public static final OptionKey<String> DumpPath = new OptionKey<>("graal_dumps"); @Option(help = "Print the name of each dump file path as it's created.") public static final OptionKey<Boolean> ShowDumpFiles = new OptionKey<>(false); @@ -127,15 +136,30 @@ @Option(help = "Enable dumping LIR, register allocation and code generation info to the C1Visualizer.", type = OptionType.Debug) public static final OptionKey<Boolean> PrintBackendCFG = new OptionKey<>(true); - @Option(help = "Enable dumping to the IdealGraphVisualizer.", type = OptionType.Debug) - public static final OptionKey<Boolean> PrintGraph = new OptionKey<>(true); - @Option(help = "Print graphs to files instead of sending them over the network.", type = OptionType.Debug) - public static final OptionKey<Boolean> PrintGraphFile = new OptionKey<>(false); + @Option(help = "file:doc-files/PrintGraphHelp.txt", type = OptionType.Debug) + public static final EnumOptionKey<PrintGraphTarget> PrintGraph = new EnumOptionKey<>(PrintGraphTarget.File); + + @Option(help = "Setting to true sets PrintGraph=file, setting to false sets PrintGraph=network", type = OptionType.Debug) + public static final OptionKey<Boolean> PrintGraphFile = new OptionKey<Boolean>(true) { + @Override + protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, Boolean oldValue, Boolean newValue) { + PrintGraphTarget v = PrintGraph.getValueOrDefault(values); + if (newValue.booleanValue()) { + if (v != PrintGraphTarget.File) { + PrintGraph.update(values, PrintGraphTarget.File); + } + } else { + if (v != PrintGraphTarget.Network) { + PrintGraph.update(values, PrintGraphTarget.Network); + } + } + } + }; @Option(help = "Host part of the address to which graphs are dumped.", type = OptionType.Debug) public static final OptionKey<String> PrintGraphHost = new OptionKey<>("127.0.0.1"); @Option(help = "Port part of the address to which graphs are dumped in binary format.", type = OptionType.Debug) - public static final OptionKey<Integer> PrintBinaryGraphPort = new OptionKey<>(4445); + public static final OptionKey<Integer> PrintGraphPort = new OptionKey<>(4445); @Option(help = "Schedule graphs as they are dumped.", type = OptionType.Debug) public static final OptionKey<Boolean> PrintGraphWithSchedule = new OptionKey<>(false);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/IgvDumpChannel.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/IgvDumpChannel.java Tue Mar 12 19:17:42 2019 +0100 @@ -24,6 +24,10 @@ package org.graalvm.compiler.debug; +import static org.graalvm.compiler.debug.DebugOptions.PrintGraphHost; +import static org.graalvm.compiler.debug.DebugOptions.PrintGraphPort; + +import java.io.File; import java.io.IOException; import java.io.InterruptedIOException; import java.net.InetSocketAddress; @@ -35,10 +39,12 @@ import java.nio.file.Path; import java.nio.file.StandardOpenOption; import java.util.function.Supplier; -import static org.graalvm.compiler.debug.DebugOptions.PrintBinaryGraphPort; -import static org.graalvm.compiler.debug.DebugOptions.PrintGraphHost; + +import org.graalvm.compiler.debug.DebugOptions.PrintGraphTarget; import org.graalvm.compiler.options.OptionValues; +import jdk.vm.ci.common.NativeImageReinitialize; + final class IgvDumpChannel implements WritableByteChannel { private final Supplier<Path> pathProvider; private final OptionValues options; @@ -52,7 +58,8 @@ @Override public int write(ByteBuffer src) throws IOException { - return channel().write(src); + WritableByteChannel channel = channel(); + return channel == null ? 0 : channel.write(src); } @Override @@ -77,10 +84,13 @@ throw new IOException(); } if (sharedChannel == null) { - if (DebugOptions.PrintGraphFile.getValue(options)) { - sharedChannel = createFileChannel(pathProvider); + PrintGraphTarget target = DebugOptions.PrintGraph.getValue(options); + if (target == PrintGraphTarget.File) { + sharedChannel = createFileChannel(pathProvider, null); + } else if (target == PrintGraphTarget.Network) { + sharedChannel = createNetworkChannel(pathProvider, options); } else { - sharedChannel = createNetworkChannel(pathProvider, options); + TTY.println("WARNING: Graph dumping requested but value of %s option is %s", DebugOptions.PrintGraph.getName(), PrintGraphTarget.Disable); } } return sharedChannel; @@ -88,10 +98,11 @@ private static WritableByteChannel createNetworkChannel(Supplier<Path> pathProvider, OptionValues options) throws IOException { String host = PrintGraphHost.getValue(options); - int port = PrintBinaryGraphPort.getValue(options); + int port = PrintGraphPort.getValue(options); try { WritableByteChannel channel = SocketChannel.open(new InetSocketAddress(host, port)); - TTY.println("Connected to the IGV on %s:%d", host, port); + String targetAnnouncement = String.format("Connected to the IGV on %s:%d", host, port); + maybeAnnounceTarget(targetAnnouncement); return channel; } catch (ClosedByInterruptException | InterruptedIOException e) { /* @@ -101,18 +112,39 @@ */ return null; } catch (IOException e) { - if (!DebugOptions.PrintGraphFile.hasBeenSet(options)) { - return createFileChannel(pathProvider); + String networkFailure = String.format("Could not connect to the IGV on %s:%d", host, port); + if (pathProvider != null) { + return createFileChannel(pathProvider, networkFailure); } else { - throw new IOException(String.format("Could not connect to the IGV on %s:%d", host, port), e); + throw new IOException(networkFailure, e); } } } - private static WritableByteChannel createFileChannel(Supplier<Path> pathProvider) throws IOException { + @NativeImageReinitialize private static String lastTargetAnnouncement; + + private static void maybeAnnounceTarget(String targetAnnouncement) { + if (!targetAnnouncement.equals(lastTargetAnnouncement)) { + // Ignore races - an extra announcement is ok + lastTargetAnnouncement = targetAnnouncement; + TTY.println(targetAnnouncement); + } + } + + private static WritableByteChannel createFileChannel(Supplier<Path> pathProvider, String networkFailure) throws IOException { Path path = pathProvider.get(); try { - return FileChannel.open(path, StandardOpenOption.WRITE, StandardOpenOption.CREATE); + FileChannel channel = FileChannel.open(path, StandardOpenOption.WRITE, StandardOpenOption.CREATE); + File dir = path.toFile(); + if (!dir.isDirectory()) { + dir = dir.getParentFile(); + } + if (networkFailure == null) { + maybeAnnounceTarget("Dumping IGV graphs in " + dir); + } else { + maybeAnnounceTarget(networkFailure + ". Dumping IGV graphs in " + dir); + } + return channel; } catch (IOException e) { throw new IOException(String.format("Failed to open %s to dump IGV graphs", path), e); }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/PathUtilities.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/PathUtilities.java Tue Mar 12 19:17:42 2019 +0100 @@ -84,7 +84,7 @@ private static final String ELLIPSIS = "..."; - static Path createUnique(OptionValues options, OptionKey<String> baseNameOption, String id, String label, String ext, boolean createDirectory) throws IOException { + static Path createUnique(OptionValues options, OptionKey<String> baseNameOption, String id, String label, String ext, boolean createMissingDirectory) throws IOException { String uniqueTag = ""; int dumpCounter = 1; String prefix; @@ -118,7 +118,7 @@ Path dumpDir = DebugOptions.getDumpDirectory(options); Path result = Paths.get(dumpDir.toString(), fileName); try { - if (createDirectory) { + if (createMissingDirectory) { return Files.createDirectory(result); } else { try {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/doc-files/PrintGraphHelp.txt Tue Mar 12 19:17:42 2019 +0100 @@ -0,0 +1,6 @@ +Where IdealGraphVisualizer graph dumps triggered by Dump or DumpOnError should be written. +The accepted values are: + File - Dump IGV graphs to the local file system (see DumpPath). + Network - Dump IGV graphs to the network destination specified by PrintGraphHost and PrintGraphPort. + If a network connection cannot be opened, dumping falls back to file dumping. + Disable - Do not dump IGV graphs. \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/graphio/GraphOutputTest.java Tue Mar 12 19:17:42 2019 +0100 @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2019, 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.graph.test.graphio; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.Channels; +import java.nio.channels.WritableByteChannel; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.Objects; +import org.graalvm.graphio.GraphOutput; +import org.graalvm.graphio.GraphStructure; +import org.junit.Test; + +public final class GraphOutputTest { + + @Test + @SuppressWarnings("static-method") + public void testWritableByteChannel() throws IOException { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + WritableByteChannel channel = Channels.newChannel(out); + ByteBuffer data = generateData(1 << 17); + GraphOutput<?, ?> graphOutput = GraphOutput.newBuilder(new MockGraphStructure()).protocolVersion(6, 0).embedded(true).build(channel); + try (GraphOutput<?, ?> closable = graphOutput) { + assertTrue(closable.isOpen()); + closable.write(data); + } + assertFalse(graphOutput.isOpen()); + assertArrayEquals(data.array(), out.toByteArray()); + } + + @Test + @SuppressWarnings("static-method") + public void testWriteDuringPrint() throws IOException { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + WritableByteChannel channel = Channels.newChannel(out); + class Action implements Runnable { + GraphOutput<MockGraph, ?> out; + + @Override + public void run() { + try { + ByteBuffer data = ByteBuffer.allocate(16); + data.limit(16); + out.write(data); + } catch (IOException ioe) { + throw new RuntimeException(ioe); + } + } + } + Action action = new Action(); + try (GraphOutput<MockGraph, ?> graphOutput = GraphOutput.newBuilder(new MockGraphStructure(action)).protocolVersion(6, 0).build(channel)) { + action.out = graphOutput; + try { + graphOutput.print(new MockGraph(), Collections.emptyMap(), 0, "Mock Graph"); + fail("Expected IllegalStateException"); + } catch (IllegalStateException ise) { + // expected exception + } + } + } + + @Test + @SuppressWarnings("static-method") + public void testEmbeddedWritableByteChannel() throws IOException { + ByteArrayOutputStream expected = new ByteArrayOutputStream(); + WritableByteChannel expectedChannel = Channels.newChannel(expected); + Map<Object, Object> properties = Collections.singletonMap("version.id", 1); + try (GraphOutput<MockGraph, ?> graphOutput = GraphOutput.newBuilder(new MockGraphStructure()).protocolVersion(6, 0).build(expectedChannel)) { + graphOutput.print(new MockGraph(), properties, 1, "Graph 1"); + graphOutput.write(ByteBuffer.allocate(0)); + graphOutput.print(new MockGraph(), properties, 2, "Graph 1"); + } + ByteArrayOutputStream embedded = new ByteArrayOutputStream(); + SharedWritableByteChannel embeddChannel = new SharedWritableByteChannel(Channels.newChannel(embedded)); + try { + try (GraphOutput<MockGraph, ?> baseOutput = GraphOutput.newBuilder(new MockGraphStructure()).protocolVersion(6, 0).build(embeddChannel)) { + try (GraphOutput<MockGraph, ?> embeddedOutput = GraphOutput.newBuilder(new MockGraphStructure()).protocolVersion(6, 0).embedded(true).build((WritableByteChannel) baseOutput)) { + embeddedOutput.print(new MockGraph(), properties, 1, "Graph 1"); + baseOutput.print(new MockGraph(), properties, 2, "Graph 1"); + } + } + } finally { + embeddChannel.realClose(); + } + assertArrayEquals(expected.toByteArray(), embedded.toByteArray()); + } + + private static ByteBuffer generateData(int size) { + ByteBuffer buffer = ByteBuffer.allocate(size); + for (int i = 0; i < size; i++) { + buffer.put(i, (byte) i); + } + buffer.limit(size); + return buffer; + } + + private static final class SharedWritableByteChannel implements WritableByteChannel { + + private final WritableByteChannel delegate; + + SharedWritableByteChannel(WritableByteChannel delegate) { + Objects.requireNonNull(delegate, "Delegate must be non null."); + this.delegate = delegate; + } + + @Override + public int write(ByteBuffer bb) throws IOException { + return delegate.write(bb); + } + + @Override + public boolean isOpen() { + return delegate.isOpen(); + } + + @Override + public void close() throws IOException { + } + + void realClose() throws IOException { + delegate.close(); + } + } + + private static final class MockGraphStructure implements GraphStructure<MockGraph, Void, Void, Void> { + + private final Runnable enterAction; + + MockGraphStructure() { + this.enterAction = null; + } + + MockGraphStructure(Runnable enterAction) { + this.enterAction = enterAction; + } + + @Override + public MockGraph graph(MockGraph currentGraph, Object obj) { + onEnter(); + return null; + } + + @Override + public Iterable<? extends Void> nodes(MockGraph graph) { + onEnter(); + return Collections.emptySet(); + } + + @Override + public int nodesCount(MockGraph graph) { + onEnter(); + return 0; + } + + @Override + public int nodeId(Void node) { + onEnter(); + return 0; + } + + @Override + public boolean nodeHasPredecessor(Void node) { + onEnter(); + return false; + } + + @Override + public void nodeProperties(MockGraph graph, Void node, Map<String, ? super Object> properties) { + onEnter(); + } + + @Override + public Void node(Object obj) { + onEnter(); + return null; + } + + @Override + public Void nodeClass(Object obj) { + onEnter(); + return null; + } + + @Override + public Void classForNode(Void node) { + onEnter(); + return null; + } + + @Override + public String nameTemplate(Void nodeClass) { + onEnter(); + return null; + } + + @Override + public Object nodeClassType(Void nodeClass) { + onEnter(); + return null; + } + + @Override + public Void portInputs(Void nodeClass) { + onEnter(); + return null; + } + + @Override + public Void portOutputs(Void nodeClass) { + onEnter(); + return null; + } + + @Override + public int portSize(Void port) { + onEnter(); + return 0; + } + + @Override + public boolean edgeDirect(Void port, int index) { + onEnter(); + return false; + } + + @Override + public String edgeName(Void port, int index) { + onEnter(); + return null; + } + + @Override + public Object edgeType(Void port, int index) { + onEnter(); + return null; + } + + @Override + public Collection<? extends Void> edgeNodes(MockGraph graph, Void node, Void port, int index) { + onEnter(); + return null; + } + + private void onEnter() { + if (enterAction != null) { + enterAction.run(); + } + } + } + + private static final class MockGraph { + } +}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java Tue Mar 12 19:17:42 2019 +0100 @@ -24,9 +24,7 @@ package org.graalvm.compiler.graph; -import static org.graalvm.compiler.core.common.Fields.translateInto; import static org.graalvm.compiler.debug.GraalError.shouldNotReachHere; -import static org.graalvm.compiler.graph.Edges.translateInto; import static org.graalvm.compiler.graph.Graph.isModificationCountsEnabled; import static org.graalvm.compiler.graph.InputEdges.translateInto; import static org.graalvm.compiler.graph.Node.WithAllEdges;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java Tue Mar 12 19:17:42 2019 +0100 @@ -36,6 +36,7 @@ import jdk.internal.vm.compiler.collections.EconomicSet; import org.graalvm.compiler.asm.Assembler; +import org.graalvm.compiler.asm.BranchTargetOutOfBoundsException; import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.asm.aarch64.AArch64Address; import org.graalvm.compiler.asm.aarch64.AArch64Assembler; @@ -47,6 +48,7 @@ import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; +import org.graalvm.compiler.core.gen.LIRGenerationProvider; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotDataBuilder; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; @@ -86,21 +88,16 @@ /** * HotSpot AArch64 specific backend. */ -public class AArch64HotSpotBackend extends HotSpotHostBackend { +public class AArch64HotSpotBackend extends HotSpotHostBackend implements LIRGenerationProvider { public AArch64HotSpotBackend(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, HotSpotProviders providers) { super(config, runtime, providers); } - @Override - public FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig) { + private FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig) { RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig; - return new AArch64FrameMapBuilder(newFrameMap(registerConfigNonNull), getCodeCache(), registerConfigNonNull); - } - - @Override - public FrameMap newFrameMap(RegisterConfig registerConfig) { - return new AArch64FrameMap(getCodeCache(), registerConfig, this); + FrameMap frameMap = new AArch64FrameMap(getCodeCache(), registerConfigNonNull, this); + return new AArch64FrameMapBuilder(frameMap, getCodeCache(), registerConfigNonNull); } @Override @@ -109,8 +106,9 @@ } @Override - public LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, FrameMapBuilder frameMapBuilder, StructuredGraph graph, Object stub) { - return new HotSpotLIRGenerationResult(compilationId, lir, frameMapBuilder, makeCallingConvention(graph, (Stub) stub), stub, config.requiresReservedStackCheck(graph.getMethods())); + public LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, RegisterConfig registerConfig, StructuredGraph graph, Object stub) { + return new HotSpotLIRGenerationResult(compilationId, lir, newFrameMapBuilder(registerConfig), makeCallingConvention(graph, (Stub) stub), stub, + config.requiresReservedStackCheck(graph.getMethods())); } @Override @@ -219,18 +217,13 @@ } @Override - protected Assembler createAssembler(FrameMap frameMap) { - return new AArch64MacroAssembler(getTarget()); - } - - @Override public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenRen, FrameMap frameMap, CompilationResult compilationResult, CompilationResultBuilderFactory factory) { HotSpotLIRGenerationResult gen = (HotSpotLIRGenerationResult) lirGenRen; LIR lir = gen.getLIR(); assert gen.getDeoptimizationRescueSlot() == null || frameMap.frameNeedsAllocating() : "method that can deoptimize must have a frame"; Stub stub = gen.getStub(); - Assembler masm = createAssembler(frameMap); + Assembler masm = new AArch64MacroAssembler(getTarget()); HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null); DataBuilder dataBuilder = new HotSpotDataBuilder(getCodeCache().getTarget()); @@ -252,11 +245,25 @@ @Override public void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner) { + Label verifiedStub = new Label(); + crb.buildLabelOffsets(lir); + try { + emitCode(crb, lir, installedCodeOwner, verifiedStub); + } catch (BranchTargetOutOfBoundsException e) { + // A branch estimation was wrong, now retry with conservative label ranges, this + // should always work + crb.setConservativeLabelRanges(); + crb.resetForEmittingCode(); + lir.resetLabels(); + verifiedStub.reset(); + emitCode(crb, lir, installedCodeOwner, verifiedStub); + } + } + + private void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner, Label verifiedStub) { AArch64MacroAssembler masm = (AArch64MacroAssembler) crb.asm; FrameMap frameMap = crb.frameMap; RegisterConfig regConfig = frameMap.getRegisterConfig(); - Label verifiedStub = new Label(); - emitCodePrefix(crb, installedCodeOwner, masm, regConfig, verifiedStub); emitCodeBody(crb, lir, masm); emitCodeSuffix(crb, masm, frameMap);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotJumpToExceptionHandlerInCallerOp.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotJumpToExceptionHandlerInCallerOp.java Tue Mar 12 19:17:42 2019 +0100 @@ -37,7 +37,7 @@ import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.Opcode; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; -import org.graalvm.compiler.serviceprovider.GraalServices; +import org.graalvm.compiler.serviceprovider.JavaVersionUtil; import jdk.vm.ci.code.Register; import jdk.vm.ci.meta.AllocatableValue; @@ -71,7 +71,7 @@ public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { leaveFrame(crb, masm, /* emitSafepoint */false, false); - if (GraalServices.JAVA_SPECIFICATION_VERSION < 8) { + if (JavaVersionUtil.JAVA_SPECIFICATION_VERSION < 8) { // Restore sp from fp if the exception PC is a method handle call site. try (ScratchRegister sc = masm.getScratchRegister()) { Register scratch = sc.getRegister();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/BinaryMathStubTest.java Tue Mar 12 19:17:42 2019 +0100 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, 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.amd64.test; + +import static org.junit.Assume.assumeTrue; + +import java.util.ArrayList; +import java.util.List; + +import org.graalvm.compiler.api.test.Graal; +import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.runtime.RuntimeProvider; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import jdk.vm.ci.amd64.AMD64; +import jdk.vm.ci.code.Architecture; + +@RunWith(Parameterized.class) +public class BinaryMathStubTest extends GraalCompilerTest { + + @Parameterized.Parameters(name = "{0}") + public static List<Object[]> data() { + ArrayList<Object[]> ret = new ArrayList<>(); + ret.add(new Object[]{"pow"}); + return ret; + } + + private static final double[] inputs = {0.0D, Math.PI / 2, Math.PI, -1.0D, Double.MAX_VALUE, Double.MIN_VALUE, Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY}; + private final String stub; + + public BinaryMathStubTest(String stub) { + this.stub = stub; + } + + @Before + public void checkAMD64() { + Architecture arch = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getTarget().arch; + assumeTrue("skipping AMD64 specific test", arch instanceof AMD64); + } + + public static double pow(double x, double y) { + return Math.pow(x, y); + } + + @Test + public void testStub() { + for (double x : inputs) { + for (double y : inputs) { + test(stub, x, y); + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/UnaryMathStubTest.java Tue Mar 12 19:17:42 2019 +0100 @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2018, 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.amd64.test; + +import static org.junit.Assume.assumeTrue; + +import java.util.ArrayList; +import java.util.List; + +import org.graalvm.compiler.api.test.Graal; +import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.runtime.RuntimeProvider; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import jdk.vm.ci.amd64.AMD64; +import jdk.vm.ci.code.Architecture; + +@RunWith(Parameterized.class) +public class UnaryMathStubTest extends GraalCompilerTest { + + @Parameterized.Parameters(name = "{0}") + public static List<Object[]> data() { + ArrayList<Object[]> ret = new ArrayList<>(); + ret.add(new Object[]{"sin"}); + ret.add(new Object[]{"cos"}); + ret.add(new Object[]{"tan"}); + ret.add(new Object[]{"exp"}); + ret.add(new Object[]{"log"}); + ret.add(new Object[]{"log10"}); + return ret; + } + + private static final double[] inputs = {0.0D, Math.PI / 2, Math.PI, -1.0D, Double.MAX_VALUE, Double.MIN_VALUE, Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY}; + private final String stub; + + public UnaryMathStubTest(String stub) { + this.stub = stub; + } + + @Before + public void checkAMD64() { + Architecture arch = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getTarget().arch; + assumeTrue("skipping AMD64 specific test", arch instanceof AMD64); + } + + public static double sin(double value) { + return Math.sin(value); + } + + public static double cos(double value) { + return Math.cos(value); + } + + public static double tan(double value) { + return Math.tan(value); + } + + public static double exp(double value) { + return Math.exp(value); + } + + public static double log(double value) { + return Math.log(value); + } + + public static double log10(double value) { + return Math.log10(value); + } + + @Test + public void testStub() { + for (double input : inputs) { + test(stub, input); + } + } +}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java Tue Mar 12 19:17:42 2019 +0100 @@ -199,7 +199,7 @@ CountedLoopInfo countedLoopInfo = loop.counted(); IntegerStamp initStamp = (IntegerStamp) inductionVariable.initNode().stamp(NodeView.DEFAULT); if (initStamp.isPositive()) { - if (inductionVariable.isConstantExtremum()) { + if (inductionVariable.isConstantExtremum() && countedLoopInfo.counterNeverOverflows()) { long init = inductionVariable.constantInit(); long stride = inductionVariable.constantStride(); long extremum = inductionVariable.constantExtremum(); @@ -211,7 +211,9 @@ } } } - if (countedLoopInfo.getCounter() == inductionVariable && inductionVariable.direction() == InductionVariable.Direction.Up && countedLoopInfo.getOverFlowGuard() != null) { + if (countedLoopInfo.getCounter() == inductionVariable && + inductionVariable.direction() == InductionVariable.Direction.Up && + (countedLoopInfo.getOverFlowGuard() != null || countedLoopInfo.counterNeverOverflows())) { return graph.unique(new ZeroExtendNode(input, INT_BITS, ADDRESS_BITS, true)); } }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java Tue Mar 12 19:17:42 2019 +0100 @@ -43,7 +43,7 @@ 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.core.gen.LIRGenerationProvider; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotDataBuilder; @@ -85,21 +85,16 @@ /** * HotSpot AMD64 specific backend. */ -public class AMD64HotSpotBackend extends HotSpotHostBackend { +public class AMD64HotSpotBackend extends HotSpotHostBackend implements LIRGenerationProvider { public AMD64HotSpotBackend(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, HotSpotProviders providers) { super(config, runtime, providers); } - @Override - public FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig) { + private FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig) { RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig; - return new AMD64FrameMapBuilder(newFrameMap(registerConfigNonNull), getCodeCache(), registerConfigNonNull); - } - - @Override - public FrameMap newFrameMap(RegisterConfig registerConfig) { - return new AMD64FrameMap(getCodeCache(), registerConfig, this); + FrameMap frameMap = new AMD64FrameMap(getCodeCache(), registerConfigNonNull, this); + return new AMD64FrameMapBuilder(frameMap, getCodeCache(), registerConfigNonNull); } @Override @@ -108,8 +103,9 @@ } @Override - public LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, FrameMapBuilder frameMapBuilder, StructuredGraph graph, Object stub) { - return new HotSpotLIRGenerationResult(compilationId, lir, frameMapBuilder, makeCallingConvention(graph, (Stub) stub), stub, config.requiresReservedStackCheck(graph.getMethods())); + public LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, RegisterConfig registerConfig, StructuredGraph graph, Object stub) { + return new HotSpotLIRGenerationResult(compilationId, lir, newFrameMapBuilder(registerConfig), makeCallingConvention(graph, (Stub) stub), stub, + config.requiresReservedStackCheck(graph.getMethods())); } @Override @@ -196,11 +192,6 @@ } @Override - protected Assembler createAssembler(FrameMap frameMap) { - return new AMD64MacroAssembler(getTarget()); - } - - @Override public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenRen, FrameMap frameMap, CompilationResult compilationResult, CompilationResultBuilderFactory factory) { // Omit the frame if the method: // - has no spill slots or other slots allocated during register allocation @@ -216,7 +207,7 @@ boolean omitFrame = CanOmitFrame.getValue(options) && !frameMap.frameNeedsAllocating() && !lir.hasArgInCallerFrame() && !gen.hasForeignCall(); Stub stub = gen.getStub(); - Assembler masm = createAssembler(frameMap); + Assembler masm = new AMD64MacroAssembler(getTarget()); HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null, omitFrame); DataBuilder dataBuilder = new HotSpotDataBuilder(getCodeCache().getTarget()); CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, dataBuilder, frameContext, options, debug, compilationResult, Register.None); @@ -258,7 +249,7 @@ /** * Emits the code prior to the verified entry point. * - * @param installedCodeOwner see {@link Backend#emitCode} + * @param installedCodeOwner see {@link LIRGenerationProvider#emitCode} */ public void emitCodePrefix(ResolvedJavaMethod installedCodeOwner, CompilationResultBuilder crb, AMD64MacroAssembler asm, RegisterConfig regConfig, Label verifiedEntry) { HotSpotProviders providers = getProviders(); @@ -309,14 +300,14 @@ /** * Emits the code which starts at the verified entry point. * - * @param installedCodeOwner see {@link Backend#emitCode} + * @param installedCodeOwner see {@link LIRGenerationProvider#emitCode} */ public void emitCodeBody(ResolvedJavaMethod installedCodeOwner, CompilationResultBuilder crb, LIR lir) { crb.emit(lir); } /** - * @param installedCodeOwner see {@link Backend#emitCode} + * @param installedCodeOwner see {@link LIRGenerationProvider#emitCode} */ public void emitCodeSuffix(ResolvedJavaMethod installedCodeOwner, CompilationResultBuilder crb, AMD64MacroAssembler asm, FrameMap frameMap) { HotSpotProviders providers = getProviders();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java Tue Mar 12 19:17:42 2019 +0100 @@ -25,7 +25,6 @@ package org.graalvm.compiler.hotspot.amd64; import static jdk.vm.ci.common.InitTimer.timer; -import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.GraalArithmeticStubs; import java.util.ArrayList; import java.util.List; @@ -141,7 +140,7 @@ replacements = createReplacements(options, p, snippetReflection, bytecodeProvider); } try (InitTimer rt = timer("create GraphBuilderPhase plugins")) { - plugins = createGraphBuilderPlugins(compilerConfiguration, config, options, target, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes); + plugins = createGraphBuilderPlugins(compilerConfiguration, config, target, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes); replacements.setGraphBuilderPlugins(plugins); } try (InitTimer rt = timer("create Suites provider")) { @@ -157,11 +156,11 @@ } } - protected Plugins createGraphBuilderPlugins(CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, OptionValues options, TargetDescription target, + protected Plugins createGraphBuilderPlugins(CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, TargetDescription target, HotSpotConstantReflectionProvider constantReflection, HotSpotHostForeignCallsProvider foreignCalls, HotSpotMetaAccessProvider metaAccess, HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes) { Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, replacements); - AMD64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), (AMD64) target.arch, GraalArithmeticStubs.getValue(options), false); + AMD64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), (AMD64) target.arch, false); return plugins; }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java Tue Mar 12 19:17:42 2019 +0100 @@ -30,6 +30,7 @@ import static jdk.vm.ci.meta.Value.ILLEGAL; import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER; import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER; +import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.GraalArithmeticStubs; import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.JUMP_ADDRESS; import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Reexecutability.REEXECUTABLE; import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Reexecutability.REEXECUTABLE_ONLY_AFTER_EXCEPTION; @@ -38,10 +39,16 @@ import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF_NOFP; import static org.graalvm.compiler.hotspot.replacements.CRC32CSubstitutions.UPDATE_BYTES_CRC32C; import static org.graalvm.compiler.hotspot.replacements.CRC32Substitutions.UPDATE_BYTES_CRC32; +import static org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode.BinaryOperation.POW; +import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.COS; +import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.EXP; +import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.LOG; +import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.LOG10; +import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.SIN; +import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.TAN; import static jdk.internal.vm.compiler.word.LocationIdentity.any; import org.graalvm.compiler.core.common.LIRKind; -import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkageImpl; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; @@ -62,14 +69,6 @@ public class AMD64HotSpotForeignCallsProvider extends HotSpotHostForeignCallsProvider { - public static final ForeignCallDescriptor ARITHMETIC_SIN_STUB = new ForeignCallDescriptor("arithmeticSinStub", double.class, double.class); - public static final ForeignCallDescriptor ARITHMETIC_COS_STUB = new ForeignCallDescriptor("arithmeticCosStub", double.class, double.class); - public static final ForeignCallDescriptor ARITHMETIC_TAN_STUB = new ForeignCallDescriptor("arithmeticTanStub", double.class, double.class); - public static final ForeignCallDescriptor ARITHMETIC_EXP_STUB = new ForeignCallDescriptor("arithmeticExpStub", double.class, double.class); - public static final ForeignCallDescriptor ARITHMETIC_POW_STUB = new ForeignCallDescriptor("arithmeticPowStub", double.class, double.class, double.class); - public static final ForeignCallDescriptor ARITHMETIC_LOG_STUB = new ForeignCallDescriptor("arithmeticLogStub", double.class, double.class); - public static final ForeignCallDescriptor ARITHMETIC_LOG10_STUB = new ForeignCallDescriptor("arithmeticLog10Stub", double.class, double.class); - private final Value[] nativeABICallerSaveRegisters; public AMD64HotSpotForeignCallsProvider(HotSpotJVMCIRuntime jvmciRuntime, HotSpotGraalRuntimeProvider runtime, MetaAccessProvider metaAccess, CodeCacheProvider codeCache, @@ -93,14 +92,6 @@ register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, exceptionCc, null, any())); register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, exceptionCc, null, any())); - link(new AMD64MathStub(ARITHMETIC_LOG_STUB, options, providers, registerStubCall(ARITHMETIC_LOG_STUB, LEAF, REEXECUTABLE, NO_LOCATIONS))); - link(new AMD64MathStub(ARITHMETIC_LOG10_STUB, options, providers, registerStubCall(ARITHMETIC_LOG10_STUB, LEAF, REEXECUTABLE, NO_LOCATIONS))); - link(new AMD64MathStub(ARITHMETIC_SIN_STUB, options, providers, registerStubCall(ARITHMETIC_SIN_STUB, LEAF, REEXECUTABLE, NO_LOCATIONS))); - link(new AMD64MathStub(ARITHMETIC_COS_STUB, options, providers, registerStubCall(ARITHMETIC_COS_STUB, LEAF, REEXECUTABLE, NO_LOCATIONS))); - link(new AMD64MathStub(ARITHMETIC_TAN_STUB, options, providers, registerStubCall(ARITHMETIC_TAN_STUB, LEAF, REEXECUTABLE, NO_LOCATIONS))); - link(new AMD64MathStub(ARITHMETIC_EXP_STUB, options, providers, registerStubCall(ARITHMETIC_EXP_STUB, LEAF, REEXECUTABLE, NO_LOCATIONS))); - link(new AMD64MathStub(ARITHMETIC_POW_STUB, options, providers, registerStubCall(ARITHMETIC_POW_STUB, LEAF, REEXECUTABLE, NO_LOCATIONS))); - if (config.useCRC32Intrinsics) { // This stub does callee saving registerForeignCall(UPDATE_BYTES_CRC32, config.updateBytesCRC32Stub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any()); @@ -138,4 +129,19 @@ return nativeABICallerSaveRegisters; } + @Override + protected void registerMathStubs(GraalHotSpotVMConfig hotSpotVMConfig, HotSpotProviders providers, OptionValues options) { + if (GraalArithmeticStubs.getValue(options)) { + link(new AMD64MathStub(SIN, options, providers, registerStubCall(SIN.foreignCallDescriptor, LEAF, REEXECUTABLE, NO_LOCATIONS))); + link(new AMD64MathStub(COS, options, providers, registerStubCall(COS.foreignCallDescriptor, LEAF, REEXECUTABLE, NO_LOCATIONS))); + link(new AMD64MathStub(TAN, options, providers, registerStubCall(TAN.foreignCallDescriptor, LEAF, REEXECUTABLE, NO_LOCATIONS))); + link(new AMD64MathStub(EXP, options, providers, registerStubCall(EXP.foreignCallDescriptor, LEAF, REEXECUTABLE, NO_LOCATIONS))); + link(new AMD64MathStub(LOG, options, providers, registerStubCall(LOG.foreignCallDescriptor, LEAF, REEXECUTABLE, NO_LOCATIONS))); + link(new AMD64MathStub(LOG10, options, providers, registerStubCall(LOG10.foreignCallDescriptor, LEAF, REEXECUTABLE, NO_LOCATIONS))); + link(new AMD64MathStub(POW, options, providers, registerStubCall(POW.foreignCallDescriptor, LEAF, REEXECUTABLE, NO_LOCATIONS))); + } else { + super.registerMathStubs(hotSpotVMConfig, providers, options); + } + } + }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotJumpToExceptionHandlerInCallerOp.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotJumpToExceptionHandlerInCallerOp.java Tue Mar 12 19:17:42 2019 +0100 @@ -24,10 +24,10 @@ package org.graalvm.compiler.hotspot.amd64; -import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; import static jdk.vm.ci.amd64.AMD64.rbp; import static jdk.vm.ci.amd64.AMD64.rsp; import static jdk.vm.ci.code.ValueUtil.asRegister; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; import org.graalvm.compiler.asm.amd64.AMD64Address; import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag; @@ -35,7 +35,7 @@ import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.Opcode; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; -import org.graalvm.compiler.serviceprovider.GraalServices; +import org.graalvm.compiler.serviceprovider.JavaVersionUtil; import jdk.vm.ci.code.Register; import jdk.vm.ci.meta.AllocatableValue; @@ -71,7 +71,7 @@ // Discard the return address, thus completing restoration of caller frame masm.incrementq(rsp, 8); - if (GraalServices.JAVA_SPECIFICATION_VERSION < 8) { + if (JavaVersionUtil.JAVA_SPECIFICATION_VERSION < 8) { // Restore rsp from rbp if the exception PC is a method handle call site. AMD64Address dst = new AMD64Address(thread, isMethodHandleReturnOffset); masm.cmpl(dst, 0);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java Tue Mar 12 19:17:42 2019 +0100 @@ -118,7 +118,7 @@ } private AMD64HotSpotLIRGenerator(HotSpotProviders providers, GraalHotSpotVMConfig config, LIRGenerationResult lirGenRes, BackupSlotProvider backupSlotProvider) { - this(new AMD64HotSpotLIRKindTool(), new AMD64ArithmeticLIRGenerator(null, new AMD64HotSpotMaths()), new AMD64HotSpotMoveFactory(backupSlotProvider), providers, config, lirGenRes); + this(new AMD64HotSpotLIRKindTool(), new AMD64ArithmeticLIRGenerator(null), new AMD64HotSpotMoveFactory(backupSlotProvider), providers, config, lirGenRes); } protected AMD64HotSpotLIRGenerator(LIRKindTool lirKindTool, AMD64ArithmeticLIRGenerator arithmeticLIRGen, MoveFactory moveFactory, HotSpotProviders providers, GraalHotSpotVMConfig config,
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java Tue Mar 12 19:17:42 2019 +0100 @@ -25,15 +25,8 @@ package org.graalvm.compiler.hotspot.amd64; import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.GraalArithmeticStubs; -import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_COS_STUB; -import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_EXP_STUB; -import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_LOG10_STUB; -import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_LOG_STUB; -import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_POW_STUB; -import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_SIN_STUB; -import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_TAN_STUB; -import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; +import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.graph.Node; @@ -44,21 +37,26 @@ import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; import org.graalvm.compiler.hotspot.nodes.profiling.ProfileNode; import org.graalvm.compiler.hotspot.replacements.profiling.ProbabilisticProfileSnippets; +import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.calc.FloatConvertNode; +import org.graalvm.compiler.nodes.extended.ForeignCallNode; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.amd64.AMD64ConvertSnippets; -import org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode.BinaryOperation; +import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode; import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation; +import org.graalvm.compiler.serviceprovider.JavaVersionUtil; import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider; import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaMethod; public class AMD64HotSpotLoweringProvider extends DefaultHotSpotLoweringProvider { private AMD64ConvertSnippets.Templates convertSnippets; private ProbabilisticProfileSnippets.Templates profileSnippets; + private AMD64X87MathSnippets.Templates mathSnippets; public AMD64HotSpotLoweringProvider(HotSpotGraalRuntimeProvider runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers, HotSpotConstantReflectionProvider constantReflection, TargetDescription target) { @@ -68,9 +66,10 @@ @Override public void initialize(OptionValues options, Iterable<DebugHandlersFactory> factories, HotSpotProviders providers, GraalHotSpotVMConfig config) { convertSnippets = new AMD64ConvertSnippets.Templates(options, factories, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget()); - profileSnippets = ProfileNode.Options.ProbabilisticProfiling.getValue(options) + profileSnippets = ProfileNode.Options.ProbabilisticProfiling.getValue(options) && !JavaVersionUtil.Java8OrEarlier ? new ProbabilisticProfileSnippets.Templates(options, factories, providers, providers.getCodeCache().getTarget()) : null; + mathSnippets = new AMD64X87MathSnippets.Templates(options, factories, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget()); super.initialize(options, factories, providers, config); } @@ -80,47 +79,49 @@ convertSnippets.lower((FloatConvertNode) n, tool); } else if (profileSnippets != null && n instanceof ProfileNode) { profileSnippets.lower((ProfileNode) n, tool); + } else if (n instanceof UnaryMathIntrinsicNode) { + lowerUnaryMath((UnaryMathIntrinsicNode) n, tool); } else { super.lower(n, tool); } } - @Override - protected ForeignCallDescriptor toForeignCall(UnaryOperation operation) { - if (GraalArithmeticStubs.getValue(runtime.getOptions())) { - switch (operation) { + private void lowerUnaryMath(UnaryMathIntrinsicNode math, LoweringTool tool) { + if (tool.getLoweringStage() == LoweringTool.StandardLoweringStage.HIGH_TIER) { + return; + } + StructuredGraph graph = math.graph(); + ResolvedJavaMethod method = graph.method(); + if (method != null) { + if (method.getAnnotation(Snippet.class) != null) { + // In the context of SnippetStub, i.e., Graal-generated stubs, use the LIR + // lowering to emit the stub assembly code instead of the Node lowering. + return; + } + } + if (!GraalArithmeticStubs.getValue(graph.getOptions())) { + switch (math.getOperation()) { + case SIN: + case COS: + case TAN: + // Math.sin(), .cos() and .tan() guarantee a value within 1 ULP of the exact + // result, but x87 trigonometric FPU instructions are only that accurate within + // [-pi/4, pi/4]. The snippets fall back to a foreign call to HotSpot stubs + // should the inputs outside of that interval. + mathSnippets.lower(math, tool); + return; case LOG: - return ARITHMETIC_LOG_STUB; + math.replaceAtUsages(graph.addOrUnique(new AMD64X87MathIntrinsicNode(math.getValue(), UnaryOperation.LOG))); + return; case LOG10: - return ARITHMETIC_LOG10_STUB; - case SIN: - return ARITHMETIC_SIN_STUB; - case COS: - return ARITHMETIC_COS_STUB; - case TAN: - return ARITHMETIC_TAN_STUB; - case EXP: - return ARITHMETIC_EXP_STUB; + math.replaceAtUsages(graph.addOrUnique(new AMD64X87MathIntrinsicNode(math.getValue(), UnaryOperation.LOG10))); + return; } - } else if (operation == UnaryOperation.EXP) { - return operation.foreignCallDescriptor; } - // Lower only using LIRGenerator - return null; - } - @Override - protected ForeignCallDescriptor toForeignCall(BinaryOperation operation) { - if (GraalArithmeticStubs.getValue(runtime.getOptions())) { - switch (operation) { - case POW: - return ARITHMETIC_POW_STUB; - } - } else if (operation == BinaryOperation.POW) { - return operation.foreignCallDescriptor; - } - // Lower only using LIRGenerator - return null; + ForeignCallNode call = graph.add(new ForeignCallNode(foreignCalls, math.getOperation().foreignCallDescriptor, math.getValue())); + graph.addAfterFixed(tool.lastFixedNode(), call); + math.replaceAtUsages(call); } @Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMaths.java Tue Mar 12 12:12:01 2019 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2016, 2018, 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.amd64; - -import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.GraalArithmeticStubs; -import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.COS; -import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.LOG; -import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.LOG10; -import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.SIN; -import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.TAN; - -import org.graalvm.compiler.core.amd64.AMD64ArithmeticLIRGenerator; -import org.graalvm.compiler.core.common.LIRKind; -import org.graalvm.compiler.hotspot.HotSpotBackend.Options; -import org.graalvm.compiler.lir.Variable; -import org.graalvm.compiler.lir.gen.LIRGenerator; - -import jdk.vm.ci.meta.Value; - -/** - * Lowering of selected {@link Math} routines that depends on the value of - * {@link Options#GraalArithmeticStubs}. - */ -public class AMD64HotSpotMaths implements AMD64ArithmeticLIRGenerator.Maths { - - @Override - public Variable emitLog(LIRGenerator gen, Value input, boolean base10) { - if (GraalArithmeticStubs.getValue(gen.getResult().getLIR().getOptions())) { - return null; - } - Variable result = gen.newVariable(LIRKind.combine(input)); - gen.append(new AMD64HotSpotMathIntrinsicOp(base10 ? LOG10 : LOG, result, gen.asAllocatable(input))); - return result; - } - - @Override - public Variable emitCos(LIRGenerator gen, Value input) { - if (GraalArithmeticStubs.getValue(gen.getResult().getLIR().getOptions())) { - return null; - } - Variable result = gen.newVariable(LIRKind.combine(input)); - gen.append(new AMD64HotSpotMathIntrinsicOp(COS, result, gen.asAllocatable(input))); - return result; - } - - @Override - public Variable emitSin(LIRGenerator gen, Value input) { - if (GraalArithmeticStubs.getValue(gen.getResult().getLIR().getOptions())) { - return null; - } - Variable result = gen.newVariable(LIRKind.combine(input)); - gen.append(new AMD64HotSpotMathIntrinsicOp(SIN, result, gen.asAllocatable(input))); - return result; - } - - @Override - public Variable emitTan(LIRGenerator gen, Value input) { - if (GraalArithmeticStubs.getValue(gen.getResult().getLIR().getOptions())) { - return null; - } - Variable result = gen.newVariable(LIRKind.combine(input)); - gen.append(new AMD64HotSpotMathIntrinsicOp(TAN, result, gen.asAllocatable(input))); - return result; - } - -}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64MathStub.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64MathStub.java Tue Mar 12 19:17:42 2019 +0100 @@ -24,16 +24,8 @@ package org.graalvm.compiler.hotspot.amd64; -import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_COS_STUB; -import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_EXP_STUB; -import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_LOG10_STUB; -import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_LOG_STUB; -import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_POW_STUB; -import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_SIN_STUB; -import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_TAN_STUB; - import org.graalvm.compiler.api.replacements.Snippet; -import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; +import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.stubs.SnippetStub; @@ -48,33 +40,38 @@ */ public class AMD64MathStub extends SnippetStub { - public AMD64MathStub(ForeignCallDescriptor descriptor, OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super(snippetName(descriptor), options, providers, linkage); + public AMD64MathStub(UnaryOperation operation, OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super(snippetName(operation), options, providers, linkage); } - private static String snippetName(ForeignCallDescriptor descriptor) { - if (descriptor == ARITHMETIC_LOG_STUB) { - return "log"; + public AMD64MathStub(BinaryOperation operation, OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super(snippetName(operation), options, providers, linkage); + } + + private static String snippetName(UnaryOperation operation) { + switch (operation) { + case SIN: + return "sin"; + case COS: + return "cos"; + case TAN: + return "tan"; + case EXP: + return "exp"; + case LOG: + return "log"; + case LOG10: + return "log10"; + default: + throw GraalError.shouldNotReachHere("Unknown operation " + operation); } - if (descriptor == ARITHMETIC_LOG10_STUB) { - return "log10"; - } - if (descriptor == ARITHMETIC_SIN_STUB) { - return "sin"; - } - if (descriptor == ARITHMETIC_COS_STUB) { - return "cos"; - } - if (descriptor == ARITHMETIC_TAN_STUB) { - return "tan"; - } - if (descriptor == ARITHMETIC_EXP_STUB) { - return "exp"; - } - if (descriptor == ARITHMETIC_POW_STUB) { + } + + private static String snippetName(BinaryOperation operation) { + if (operation == BinaryOperation.POW) { return "pow"; } - throw new InternalError("Unknown operation " + descriptor); + throw GraalError.shouldNotReachHere("Unknown operation " + operation); } @Snippet
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64X87MathIntrinsicNode.java Tue Mar 12 19:17:42 2019 +0100 @@ -0,0 +1,111 @@ +/* + * 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.hotspot.amd64; + +import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.COS; +import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.LOG; +import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.LOG10; +import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.SIN; +import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.TAN; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_64; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; + +import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.core.common.type.FloatStamp; +import org.graalvm.compiler.core.common.type.PrimitiveStamp; +import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.graph.spi.CanonicalizerTool; +import org.graalvm.compiler.lir.Variable; +import org.graalvm.compiler.lir.gen.LIRGeneratorTool; +import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.NodeView; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.calc.UnaryNode; +import org.graalvm.compiler.nodes.spi.LIRLowerable; +import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; +import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation; + +import jdk.vm.ci.meta.Value; + +@NodeInfo(nameTemplate = "X87MathIntrinsic#{p#operation/s}", cycles = CYCLES_64, size = SIZE_1) +public final class AMD64X87MathIntrinsicNode extends UnaryNode implements LIRLowerable { + + public static final NodeClass<AMD64X87MathIntrinsicNode> TYPE = NodeClass.create(AMD64X87MathIntrinsicNode.class); + protected final UnaryOperation operation; + + protected AMD64X87MathIntrinsicNode(ValueNode value, UnaryOperation op) { + super(TYPE, op.computeStamp(value.stamp(NodeView.DEFAULT)), value); + assert value.stamp(NodeView.DEFAULT) instanceof FloatStamp && PrimitiveStamp.getBits(value.stamp(NodeView.DEFAULT)) == 64; + this.operation = op; + } + + @Override + public Stamp foldStamp(Stamp valueStamp) { + return operation.computeStamp(valueStamp); + } + + @Override + public void generate(NodeLIRBuilderTool generator) { + LIRGeneratorTool gen = generator.getLIRGeneratorTool(); + Value input = generator.operand(getValue()); + Variable result = gen.newVariable(LIRKind.combine(input)); + + switch (operation) { + case SIN: + gen.append(new AMD64HotSpotMathIntrinsicOp(SIN, result, gen.asAllocatable(input))); + break; + case COS: + gen.append(new AMD64HotSpotMathIntrinsicOp(COS, result, gen.asAllocatable(input))); + break; + case TAN: + gen.append(new AMD64HotSpotMathIntrinsicOp(TAN, result, gen.asAllocatable(input))); + break; + case LOG: + gen.append(new AMD64HotSpotMathIntrinsicOp(LOG, result, gen.asAllocatable(input))); + break; + case LOG10: + gen.append(new AMD64HotSpotMathIntrinsicOp(LOG10, result, gen.asAllocatable(input))); + break; + default: + throw GraalError.shouldNotReachHere(); + } + generator.setResult(this, result); + } + + @Override + public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { + if (forValue.isConstant()) { + return ConstantNode.forDouble(operation.compute(forValue.asJavaConstant().asDouble())); + } + return this; + } + + @NodeIntrinsic + public static native double compute(double value, @ConstantNodeParameter UnaryOperation op); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64X87MathSnippets.java Tue Mar 12 19:17:42 2019 +0100 @@ -0,0 +1,117 @@ +/* + * 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.hotspot.amd64; + +import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER; + +import org.graalvm.compiler.api.replacements.Snippet; +import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; +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; +import org.graalvm.compiler.nodes.extended.ForeignCallNode; +import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.phases.util.Providers; +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.replacements.nodes.UnaryMathIntrinsicNode; +import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation; + +import jdk.vm.ci.code.TargetDescription; + +public class AMD64X87MathSnippets implements Snippets { + + private static final double PI_4 = Math.PI / 4; + + @Snippet + public static double sin(double input) { + if (Math.abs(input) < PI_4) { + return AMD64X87MathIntrinsicNode.compute(input, UnaryOperation.SIN); + } + return callDouble1(UnaryOperation.SIN.foreignCallDescriptor, input); + } + + @Snippet + public static double cos(double input) { + if (Math.abs(input) < PI_4) { + return AMD64X87MathIntrinsicNode.compute(input, UnaryOperation.COS); + } + return callDouble1(UnaryOperation.COS.foreignCallDescriptor, input); + } + + @Snippet + public static double tan(double input) { + if (Math.abs(input) < PI_4) { + return AMD64X87MathIntrinsicNode.compute(input, UnaryOperation.TAN); + } + return callDouble1(UnaryOperation.TAN.foreignCallDescriptor, input); + } + + @NodeIntrinsic(value = ForeignCallNode.class) + private static native double callDouble1(@ConstantNodeParameter ForeignCallDescriptor descriptor, double value); + + public static class Templates extends AbstractTemplates { + + private final SnippetInfo sin; + private final SnippetInfo cos; + private final SnippetInfo tan; + + public Templates(OptionValues options, Iterable<DebugHandlersFactory> factories, Providers providers, SnippetReflectionProvider snippetReflection, TargetDescription target) { + super(options, factories, providers, snippetReflection, target); + + sin = snippet(AMD64X87MathSnippets.class, "sin"); + cos = snippet(AMD64X87MathSnippets.class, "cos"); + tan = snippet(AMD64X87MathSnippets.class, "tan"); + } + + public void lower(UnaryMathIntrinsicNode mathIntrinsicNode, LoweringTool tool) { + SnippetInfo info; + + switch (mathIntrinsicNode.getOperation()) { + case SIN: + info = sin; + break; + case COS: + info = cos; + break; + case TAN: + info = tan; + break; + default: + throw GraalError.shouldNotReachHere("Snippet not found for math intrinsic " + mathIntrinsicNode.getOperation().name()); + } + + Arguments args = new Arguments(info, mathIntrinsicNode.graph().getGuardsStage(), tool.getLoweringStage()); + args.add("input", mathIntrinsicNode.getValue()); + template(mathIntrinsicNode, args).instantiate(providers.getMetaAccess(), mathIntrinsicNode, DEFAULT_REPLACER, tool, args); + mathIntrinsicNode.safeDelete(); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.jdk9.test/src/org/graalvm/compiler/hotspot/jdk9/test/StringUTF16ToBytesGetCharsTest.java Tue Mar 12 19:17:42 2019 +0100 @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2018, 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.jdk9.test; + +import static org.junit.Assume.assumeFalse; + +import jdk.vm.ci.code.InstalledCode; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import org.graalvm.compiler.core.common.CompilationIdentifier; +import org.graalvm.compiler.hotspot.replacements.StringUTF16Substitutions; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.java.NewArrayNode; +import org.graalvm.compiler.replacements.arraycopy.ArrayCopyCallNode; +import org.graalvm.compiler.replacements.test.MethodSubstitutionTest; +import org.graalvm.compiler.test.AddExports; +import org.junit.Before; +import org.junit.Test; + +/** + * Test substitutions for (innate) methods StringUTF16.toBytes and StringUTF16.getChars provided by + * {@link StringUTF16Substitutions}. + */ +@AddExports({"java.base/java.lang"}) +public final class StringUTF16ToBytesGetCharsTest extends MethodSubstitutionTest { + + private static final int N = 1000; + private static final int N_OVERFLOW = 10; + + @Before + public void checkAMD64() { + assumeFalse(Java8OrEarlier); + } + + @Test + public void testStringUTF16ToBytes() throws ClassNotFoundException { + Class<?> javaclass = Class.forName("java.lang.StringUTF16"); + + ResolvedJavaMethod caller = getResolvedJavaMethod(javaclass, "toBytes", char[].class, int.class, int.class); + StructuredGraph graph = getReplacements().getIntrinsicGraph(caller, CompilationIdentifier.INVALID_COMPILATION_ID, getDebugContext()); + assertInGraph(graph, NewArrayNode.class); + assertInGraph(graph, ArrayCopyCallNode.class); + + InstalledCode code = getCode(caller, graph); + + for (int srcOffset = 0; srcOffset < 2; srcOffset++) { + for (int i = 0; i < N; i++) { + int length = i2sz(i); + char[] src = fillUTF16Chars(new char[length]); + int copiedLength = Math.max(0, length - srcOffset); + int srcDelta = Math.min(srcOffset, copiedLength); + byte[] dst = (byte[]) invokeSafe(caller, null, src, srcDelta, copiedLength); + assert dst.length == copiedLength * 2; + byte[] dst2 = (byte[]) executeVarargsSafe(code, src, srcDelta, copiedLength); + assertDeepEquals(dst, dst2); + } + } + for (int srcOff = 0; srcOff < N_OVERFLOW; ++srcOff) { + for (int len = 0; len < N_OVERFLOW; ++len) { + char[] src = fillUTF16Chars(new char[N_OVERFLOW]); + test(caller, null, src, srcOff, len); + } + } + } + + @Test + public void testStringUTF16getChars() throws ClassNotFoundException { + Class<?> javaclass = Class.forName("java.lang.StringUTF16"); + + ResolvedJavaMethod caller = getResolvedJavaMethod(javaclass, "getChars", byte[].class, int.class, int.class, char[].class, int.class); + StructuredGraph graph = getReplacements().getIntrinsicGraph(caller, CompilationIdentifier.INVALID_COMPILATION_ID, getDebugContext()); + assertInGraph(graph, ArrayCopyCallNode.class); + + InstalledCode code = getCode(caller, graph); + + for (int dstOffset = 0; dstOffset < 2; dstOffset++) { + for (int srcOffset = 0; srcOffset < 2; srcOffset++) { + for (int i = 0; i < N; i++) { + int length = i2sz(i); + byte[] src = fillUTF16Bytes(new byte[length * 2]); + char[] dst = new char[length]; + int copiedLength = Math.max(0, length - Math.max(dstOffset, srcOffset)); + int dstDelta = Math.min(dstOffset, copiedLength); + int srcDelta = Math.min(srcOffset, copiedLength); + invokeSafe(caller, null, src, srcDelta, srcDelta + copiedLength, dst, dstDelta); + char[] dst2 = new char[length]; + executeVarargsSafe(code, src, srcDelta, srcDelta + copiedLength, dst2, dstDelta); + assertDeepEquals(dst, dst2); + } + } + } + for (int srcOff = 0; srcOff < N_OVERFLOW; ++srcOff) { + for (int dstOff = 0; dstOff < N_OVERFLOW; ++dstOff) { + for (int len = 0; len < N_OVERFLOW; ++len) { + byte[] src = fillUTF16Bytes(new byte[N_OVERFLOW]); + char[] dst = new char[N_OVERFLOW]; + test(caller, null, src, srcOff, len, dst, dstOff); + } + } + } + } + + private static char[] fillUTF16Chars(char[] v) { + for (int ch = 0, i = 0; i < v.length; i++, ch += 0x101) { + v[i] = (char) ch; + } + return v; + } + + private static byte[] fillUTF16Bytes(byte[] v) { + for (int ch = 1, i = 0; i < v.length; i += 2, ch++) { + v[i] = (byte) (ch - 1); + v[i + 1] = (byte) ch; + } + return v; + } + + private static int i2sz(int i) { + return i * 3; + } +}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.lir.test/src/org/graalvm/compiler/hotspot/lir/test/BenchmarkCounterOverflowTest.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.lir.test/src/org/graalvm/compiler/hotspot/lir/test/BenchmarkCounterOverflowTest.java Tue Mar 12 19:17:42 2019 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, 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 @@ -27,9 +27,12 @@ import static org.graalvm.compiler.test.SubprocessUtil.getVMCommandLine; import static org.graalvm.compiler.test.SubprocessUtil.withoutDebuggerArguments; +import java.io.File; import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.core.common.LIRKind; @@ -121,6 +124,7 @@ Assert.assertNotEquals("Expected non-zero exit status", 0, proc.exitCode); Iterator<String> it = proc.output.iterator(); + boolean foundProblematicFrame = false; while (it.hasNext()) { String line = it.next(); if (line.contains("Problematic frame:")) { @@ -130,11 +134,34 @@ } line = it.next(); if (line.contains(BenchmarkCounterOverflowTest.class.getName() + ".test")) { - return; + foundProblematicFrame = true; + break; } Assert.fail("Unexpected stack trace: " + line); } } - Assert.fail(String.format("Could not find method in output:%n%s", proc)); + // find and delete hserr file + while (it.hasNext()) { + String line = it.next(); + if (line.contains("An error report file with more information is saved as:")) { + if (!it.hasNext()) { + // no more line + break; + } + line = it.next(); + Pattern pattern = Pattern.compile("^# (.*hs_err_pid.*log)$"); + Matcher matcher = pattern.matcher(line); + if (matcher.matches()) { + File hserrFile = new File(matcher.group(1)); + if (hserrFile.exists()) { + if (VERBOSE) { + System.out.println("Deleting error report file:" + hserrFile.getAbsolutePath()); + } + hserrFile.delete(); + } + } + } + } + Assert.assertTrue(String.format("Could not find method in output:%n%s", proc), foundProblematicFrame); } }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackend.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackend.java Tue Mar 12 19:17:42 2019 +0100 @@ -63,6 +63,7 @@ import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.gen.LIRGenerationProvider; import org.graalvm.compiler.core.sparc.SPARCNodeMatchRules; import org.graalvm.compiler.debug.CounterKey; import org.graalvm.compiler.debug.DebugContext; @@ -109,7 +110,7 @@ /** * HotSpot SPARC specific backend. */ -public class SPARCHotSpotBackend extends HotSpotHostBackend { +public class SPARCHotSpotBackend extends HotSpotHostBackend implements LIRGenerationProvider { private static final SizeEstimateStatistics CONSTANT_ESTIMATED_STATS = new SizeEstimateStatistics("ESTIMATE"); private static final SizeEstimateStatistics CONSTANT_ACTUAL_STATS = new SizeEstimateStatistics("ACTUAL"); @@ -134,15 +135,10 @@ } } - @Override - public FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig) { + private FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig) { RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig; - return new SPARCFrameMapBuilder(newFrameMap(registerConfigNonNull), getCodeCache(), registerConfigNonNull); - } - - @Override - public FrameMap newFrameMap(RegisterConfig registerConfig) { - return new SPARCFrameMap(getCodeCache(), registerConfig, this); + FrameMap frameMap = new SPARCFrameMap(getCodeCache(), registerConfigNonNull, this); + return new SPARCFrameMapBuilder(frameMap, getCodeCache(), registerConfigNonNull); } @Override @@ -151,8 +147,9 @@ } @Override - public LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, FrameMapBuilder frameMapBuilder, StructuredGraph graph, Object stub) { - return new HotSpotLIRGenerationResult(compilationId, lir, frameMapBuilder, makeCallingConvention(graph, (Stub) stub), stub, config.requiresReservedStackCheck(graph.getMethods())); + public LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, RegisterConfig registerConfig, StructuredGraph graph, Object stub) { + return new HotSpotLIRGenerationResult(compilationId, lir, newFrameMapBuilder(registerConfig), makeCallingConvention(graph, (Stub) stub), stub, + config.requiresReservedStackCheck(graph.getMethods())); } @Override @@ -227,18 +224,13 @@ } @Override - protected Assembler createAssembler(FrameMap frameMap) { - return new SPARCMacroAssembler(getTarget()); - } - - @Override public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenRes, FrameMap frameMap, CompilationResult compilationResult, CompilationResultBuilderFactory factory) { HotSpotLIRGenerationResult gen = (HotSpotLIRGenerationResult) lirGenRes; LIR lir = gen.getLIR(); assert gen.getDeoptimizationRescueSlot() == null || frameMap.frameNeedsAllocating() : "method that can deoptimize must have a frame"; Stub stub = gen.getStub(); - Assembler masm = createAssembler(frameMap); + Assembler masm = new SPARCMacroAssembler(getTarget()); // On SPARC we always use stack frames. HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null); DataBuilder dataBuilder = new HotSpotDataBuilder(getCodeCache().getTarget());
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotMove.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotMove.java Tue Mar 12 19:17:42 2019 +0100 @@ -24,20 +24,21 @@ package org.graalvm.compiler.hotspot.sparc; +import static jdk.vm.ci.code.ValueUtil.asRegister; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BPR; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Annul.ANNUL; +import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Annul.NOT_ANNUL; +import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BranchPredict.PREDICT_NOT_TAKEN; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BranchPredict.PREDICT_TAKEN; +import static org.graalvm.compiler.asm.sparc.SPARCAssembler.RCondition.Rc_nz; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.RCondition.Rc_z; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK; import static org.graalvm.compiler.lir.sparc.SPARCMove.loadFromConstantTable; -import static jdk.vm.ci.code.ValueUtil.asRegister; import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.asm.sparc.SPARCAddress; -import org.graalvm.compiler.asm.sparc.SPARCAssembler.CC; -import org.graalvm.compiler.asm.sparc.SPARCAssembler.ConditionFlag; import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler; import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler.ScratchRegister; import org.graalvm.compiler.core.common.CompressEncoding; @@ -53,6 +54,7 @@ import jdk.vm.ci.hotspot.HotSpotConstant; import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.sparc.SPARC; public class SPARCHotSpotMove { @@ -150,17 +152,33 @@ if (encoding.hasBase()) { Register baseReg = asRegister(baseRegister); if (!nonNull) { - masm.cmp(inputRegister, baseReg); - masm.movcc(ConditionFlag.Equal, CC.Xcc, baseReg, resReg); - masm.sub(resReg, baseReg, resReg); + Label done = new Label(); + if (inputRegister.equals(resReg)) { + BPR.emit(masm, Rc_nz, ANNUL, PREDICT_TAKEN, inputRegister, done); + masm.sub(inputRegister, baseReg, resReg); + masm.bind(done); + if (encoding.getShift() != 0) { + masm.srlx(resReg, encoding.getShift(), resReg); + } + } else { + BPR.emit(masm, Rc_z, NOT_ANNUL, PREDICT_NOT_TAKEN, inputRegister, done); + masm.mov(SPARC.g0, resReg); + masm.sub(inputRegister, baseReg, resReg); + if (encoding.getShift() != 0) { + masm.srlx(resReg, encoding.getShift(), resReg); + } + masm.bind(done); + } } else { masm.sub(inputRegister, baseReg, resReg); - } - if (encoding.getShift() != 0) { - masm.srlx(resReg, encoding.getShift(), resReg); + if (encoding.getShift() != 0) { + masm.srlx(resReg, encoding.getShift(), resReg); + } } } else { - masm.srlx(inputRegister, encoding.getShift(), resReg); + if (encoding.getShift() != 0) { + masm.srlx(inputRegister, encoding.getShift(), resReg); + } } } } @@ -196,7 +214,7 @@ public static void emitUncompressCode(SPARCMacroAssembler masm, Register inputRegister, Register resReg, Register baseReg, int shift, boolean nonNull) { Register secondaryInput; if (shift != 0) { - masm.sll(inputRegister, shift, resReg); + masm.sllx(inputRegister, shift, resReg); secondaryInput = resReg; } else { secondaryInput = inputRegister; @@ -207,7 +225,7 @@ masm.add(secondaryInput, baseReg, resReg); } else { Label done = new Label(); - BPR.emit(masm, Rc_z, ANNUL, PREDICT_TAKEN, secondaryInput, done); + BPR.emit(masm, Rc_nz, ANNUL, PREDICT_TAKEN, secondaryInput, done); masm.add(baseReg, secondaryInput, resReg); masm.bind(done); }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java Tue Mar 12 19:17:42 2019 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2019, 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 @@ -47,7 +47,7 @@ import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Binding; import org.graalvm.compiler.runtime.RuntimeProvider; -import org.graalvm.compiler.serviceprovider.GraalServices; +import org.graalvm.compiler.serviceprovider.JavaVersionUtil; import org.graalvm.compiler.test.GraalTest; import org.junit.Test; @@ -257,7 +257,8 @@ "java/lang/reflect/Array.newArray(Ljava/lang/Class;I)Ljava/lang/Object;", // HotSpot MacroAssembler-based intrinsic "sun/nio/cs/ISO_8859_1$Encoder.encodeISOArray([CI[BII)I", - // Stub based intrinsics but implementation seems complex in C2 + // We have implemented implCompressMultiBlock0 on JDK9+. Does it worth + // backporting as corresponding HotSpot stubs are only generated on SPARC? "sun/security/provider/DigestBase.implCompressMultiBlock([BII)I"); // See JDK-8207146. @@ -271,18 +272,12 @@ "jdk/jfr/internal/JVM.getClassId(Ljava/lang/Class;)J"); add(toBeInvestigated, - // Some logic and a stub call - "com/sun/crypto/provider/CounterMode.implCrypt([BII[BI)I", - // Stub and very little logic - "com/sun/crypto/provider/GHASH.processBlocks([BII[J[J)V", // HotSpot MacroAssembler-based intrinsic "java/lang/Math.fma(DDD)D", // HotSpot MacroAssembler-based intrinsic "java/lang/Math.fma(FFF)F", // Just check if the argument is a compile time constant "java/lang/invoke/MethodHandleImpl.isCompileConstant(Ljava/lang/Object;)Z", - // Some logic and a runtime call - "java/util/ArraysSupport.vectorizedMismatch(Ljava/lang/Object;JLjava/lang/Object;JII)I", // Only used as a marker for vectorization? "java/util/stream/Streams$RangeIntSpliterator.forEachRemaining(Ljava/util/function/IntConsumer;)V", // Only implemented on non-AMD64 platforms (some logic and runtime call) @@ -295,9 +290,7 @@ // Control flow, deopts, and a cast "jdk/internal/util/Preconditions.checkIndex(IILjava/util/function/BiFunction;)I", // HotSpot MacroAssembler-based intrinsic - "sun/nio/cs/ISO_8859_1$Encoder.implEncodeISOArray([CI[BII)I", - // Runtime call and some complex compiler logic - "sun/security/provider/DigestBase.implCompressMultiBlock0([BII)I"); + "sun/nio/cs/ISO_8859_1$Encoder.implEncodeISOArray([CI[BII)I"); /* * Per default, all these operations are mapped to some generic method for which we @@ -344,27 +337,45 @@ // Compact string support - HotSpot MacroAssembler-based intrinsic or complex C2 logic. add(toBeInvestigated, "java/lang/StringCoding.hasNegatives([BII)Z", - "java/lang/StringCoding.implEncodeISOArray([BI[BII)I", + "java/lang/StringCoding.implEncodeISOArray([BI[BII)I"); + add(ignore, + // handled through an intrinsic for String.equals itself + "java/lang/StringLatin1.equals([B[B)Z", + + // handled by an intrinsic for StringLatin1.indexOf([BI[BII)I "java/lang/StringLatin1.indexOf([B[B)I", - "java/lang/StringUTF16.getChar([BI)C", - "java/lang/StringUTF16.getChars([BII[CI)V", + + // handled through an intrinsic for String.equals itself + "java/lang/StringUTF16.equals([B[B)Z", + + // handled by an intrinsic for StringUTF16.indexOfUnsafe "java/lang/StringUTF16.indexOf([BI[BII)I", "java/lang/StringUTF16.indexOf([B[B)I", + + // handled by an intrinsic for StringUTF16.indexOfCharUnsafe "java/lang/StringUTF16.indexOfChar([BIII)I", + + // handled by an intrinsic for StringUTF16.indexOfLatin1Unsafe "java/lang/StringUTF16.indexOfLatin1([BI[BII)I", - "java/lang/StringUTF16.indexOfLatin1([B[B)I", - "java/lang/StringUTF16.putChar([BII)V", - "java/lang/StringUTF16.toBytes([CII)[B"); - // These are handled through an intrinsic for String.equals itself - add(ignore, - "java/lang/StringLatin1.equals([B[B)Z", - "java/lang/StringUTF16.equals([B[B)Z"); + "java/lang/StringUTF16.indexOfLatin1([B[B)I"); + + if (!config.useAESCTRIntrinsics) { + add(ignore, + "com/sun/crypto/provider/CounterMode.implCrypt([BII[BI)I"); + } + if (!config.useGHASHIntrinsics()) { + add(ignore, + "com/sun/crypto/provider/GHASH.processBlocks([BII[J[J)V"); + } + if (!(config.useSHA1Intrinsics() || config.useSHA256Intrinsics() || config.useSHA512Intrinsics())) { + add(ignore, + "sun/security/provider/DigestBase.implCompressMultiBlock0([BII)I"); + } } if (isJDK10OrHigher()) { add(toBeInvestigated, - "java/lang/Math.multiplyHigh(JJ)J", - "jdk/internal/util/ArraysSupport.vectorizedMismatch(Ljava/lang/Object;JLjava/lang/Object;JII)I"); + "java/lang/Math.multiplyHigh(JJ)J"); } if (isJDK11OrHigher()) { @@ -401,10 +412,16 @@ // Can we implement these on non-AMD64 platforms? C2 seems to. add(toBeInvestigated, "java/lang/String.compareTo(Ljava/lang/String;)I", + "java/lang/StringLatin1.indexOf([B[B)I", "java/lang/StringLatin1.inflate([BI[BII)V", "java/lang/StringLatin1.inflate([BI[CII)V", "java/lang/StringUTF16.compress([BI[BII)I", "java/lang/StringUTF16.compress([CI[BII)I", + "java/lang/StringUTF16.indexOf([BI[BII)I", + "java/lang/StringUTF16.indexOf([B[B)I", + "java/lang/StringUTF16.indexOfChar([BIII)I", + "java/lang/StringUTF16.indexOfLatin1([BI[BII)I", + "java/lang/StringUTF16.indexOfLatin1([B[B)I", "jdk/internal/misc/Unsafe.compareAndExchangeByte(Ljava/lang/Object;JBB)B", "jdk/internal/misc/Unsafe.compareAndExchangeShort(Ljava/lang/Object;JSS)S", "jdk/internal/misc/Unsafe.compareAndSetByte(Ljava/lang/Object;JBB)Z", @@ -433,7 +450,9 @@ "jdk/internal/misc/Unsafe.getAndSet" + oopName + "(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;"); } add(toBeInvestigated, + "com/sun/crypto/provider/CounterMode.implCrypt([BII[BI)I", "java/lang/Thread.onSpinWait()V", + "java/util/ArraysSupport.vectorizedMismatch(Ljava/lang/Object;JLjava/lang/Object;JII)I", "jdk/internal/misc/Unsafe.getCharUnaligned(Ljava/lang/Object;J)C", "jdk/internal/misc/Unsafe.getIntUnaligned(Ljava/lang/Object;J)I", "jdk/internal/misc/Unsafe.getLongUnaligned(Ljava/lang/Object;J)J", @@ -443,6 +462,10 @@ "jdk/internal/misc/Unsafe.putLongUnaligned(Ljava/lang/Object;JJ)V", "jdk/internal/misc/Unsafe.putShortUnaligned(Ljava/lang/Object;JS)V"); } + if (isJDK10OrHigher()) { + add(toBeInvestigated, + "jdk/internal/util/ArraysSupport.vectorizedMismatch(Ljava/lang/Object;JLjava/lang/Object;JII)I"); + } } /* @@ -535,23 +558,23 @@ } private static boolean isJDK9OrHigher() { - return GraalServices.JAVA_SPECIFICATION_VERSION >= 9; + return JavaVersionUtil.JAVA_SPECIFICATION_VERSION >= 9; } private static boolean isJDK10OrHigher() { - return GraalServices.JAVA_SPECIFICATION_VERSION >= 10; + return JavaVersionUtil.JAVA_SPECIFICATION_VERSION >= 10; } private static boolean isJDK11OrHigher() { - return GraalServices.JAVA_SPECIFICATION_VERSION >= 11; + return JavaVersionUtil.JAVA_SPECIFICATION_VERSION >= 11; } private static boolean isJDK12OrHigher() { - return GraalServices.JAVA_SPECIFICATION_VERSION >= 12; + return JavaVersionUtil.JAVA_SPECIFICATION_VERSION >= 12; } private static boolean isJDK13OrHigher() { - return GraalServices.JAVA_SPECIFICATION_VERSION >= 13; + return JavaVersionUtil.JAVA_SPECIFICATION_VERSION >= 13; } public interface Refiner {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java Tue Mar 12 19:17:42 2019 +0100 @@ -31,7 +31,7 @@ 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.GraalServices.Java8OrEarlier; +import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.Java8OrEarlier; import java.io.Closeable; import java.io.File; @@ -90,7 +90,7 @@ import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.options.OptionsParser; -import org.graalvm.compiler.serviceprovider.GraalServices; +import org.graalvm.compiler.serviceprovider.JavaVersionUtil; import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; import jdk.vm.ci.hotspot.HotSpotCompilationRequest; @@ -110,7 +110,7 @@ /** * Magic token to denote that JDK classes are to be compiled. If - * {@link GraalServices#Java8OrEarlier}, then the classes in {@code rt.jar} are compiled. + * {@link JavaVersionUtil#Java8OrEarlier}, then the classes in {@code rt.jar} are compiled. * Otherwise the classes in the Java runtime image are compiled. */ public static final String SUN_BOOT_CLASS_PATH = "sun.boot.class.path";
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/EliminateRedundantInitializationPhaseTest.java Tue Mar 12 19:17:42 2019 +0100 @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2017, 2018, 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.test; + +import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.hotspot.meta.HotSpotClassInitializationPlugin; +import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode; +import org.graalvm.compiler.hotspot.phases.aot.EliminateRedundantInitializationPhase; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; +import org.graalvm.compiler.phases.tiers.HighTierContext; +import org.junit.Assert; +import org.junit.Test; + +public class EliminateRedundantInitializationPhaseTest extends GraalCompilerTest { + @Override + protected Plugins getDefaultGraphBuilderPlugins() { + Plugins plugins = super.getDefaultGraphBuilderPlugins(); + plugins.setClassInitializationPlugin(new HotSpotClassInitializationPlugin()); + return plugins; + } + + public static class X { + public static int x; + public static int y; + public static int z; + } + + public static class Y extends X { + public static int a; + public static int b; + } + + public static void assignFields() { + X.x = 1; + X.y = 2; + X.z = 3; + } + + public static void assignFieldsConditionally(boolean choice) { + X.x = 1; + if (choice) { + X.y = 2; + } else { + X.z = 3; + } + } + + public static void assignFieldsSubclassDominates() { + Y.a = 1; + X.x = 2; + X.y = 3; + X.z = 4; + } + + public static void assignFieldsConditionallySubclassDominates(boolean choice) { + Y.a = 1; + if (choice) { + X.x = 2; + } else { + X.y = 3; + } + Y.z = 4; + } + + public static void assignFieldsSubclassPostdominates() { + X.x = 1; + Y.a = 2; + } + + public static void assignFieldsConditionallySubclassPostdominates(boolean choice) { + X.x = 1; + if (choice) { + X.y = 2; + } else { + X.z = 3; + } + Y.a = 4; + } + + public static void assignFieldsConditionallyMixed(boolean choice) { + X.x = 1; + if (choice) { + Y.a = 2; + } else { + X.z = 3; + } + Y.b = 4; + } + + public static void assignFieldsInLoop() { + X.x = 1; + for (int i = 0; i < 10; i++) { + X.y += X.z; + } + } + + public static void assignFieldsInBranches(boolean choice) { + if (choice) { + X.x = 1; + } else { + X.y = 2; + } + X.z = 3; + } + + public static void assignFieldsInBranchesMixed(boolean choice) { + if (choice) { + X.x = 1; + } else { + Y.a = 2; + } + X.z = 3; + } + + static class SomeClass { + @BytecodeParserNeverInline + static void method() { + } + + @BytecodeParserForceInline + static void inlinedMethod() { + } + } + + public static void invokestatic() { + SomeClass.method(); + } + + public static void invokestaticInlined() { + SomeClass.inlinedMethod(); + } + + private void test(String name, int initNodesAfterParse, int initNodesAfterOpt) { + StructuredGraph graph = parseEager(name, AllowAssumptions.NO); + Assert.assertEquals(initNodesAfterParse, graph.getNodes().filter(InitializeKlassNode.class).count()); + HighTierContext highTierContext = getDefaultHighTierContext(); + new EliminateRedundantInitializationPhase().apply(graph, highTierContext); + Assert.assertEquals(initNodesAfterOpt, graph.getNodes().filter(InitializeKlassNode.class).count()); + } + + @Test + public void test1() { + test("assignFields", 3, 1); + } + + @Test + public void test2() { + test("assignFieldsConditionally", 3, 1); + } + + @Test + public void test3() { + test("assignFieldsSubclassDominates", 4, 1); + } + + @Test + public void test4() { + test("assignFieldsConditionallySubclassDominates", 4, 1); + } + + @Test + public void test5() { + test("assignFieldsSubclassPostdominates", 2, 2); + } + + @Test + public void test6() { + test("assignFieldsConditionallySubclassPostdominates", 4, 2); + } + + @Test + public void test7() { + test("assignFieldsConditionallyMixed", 4, 3); + } + + @Test + public void test8() { + test("assignFieldsInLoop", 4, 1); + } + + @Test + public void test9() { + test("assignFieldsInBranches", 3, 2); + } + + @Test + public void test10() { + test("assignFieldsInBranchesMixed", 3, 2); + } + + @Test + public void test11() { + test("invokestatic", 1, 0); + } + + @Test + public void test12() { + test("invokestaticInlined", 1, 1); + } +}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTest.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTest.java Tue Mar 12 19:17:42 2019 +0100 @@ -53,6 +53,11 @@ testOSR(getInitialOptions(), "testNonReduceLoop"); } + @Test + public void testOSR04() { + testOSR(getInitialOptions(), "testDeoptAfterCountedLoop"); + } + static int limit = 10000; public static int sideEffect; @@ -100,4 +105,14 @@ GraalDirectives.controlFlowAnchor(); return ret; } + + public static ReturnValue testDeoptAfterCountedLoop() { + long ret = 0; + for (int i = 0; GraalDirectives.injectBranchProbability(1, i < limit * limit); i++) { + GraalDirectives.blackhole(i); + ret = GraalDirectives.opaque(i); + } + GraalDirectives.controlFlowAnchor(); + return ret + 1 == limit * limit ? ReturnValue.SUCCESS : ReturnValue.FAILURE; + } }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/JVMCIInfopointErrorTest.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/JVMCIInfopointErrorTest.java Tue Mar 12 19:17:42 2019 +0100 @@ -24,6 +24,7 @@ package org.graalvm.compiler.hotspot.test; +import static org.graalvm.compiler.debug.DebugOptions.DumpOnError; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED; @@ -52,6 +53,7 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; +import org.graalvm.compiler.options.OptionValues; import org.junit.Test; import jdk.vm.ci.code.BytecodeFrame; @@ -139,6 +141,14 @@ test(getDebugContext(), spec); } + /** + * Avoids dumping during tests which are expected to fail. + */ + private void testNoDump(TestSpec spec) { + OptionValues options = new OptionValues(getInitialOptions(), DumpOnError, false); + test(getDebugContext(options, null, null), spec); + } + private void test(DebugContext debug, TestSpec spec) { ResolvedJavaMethod method = getResolvedJavaMethod("testMethod"); @@ -154,7 +164,7 @@ @Test(expected = Error.class) public void testInvalidShortOop() { - test((tool, state, safepoint) -> { + testNoDump((tool, state, safepoint) -> { PlatformKind kind = tool.target().arch.getPlatformKind(JavaKind.Short); LIRKind lirKind = LIRKind.reference(kind); @@ -167,7 +177,7 @@ @Test(expected = Error.class) public void testInvalidShortDerivedOop() { - test((tool, state, safepoint) -> { + testNoDump((tool, state, safepoint) -> { Variable baseOop = tool.newVariable(LIRKind.fromJavaKind(tool.target().arch, JavaKind.Object)); tool.append(new ValueDef(baseOop));
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/OptionsInFileTest.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/OptionsInFileTest.java Tue Mar 12 19:17:42 2019 +0100 @@ -37,6 +37,7 @@ import java.util.List; import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.debug.DebugOptions.PrintGraphTarget; import org.graalvm.compiler.test.SubprocessUtil; import org.graalvm.compiler.test.SubprocessUtil.Subprocess; import org.junit.Assert; @@ -54,12 +55,12 @@ try { Assert.assertFalse(methodFilterValue.equals(MethodFilter.getDefaultValue())); Assert.assertFalse(debugFilterValue.equals(Dump.getDefaultValue())); - Assert.assertTrue(PrintGraph.getDefaultValue()); + Assert.assertEquals(PrintGraphTarget.File, PrintGraph.getDefaultValue()); try (PrintStream out = new PrintStream(new FileOutputStream(optionsFile))) { out.println(MethodFilter.getName() + "=" + methodFilterValue); out.println(Dump.getName() + "=" + debugFilterValue); - out.println(PrintGraph.getName() + " = false"); + out.println(PrintGraph.getName() + " = Network"); } List<String> vmArgs = withoutDebuggerArguments(getVMCommandLine()); @@ -70,7 +71,7 @@ String[] expected = { "graal.MethodFilter := \"a very unlikely method name\"", "graal.Dump := \"a very unlikely debug scope\"", - "graal.PrintGraph := false"}; + "graal.PrintGraph := Network"}; for (String line : proc.output) { for (int i = 0; i < expected.length; i++) { if (expected[i] != null && line.contains(expected[i])) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ReservedStackAccessTest.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ReservedStackAccessTest.java Tue Mar 12 19:17:42 2019 +0100 @@ -73,6 +73,10 @@ vmArgs.add("-XX:+UseJVMCICompiler"); vmArgs.add("-Dgraal.Inline=false"); vmArgs.add("-XX:CompileCommand=exclude,java/util/concurrent/locks/AbstractOwnableSynchronizer.setExclusiveOwnerThread"); + + // Avoid SOE in HotSpotJVMCIRuntime.adjustCompilationLevel + vmArgs.add("-Dgraal.CompileGraalWithC1Only=false"); + Subprocess proc = SubprocessUtil.java(vmArgs, ReservedStackAccessTest.class.getName()); boolean passed = false; for (String line : proc.output) { @@ -81,9 +85,7 @@ } } if (!passed) { - for (String line : proc.output) { - System.err.println("" + line); - } + System.err.println(proc); } assertTrue(passed); }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierAdditionTest.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierAdditionTest.java Tue Mar 12 19:17:42 2019 +0100 @@ -32,10 +32,10 @@ import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase; -import org.graalvm.compiler.hotspot.nodes.G1PostWriteBarrier; -import org.graalvm.compiler.hotspot.nodes.G1PreWriteBarrier; -import org.graalvm.compiler.hotspot.nodes.G1ReferentFieldReadBarrier; -import org.graalvm.compiler.hotspot.nodes.SerialWriteBarrier; +import org.graalvm.compiler.hotspot.gc.g1.G1PostWriteBarrier; +import org.graalvm.compiler.hotspot.gc.g1.G1PreWriteBarrier; +import org.graalvm.compiler.hotspot.gc.g1.G1ReferentFieldReadBarrier; +import org.graalvm.compiler.hotspot.gc.shared.SerialWriteBarrier; import org.graalvm.compiler.hotspot.phases.WriteBarrierAdditionPhase; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierVerificationTest.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierVerificationTest.java Tue Mar 12 19:17:42 2019 +0100 @@ -32,12 +32,12 @@ import org.graalvm.compiler.debug.DebugContext.Scope; import org.graalvm.compiler.debug.DebugDumpScope; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; -import org.graalvm.compiler.hotspot.nodes.G1ArrayRangePostWriteBarrier; -import org.graalvm.compiler.hotspot.nodes.G1ArrayRangePreWriteBarrier; -import org.graalvm.compiler.hotspot.nodes.G1PostWriteBarrier; -import org.graalvm.compiler.hotspot.nodes.G1PreWriteBarrier; -import org.graalvm.compiler.hotspot.nodes.SerialArrayRangeWriteBarrier; -import org.graalvm.compiler.hotspot.nodes.SerialWriteBarrier; +import org.graalvm.compiler.hotspot.gc.g1.G1ArrayRangePostWriteBarrier; +import org.graalvm.compiler.hotspot.gc.g1.G1ArrayRangePreWriteBarrier; +import org.graalvm.compiler.hotspot.gc.g1.G1PostWriteBarrier; +import org.graalvm.compiler.hotspot.gc.g1.G1PreWriteBarrier; +import org.graalvm.compiler.hotspot.gc.shared.SerialArrayRangeWriteBarrier; +import org.graalvm.compiler.hotspot.gc.shared.SerialWriteBarrier; import org.graalvm.compiler.hotspot.phases.WriteBarrierAdditionPhase; import org.graalvm.compiler.hotspot.phases.WriteBarrierVerificationPhase; import org.graalvm.compiler.nodes.AbstractBeginNode;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java Tue Mar 12 19:17:42 2019 +0100 @@ -368,8 +368,14 @@ installedCode = null; Object[] context = {new DebugDumpScope(getIdString(), true), codeCache, getMethod(), compResult}; try (DebugContext.Scope s = debug.scope("CodeInstall", context)) { - installedCode = (HotSpotInstalledCode) backend.createInstalledCode(debug, getRequest().getMethod(), getRequest(), compResult, - getRequest().getMethod().getSpeculationLog(), null, installAsDefault, context); + HotSpotCompilationRequest request = getRequest(); + installedCode = (HotSpotInstalledCode) backend.createInstalledCode(debug, + request.getMethod(), + request, + compResult, + null, + installAsDefault, + context); } catch (Throwable e) { throw debug.handle(e); }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java Tue Mar 12 19:17:42 2019 +0100 @@ -92,6 +92,7 @@ public final boolean useBiasedLocking = getFlag("UseBiasedLocking", Boolean.class); public final boolean usePopCountInstruction = getFlag("UsePopCountInstruction", Boolean.class); public final boolean useAESIntrinsics = getFlag("UseAESIntrinsics", Boolean.class); + public final boolean useAESCTRIntrinsics = getFlag("UseAESCTRIntrinsics", Boolean.class, false); public final boolean useCRC32Intrinsics = getFlag("UseCRC32Intrinsics", Boolean.class); public final boolean useCRC32CIntrinsics = versioned.useCRC32CIntrinsics; public final boolean threadLocalHandshakes = getFlag("ThreadLocalHandshakes", Boolean.class, false); @@ -100,10 +101,12 @@ private final boolean useSHA1Intrinsics = getFlag("UseSHA1Intrinsics", Boolean.class); private final boolean useSHA256Intrinsics = getFlag("UseSHA256Intrinsics", Boolean.class); private final boolean useSHA512Intrinsics = getFlag("UseSHA512Intrinsics", Boolean.class); + private final boolean useGHASHIntrinsics = getFlag("UseGHASHIntrinsics", Boolean.class, false); private final boolean useMontgomeryMultiplyIntrinsic = getFlag("UseMontgomeryMultiplyIntrinsic", Boolean.class, false); private final boolean useMontgomerySquareIntrinsic = getFlag("UseMontgomerySquareIntrinsic", Boolean.class, false); private final boolean useMulAddIntrinsic = getFlag("UseMulAddIntrinsic", Boolean.class, false); private final boolean useSquareToLenIntrinsic = getFlag("UseSquareToLenIntrinsic", Boolean.class, false); + public final boolean useVectorizedMismatchIntrinsic = getFlag("UseVectorizedMismatchIntrinsic", Boolean.class, false); /* * These are methods because in some JDKs the flags are visible but the stubs themselves haven't @@ -114,15 +117,19 @@ } public boolean useSHA1Intrinsics() { - return useSHA1Intrinsics && sha1ImplCompress != 0; + return useSHA1Intrinsics && sha1ImplCompress != 0 && sha1ImplCompressMultiBlock != 0; } public boolean useSHA256Intrinsics() { - return useSHA256Intrinsics && sha256ImplCompress != 0; + return useSHA256Intrinsics && sha256ImplCompress != 0 && sha256ImplCompressMultiBlock != 0; } public boolean useSHA512Intrinsics() { - return useSHA512Intrinsics && sha512ImplCompress != 0; + return useSHA512Intrinsics && sha512ImplCompress != 0 && sha512ImplCompressMultiBlock != 0; + } + + public boolean useGHASHIntrinsics() { + return useGHASHIntrinsics && ghashProcessBlocks != 0; } public boolean useMontgomeryMultiplyIntrinsic() { @@ -309,7 +316,17 @@ public final int jvmAccWrittenFlags = getConstant("JVM_ACC_WRITTEN_FLAGS", Integer.class); public final int jvmAccSynthetic = getConstant("JVM_ACC_SYNTHETIC", Integer.class); - public final int jvmciCompileStateCanPostOnExceptionsOffset = getFieldOffset("JVMCIEnv::_jvmti_can_post_on_exceptions", Integer.class, "jbyte", Integer.MIN_VALUE); + public final int jvmciCompileStateCanPostOnExceptionsOffset = getJvmciCompileStateCanPostOnExceptionsOffset(); + + // Integer.MIN_VALUE if not available + private int getJvmciCompileStateCanPostOnExceptionsOffset() { + int offset = getFieldOffset("JVMCICompileState::_jvmti_can_post_on_exceptions", Integer.class, "jbyte", Integer.MIN_VALUE); + if (offset == Integer.MIN_VALUE) { + // JDK 12 + offset = getFieldOffset("JVMCIEnv::_jvmti_can_post_on_exceptions", Integer.class, "jbyte", Integer.MIN_VALUE); + } + return offset; + } public final int threadTlabOffset = getFieldOffset("Thread::_tlab", Integer.class, "ThreadLocalAllocBuffer"); public final int javaThreadAnchorOffset = getFieldOffset("JavaThread::_anchor", Integer.class, "JavaFrameAnchor"); @@ -372,12 +389,29 @@ public final int pendingExceptionOffset = getFieldOffset("ThreadShadow::_pending_exception", Integer.class, "oop"); public final int pendingDeoptimizationOffset = getFieldOffset("JavaThread::_pending_deoptimization", Integer.class, "int"); - public final int pendingFailedSpeculationOffset = getFieldOffset("JavaThread::_pending_failed_speculation", Integer.class, "long"); public final int pendingTransferToInterpreterOffset = getFieldOffset("JavaThread::_pending_transfer_to_interpreter", Integer.class, "bool"); private final int javaFrameAnchorLastJavaSpOffset = getFieldOffset("JavaFrameAnchor::_last_Java_sp", Integer.class, "intptr_t*"); private final int javaFrameAnchorLastJavaPcOffset = getFieldOffset("JavaFrameAnchor::_last_Java_pc", Integer.class, "address"); + public final int pendingFailedSpeculationOffset; + { + String name = "JavaThread::_pending_failed_speculation"; + int offset = -1; + try { + offset = getFieldOffset(name, Integer.class, "jlong"); + } catch (JVMCIError e) { + try { + offset = getFieldOffset(name, Integer.class, "long"); + } catch (JVMCIError e2) { + } + } + if (offset == -1) { + throw new JVMCIError("cannot get offset of field " + name + " with type long or jlong"); + } + pendingFailedSpeculationOffset = offset; + } + public int threadLastJavaSpOffset() { return javaThreadAnchorOffset + javaFrameAnchorLastJavaSpOffset; } @@ -602,11 +636,11 @@ public final long crcTableAddress = getFieldValue("StubRoutines::_crc_table_adr", Long.class, "address"); public final long sha1ImplCompress = getFieldValue("StubRoutines::_sha1_implCompress", Long.class, "address", 0L); - public final long sha1ImplCompressMB = getFieldValue("StubRoutines::_sha1_implCompressMB", Long.class, "address", 0L); + public final long sha1ImplCompressMultiBlock = getFieldValue("StubRoutines::_sha1_implCompressMB", Long.class, "address", 0L); public final long sha256ImplCompress = getFieldValue("StubRoutines::_sha256_implCompress", Long.class, "address", 0L); - public final long sha256ImplCompressMB = getFieldValue("StubRoutines::_sha256_implCompressMB", Long.class, "address", 0L); + public final long sha256ImplCompressMultiBlock = getFieldValue("StubRoutines::_sha256_implCompressMB", Long.class, "address", 0L); public final long sha512ImplCompress = getFieldValue("StubRoutines::_sha512_implCompress", Long.class, "address", 0L); - public final long sha512ImplCompressMB = getFieldValue("StubRoutines::_sha512_implCompressMB", Long.class, "address", 0L); + public final long sha512ImplCompressMultiBlock = getFieldValue("StubRoutines::_sha512_implCompressMB", Long.class, "address", 0L); public final long multiplyToLen = getFieldValue("StubRoutines::_multiplyToLen", Long.class, "address", longRequiredOnAMD64); public final long counterModeAESCrypt = getFieldValue("StubRoutines::_counterMode_AESCrypt", Long.class, "address", 0L);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java Tue Mar 12 19:17:42 2019 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019, 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 @@ -46,6 +46,7 @@ import org.graalvm.compiler.hotspot.replacements.AESCryptSubstitutions; import org.graalvm.compiler.hotspot.replacements.BigIntegerSubstitutions; import org.graalvm.compiler.hotspot.replacements.CipherBlockChainingSubstitutions; +import org.graalvm.compiler.hotspot.replacements.DigestBaseSubstitutions; import org.graalvm.compiler.hotspot.replacements.SHA2Substitutions; import org.graalvm.compiler.hotspot.replacements.SHA5Substitutions; import org.graalvm.compiler.hotspot.replacements.SHASubstitutions; @@ -71,6 +72,7 @@ import org.graalvm.compiler.options.OptionType; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.SuitesProvider; +import org.graalvm.compiler.serviceprovider.JavaVersionUtil; import org.graalvm.compiler.word.Word; import jdk.internal.vm.compiler.word.Pointer; @@ -95,7 +97,7 @@ public static class Options { // @formatter:off @Option(help = "Use Graal arithmetic stubs instead of HotSpot stubs where possible") - public static final OptionKey<Boolean> GraalArithmeticStubs = new OptionKey<>(false); // GR-8276 + public static final OptionKey<Boolean> GraalArithmeticStubs = new OptionKey<>(JavaVersionUtil.JAVA_SPECIFICATION_VERSION >= 9); @Option(help = "Enables instruction profiling on assembler level. Valid values are a comma separated list of supported instructions." + " Compare with subclasses of Assembler.InstructionCounter.", type = OptionType.Debug) public static final OptionKey<String> ASMInstructionProfiling = new OptionKey<>(null); @@ -261,6 +263,36 @@ @NodeIntrinsic(ForeignCallNode.class) private static native void sha5ImplCompressStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word bufAddr, Object state); + /** + * @see DigestBaseSubstitutions#implCompressMultiBlock0 + */ + public static final ForeignCallDescriptor SHA_IMPL_COMPRESS_MB = new ForeignCallDescriptor("shaImplCompressMB", int.class, Word.class, Object.class, int.class, int.class); + + public static int shaImplCompressMBStub(Word bufAddr, Object stateAddr, int ofs, int limit) { + return shaImplCompressMBStub(HotSpotBackend.SHA_IMPL_COMPRESS_MB, bufAddr, stateAddr, ofs, limit); + } + + @NodeIntrinsic(ForeignCallNode.class) + private static native int shaImplCompressMBStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word bufAddr, Object state, int ofs, int limit); + + public static final ForeignCallDescriptor SHA2_IMPL_COMPRESS_MB = new ForeignCallDescriptor("sha2ImplCompressMB", int.class, Word.class, Object.class, int.class, int.class); + + public static int sha2ImplCompressMBStub(Word bufAddr, Object stateAddr, int ofs, int limit) { + return sha2ImplCompressMBStub(HotSpotBackend.SHA2_IMPL_COMPRESS_MB, bufAddr, stateAddr, ofs, limit); + } + + @NodeIntrinsic(ForeignCallNode.class) + private static native int sha2ImplCompressMBStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word bufAddr, Object state, int ofs, int limit); + + public static final ForeignCallDescriptor SHA5_IMPL_COMPRESS_MB = new ForeignCallDescriptor("sha5ImplCompressMB", int.class, Word.class, Object.class, int.class, int.class); + + public static int sha5ImplCompressMBStub(Word bufAddr, Object stateAddr, int ofs, int limit) { + return sha5ImplCompressMBStub(HotSpotBackend.SHA5_IMPL_COMPRESS_MB, bufAddr, stateAddr, ofs, limit); + } + + @NodeIntrinsic(ForeignCallNode.class) + private static native int sha5ImplCompressMBStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word bufAddr, Object state, int ofs, int limit); + public static void unsafeArraycopy(Word srcAddr, Word dstAddr, Word size) { unsafeArraycopyStub(UNSAFE_ARRAYCOPY, srcAddr, dstAddr, size); } @@ -269,6 +301,37 @@ private static native void unsafeArraycopyStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word srcAddr, Word dstAddr, Word size); /** + * Descriptor for {@code StubRoutines::_ghash_processBlocks}. + */ + public static final ForeignCallDescriptor GHASH_PROCESS_BLOCKS = new ForeignCallDescriptor("ghashProcessBlocks", void.class, Word.class, Word.class, Word.class, int.class); + + /** + * Descriptor for {@code StubRoutines::_counterMode_AESCrypt}. + */ + public static final ForeignCallDescriptor COUNTERMODE_IMPL_CRYPT = new ForeignCallDescriptor("counterModeAESCrypt", int.class, Word.class, Word.class, Word.class, Word.class, int.class, + Word.class, Word.class); + + public static int counterModeAESCrypt(Word srcAddr, Word dstAddr, Word kPtr, Word cntPtr, int len, Word encCntPtr, Word used) { + return counterModeAESCrypt(COUNTERMODE_IMPL_CRYPT, srcAddr, dstAddr, kPtr, cntPtr, len, encCntPtr, used); + } + + @NodeIntrinsic(ForeignCallNode.class) + private static native int counterModeAESCrypt(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word srcAddr, Word dstAddr, Word kPtr, Word cntPtr, int len, Word encCntPtr, + Word used); + + /** + * Descriptor for {@code StubRoutines::_vectorizedMismatch}. + */ + public static final ForeignCallDescriptor VECTORIZED_MISMATCHED = new ForeignCallDescriptor("vectorizedMismatch", int.class, Word.class, Word.class, int.class, int.class); + + public static int vectorizedMismatch(Word aAddr, Word bAddr, int length, int log2ArrayIndexScale) { + return vectorizedMismatchStub(VECTORIZED_MISMATCHED, aAddr, bAddr, length, log2ArrayIndexScale); + } + + @NodeIntrinsic(ForeignCallNode.class) + private static native int vectorizedMismatchStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word aAddr, Word bAddr, int length, int log2ArrayIndexScale); + + /** * @see VMErrorNode */ public static final ForeignCallDescriptor VM_ERROR = new ForeignCallDescriptor("vm_error", void.class, Object.class, Object.class, long.class); @@ -389,6 +452,13 @@ } /** + * Translates a set of registers from the callee's perspective to the caller's perspective. This + * is needed for architectures where input/output registers are renamed during a call (e.g. + * register windows on SPARC). Registers which are not visible by the caller are removed. + */ + protected abstract EconomicSet<Register> translateToCallerRegisters(EconomicSet<Register> calleeRegisters); + + /** * Updates a given stub with respect to the registers it destroys. * <p> * Any entry in {@code calleeSaveInfo} that {@linkplain SaveRegistersOp#supportsRemove()
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java Tue Mar 12 19:17:42 2019 +0100 @@ -88,7 +88,7 @@ ResolvedJavaMethod[] methods = compResult.getMethods(); - List<CodeAnnotation> annotations = compResult.getAnnotations(); + List<CodeAnnotation> annotations = compResult.getCodeAnnotations(); Comment[] comments = new Comment[annotations.size()]; if (!annotations.isEmpty()) { for (int i = 0; i < comments.length; i++) { @@ -129,16 +129,16 @@ boolean hasUnsafeAccess = compResult.hasUnsafeAccess(); int id; - long jvmciEnv; + long jvmciCompileState; if (compRequest != null) { id = compRequest.getId(); - jvmciEnv = compRequest.getJvmciEnv(); + jvmciCompileState = compRequest.getJvmciEnv(); } else { id = hsMethod.allocateCompileId(entryBCI); - jvmciEnv = 0L; + jvmciCompileState = 0L; } return new HotSpotCompiledNmethod(name, targetCode, targetCodeSize, sites, assumptions, methods, comments, dataSection, dataSectionAlignment, dataSectionPatches, isImmutablePIC, - totalFrameSize, customStackArea, hsMethod, entryBCI, id, jvmciEnv, hasUnsafeAccess); + totalFrameSize, customStackArea, hsMethod, entryBCI, id, jvmciCompileState, hasUnsafeAccess); } else { return new HotSpotCompiledCode(name, targetCode, targetCodeSize, sites, assumptions, methods, comments, dataSection, dataSectionAlignment, dataSectionPatches, isImmutablePIC, totalFrameSize, customStackArea);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotDataBuilder.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotDataBuilder.java Tue Mar 12 19:17:42 2019 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2019, 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 @@ -51,12 +51,6 @@ } @Override - public boolean needDetailedPatchingInformation() { - /* The HotSpot VM finds operands that need patching by decoding the instruction. */ - return false; - } - - @Override public Data createDataItem(Constant constant) { if (JavaConstant.isNull(constant)) { boolean compressed = COMPRESSED_NULL.equals(constant);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompilerFactory.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompilerFactory.java Tue Mar 12 19:17:42 2019 +0100 @@ -25,6 +25,7 @@ package org.graalvm.compiler.hotspot; import static jdk.vm.ci.common.InitTimer.timer; +import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE; import static org.graalvm.compiler.hotspot.HotSpotGraalOptionValues.GRAAL_OPTION_PROPERTY_PREFIX; import java.io.PrintStream; @@ -71,7 +72,7 @@ public void onSelection() { JVMCIVersionCheck.check(false); assert options == null : "cannot select " + getClass() + " service more than once"; - options = HotSpotGraalOptionValues.HOTSPOT_OPTIONS; + options = HotSpotGraalOptionValues.defaultOptions(); initializeGraalCompilePolicyFields(options); isGraalPredicate = compileGraalWithC1Only ? new IsGraalPredicate() : null; /* @@ -80,6 +81,10 @@ */ adjustCompilationLevelInternal(Object.class, "hashCode", "()I", CompilationLevel.FullOptimization); adjustCompilationLevelInternal(Object.class, "hashCode", "()I", CompilationLevel.Simple); + if (IS_BUILDING_NATIVE_IMAGE) { + // Triggers initialization of all option descriptors + Options.CompileGraalWithC1Only.getName(); + } } private static void initializeGraalCompilePolicyFields(OptionValues options) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalJVMCIServiceLocator.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalJVMCIServiceLocator.java Tue Mar 12 19:17:42 2019 +0100 @@ -26,6 +26,7 @@ import org.graalvm.compiler.serviceprovider.ServiceProvider; +import jdk.vm.ci.common.NativeImageReinitialize; import jdk.vm.ci.hotspot.HotSpotVMEventListener; import jdk.vm.ci.runtime.JVMCICompilerFactory; import jdk.vm.ci.services.JVMCIServiceLocator; @@ -51,7 +52,7 @@ return null; } - private HotSpotGraalRuntime graalRuntime; + @NativeImageReinitialize private HotSpotGraalRuntime graalRuntime; /** * Notifies this object of the compiler created via {@link HotSpotGraalJVMCIServiceLocator}.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalOptionValues.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalOptionValues.java Tue Mar 12 19:17:42 2019 +0100 @@ -40,9 +40,10 @@ import org.graalvm.compiler.options.OptionsParser; import jdk.vm.ci.common.InitTimer; +import jdk.vm.ci.common.NativeImageReinitialize; /** - * The {@link #HOTSPOT_OPTIONS} value contains the options values initialized in a HotSpot VM. The + * The {@link #defaultOptions()} method returns the options values initialized in a HotSpot VM. The * values are set via system properties with the {@value #GRAAL_OPTION_PROPERTY_PREFIX} prefix. */ public class HotSpotGraalOptionValues { @@ -71,7 +72,21 @@ return GRAAL_OPTION_PROPERTY_PREFIX + value.getName() + "=" + value.getValue(options); } - public static final OptionValues HOTSPOT_OPTIONS = initializeOptions(); + @NativeImageReinitialize private static volatile OptionValues hotspotOptions; + + public static OptionValues defaultOptions() { + OptionValues res = hotspotOptions; + if (res == null) { + synchronized (HotSpotGraalOptionValues.class) { + res = hotspotOptions; + if (res == null) { + res = initializeOptions(); + hotspotOptions = res; + } + } + } + return res; + } /** * Global options. The values for these options are initialized by parsing the file denoted by
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java Tue Mar 12 19:17:42 2019 +0100 @@ -95,6 +95,8 @@ */ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider { + private static final boolean IS_AOT = Boolean.getBoolean("com.oracle.graalvm.isaot"); + private static boolean checkArrayIndexScaleInvariants(MetaAccessProvider metaAccess) { assert metaAccess.getArrayIndexScale(JavaKind.Byte) == 1; assert metaAccess.getArrayIndexScale(JavaKind.Boolean) == 1; @@ -159,9 +161,13 @@ compilerConfigurationName = compilerConfigurationFactory.getName(); compiler = new HotSpotGraalCompiler(jvmciRuntime, this, options); - management = GraalServices.loadSingle(HotSpotGraalManagementRegistration.class, false); - if (management != null) { - management.initialize(this); + if (IS_AOT) { + management = null; + } else { + management = GraalServices.loadSingle(HotSpotGraalManagementRegistration.class, false); + if (management != null) { + management.initialize(this); + } } BackendMap backendMap = compilerConfigurationFactory.createBackendMap(); @@ -571,7 +577,7 @@ EconomicMap<OptionKey<?>, Object> extra = EconomicMap.create(); extra.put(DebugOptions.Dump, filter); extra.put(DebugOptions.PrintGraphHost, host); - extra.put(DebugOptions.PrintBinaryGraphPort, port); + extra.put(DebugOptions.PrintGraphPort, port); OptionValues compileOptions = new OptionValues(getOptions(), extra); compiler.compileMethod(new HotSpotCompilationRequest(hotSpotMethod, -1, 0L), false, compileOptions); }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java Tue Mar 12 19:17:42 2019 +0100 @@ -24,17 +24,34 @@ package org.graalvm.compiler.hotspot; +import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE; +import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE; +import static org.graalvm.compiler.replacements.ReplacementsImpl.Options.UseEncodedSnippets; + +import java.util.Set; + +import jdk.internal.vm.compiler.collections.EconomicSet; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.bytecode.BytecodeProvider; +import org.graalvm.compiler.core.common.CompilationIdentifier; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.graph.NodeSourcePosition; import org.graalvm.compiler.hotspot.meta.HotSpotWordOperationPlugin; import org.graalvm.compiler.hotspot.word.HotSpotOperation; +import org.graalvm.compiler.nodes.Invoke; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderPlugin; +import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; +import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin; 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; +import jdk.vm.ci.common.NativeImageReinitialize; import jdk.vm.ci.meta.ResolvedJavaMethod; /** @@ -46,21 +63,149 @@ super(options, new GraalDebugHandlersFactory(snippetReflection), providers, snippetReflection, bytecodeProvider, target); } + protected HotSpotReplacementsImpl(HotSpotReplacementsImpl replacements, Providers providers) { + super(replacements.options, new GraalDebugHandlersFactory(replacements.snippetReflection), providers, replacements.snippetReflection, + replacements.getDefaultReplacementBytecodeProvider(), replacements.target); + } + @Override public Class<? extends GraphBuilderPlugin> getIntrinsifyingPlugin(ResolvedJavaMethod method) { return method.getAnnotation(HotSpotOperation.class) != null ? HotSpotWordOperationPlugin.class : super.getIntrinsifyingPlugin(method); } + public void registerMethodSubstitution(ResolvedJavaMethod method, ResolvedJavaMethod original) { + if (!IS_IN_NATIVE_IMAGE) { + if (IS_BUILDING_NATIVE_IMAGE || UseEncodedSnippets.getValue(options)) { + synchronized (HotSpotReplacementsImpl.class) { + if (snippetEncoder == null) { + snippetEncoder = new SymbolicSnippetEncoder(this); + } + snippetEncoder.registerMethodSubstitution(method, original); + } + } + } + } + + @Override + public StructuredGraph getIntrinsicGraph(ResolvedJavaMethod method, CompilationIdentifier compilationId, DebugContext debug) { + if (IS_IN_NATIVE_IMAGE) { + HotSpotReplacementsImpl replacements = (HotSpotReplacementsImpl) providers.getReplacements(); + InvocationPlugin plugin = replacements.getGraphBuilderPlugins().getInvocationPlugins().lookupInvocation(method); + if (plugin instanceof MethodSubstitutionPlugin) { + MethodSubstitutionPlugin msp = (MethodSubstitutionPlugin) plugin; + return replacements.getMethodSubstitution(msp, method); + } + return null; + } + return super.getIntrinsicGraph(method, compilationId, debug); + } + + @Override + public void notifyNotInlined(GraphBuilderContext b, ResolvedJavaMethod method, Invoke invoke) { + if (b.parsingIntrinsic() && snippetEncoder != null) { + if (getIntrinsifyingPlugin(method) != null) { + snippetEncoder.addDelayedInvocationPluginMethod(method); + return; + } + } + super.notifyNotInlined(b, method, invoke); + } + + // When assertions are enabled, these fields are used to ensure all snippets are + // registered during Graal initialization which in turn ensures that native image + // building will not miss any snippets. + @NativeImageReinitialize private EconomicSet<ResolvedJavaMethod> registeredSnippets = EconomicSet.create(); private boolean snippetRegistrationClosed; @Override public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition) { - assert !snippetRegistrationClosed; - super.registerSnippet(method, original, receiver, trackNodeSourcePosition); + if (!IS_IN_NATIVE_IMAGE) { + assert !snippetRegistrationClosed : "Cannot register snippet after registration is closed: " + method.format("%H.%n(%p)"); + assert registeredSnippets.add(method) : "Cannot register snippet twice: " + method.format("%H.%n(%p)"); + if (IS_BUILDING_NATIVE_IMAGE || UseEncodedSnippets.getValue(options)) { + synchronized (HotSpotReplacementsImpl.class) { + if (snippetEncoder == null) { + snippetEncoder = new SymbolicSnippetEncoder(this); + } + snippetEncoder.registerSnippet(method, original, receiver, trackNodeSourcePosition); + } + } + } } @Override public void closeSnippetRegistration() { snippetRegistrationClosed = true; } + + static SymbolicSnippetEncoder.EncodedSnippets getEncodedSnippets() { + return encodedSnippets; + } + + public Set<ResolvedJavaMethod> getSnippetMethods() { + if (snippetEncoder != null) { + return snippetEncoder.getSnippetMethods(); + } + return null; + } + + static void setEncodedSnippets(SymbolicSnippetEncoder.EncodedSnippets encodedSnippets) { + HotSpotReplacementsImpl.encodedSnippets = encodedSnippets; + } + + public boolean encode() { + SymbolicSnippetEncoder encoder = HotSpotReplacementsImpl.snippetEncoder; + if (encoder != null) { + return encoder.encode(); + } + return false; + } + + private static volatile SymbolicSnippetEncoder.EncodedSnippets encodedSnippets; + + @NativeImageReinitialize static SymbolicSnippetEncoder snippetEncoder; + + @Override + public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod recursiveEntry, Object[] args, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition) { + StructuredGraph graph = getEncodedSnippet(method, args); + if (graph != null) { + return graph; + } + + assert !IS_IN_NATIVE_IMAGE : "should be using encoded snippets"; + return super.getSnippet(method, recursiveEntry, args, trackNodeSourcePosition, replaceePosition); + } + + public StructuredGraph getEncodedSnippet(ResolvedJavaMethod method, Object[] args) { + if (IS_IN_NATIVE_IMAGE || UseEncodedSnippets.getValue(options)) { + synchronized (HotSpotReplacementsImpl.class) { + if (!IS_IN_NATIVE_IMAGE && UseEncodedSnippets.getValue(options)) { + snippetEncoder.encode(); + } + + if (getEncodedSnippets() == null) { + throw GraalError.shouldNotReachHere("encoded snippets not found"); + } + StructuredGraph graph = getEncodedSnippets().getEncodedSnippet(method, this, args); + if (graph == null) { + throw GraalError.shouldNotReachHere("snippet not found: " + method.format("%H.%n(%p)")); + } + return graph; + } + } else if (registeredSnippets != null) { + assert registeredSnippets.contains(method) : "Asking for snippet method that was never registered: " + method.format("%H.%n(%p)"); + } + return null; + } + + public StructuredGraph getMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original) { + if (IS_IN_NATIVE_IMAGE || UseEncodedSnippets.getValue(options)) { + if (getEncodedSnippets() == null) { + throw GraalError.shouldNotReachHere("encoded snippets not found"); + } + return getEncodedSnippets().getMethodSubstitutionGraph(plugin, original, this); + } + return null; + } + }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotTTYStreamProvider.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotTTYStreamProvider.java Tue Mar 12 19:17:42 2019 +0100 @@ -25,7 +25,7 @@ package org.graalvm.compiler.hotspot; import static org.graalvm.compiler.hotspot.HotSpotGraalOptionValues.GRAAL_OPTION_PROPERTY_PREFIX; -import static org.graalvm.compiler.hotspot.HotSpotGraalOptionValues.HOTSPOT_OPTIONS; +import static org.graalvm.compiler.hotspot.HotSpotGraalOptionValues.defaultOptions; import java.io.FileNotFoundException; import java.io.FileOutputStream; @@ -59,7 +59,7 @@ @Override public PrintStream getStream() { - return Options.LogFile.getStream(HOTSPOT_OPTIONS); + return Options.LogFile.getStream(defaultOptions()); } /**
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java Tue Mar 12 12:12:01 2019 -0700 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java Tue Mar 12 19:17:42 2019 +0100 @@ -38,8 +38,9 @@ */ class JVMCIVersionCheck { + // 0.55 introduces new HotSpotSpeculationLog API private static final int JVMCI8_MIN_MAJOR_VERSION = 0; - private static final int JVMCI8_MIN_MINOR_VERSION = 46; + private static final int JVMCI8_MIN_MINOR_VERSION = 55; private static void failVersionCheck(boolean exit, String reason, Object... args) { Formatter errorMessage = new Formatter().format(reason, args);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java Tue Mar 12 19:17:42 2019 +0100 @@ -0,0 +1,1034 @@ +/* + * Copyright (c) 2018, 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 static jdk.vm.ci.runtime.JVMCI.getRuntime; +import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE; +import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE; +import static org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo.createIntrinsicInlineInfo; +import static org.graalvm.compiler.replacements.ReplacementsImpl.Options.UseEncodedSnippets; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import org.graalvm.compiler.api.replacements.Fold; +import org.graalvm.compiler.api.replacements.MethodSubstitution; +import org.graalvm.compiler.api.replacements.Snippet; +import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; +import org.graalvm.compiler.api.runtime.GraalJVMCICompiler; +import org.graalvm.compiler.api.runtime.GraalRuntime; +import org.graalvm.compiler.bytecode.BytecodeProvider; +import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; +import org.graalvm.compiler.core.common.type.AbstractObjectStamp; +import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.core.common.type.StampPair; +import org.graalvm.compiler.core.common.type.SymbolicJVMCIReference; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.graph.NodeMap; +import org.graalvm.compiler.graph.NodeSourcePosition; +import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider; +import org.graalvm.compiler.hotspot.meta.HotSpotProviders; +import org.graalvm.compiler.java.BytecodeParser; +import org.graalvm.compiler.java.GraphBuilderPhase; +import org.graalvm.compiler.nodeinfo.Verbosity; +import org.graalvm.compiler.nodes.CallTargetNode; +import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.EncodedGraph; +import org.graalvm.compiler.nodes.FrameState; +import org.graalvm.compiler.nodes.FullInfopointNode; +import org.graalvm.compiler.nodes.GraphEncoder; +import org.graalvm.compiler.nodes.ParameterNode; +import org.graalvm.compiler.nodes.ProxyNode; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.graphbuilderconf.GeneratedInvocationPlugin; +import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; +import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; +import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin; +import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext; +import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; +import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; +import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin; +import org.graalvm.compiler.nodes.graphbuilderconf.NodePlugin; +import org.graalvm.compiler.nodes.graphbuilderconf.ParameterPlugin; +import org.graalvm.compiler.nodes.java.AccessFieldNode; +import org.graalvm.compiler.nodes.java.MethodCallTargetNode; +import org.graalvm.compiler.nodes.spi.DelegatingReplacements; +import org.graalvm.compiler.nodes.spi.StampProvider; +import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.phases.OptimisticOptimizations; +import org.graalvm.compiler.phases.schedule.SchedulePhase; +import org.graalvm.compiler.phases.util.Providers; +import org.graalvm.compiler.replacements.ConstantBindingParameterPlugin; +import org.graalvm.compiler.replacements.PEGraphDecoder; +import org.graalvm.compiler.replacements.ReplacementsImpl; +import org.graalvm.compiler.replacements.SnippetCounter; +import org.graalvm.compiler.replacements.SnippetIntegerHistogram; + +import jdk.vm.ci.code.Architecture; +import jdk.vm.ci.code.TargetDescription; +import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaField; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaType; +import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.ConstantReflectionProvider; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.JavaType; +import jdk.vm.ci.meta.MemoryAccessProvider; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.MethodHandleAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaField; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.meta.UnresolvedJavaField; +import jdk.vm.ci.meta.UnresolvedJavaMethod; +import jdk.vm.ci.meta.UnresolvedJavaType; + +/** + * This class performs graph encoding using {@link GraphEncoder} but also converts JVMCI type and + * method references into a symbolic form that can be resolved at graph decode time using + * {@link SymbolicJVMCIReference}. + */ +public class SymbolicSnippetEncoder extends DelegatingReplacements { + + /** + * This is a customized HotSpotReplacementsImpl intended only for parsing snippets and method + * substitutions for graph encoding. + */ + private final HotSpotSnippetReplacementsImpl replacements; + + /** + * The set of all snippet methods that have been encoded. + */ + private final Set<ResolvedJavaMethod> snippetMethods = Collections.synchronizedSet(new HashSet<>()); + + /** + * A mapping from the method substitution method to the original method name. The string key and + * values are produced using {@link #methodKey(ResolvedJavaMethod)}. + */ + private final Map<String, String> originalMethods = new ConcurrentHashMap<>(); + + /** + * The current count of graphs encoded. Used to detect when new graphs have been enqueued for + * encoding. + */ + int encodedGraphs = 0; + + /** + * All the graphs parsed so far. + */ + private Map<String, StructuredGraph> preparedSnippetGraphs = new HashMap<>(); + + /** + * The invocation plugins which were delayed during graph preparation. + */ + private Set<ResolvedJavaMethod> delayedInvocationPluginMethods = new HashSet<>(); + + void addDelayedInvocationPluginMethod(ResolvedJavaMethod method) { + delayedInvocationPluginMethods.add(method); + } + + Set<ResolvedJavaMethod> getSnippetMethods() { + return snippetMethods; + } + + protected class SnippetInlineInvokePlugin implements InlineInvokePlugin { + + @Override + public InlineInfo shouldInlineInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) { + if (method.getAnnotation(Fold.class) != null) { + delayedInvocationPluginMethods.add(method); + return InlineInfo.DO_NOT_INLINE_NO_EXCEPTION; + } + + if (getIntrinsifyingPlugin(method) != null) { + delayedInvocationPluginMethods.add(method); + return InlineInfo.DO_NOT_INLINE_NO_EXCEPTION; + } + + // Force inlining when parsing replacements + return createIntrinsicInlineInfo(method, null, getDefaultReplacementBytecodeProvider()); + } + + @Override + public void notifyAfterInline(ResolvedJavaMethod methodToInline) { + assert methodToInline.getAnnotation(Fold.class) == null : methodToInline; + } + } + + public static class SnippetInvocationPlugins extends InvocationPlugins { + + SnippetInvocationPlugins(InvocationPlugins invocationPlugins) { + super(invocationPlugins); + } + + @Override + public InvocationPlugin lookupInvocation(ResolvedJavaMethod method) { + if (method.getAnnotation(Fold.class) != null) { + return null; + } + return super.lookupInvocation(method); + } + } + + /** + * This plugin disables the snippet counter machinery. + */ + private class SnippetCounterPlugin implements NodePlugin { + String snippetCounterName = 'L' + SnippetCounter.class.getName().replace('.', '/') + ';'; + String snippetIntegerHistogramName = 'L' + SnippetIntegerHistogram.class.getName().replace('.', '/') + ';'; + + @Override + public boolean handleLoadField(GraphBuilderContext b, ValueNode object, ResolvedJavaField field) { + if (field.getName().equals("group") && field.getDeclaringClass().getName().equals(snippetCounterName)) { + b.addPush(JavaKind.Object, ConstantNode.forConstant(JavaConstant.NULL_POINTER, b.getMetaAccess())); + return true; + } + if (field.getType().getName().equals(snippetCounterName)) { + b.addPush(JavaKind.Object, ConstantNode.forConstant(replacements.snippetReflection.forObject(SnippetCounter.DISABLED_COUNTER), b.getMetaAccess())); + return true; + } + + if (field.getType().getName().equals(snippetIntegerHistogramName)) { + b.addPush(JavaKind.Object, ConstantNode.forConstant(replacements.snippetReflection.forObject(SnippetIntegerHistogram.DISABLED_COUNTER), b.getMetaAccess())); + return true; + } + return false; + } + } + + /** + * Generate a String name for a method including all type information. Used as a symbolic key + * for lookup. + */ + private static String methodKey(ResolvedJavaMethod method) { + return method.format("%f %H.%n(%P)"); + } + + SymbolicSnippetEncoder(HotSpotReplacementsImpl replacements) { + super(replacements); + + GraphBuilderConfiguration.Plugins plugins = replacements.getGraphBuilderPlugins(); + SnippetInvocationPlugins invocationPlugins = new SnippetInvocationPlugins(plugins.getInvocationPlugins()); + GraphBuilderConfiguration.Plugins copy = new GraphBuilderConfiguration.Plugins(plugins, invocationPlugins); + copy.clearInlineInvokePlugins(); + copy.appendInlineInvokePlugin(new SnippetInlineInvokePlugin()); + copy.appendNodePlugin(new SnippetCounterPlugin()); + HotSpotProviders providers = (HotSpotProviders) replacements.getProviders().copyWith(new HotSpotSubstrateConstantReflectionProvider(replacements.getProviders().getConstantReflection())); + this.replacements = new HotSpotSnippetReplacementsImpl(replacements, providers.copyWith(copy)); + this.replacements.setGraphBuilderPlugins(copy); + } + + @Override + public GraphBuilderConfiguration.Plugins getGraphBuilderPlugins() { + return replacements.getGraphBuilderPlugins(); + } + + /** + * Compiles the snippet and stores the graph. + */ + public void registerMethodSubstitution(ResolvedJavaMethod method, ResolvedJavaMethod original) { + assert method.getAnnotation(MethodSubstitution.class) != null : "MethodSubstitution must be annotated with @" + MethodSubstitution.class.getSimpleName(); + buildGraph(method, original, null, false, false); + snippetMethods.add(method); + } + + static class EncodedSnippets { + private byte[] snippetEncoding; + private Object[] snippetObjects; + private NodeClass<?>[] snippetNodeClasses; + private Map<String, Integer> snippetStartOffsets; + private Map<String, String> originalMethods; + + EncodedSnippets(byte[] snippetEncoding, Object[] snippetObjects, NodeClass<?>[] snippetNodeClasses, Map<String, Integer> snippetStartOffsets, Map<String, String> originalMethods) { + this.snippetEncoding = snippetEncoding; + this.snippetObjects = snippetObjects; + this.snippetNodeClasses = snippetNodeClasses; + this.snippetStartOffsets = snippetStartOffsets; + this.originalMethods = originalMethods; + } + + public StructuredGraph getMethodSubstitutionGraph(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, ReplacementsImpl replacements) { + Integer startOffset = snippetStartOffsets.get(plugin.toString()); + if (startOffset == null) { + throw GraalError.shouldNotReachHere("plugin graph not found: " + plugin); + } + + return decodeGraph(original, null, startOffset, replacements); + } + + @SuppressWarnings("try") + private StructuredGraph decodeGraph(ResolvedJavaMethod method, Object[] args, int startOffset, ReplacementsImpl replacements) { + OptionValues options = replacements.getOptions(); + SnippetReflectionProvider snippetReflection = replacements.snippetReflection; + ParameterPlugin parameterPlugin = null; + Providers providers = replacements.getProviders(); + if (args != null) { + parameterPlugin = new ConstantBindingParameterPlugin(args, providers.getMetaAccess(), snippetReflection); + } + + EncodedGraph encodedGraph = new SymbolicEncodedGraph(snippetEncoding, startOffset, snippetObjects, snippetNodeClasses, method.getDeclaringClass(), + originalMethods.get(methodKey(method))); + try (DebugContext debug = replacements.openDebugContext("SVMSnippet_", method)) { + StructuredGraph result = new StructuredGraph.Builder(options, debug).method(method).setIsSubstitution(true).build(); + PEGraphDecoder graphDecoder = new PEGraphDecoder( + providers.getCodeCache().getTarget().arch, + result, + providers.getMetaAccess(), + providers.getConstantReflection(), + providers.getConstantFieldProvider(), + providers.getStampProvider(), + null, // loopExplosionPlugin + replacements.getGraphBuilderPlugins().getInvocationPlugins(), + new InlineInvokePlugin[0], + parameterPlugin, + null, // nodePlugins + null, // callInlinedMethod + null // sourceLanguagePositionProvider + ) { + @Override + protected EncodedGraph lookupEncodedGraph(ResolvedJavaMethod lookupMethod, + ResolvedJavaMethod originalMethod, + BytecodeProvider intrinsicBytecodeProvider, + boolean isSubstitution, + boolean trackNodeSourcePosition) { + if (lookupMethod.equals(method)) { + return encodedGraph; + } else { + throw GraalError.shouldNotReachHere(method.format("%H.%n(%p)")); + } + } + }; + + graphDecoder.decode(method, result.isSubstitution(), encodedGraph.trackNodeSourcePosition()); + + assert result.verify(); + return result; + } + } + + StructuredGraph getEncodedSnippet(ResolvedJavaMethod method, ReplacementsImpl replacements, Object[] args) { + Integer startOffset = null; + if (snippetStartOffsets != null) { + startOffset = snippetStartOffsets.get(methodKey(method)); + } + if (startOffset == null) { + if (IS_IN_NATIVE_IMAGE) { + throw GraalError.shouldNotReachHere("snippet not found: " + method.format("%H.%n(%p)")); + } else { + return null; + } + } + + SymbolicEncodedGraph encodedGraph = new SymbolicEncodedGraph(snippetEncoding, startOffset, snippetObjects, snippetNodeClasses, method.getDeclaringClass(), + originalMethods.get(methodKey(method))); + return decodeSnippetGraph(encodedGraph, method, replacements, args, HotSpotJVMCIRuntime.runtime().getHostJVMCIBackend().getTarget().arch); + } + + } + + private StructuredGraph buildGraph(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean requireInlining, boolean trackNodeSourcePosition) { + assert method.hasBytecodes() : "Snippet must not be abstract or native"; + Object[] args = null; + if (receiver != null) { + args = new Object[method.getSignature().getParameterCount(true)]; + args[0] = receiver;