--- old/make/test/JtregGraalUnit.gmk 2019-03-28 07:36:37.652415270 +0100 +++ new/make/test/JtregGraalUnit.gmk 2019-03-28 07:36:37.268412701 +0100 @@ -78,36 +78,36 @@ $(eval $(call SetupJavaCompilation, BUILD_VM_COMPILER_TESTS, \ SETUP := GENERATE_USINGJDKBYTECODE, \ SRC := \ - $(SRC_DIR)/jdk.internal.vm.compiler.collections.test/src \ - $(SRC_DIR)/org.graalvm.compiler.api.directives.test/src \ - $(SRC_DIR)/org.graalvm.compiler.api.test/src \ - $(SRC_DIR)/org.graalvm.compiler.asm.aarch64.test/src \ - $(SRC_DIR)/org.graalvm.compiler.asm.amd64.test/src \ - $(SRC_DIR)/org.graalvm.compiler.asm.sparc.test/src \ - $(SRC_DIR)/org.graalvm.compiler.asm.test/src \ - $(SRC_DIR)/org.graalvm.compiler.core.aarch64.test/src \ - $(SRC_DIR)/org.graalvm.compiler.core.amd64.test/src \ - $(SRC_DIR)/org.graalvm.compiler.core.jdk9.test/src \ - $(SRC_DIR)/org.graalvm.compiler.core.test/src \ - $(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 \ - $(SRC_DIR)/org.graalvm.compiler.jtt/src \ - $(SRC_DIR)/org.graalvm.compiler.lir.jtt/src \ - $(SRC_DIR)/org.graalvm.compiler.lir.test/src \ - $(SRC_DIR)/org.graalvm.compiler.loop.test/src \ - $(SRC_DIR)/org.graalvm.compiler.nodes.test/src \ - $(SRC_DIR)/org.graalvm.compiler.options.test/src \ - $(SRC_DIR)/org.graalvm.compiler.phases.common.test/src \ - $(SRC_DIR)/org.graalvm.compiler.replacements.jdk12.test/src \ - $(SRC_DIR)/org.graalvm.compiler.replacements.jdk9.test/src \ - $(SRC_DIR)/org.graalvm.compiler.replacements.test/src \ - $(SRC_DIR)/org.graalvm.compiler.test/src \ - $(SRC_DIR)/org.graalvm.util.test/src \ + $(SRC_DIR)/jdk.internal.vm.compiler.collections.test/src \ + $(SRC_DIR)/org.graalvm.compiler.api.directives.test/src \ + $(SRC_DIR)/org.graalvm.compiler.api.test/src \ + $(SRC_DIR)/org.graalvm.compiler.asm.aarch64.test/src \ + $(SRC_DIR)/org.graalvm.compiler.asm.amd64.test/src \ + $(SRC_DIR)/org.graalvm.compiler.asm.sparc.test/src \ + $(SRC_DIR)/org.graalvm.compiler.asm.test/src \ + $(SRC_DIR)/org.graalvm.compiler.core.aarch64.test/src \ + $(SRC_DIR)/org.graalvm.compiler.core.amd64.test/src \ + $(SRC_DIR)/org.graalvm.compiler.core.jdk9.test/src \ + $(SRC_DIR)/org.graalvm.compiler.core.test/src \ + $(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 \ + $(SRC_DIR)/org.graalvm.compiler.jtt/src \ + $(SRC_DIR)/org.graalvm.compiler.lir.jtt/src \ + $(SRC_DIR)/org.graalvm.compiler.lir.test/src \ + $(SRC_DIR)/org.graalvm.compiler.loop.test/src \ + $(SRC_DIR)/org.graalvm.compiler.nodes.test/src \ + $(SRC_DIR)/org.graalvm.compiler.options.test/src \ + $(SRC_DIR)/org.graalvm.compiler.phases.common.test/src \ + $(SRC_DIR)/org.graalvm.compiler.replacements.jdk12.test/src \ + $(SRC_DIR)/org.graalvm.compiler.replacements.jdk9.test/src \ + $(SRC_DIR)/org.graalvm.compiler.replacements.test/src \ + $(SRC_DIR)/org.graalvm.compiler.test/src \ + $(SRC_DIR)/org.graalvm.util.test/src \ , \ EXCLUDE_FILES := org/graalvm/compiler/core/test/VerifyDebugUsageTest.java, \ BIN := $(COMPILE_OUTPUTDIR)/jdk.vm.compiler.tests, \ --- old/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataPatchProcessor.java 2019-03-28 07:36:38.148418589 +0100 +++ new/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataPatchProcessor.java 2019-03-28 07:36:37.764416020 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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,6 +47,7 @@ import jdk.vm.ci.hotspot.HotSpotObjectConstant; import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; import jdk.vm.ci.hotspot.HotSpotSentinelConstant; +import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.VMConstant; final class DataPatchProcessor { @@ -95,21 +96,24 @@ gotName = "got." + targetSymbol; binaryContainer.addCountersSymbol(targetSymbol); } - } else if (constant instanceof HotSpotObjectConstant) { - HotSpotObjectConstant oopConstant = (HotSpotObjectConstant) constant; - if (oopConstant instanceof HotSpotConstantPoolObject) { - HotSpotConstantPoolObject cpo = (HotSpotConstantPoolObject) oopConstant; + } else if (constant instanceof JavaConstant) { + JavaConstant jConstant = (JavaConstant) constant; + if (jConstant instanceof HotSpotConstantPoolObject) { + HotSpotConstantPoolObject cpo = (HotSpotConstantPoolObject) jConstant; // Even if two locations use the same object, resolve separately - targetSymbol = "ldc." + cpo.getCpType().getName() + cpo.getCpi(); - } else { + targetSymbol = "ldc." + cpo.toValueString(); + Integer offset = binaryContainer.addOopSymbol(targetSymbol); + gotName = "got.ldc." + offset; + } else if (jConstant instanceof HotSpotObjectConstant) { + HotSpotObjectConstant oopConstant = (HotSpotObjectConstant) jConstant; // String constant. targetSymbol = "ldc." + oopConstant.toValueString(); + Integer offset = binaryContainer.addOopSymbol(targetSymbol); + gotName = "got.ldc." + offset; + } else if (jConstant instanceof HotSpotSentinelConstant) { + targetSymbol = "state.M" + methodInfo.getCodeId(); + gotName = "got." + targetSymbol; } - Integer offset = binaryContainer.addOopSymbol(targetSymbol); - gotName = "got.ldc." + offset; - } else if (constant instanceof HotSpotSentinelConstant) { - targetSymbol = "state.M" + methodInfo.getCodeId(); - gotName = "got." + targetSymbol; } assert gotName != null : "Unknown constant type: " + constant; --- old/src/jdk.internal.vm.ci/share/classes/module-info.java 2019-03-28 07:36:38.640421879 +0100 +++ new/src/jdk.internal.vm.ci/share/classes/module-info.java 2019-03-28 07:36:38.264419364 +0100 @@ -24,7 +24,9 @@ */ module jdk.internal.vm.ci { - exports jdk.vm.ci.services to jdk.internal.vm.compiler; + exports jdk.vm.ci.services to + jdk.internal.vm.compiler, + jdk.internal.vm.compiler.management; exports jdk.vm.ci.runtime to jdk.internal.vm.compiler, jdk.internal.vm.compiler.management; --- old/src/jdk.internal.vm.compiler.management/share/classes/org.graalvm.compiler.hotspot.management/src/org/graalvm/compiler/hotspot/management/HotSpotGraalRuntimeMBean.java 2019-03-28 07:36:39.136425198 +0100 +++ new/src/jdk.internal.vm.compiler.management/share/classes/org.graalvm.compiler.hotspot.management/src/org/graalvm/compiler/hotspot/management/HotSpotGraalRuntimeMBean.java 2019-03-28 07:36:38.756422656 +0100 @@ -52,6 +52,8 @@ import org.graalvm.compiler.options.OptionsParser; import org.graalvm.compiler.serviceprovider.GraalServices; +import jdk.vm.ci.services.Services; + /** * MBean used to access properties and operations of a {@link HotSpotGraalRuntime} instance. */ @@ -84,7 +86,7 @@ private static boolean initDebug() { try { - return Boolean.getBoolean(HotSpotGraalRuntimeMBean.class.getSimpleName() + ".debug"); + return Boolean.parseBoolean(Services.getSavedProperties().get(HotSpotGraalRuntimeMBean.class.getSimpleName() + ".debug")); } catch (SecurityException e) { // Swallow the exception return false; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java 2019-03-28 07:36:39.636428542 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java 2019-03-28 07:36:39.256426001 +0100 @@ -40,6 +40,7 @@ import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.BR; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.BRK; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CAS; +import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CCMP; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CLREX; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CLS; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CLZ; @@ -86,6 +87,7 @@ import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.MOVK; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.MOVN; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.MOVZ; +import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.MRS; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.MSUB; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ORN; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ORR; @@ -436,6 +438,7 @@ private static final int FpImmOffset = 13; private static final int FpCmpOp = 0x1E202000; + private static final int FpCmpeOp = 0x1E202010; private static final int PcRelImmHiOffset = 5; private static final int PcRelImmLoOffset = 29; @@ -532,6 +535,8 @@ SUB(0x40000000), SUBS(SUB.encoding | AddSubSetFlag), + CCMP(0x7A400000), + NOT(0x00200000), AND(0x00000000), BIC(AND.encoding | NOT.encoding), @@ -618,6 +623,9 @@ HINT(0xD503201F), DMB(0x000000A0), + MRS(0xD5300000), + MSR(0xD5100000), + BLR_NATIVE(0xc0000000); public final int encoding; @@ -628,6 +636,29 @@ } + public enum SystemRegister { + FPCR(0b11, 0b011, 0b0100, 0b0100, 0b000), + FPSR(0b11, 0b011, 0b0100, 0b0100, 0b001); + + SystemRegister(int op0, int op1, int crn, int crm, int op2) { + this.op0 = op0; + this.op1 = op1; + this.crn = crn; + this.crm = crm; + this.op2 = op2; + } + + public int encoding() { + return op0 << 19 | op1 << 16 | crn << 12 | crm << 8 | op2 << 5; + } + + private final int op0; + private final int op1; + private final int crn; + private final int crm; + private final int op2; + } + public enum ShiftType { LSL(0), LSR(1), @@ -971,8 +1002,10 @@ int imm = (imm28 & NumUtil.getNbitNumberInt(28)) >> 2; int instrEncoding = instr.encoding | UnconditionalBranchImmOp; if (pos == -1) { + annotatePatchingImmediate(position(), instr, 26, 0, 2); emitInt(instrEncoding | imm); } else { + annotatePatchingImmediate(pos, instr, 26, 0, 2); emitInt(instrEncoding | imm, pos); } } @@ -1011,6 +1044,7 @@ assert !reg.equals(zr); assert !reg.equals(sp); emitInt(instr.encoding | UnconditionalBranchRegOp | rs1(reg)); + } /* Load-Store Single Register (5.3.1) */ @@ -1161,9 +1195,11 @@ int memop = instr.encoding | transferSizeEncoding | is32Bit | isFloat | rt(reg); switch (address.getAddressingMode()) { case IMMEDIATE_SCALED: + annotatePatchingImmediate(position(), instr, 12, LoadStoreScaledImmOffset, log2TransferSize); emitInt(memop | LoadStoreScaledOp | address.getImmediate() << LoadStoreScaledImmOffset | rs1(address.getBase())); break; case IMMEDIATE_UNSCALED: + annotatePatchingImmediate(position(), instr, 9, LoadStoreUnscaledImmOffset, 0); emitInt(memop | LoadStoreUnscaledOp | address.getImmediate() << LoadStoreUnscaledImmOffset | rs1(address.getBase())); break; case BASE_REGISTER_ONLY: @@ -1178,12 +1214,15 @@ case PC_LITERAL: assert log2TransferSize >= 2 : "PC literal loads only works for load/stores of 32-bit and larger"; transferSizeEncoding = (log2TransferSize - 2) << LoadStoreTransferSizeOffset; + annotatePatchingImmediate(position(), instr, 21, LoadLiteralImmeOffset, 2); emitInt(transferSizeEncoding | isFloat | LoadLiteralOp | rd(reg) | address.getImmediate() << LoadLiteralImmeOffset); break; case IMMEDIATE_POST_INDEXED: + annotatePatchingImmediate(position(), instr, 9, LoadStoreIndexedImmOffset, 0); emitInt(memop | LoadStorePostIndexedOp | rs1(address.getBase()) | address.getImmediate() << LoadStoreIndexedImmOffset); break; case IMMEDIATE_PRE_INDEXED: + annotatePatchingImmediate(position(), instr, 9, LoadStoreIndexedImmOffset, 0); emitInt(memop | LoadStorePreIndexedOp | rs1(address.getBase()) | address.getImmediate() << LoadStoreIndexedImmOffset); break; default: @@ -1529,6 +1568,10 @@ emitInt(type.encoding | instr.encoding | AddSubImmOp | encodeAimm(aimm) | rd(dst) | rs1(src)); } + public void ccmp(int size, Register x, Register y, int aimm, ConditionFlag condition) { + emitInt(generalFromSize(size).encoding | CCMP.encoding | rs1(x) | rs2(y) | encodeAimm(aimm) | condition.encoding << ConditionalConditionOffset); + } + /** * Encodes arithmetic immediate. * @@ -2414,7 +2457,8 @@ return false; } // bits[62] and bits[61] are opposites. - return ((bits ^ (bits << 1)) & (1L << 62)) != 0; + boolean result = ((bits ^ (bits << 1)) & (1L << 62)) != 0; + return result; } private static int getFloatImmediate(float imm) { @@ -2694,6 +2738,20 @@ } /** + * Signalling compares src1 to src2. + * + * @param size register size. + * @param src1 floating point register. May not be null. + * @param src2 floating point register. May not be null. + */ + public void fcmpe(int size, Register src1, Register src2) { + assert src1.getRegisterCategory().equals(SIMD); + assert src2.getRegisterCategory().equals(SIMD); + InstructionType type = floatFromSize(size); + emitInt(type.encoding | FCMP.encoding | FpCmpeOp | rs1(src1) | rs2(src2)); + } + + /** * Conditional compare. NZCV = fcmp(src1, src2) if condition else uimm4. * * @param size register size. @@ -2722,6 +2780,18 @@ emitInt(type.encoding | FCMPZERO.encoding | FpCmpOp | rs1(src)); } + /** + * Signalling compare register to 0.0 . + * + * @param size register size. + * @param src floating point register. May not be null. + */ + public void fcmpeZero(int size, Register src) { + assert src.getRegisterCategory().equals(SIMD); + InstructionType type = floatFromSize(size); + emitInt(type.encoding | FCMPZERO.encoding | FpCmpeOp | rs1(src)); + } + /* Floating-point Conditional Select (5.7.11) */ /** @@ -2833,4 +2903,58 @@ emitInt(DMB.encoding | BarrierOp | barrierKind.encoding << BarrierKindOffset); } + public void mrs(Register dst, SystemRegister systemRegister) { + emitInt(MRS.encoding | systemRegister.encoding() | rt(dst)); + } + + public void msr(SystemRegister systemRegister, Register src) { + emitInt(MRS.encoding | systemRegister.encoding() | rt(src)); + } + + public void annotatePatchingImmediate(int pos, Instruction instruction, int operandSizeBits, int offsetBits, int shift) { + if (codePatchingAnnotationConsumer != null) { + codePatchingAnnotationConsumer.accept(new OperandDataAnnotation(pos, instruction, operandSizeBits, offsetBits, shift)); + } + } + + void annotatePatchingImmediateNativeAddress(int pos, int operandSizeBits, int numInstrs) { + if (codePatchingAnnotationConsumer != null) { + codePatchingAnnotationConsumer.accept(new MovSequenceAnnotation(pos, operandSizeBits, numInstrs)); + } + } + + public static class OperandDataAnnotation extends CodeAnnotation { + + /** + * The size of the operand, in bytes. + */ + public final int operandSizeBits; + public final int offsetBits; + public final Instruction instruction; + public final int shift; + + OperandDataAnnotation(int instructionPosition, Instruction instruction, int operandSizeBits, int offsetBits, int shift) { + super(instructionPosition); + this.operandSizeBits = operandSizeBits; + this.offsetBits = offsetBits; + this.shift = shift; + this.instruction = instruction; + } + } + + public static class MovSequenceAnnotation extends CodeAnnotation { + + /** + * The size of the operand, in bytes. + */ + public final int operandSizeBits; + public final int numInstrs; + + MovSequenceAnnotation(int instructionPosition, int operandSizeBits, int numInstrs) { + super(instructionPosition); + this.operandSizeBits = operandSizeBits; + this.numInstrs = numInstrs; + } + } + } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java 2019-03-28 07:36:40.180432182 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java 2019-03-28 07:36:39.792429586 +0100 @@ -266,7 +266,8 @@ * @return AArch64Address pointing to memory at {@code base + displacement}. */ public AArch64Address makeAddress(Register base, long displacement, int transferSize) { - return makeAddress(base, displacement, zr, /* signExtend */false, transferSize, zr, /* allowOverwrite */false); + return makeAddress(base, displacement, zr, /* signExtend */false, // + transferSize, zr, /* allowOverwrite */false); } /** @@ -365,7 +366,19 @@ * @param imm immediate loaded into register. */ public void mov(Register dst, long imm) { + mov(dst, imm, false); + } + + /** + * Loads immediate into register. + * + * @param dst general purpose register. May not be null, zero-register or stackpointer. + * @param imm immediate loaded into register. + * @param annotateImm Flag to signal of the immediate value should be annotated. + */ + public void mov(Register dst, long imm, boolean annotateImm) { assert dst.getRegisterCategory().equals(CPU); + int pos = position(); if (imm == 0L) { movx(dst, zr); } else if (LogicalImmediateTable.isRepresentable(true, imm) != LogicalImmediateTable.Representable.NO) { @@ -379,6 +392,9 @@ sxt(64, 32, dst, dst); } else { mov64(dst, imm); + if (annotateImm) { + annotatePatchingImmediateNativeAddress(pos, 64, 4); + } } } @@ -403,9 +419,25 @@ * @param imm */ public void movNativeAddress(Register dst, long imm) { + movNativeAddress(dst, imm, false); + } + + /** + * Generates a 48-bit immediate move code sequence. The immediate may later be updated by + * HotSpot. + * + * In AArch64 mode the virtual address space is 48-bits in size, so we only need three + * instructions to create a patchable instruction sequence that can reach anywhere. + * + * @param dst general purpose register. May not be null, stackpointer or zero-register. + * @param imm The immediate address + * @param annotateImm Flag to signal of the immediate value should be annotated. + */ + public void movNativeAddress(Register dst, long imm, boolean annotateImm) { assert (imm & 0xFFFF_0000_0000_0000L) == 0; // We have to move all non zero parts of the immediate in 16-bit chunks boolean firstMove = true; + int pos = position(); for (int offset = 0; offset < 48; offset += 16) { int chunk = (int) (imm >> offset) & NumUtil.getNbitNumberInt(16); if (firstMove) { @@ -415,6 +447,9 @@ movk(64, dst, chunk, offset); } } + if (annotateImm) { + annotatePatchingImmediateNativeAddress(pos, 48, 3); + } assert !firstMove; } @@ -1597,7 +1632,7 @@ } public void pause() { - throw GraalError.unimplemented(); + super.hint(SystemHint.YIELD); } /** @@ -1721,7 +1756,8 @@ */ @Override public AArch64Address makeAddress(Register base, int displacement) { - return makeAddress(base, displacement, zr, /* signExtend */false, /* transferSize */0, zr, /* allowOverwrite */false); + return makeAddress(base, displacement, zr, /* signExtend */false, /* transferSize */0, // + zr, /* allowOverwrite */false); } @Override @@ -1730,7 +1766,9 @@ } public void addressOf(Register dst) { - // This will be fixed up later. + if (codePatchingAnnotationConsumer != null) { + codePatchingAnnotationConsumer.accept(new AdrpAddMacroInstruction(position())); + } super.adrp(dst); super.add(64, dst, dst, 0); } @@ -1744,4 +1782,51 @@ public void lea(Register d, AArch64Address a) { a.lea(this, d); } + + public interface MacroInstruction { + void patch(int codePos, int relative, byte[] code); + } + + /** + * Emits elf patchable adrp add sequence. + */ + public void adrAddRel(int srcSize, Register result, AArch64Address a) { + if (codePatchingAnnotationConsumer != null) { + codePatchingAnnotationConsumer.accept(new ADRADDPRELMacroInstruction(position())); + } + super.adrp(a.getBase()); + this.ldr(srcSize, result, a); + } + + public static class ADRADDPRELMacroInstruction extends CodeAnnotation implements MacroInstruction { + public ADRADDPRELMacroInstruction(int position) { + super(position); + } + + @Override + public String toString() { + return "ADR_PREL_PG"; + } + + @Override + public void patch(int codePos, int relative, byte[] code) { + throw GraalError.unimplemented(); + } + } + + public static class AdrpAddMacroInstruction extends CodeAnnotation implements MacroInstruction { + public AdrpAddMacroInstruction(int position) { + super(position); + } + + @Override + public String toString() { + return "ADRP_ADD"; + } + + @Override + public void patch(int codePos, int relative, byte[] code) { + throw GraalError.unimplemented(); + } + } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/Assembler.java 2019-03-28 07:36:40.700435660 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/Assembler.java 2019-03-28 07:36:40.316433092 +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 @@ -123,7 +123,7 @@ return codeBuffer.getInt(pos); } - private static final String NEWLINE = System.getProperty("line.separator"); + private static final String NEWLINE = System.lineSeparator(); /** * Some GPU architectures have a text based encoding. --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java 2019-03-28 07:36:41.208439058 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java 2019-03-28 07:36:40.820436463 +0100 @@ -62,11 +62,26 @@ public class AArch64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implements AArch64ArithmeticLIRGeneratorTool { + public AArch64ArithmeticLIRGenerator(AllocatableValue nullRegisterValue) { + this.nullRegisterValue = nullRegisterValue; + } + + private final AllocatableValue nullRegisterValue; + @Override public AArch64LIRGenerator getLIRGen() { return (AArch64LIRGenerator) super.getLIRGen(); } + public boolean mustReplaceNullWithNullRegister(JavaConstant nullConstant) { + /* Uncompressed null pointers only */ + return nullRegisterValue != null && JavaConstant.NULL_POINTER.equals(nullConstant); + } + + public AllocatableValue getNullRegisterValue() { + return nullRegisterValue; + } + @Override protected boolean isNumericInteger(PlatformKind kind) { return ((AArch64Kind) kind).isInteger(); @@ -485,11 +500,6 @@ } @Override - public void emitCompareOp(AArch64Kind cmpKind, Variable left, Value right) { - throw GraalError.unimplemented(); - } - - @Override public Value emitRound(Value value, RoundingMode mode) { AArch64ArithmeticOp op; switch (mode) { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRGenerator.java 2019-03-28 07:36:41.740442616 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRGenerator.java 2019-03-28 07:36:41.352440021 +0100 @@ -164,7 +164,7 @@ public Variable emitValueCompareAndSwap(LIRKind accessKind, Value address, Value expectedValue, Value newValue) { Variable result = newVariable(newValue.getValueKind()); Variable scratch = newVariable(LIRKind.value(AArch64Kind.WORD)); - append(new CompareAndSwapOp(result, loadNonCompareConst(expectedValue), loadReg(newValue), asAllocatable(address), scratch)); + append(new CompareAndSwapOp(result, loadReg(expectedValue), loadReg(newValue), asAllocatable(address), scratch)); return result; } @@ -238,8 +238,13 @@ * null. */ @Override - public Variable emitConditionalMove(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) { - boolean mirrored = emitCompare(cmpKind, left, right, cond, unorderedIsTrue); + public Variable emitConditionalMove(PlatformKind cmpKind, Value left, final Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) { + AArch64ArithmeticLIRGenerator arithLir = ((AArch64ArithmeticLIRGenerator) arithmeticLIRGen); + Value actualRight = right; + if (isJavaConstant(actualRight) && arithLir.mustReplaceNullWithNullRegister((asJavaConstant(actualRight)))) { + actualRight = arithLir.getNullRegisterValue(); + } + boolean mirrored = emitCompare(cmpKind, left, actualRight, cond, unorderedIsTrue); Condition finalCondition = mirrored ? cond.mirror() : cond; boolean finalUnorderedIsTrue = mirrored ? !unorderedIsTrue : unorderedIsTrue; ConditionFlag cmpCondition = toConditionFlag(((AArch64Kind) cmpKind).isInteger(), finalCondition, finalUnorderedIsTrue); @@ -256,30 +261,38 @@ } @Override - public void emitCompareBranch(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination, + public void emitCompareBranch(PlatformKind cmpKind, Value left, final Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability) { + Value actualRight = right; 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; + AArch64ArithmeticLIRGenerator arithLir = ((AArch64ArithmeticLIRGenerator) arithmeticLIRGen); + if (LIRValueUtil.isNullConstant(actualRight)) { + JavaConstant rightConstant = asJavaConstant(actualRight); + if (arithLir.mustReplaceNullWithNullRegister(rightConstant)) { + actualRight = arithLir.getNullRegisterValue(); + } else { + 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)); + append(new CompareBranchZeroOp(asAllocatable(actualRight), trueDestination, falseDestination, trueDestinationProbability)); return; - } else if (isIntConstant(right, 0)) { + } else if (isIntConstant(actualRight, 0)) { append(new CompareBranchZeroOp(asAllocatable(left), trueDestination, falseDestination, trueDestinationProbability)); return; } } } - boolean mirrored = emitCompare(cmpKind, left, right, cond, unorderedIsTrue); + boolean mirrored = emitCompare(cmpKind, left, actualRight, cond, unorderedIsTrue); Condition finalCondition = mirrored ? cond.mirror() : cond; boolean finalUnorderedIsTrue = mirrored ? !unorderedIsTrue : unorderedIsTrue; ConditionFlag cmpCondition = toConditionFlag(((AArch64Kind) cmpKind).isInteger(), finalCondition, finalUnorderedIsTrue); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/AMD64MatchRuleTest.java 2019-03-28 07:36:42.248446014 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/AMD64MatchRuleTest.java 2019-03-28 07:36:41.868443472 +0100 @@ -26,14 +26,19 @@ import static org.junit.Assume.assumeTrue; +import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; import org.graalvm.compiler.core.test.MatchRuleTest; import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.LIRInstruction; +import org.graalvm.compiler.lir.amd64.AMD64Binary; import org.graalvm.compiler.lir.amd64.AMD64BinaryConsumer.MemoryConstOp; +import org.graalvm.compiler.lir.amd64.AMD64BinaryConsumer.ConstOp; +import org.graalvm.compiler.lir.amd64.AMD64Unary; import org.junit.Before; import org.junit.Test; import jdk.vm.ci.amd64.AMD64; +import jdk.vm.ci.amd64.AMD64Kind; public class AMD64MatchRuleTest extends MatchRuleTest { @Before @@ -77,4 +82,182 @@ this.x = x; } } + + static volatile short shortValue; + + public static long testVolatileExtensionSnippet() { + return shortValue; + } + + @Test + public void testVolatileExtension() { + compile(getResolvedJavaMethod("testVolatileExtensionSnippet"), null); + LIR lir = getLIR(); + boolean found = false; + for (LIRInstruction ins : lir.getLIRforBlock(lir.codeEmittingOrder()[0])) { + if (ins instanceof AMD64Unary.MemoryOp) { + ins.visitEachOutput((value, mode, flags) -> assertTrue(value.getPlatformKind().toString(), value.getPlatformKind().equals(AMD64Kind.QWORD))); + assertFalse("MemoryOp expected only once in first block", found); + found = true; + } + } + assertTrue("sign extending load must be in the LIR", found); + } + + static int intValue; + static volatile int volatileIntValue; + + /** + * Can't match test and load of input because of volatile store in between. + */ + public static short testLoadTestNoMatchSnippet() { + int v = intValue; + volatileIntValue = 42; + if (v == 42) { + return shortValue; + } + return 0; + } + + @Test + public void testLoadTestNoMatch() { + compile(getResolvedJavaMethod("testLoadTestNoMatchSnippet"), null); + LIR lir = getLIR(); + boolean found = false; + for (LIRInstruction ins : lir.getLIRforBlock(lir.codeEmittingOrder()[0])) { + if (ins instanceof ConstOp && ((ConstOp) ins).getOpcode().toString().equals("CMP")) { + assertFalse("CMP expected only once in first block", found); + found = true; + } + } + assertTrue("CMP must be in the LIR", found); + } + + /** + * Should match as an add with a memory operand. + */ + public static int testAddLoadSnippet() { + int v1 = volatileIntValue; + int v2 = intValue; + return v2 + (2 * v1); + } + + @Test + public void testAddLoad() { + compile(getResolvedJavaMethod("testAddLoadSnippet"), null); + LIR lir = getLIR(); + boolean found = false; + for (LIRInstruction ins : lir.getLIRforBlock(lir.codeEmittingOrder()[0])) { + if (ins instanceof AMD64Binary.MemoryTwoOp && ((AMD64Binary.MemoryTwoOp) ins).getOpcode().toString().equals("ADD")) { + assertFalse("MemoryTwoOp expected only once in first block", found); + found = true; + } + } + assertTrue("ADD with memory argument must be in the LIR", found); + } + + /** + * Can't match as an add with a memory operand because the other add input is too late. + */ + public static int testAddLoadNoMatchSnippet() { + int v1 = volatileIntValue; + int v2 = intValue; + return v1 + (2 * v2); + } + + @Test + public void testAddLoadNoMatch() { + compile(getResolvedJavaMethod("testAddLoadNoMatchSnippet"), null); + LIR lir = getLIR(); + boolean found = false; + for (LIRInstruction ins : lir.getLIRforBlock(lir.codeEmittingOrder()[0])) { + if (ins instanceof AMD64Binary.CommutativeTwoOp && ((AMD64Binary.CommutativeTwoOp) ins).getOpcode().toString().equals("ADD")) { + assertFalse("CommutativeTwoOp expected only once in first block", found); + found = true; + } + } + assertTrue("ADD with memory argument must not be in the LIR", found); + } + + /** + * sign extension and load are in different blocks but can still be matched as a single + * instruction. + */ + public static long testVolatileExtensionDifferentBlocksSnippet(boolean flag) { + short v = shortValue; + if (flag) { + return v; + } + return 0; + } + + @Test + public void testVolatileExtensionDifferentBlocks() { + compile(getResolvedJavaMethod("testVolatileExtensionDifferentBlocksSnippet"), null); + LIR lir = getLIR(); + boolean found = false; + for (LIRInstruction ins : lir.getLIRforBlock(lir.codeEmittingOrder()[0])) { + if (ins instanceof AMD64Unary.MemoryOp) { + ins.visitEachOutput((value, mode, flags) -> assertTrue(value.getPlatformKind().toString(), value.getPlatformKind().equals(AMD64Kind.QWORD))); + assertFalse("MemoryOp expected only once in first block", found); + found = true; + } + } + assertTrue("sign extending load must be in the LIR", found); + } + + /** + * Add and load are not in the same block and one input is too late: can't match. + */ + public static int testAddLoadDifferentBlocksNoMatchSnippet(boolean flag) { + int v1 = volatileIntValue; + if (flag) { + int v2 = intValue; + return v1 + (2 * v2); + } + return 0; + } + + @Test + public void testAddLoadDifferentBlocksNoMatch() { + compile(getResolvedJavaMethod("testAddLoadDifferentBlocksNoMatchSnippet"), null); + LIR lir = getLIR(); + boolean found = false; + for (AbstractBlockBase b : lir.codeEmittingOrder()) { + for (LIRInstruction ins : lir.getLIRforBlock(b)) { + if (ins instanceof AMD64Binary.CommutativeTwoOp && ((AMD64Binary.CommutativeTwoOp) ins).getOpcode().toString().equals("ADD")) { + assertFalse("CommutativeTwoOp expected only once in first block", found); + found = true; + } + } + } + assertTrue("ADD with memory argument must not be in the LIR", found); + } + + /** + * Add and load are in different blocks but can still match. + */ + public static int testAddLoadDifferentBlocksSnippet(boolean flag) { + int v2 = intValue; + int v1 = volatileIntValue; + if (flag) { + return v1 + v2; + } + return 0; + } + + @Test + public void testAddLoadDifferentBlocks() { + compile(getResolvedJavaMethod("testAddLoadDifferentBlocksSnippet"), null); + LIR lir = getLIR(); + boolean found = false; + for (LIRInstruction ins : lir.getLIRforBlock(lir.codeEmittingOrder()[0])) { + if (ins instanceof AMD64Binary.MemoryTwoOp && ((AMD64Binary.MemoryTwoOp) ins).getOpcode().toString().equals("ADD")) { + assertFalse("MemoryTwoOp expected only once in first block", found); + found = true; + } + } + assertTrue("ADD with memory argument must be in the LIR", found); + } + } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java 2019-03-28 07:36:42.744449331 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java 2019-03-28 07:36:42.360446763 +0100 @@ -689,10 +689,9 @@ getLIRGen().append(new AMD64Unary.MOp(op.m1Op, size, result, input)); } else { /* - * c is implicitly masked to 5 or 6 bits by the CPU, so casting it to (int) is - * always correct, even without the NumUtil.is32bit() test. + * c needs to be masked here, because shifts with immediate expect a byte. */ - getLIRGen().append(new AMD64Binary.ConstOp(op.miOp, size, result, input, (int) c.asLong())); + getLIRGen().append(new AMD64Binary.ConstOp(op.miOp, size, result, input, (byte) c.asLong())); } } else { getLIRGen().emitMove(RCX_I, b); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/Fields.java 2019-03-28 07:36:43.256452755 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/Fields.java 2019-03-28 07:36:42.876450214 +0100 @@ -24,7 +24,7 @@ package org.graalvm.compiler.core.common; -import static org.graalvm.compiler.core.common.UnsafeAccess.UNSAFE; +import static org.graalvm.compiler.serviceprovider.GraalUnsafeAccess.getUnsafe; import java.util.ArrayList; import java.util.Collections; @@ -38,6 +38,8 @@ */ public class Fields { + private static final Unsafe UNSAFE = getUnsafe(); + /** * Offsets used with {@link Unsafe} to access the fields. */ --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/FieldsScanner.java 2019-03-28 07:36:43.768456180 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/FieldsScanner.java 2019-03-28 07:36:43.392453665 +0100 @@ -24,7 +24,7 @@ package org.graalvm.compiler.core.common; -import static org.graalvm.compiler.core.common.UnsafeAccess.UNSAFE; +import static org.graalvm.compiler.serviceprovider.GraalUnsafeAccess.getUnsafe; import java.lang.reflect.Field; import java.lang.reflect.Modifier; @@ -50,6 +50,8 @@ */ public static class DefaultCalcOffset implements CalcOffset { + private static final Unsafe UNSAFE = getUnsafe(); + @Override public long getOffset(Field field) { return UNSAFE.objectFieldOffset(field); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java 2019-03-28 07:36:44.256459443 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java 2019-03-28 07:36:43.872456876 +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 @@ -278,4 +278,8 @@ @Option(help = "Enable inlining decision tracing in stubs and snippets.", type = OptionType.Debug) public static final OptionKey TraceInliningForStubsAndSnippets = new OptionKey<>(false); + + @Option(help = "Use Graal-generated stubs for complicated LIR operations instead of embedding all the emitted code.") + public static final OptionKey UseGraalStubs = new OptionKey<>(true); + } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/UnsafeArrayTypeReader.java 2019-03-28 07:36:44.768462868 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/UnsafeArrayTypeReader.java 2019-03-28 07:36:44.388460326 +0100 @@ -24,7 +24,8 @@ package org.graalvm.compiler.core.common.util; -import static org.graalvm.compiler.core.common.util.UnsafeAccess.UNSAFE; +import static org.graalvm.compiler.serviceprovider.GraalUnsafeAccess.getUnsafe; + import sun.misc.Unsafe; /** @@ -41,6 +42,8 @@ */ public abstract class UnsafeArrayTypeReader implements TypeReader { + private static final Unsafe UNSAFE = getUnsafe(); + public static int getS1(byte[] data, long byteIndex) { return UNSAFE.getByte(data, readOffset(data, byteIndex, Byte.BYTES)); } @@ -142,6 +145,8 @@ } final class UnalignedUnsafeArrayTypeReader extends UnsafeArrayTypeReader { + private static final Unsafe UNSAFE = getUnsafe(); + protected static int getS2(byte[] data, long byteIndex) { return UNSAFE.getShort(data, readOffset(data, byteIndex, Short.BYTES)); } @@ -181,6 +186,8 @@ } class AlignedUnsafeArrayTypeReader extends UnsafeArrayTypeReader { + private static final Unsafe UNSAFE = getUnsafe(); + protected static int getS2(byte[] data, long byteIndex) { long offset = readOffset(data, byteIndex, Short.BYTES); return ((UNSAFE.getByte(data, offset + 0) & 0xFF) << 0) | // --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/UnsafeArrayTypeWriter.java 2019-03-28 07:36:45.280466291 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/UnsafeArrayTypeWriter.java 2019-03-28 07:36:44.896463723 +0100 @@ -30,6 +30,8 @@ import static org.graalvm.compiler.core.common.util.TypeConversion.asU1; import static org.graalvm.compiler.core.common.util.TypeConversion.asU2; import static org.graalvm.compiler.core.common.util.TypeConversion.asU4; +import static org.graalvm.compiler.serviceprovider.GraalUnsafeAccess.getUnsafe; + import sun.misc.Unsafe; /** @@ -44,6 +46,7 @@ */ public abstract class UnsafeArrayTypeWriter implements TypeWriter { + private static final Unsafe UNSAFE = getUnsafe(); private static final int MIN_CHUNK_LENGTH = 200; private static final int MAX_CHUNK_LENGTH = 16000; @@ -96,13 +99,13 @@ @Override public final void putS1(long value) { long offset = writeOffset(Byte.BYTES); - UnsafeAccess.UNSAFE.putByte(writeChunk.data, offset, asS1(value)); + UNSAFE.putByte(writeChunk.data, offset, asS1(value)); } @Override public final void putU1(long value) { long offset = writeOffset(Byte.BYTES); - UnsafeAccess.UNSAFE.putByte(writeChunk.data, offset, asU1(value)); + UNSAFE.putByte(writeChunk.data, offset, asU1(value)); } @Override @@ -134,52 +137,56 @@ } final class UnalignedUnsafeArrayTypeWriter extends UnsafeArrayTypeWriter { + private static final Unsafe UNSAFE = getUnsafe(); + @Override public void putS2(long value) { long offset = writeOffset(Short.BYTES); - UnsafeAccess.UNSAFE.putShort(writeChunk.data, offset, asS2(value)); + UNSAFE.putShort(writeChunk.data, offset, asS2(value)); } @Override public void putS4(long value) { long offset = writeOffset(Integer.BYTES); - UnsafeAccess.UNSAFE.putInt(writeChunk.data, offset, asS4(value)); + UNSAFE.putInt(writeChunk.data, offset, asS4(value)); } @Override public void putS8(long value) { long offset = writeOffset(Long.BYTES); - UnsafeAccess.UNSAFE.putLong(writeChunk.data, offset, value); + UNSAFE.putLong(writeChunk.data, offset, value); } } final class AlignedUnsafeArrayTypeWriter extends UnsafeArrayTypeWriter { + private static final Unsafe UNSAFE = getUnsafe(); + @Override public void putS2(long value) { long offset = writeOffset(Short.BYTES); - UnsafeAccess.UNSAFE.putByte(writeChunk.data, offset + 0, (byte) (value >> 0)); - UnsafeAccess.UNSAFE.putByte(writeChunk.data, offset + 1, (byte) (value >> 8)); + UNSAFE.putByte(writeChunk.data, offset + 0, (byte) (value >> 0)); + UNSAFE.putByte(writeChunk.data, offset + 1, (byte) (value >> 8)); } @Override public void putS4(long value) { long offset = writeOffset(Integer.BYTES); - UnsafeAccess.UNSAFE.putByte(writeChunk.data, offset + 0, (byte) (value >> 0)); - UnsafeAccess.UNSAFE.putByte(writeChunk.data, offset + 1, (byte) (value >> 8)); - UnsafeAccess.UNSAFE.putByte(writeChunk.data, offset + 2, (byte) (value >> 16)); - UnsafeAccess.UNSAFE.putByte(writeChunk.data, offset + 3, (byte) (value >> 24)); + UNSAFE.putByte(writeChunk.data, offset + 0, (byte) (value >> 0)); + UNSAFE.putByte(writeChunk.data, offset + 1, (byte) (value >> 8)); + UNSAFE.putByte(writeChunk.data, offset + 2, (byte) (value >> 16)); + UNSAFE.putByte(writeChunk.data, offset + 3, (byte) (value >> 24)); } @Override public void putS8(long value) { long offset = writeOffset(Long.BYTES); - UnsafeAccess.UNSAFE.putByte(writeChunk.data, offset + 0, (byte) (value >> 0)); - UnsafeAccess.UNSAFE.putByte(writeChunk.data, offset + 1, (byte) (value >> 8)); - UnsafeAccess.UNSAFE.putByte(writeChunk.data, offset + 2, (byte) (value >> 16)); - UnsafeAccess.UNSAFE.putByte(writeChunk.data, offset + 3, (byte) (value >> 24)); - UnsafeAccess.UNSAFE.putByte(writeChunk.data, offset + 4, (byte) (value >> 32)); - UnsafeAccess.UNSAFE.putByte(writeChunk.data, offset + 5, (byte) (value >> 40)); - UnsafeAccess.UNSAFE.putByte(writeChunk.data, offset + 6, (byte) (value >> 48)); - UnsafeAccess.UNSAFE.putByte(writeChunk.data, offset + 7, (byte) (value >> 56)); + UNSAFE.putByte(writeChunk.data, offset + 0, (byte) (value >> 0)); + UNSAFE.putByte(writeChunk.data, offset + 1, (byte) (value >> 8)); + UNSAFE.putByte(writeChunk.data, offset + 2, (byte) (value >> 16)); + UNSAFE.putByte(writeChunk.data, offset + 3, (byte) (value >> 24)); + UNSAFE.putByte(writeChunk.data, offset + 4, (byte) (value >> 32)); + UNSAFE.putByte(writeChunk.data, offset + 5, (byte) (value >> 40)); + UNSAFE.putByte(writeChunk.data, offset + 6, (byte) (value >> 48)); + UNSAFE.putByte(writeChunk.data, offset + 7, (byte) (value >> 56)); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.match.processor/src/org/graalvm/compiler/core/match/processor/MatchProcessor.java 2019-03-28 07:36:45.780469635 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.match.processor/src/org/graalvm/compiler/core/match/processor/MatchProcessor.java 2019-03-28 07:36:45.400467094 +0100 @@ -348,9 +348,15 @@ */ final boolean shareable; + /** + * Can this node be subsumed into a match even if there are side effecting nodes between + * this node and the match. + */ + final boolean ignoresSideEffects; + final Set originatingElements = new HashSet<>(); - TypeDescriptor(TypeMirror mirror, String shortName, String nodeClass, String nodePackage, List inputs, boolean commutative, boolean shareable) { + TypeDescriptor(TypeMirror mirror, String shortName, String nodeClass, String nodePackage, List inputs, boolean commutative, boolean shareable, boolean ignoresSideEffects) { this.mirror = mirror; this.shortName = shortName; this.nodeClass = nodeClass; @@ -358,6 +364,7 @@ this.inputs = inputs; this.commutative = commutative; this.shareable = shareable; + this.ignoresSideEffects = ignoresSideEffects; assert !commutative || inputs.size() == 2; } } @@ -369,8 +376,9 @@ private TypeDescriptor valueType; - private void declareType(TypeMirror mirror, String shortName, String nodeClass, String nodePackage, List inputs, boolean commutative, boolean shareable, Element element) { - TypeDescriptor descriptor = new TypeDescriptor(mirror, shortName, nodeClass, nodePackage, inputs, commutative, shareable); + private void declareType(TypeMirror mirror, String shortName, String nodeClass, String nodePackage, List inputs, boolean commutative, boolean shareable, boolean ignoresSideEffects, + Element element) { + TypeDescriptor descriptor = new TypeDescriptor(mirror, shortName, nodeClass, nodePackage, inputs, commutative, shareable, ignoresSideEffects); descriptor.originatingElements.add(element); knownTypes.put(shortName, descriptor); } @@ -453,7 +461,7 @@ private String formatPrefix() { if (nodeType == valueType) { - return String.format("new MatchPattern(%s, false", name != null ? ("\"" + name + "\"") : "null"); + return String.format("new MatchPattern(%s, false, false", name != null ? ("\"" + name + "\"") : "null"); } else { return String.format("new MatchPattern(%s.class, %s", nodeType.nodeClass, name != null ? ("\"" + name + "\"") : "null"); } @@ -462,13 +470,13 @@ private String formatSuffix() { if (nodeType != null) { if (inputs.length != nodeType.inputs.size()) { - return ", true)"; + return ", true, " + nodeType.ignoresSideEffects + ")"; } else { if (nodeType.inputs.size() > 0) { - return ", " + nodeType.nodeClass + "_positions, " + !nodeType.shareable + ")"; + return ", " + nodeType.nodeClass + "_positions, " + !nodeType.shareable + ", " + nodeType.ignoresSideEffects + ")"; } if (nodeType.shareable) { - return ", false)"; + return ", false, " + nodeType.ignoresSideEffects + ")"; } } } @@ -721,7 +729,7 @@ // Define a TypeDescriptor for the generic node but don't enter it into the nodeTypes // table since it shouldn't be mentioned in match rules. TypeMirror valueTypeMirror = getTypeElement(VALUE_NODE_CLASS_NAME).asType(); - valueType = new TypeDescriptor(valueTypeMirror, "Value", "ValueNode", "org.graalvm.compiler.nodes", Collections.emptyList(), false, false); + valueType = new TypeDescriptor(valueTypeMirror, "Value", "ValueNode", "org.graalvm.compiler.nodes", Collections.emptyList(), false, false, false); Map map = new HashMap<>(); @@ -831,7 +839,8 @@ boolean commutative = getAnnotationValue(matchable, "commutative", Boolean.class); boolean shareable = getAnnotationValue(matchable, "shareable", Boolean.class); - declareType(nodeClassMirror, shortName, nodeClass, nodePackage, inputs, commutative, shareable, element); + boolean ignoresSideEffects = getAnnotationValue(matchable, "ignoresSideEffects", Boolean.class); + declareType(nodeClassMirror, shortName, nodeClass, nodePackage, inputs, commutative, shareable, ignoresSideEffects, element); } private void processMatchRules(Map map, Element element, List matchRules) { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java 2019-03-28 07:36:46.292473060 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java 2019-03-28 07:36:45.908470491 +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 @@ -32,6 +32,7 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Enumeration; import java.util.List; @@ -266,9 +267,11 @@ verifiers.add(new VerifyVirtualizableUsage()); verifiers.add(new VerifyUpdateUsages()); verifiers.add(new VerifyBailoutUsage()); + verifiers.add(new VerifySystemPropertyUsage()); verifiers.add(new VerifyInstanceOfUsage()); verifiers.add(new VerifyGraphAddUsage()); verifiers.add(new VerifyGetOptionsUsage()); + verifiers.add(new VerifyUnsafeAccess()); VerifyFoldableMethods foldableMethodsVerifier = new VerifyFoldableMethods(); if (tool.shouldVerifyFoldableMethods()) { @@ -301,21 +304,29 @@ String className = c.getName(); executor.execute(() -> { try { - checkClass(c, metaAccess); + checkClass(c, metaAccess, verifiers); } catch (Throwable e) { errors.add(String.format("Error while checking %s:%n%s", className, printStackTraceToString(e))); } }); - for (Method m : c.getDeclaredMethods()) { - if (Modifier.isNative(m.getModifiers()) || Modifier.isAbstract(m.getModifiers())) { + ResolvedJavaType type = metaAccess.lookupJavaType(c); + List methods = new ArrayList<>(); + methods.addAll(Arrays.asList(type.getDeclaredMethods())); + methods.addAll(Arrays.asList(type.getDeclaredConstructors())); + ResolvedJavaMethod clinit = type.getClassInitializer(); + if (clinit != null) { + methods.add(clinit); + } + + for (ResolvedJavaMethod method : methods) { + if (Modifier.isNative(method.getModifiers()) || Modifier.isAbstract(method.getModifiers())) { // ignore } else { - String methodName = className + "." + m.getName(); + String methodName = className + "." + method.getName(); if (matches(filters, methodName)) { executor.execute(() -> { try (DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER)) { - ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m); boolean isSubstitution = method.getAnnotation(Snippet.class) != null || method.getAnnotation(MethodSubstitution.class) != null; StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(method).setIsSubstitution(isSubstitution).build(); try (DebugCloseable s = debug.disableIntercept(); DebugContext.Scope ds = debug.scope("CheckingGraph", graph, method)) { @@ -400,14 +411,18 @@ /** * @param metaAccess + * @param verifiers */ - private static void checkClass(Class c, MetaAccessProvider metaAccess) { + private static void checkClass(Class c, MetaAccessProvider metaAccess, List> verifiers) { if (Node.class.isAssignableFrom(c)) { if (c.getAnnotation(NodeInfo.class) == null) { throw new AssertionError(String.format("Node subclass %s requires %s annotation", c.getName(), NodeClass.class.getSimpleName())); } VerifyNodeCosts.verifyNodeClass(c); } + for (VerifyPhase verifier : verifiers) { + verifier.verifyClass(c, metaAccess); + } } private static void checkMethod(ResolvedJavaMethod method) { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FinalizableSubclassTest.java 2019-03-28 07:36:46.796476429 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FinalizableSubclassTest.java 2019-03-28 07:36:46.416473889 +0100 @@ -77,8 +77,7 @@ StructuredGraph graph = new StructuredGraph.Builder(options, getDebugContext(options, null, javaMethod), allowAssumptions).method(javaMethod).build(); GraphBuilderConfiguration conf = GraphBuilderConfiguration.getSnippetDefault(getDefaultGraphBuilderPlugins()); - new GraphBuilderPhase.Instance(getMetaAccess(), getProviders().getStampProvider(), getProviders().getConstantReflection(), getProviders().getConstantFieldProvider(), conf, - OptimisticOptimizations.ALL, null).apply(graph); + new GraphBuilderPhase.Instance(getProviders(), conf, OptimisticOptimizations.ALL, null).apply(graph); HighTierContext context = new HighTierContext(getProviders(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); createInliningPhase().apply(graph, context); new CanonicalizerPhase().apply(graph, context); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NewInstanceTest.java 2019-03-28 07:36:47.300479799 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NewInstanceTest.java 2019-03-28 07:36:46.912477205 +0100 @@ -76,8 +76,7 @@ StructuredGraph graph = new StructuredGraph.Builder(options, getDebugContext(options, null, javaMethod), AllowAssumptions.YES).method(javaMethod).build(); GraphBuilderConfiguration conf = GraphBuilderConfiguration.getSnippetDefault(getDefaultGraphBuilderPlugins()).withUnresolvedIsError(false); - new GraphBuilderPhase.Instance(getMetaAccess(), getProviders().getStampProvider(), getProviders().getConstantReflection(), getProviders().getConstantFieldProvider(), conf, - OptimisticOptimizations.ALL, null).apply(graph); + new GraphBuilderPhase.Instance(getProviders(), conf, OptimisticOptimizations.ALL, null).apply(graph); return graph; } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnbalancedMonitorsTest.java 2019-03-28 07:36:47.796483115 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnbalancedMonitorsTest.java 2019-03-28 07:36:47.408480521 +0100 @@ -94,7 +94,7 @@ GraphBuilderConfiguration graphBuilderConfig = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true).withUnresolvedIsError(true); OptimisticOptimizations optimisticOpts = OptimisticOptimizations.NONE; - GraphBuilderPhase.Instance graphBuilder = new GraphBuilderPhase.Instance(getMetaAccess(), getProviders().getStampProvider(), null, null, graphBuilderConfig, optimisticOpts, null); + GraphBuilderPhase.Instance graphBuilder = new GraphBuilderPhase.Instance(getProviders(), graphBuilderConfig, optimisticOpts, null); graphBuilder.apply(graph); } catch (BailoutException e) { if (e.getMessage().contains("unbalanced monitors")) { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyBailoutUsage.java 2019-03-28 07:36:48.292486431 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyBailoutUsage.java 2019-03-28 07:36:47.912483892 +0100 @@ -73,7 +73,7 @@ } @Override - protected boolean verify(StructuredGraph graph, PhaseContext context) { + protected void verify(StructuredGraph graph, PhaseContext context) { final ResolvedJavaType bailoutType = context.getMetaAccess().lookupJavaType(BailoutException.class); ResolvedJavaMethod caller = graph.method(); String holderQualified = caller.format("%H"); @@ -92,7 +92,6 @@ } } } - return true; } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyCallerSensitiveMethods.java 2019-03-28 07:36:48.808489881 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyCallerSensitiveMethods.java 2019-03-28 07:36:48.424487314 +0100 @@ -67,7 +67,7 @@ } @Override - protected boolean verify(StructuredGraph graph, PhaseContext context) { + protected void verify(StructuredGraph graph, PhaseContext context) { Invoke invoke = callsReflectionGetCallerClass(graph, context); Annotation annotation = graph.method().getAnnotation(callerSensitiveClass); if (invoke != null) { @@ -79,7 +79,6 @@ } else if (annotation != null) { throw new VerificationError(String.format("%s: method annotated with @CallerSensitive does not call Reflection.getCallerClass()", graph.method().format("%H.%n(%p)"))); } - return true; } private Invoke callsReflectionGetCallerClass(StructuredGraph graph, PhaseContext context) { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyDebugUsage.java 2019-03-28 07:36:49.296493144 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyDebugUsage.java 2019-03-28 07:36:48.916490604 +0100 @@ -78,7 +78,7 @@ MetaAccessProvider metaAccess; @Override - protected boolean verify(StructuredGraph graph, PhaseContext context) { + protected void verify(StructuredGraph graph, PhaseContext context) { metaAccess = context.getMetaAccess(); ResolvedJavaType debugType = metaAccess.lookupJavaType(DebugContext.class); ResolvedJavaType nodeType = metaAccess.lookupJavaType(Node.class); @@ -108,7 +108,6 @@ } } } - return true; } private void verifyParameters(MethodCallTargetNode callTarget, StructuredGraph callerGraph, NodeInputList args, ResolvedJavaType stringType, int startArgIdx) { @@ -167,6 +166,7 @@ "org.graalvm.compiler.phases.BasePhase.dumpAfter", "org.graalvm.compiler.replacements.ReplacementsImpl$GraphMaker.makeGraph", "org.graalvm.compiler.replacements.SnippetTemplate.instantiate", + "org.graalvm.compiler.replacements.SnippetTemplate.", "org.graalvm.compiler.hotspot.SymbolicSnippetEncoder.verifySnippetEncodeDecode")); private void verifyParameters(StructuredGraph callerGraph, MethodCallTargetNode debugCallTarget, List args, ResolvedJavaType stringType, int startArgIdx, --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyFoldableMethods.java 2019-03-28 07:36:49.800496514 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyFoldableMethods.java 2019-03-28 07:36:49.420493973 +0100 @@ -52,7 +52,7 @@ ResolvedJavaType generatedInvocationPluginType; @Override - protected boolean verify(StructuredGraph graph, PhaseContext context) { + protected void verify(StructuredGraph graph, PhaseContext context) { ResolvedJavaMethod method = graph.method(); if (method.getAnnotation(Fold.class) != null) { foldables.putIfAbsent(method, false); @@ -69,7 +69,6 @@ } } } - return true; } public void finish() { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyGetOptionsUsage.java 2019-03-28 07:36:50.276499696 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyGetOptionsUsage.java 2019-03-28 07:36:49.892497129 +0100 @@ -36,6 +36,7 @@ import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaMethod.Parameter; import jdk.vm.ci.meta.ResolvedJavaType; /** @@ -55,15 +56,19 @@ } @Override - protected boolean verify(StructuredGraph graph, PhaseContext context) { + protected void verify(StructuredGraph graph, PhaseContext context) { MetaAccessProvider metaAccess = context.getMetaAccess(); ResolvedJavaType canonicalizerToolClass = metaAccess.lookupJavaType(CanonicalizerTool.class); boolean hasTool = false; + ResolvedJavaMethod method = graph.method(); try { - for (ResolvedJavaMethod.Parameter parameter : graph.method().getParameters()) { - if (parameter.getType().getName().equals(canonicalizerToolClass.getName())) { - hasTool = true; - break; + Parameter[] parameters = method.getParameters(); + if (parameters != null) { + for (ResolvedJavaMethod.Parameter parameter : parameters) { + if (parameter.getType().getName().equals(canonicalizerToolClass.getName())) { + hasTool = true; + break; + } } } } catch (MalformedParametersException e) { @@ -76,13 +81,11 @@ if (callee.equals(getOptionsMethod)) { if (hasTool) { throw new VerificationError("Must use CanonicalizerTool.getOptions() instead of Node.getOptions() in method '%s' of class '%s'.", - graph.method().getName(), graph.method().getDeclaringClass().getName()); + method.getName(), method.getDeclaringClass().getName()); } } } } - - return true; } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyGraphAddUsage.java 2019-03-28 07:36:50.768502985 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyGraphAddUsage.java 2019-03-28 07:36:50.388500445 +0100 @@ -66,7 +66,7 @@ } @Override - protected boolean verify(StructuredGraph graph, PhaseContext context) { + protected void verify(StructuredGraph graph, PhaseContext context) { boolean allowed = false; for (Class cls : ALLOWED_CLASSES) { ResolvedJavaType declaringClass = graph.method().getDeclaringClass(); @@ -85,8 +85,6 @@ } } } - - return true; } private void checkNonFactory(StructuredGraph graph, EconomicSet seen, PhaseContext context, ValueNode node) { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyInstanceOfUsage.java 2019-03-28 07:36:51.264506301 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyInstanceOfUsage.java 2019-03-28 07:36:50.884503761 +0100 @@ -53,7 +53,7 @@ } @Override - protected boolean verify(StructuredGraph graph, PhaseContext context) { + protected void verify(StructuredGraph graph, PhaseContext context) { final ResolvedJavaType[] bailoutType = new ResolvedJavaType[FORBIDDEN_INSTANCE_OF_CHECKS.length]; for (int i = 0; i < FORBIDDEN_INSTANCE_OF_CHECKS.length; i++) { bailoutType[i] = context.getMetaAccess().lookupJavaType(FORBIDDEN_INSTANCE_OF_CHECKS[i]); @@ -77,7 +77,6 @@ } } } - return true; } private static boolean isTrustedInterface(ResolvedJavaType declaringClass, MetaAccessProvider metaAccess) { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyUpdateUsages.java 2019-03-28 07:36:51.744509509 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyUpdateUsages.java 2019-03-28 07:36:51.364506969 +0100 @@ -56,9 +56,9 @@ } @Override - protected boolean verify(StructuredGraph graph, PhaseContext context) { + protected void verify(StructuredGraph graph, PhaseContext context) { if (graph.method().isConstructor()) { - return true; + return; } /* * There are only two acceptable patterns for methods which update Node inputs, either a @@ -78,35 +78,51 @@ } else if (storeField2 == null) { storeField2 = store; } else { - return false; + throw new VerificationError("More than 2 stores to %s or %s fields found in %s", + Input.class.getSimpleName(), + OptionalInput.class.getSimpleName(), + graph.method().format("%H.%n(%p)")); } } } if (storeField1 == null) { - return true; + return; } if (storeField2 == null) { - // Single input field update so just check for updateUsages or updateUsagesInterface - // call - ResolvedJavaType node = context.getMetaAccess().lookupJavaType(Node.class); + // Single input field update so just check for updateUsages + // or updateUsagesInterface call + ResolvedJavaType nodeType = context.getMetaAccess().lookupJavaType(Node.class); for (MethodCallTargetNode call : graph.getNodes().filter(MethodCallTargetNode.class)) { ResolvedJavaMethod callee = call.targetMethod(); - if (callee.getDeclaringClass().equals(node) && (callee.getName().equals("updateUsages") || callee.getName().equals("updateUsagesInterface"))) { - return true; + if (callee.getDeclaringClass().equals(nodeType) && (callee.getName().equals("updateUsages") || callee.getName().equals("updateUsagesInterface"))) { + return; } } + throw new VerificationError("%s updates field '%s' without calling %s.updateUsages() or %s.updateUsagesInterface()", + graph.method().format("%H.%n(%p)"), + storeField1.field().getName(), + Node.class.getName(), + Node.class.getName()); } else { if (storeField1.value() instanceof LoadFieldNode && storeField2.value() instanceof LoadFieldNode) { LoadFieldNode load1 = (LoadFieldNode) storeField1.value(); LoadFieldNode load2 = (LoadFieldNode) storeField2.value(); // Check for swapping values within the same object - if (load1.object() == storeField1.object() && load2.object() == storeField2.object() && storeField1.object() == storeField2.object() && - load1.field().equals(storeField2.field()) && load2.field().equals(storeField1.field())) { - return true; + if (load1.object() == storeField1.object() && + load2.object() == storeField2.object() && + storeField1.object() == storeField2.object() && + load1.field().equals(storeField2.field()) && + load2.field().equals(storeField1.field())) { + return; } } + throw new VerificationError("%s performs non-swap update to fields '%s' and '%s' without calling %s.updateUsages() or %s.updateUsagesInterface()", + graph.method().format("%H.%n(%p)"), + storeField1.field().getName(), + storeField2.field().getName(), + Node.class.getName(), + Node.class.getName()); } - return false; } boolean isNodeInput(ResolvedJavaField field, ResolvedJavaType declaringClass, ResolvedJavaType nodeInputList) { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyUsageWithEquals.java 2019-03-28 07:36:52.244512851 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyUsageWithEquals.java 2019-03-28 07:36:51.868510338 +0100 @@ -143,7 +143,7 @@ } @Override - protected boolean verify(StructuredGraph graph, PhaseContext context) { + protected void verify(StructuredGraph graph, PhaseContext context) { for (ObjectEqualsNode cn : graph.getNodes().filter(ObjectEqualsNode.class)) { // bail out if we compare an object of type klass with == or != (except null checks) ResolvedJavaMethod method = graph.method(); @@ -156,6 +156,5 @@ " must use .equals() for object equality, not '==' or '!='"); } } - return true; } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyVirtualizableUsage.java 2019-03-28 07:36:52.756516274 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyVirtualizableUsage.java 2019-03-28 07:36:52.372513707 +0100 @@ -53,7 +53,7 @@ } @Override - protected boolean verify(StructuredGraph graph, PhaseContext context) { + protected void verify(StructuredGraph graph, PhaseContext context) { final ResolvedJavaType graphType = context.getMetaAccess().lookupJavaType(Graph.class); final ResolvedJavaType virtualizableType = context.getMetaAccess().lookupJavaType(Virtualizable.class); final ResolvedJavaType constantNodeType = context.getMetaAccess().lookupJavaType(ConstantNode.class); @@ -70,7 +70,6 @@ } } } - return true; } private static void verifyVirtualizableEffectArguments(ResolvedJavaType constantNodeType, ResolvedJavaMethod caller, ResolvedJavaMethod callee, int bciCaller, --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EATestBase.java 2019-03-28 07:36:53.260519643 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EATestBase.java 2019-03-28 07:36:52.876517076 +0100 @@ -152,13 +152,17 @@ Assert.assertEquals(expectedConstantResult, returnNode.result().asConstant()); } } - int newInstanceCount = graph.getNodes().filter(isA(NewInstanceNode.class).or(NewArrayNode.class).or(AllocatedObjectNode.class)).count(); + int newInstanceCount = getAllocationCount(); Assert.assertEquals("Expected allocation count does not match", expectedAllocationCount, newInstanceCount); if (expectedAllocationCount == 0) { Assert.assertTrue("Unexpected CommitAllocationNode", graph.getNodes().filter(CommitAllocationNode.class).isEmpty()); } } + protected int getAllocationCount() { + return graph.getNodes().filter(isA(NewInstanceNode.class).or(NewArrayNode.class).or(AllocatedObjectNode.class)).count(); + } + @SuppressWarnings("try") protected void prepareGraph(String snippet, boolean iterativeEscapeAnalysis) { ResolvedJavaMethod method = getResolvedJavaMethod(snippet); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/StaticAnalysis.java 2019-03-28 07:36:53.744522879 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/StaticAnalysis.java 2019-03-28 07:36:53.364520338 +0100 @@ -34,8 +34,8 @@ import java.util.Map; import java.util.Set; -import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeMap; @@ -58,7 +58,7 @@ import org.graalvm.compiler.nodes.java.NewArrayNode; import org.graalvm.compiler.nodes.java.NewInstanceNode; import org.graalvm.compiler.nodes.java.StoreFieldNode; -import org.graalvm.compiler.nodes.spi.StampProvider; +import org.graalvm.compiler.nodes.spi.CoreProviders; import org.graalvm.compiler.nodes.util.GraphUtil; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; @@ -66,7 +66,6 @@ import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaField; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; @@ -89,18 +88,21 @@ * {@link MethodState#formalReturn return value}. */ public class StaticAnalysis { - /** Access to type, method, and fields using the Graal API. */ - private final MetaAccessProvider metaAccess; - /** Access to platform dependent stamps. */ - private final StampProvider stampProvider; - /** The results of the static analysis. */ + /** + * Access to various builtin providers. + */ + private final CoreProviders providers; + /** + * The results of the static analysis. + */ private final Results results; - /** Worklist for fixpoint iteration. */ + /** + * Worklist for fixpoint iteration. + */ private final Deque worklist; - public StaticAnalysis(MetaAccessProvider metaAccess, StampProvider stampProvider) { - this.metaAccess = metaAccess; - this.stampProvider = stampProvider; + public StaticAnalysis(CoreProviders providers) { + this.providers = providers; this.results = new Results(); this.worklist = new ArrayDeque<>(); } @@ -273,7 +275,7 @@ */ OptimisticOptimizations optimisticOpts = OptimisticOptimizations.NONE; - GraphBuilderPhase.Instance graphBuilder = new GraphBuilderPhase.Instance(metaAccess, stampProvider, null, null, graphBuilderConfig, optimisticOpts, null); + GraphBuilderPhase.Instance graphBuilder = new GraphBuilderPhase.Instance(providers, graphBuilderConfig, optimisticOpts, null); graphBuilder.apply(graph); } catch (Throwable ex) { debug.handle(ex); @@ -304,7 +306,9 @@ uses = new HashSet<>(); } - /** Returns the types of this element. */ + /** + * Returns the types of this element. + */ public Set getTypes() { return types; } @@ -349,7 +353,7 @@ * Adding a new callee means linking the type flow of the actual parameters with the formal * parameters of the callee, and linking the return value of the callee with the return value * state of the invocation. - * + *

* Statically bindable methods calls ({@link InvokeKind#Static static} and * {@link InvokeKind#Special special} calls) have only one callee, but use the same code for * simplicity. --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/StaticAnalysisTests.java 2019-03-28 07:36:54.264526354 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/StaticAnalysisTests.java 2019-03-28 07:36:53.880523787 +0100 @@ -29,21 +29,18 @@ import java.util.Arrays; import java.util.Collection; -import jdk.vm.ci.meta.MetaAccessProvider; -import jdk.vm.ci.meta.ResolvedJavaField; -import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaType; - -import org.junit.Assert; -import org.junit.Test; - import org.graalvm.compiler.api.test.Graal; import org.graalvm.compiler.core.target.Backend; import org.graalvm.compiler.core.test.tutorial.StaticAnalysis.MethodState; import org.graalvm.compiler.core.test.tutorial.StaticAnalysis.TypeFlow; -import org.graalvm.compiler.nodes.spi.StampProvider; -import org.graalvm.compiler.phases.util.Providers; +import org.graalvm.compiler.nodes.spi.CoreProviders; import org.graalvm.compiler.runtime.RuntimeProvider; +import org.junit.Assert; +import org.junit.Test; + +import jdk.vm.ci.meta.ResolvedJavaField; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; public class StaticAnalysisTests { @@ -68,14 +65,11 @@ Object f; } - private final MetaAccessProvider metaAccess; - private final StampProvider stampProvider; + private final CoreProviders providers; public StaticAnalysisTests() { Backend backend = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend(); - Providers providers = backend.getProviders(); - this.metaAccess = providers.getMetaAccess(); - this.stampProvider = providers.getStampProvider(); + providers = backend.getProviders(); } static void test01Entry() { @@ -85,7 +79,7 @@ @Test public void test01() { - StaticAnalysis sa = new StaticAnalysis(metaAccess, stampProvider); + StaticAnalysis sa = new StaticAnalysis(providers); sa.addMethod(findMethod(StaticAnalysisTests.class, "test01Entry")); sa.finish(); @@ -106,7 +100,7 @@ @Test public void test02() { - StaticAnalysis sa = new StaticAnalysis(metaAccess, stampProvider); + StaticAnalysis sa = new StaticAnalysis(providers); sa.addMethod(findMethod(StaticAnalysisTests.class, "test02Entry")); sa.finish(); @@ -134,7 +128,7 @@ @Test public void test03() { - StaticAnalysis sa = new StaticAnalysis(metaAccess, stampProvider); + StaticAnalysis sa = new StaticAnalysis(providers); sa.addMethod(findMethod(StaticAnalysisTests.class, "test03Entry")); sa.finish(); @@ -165,7 +159,7 @@ @Test public void test04() { - StaticAnalysis sa = new StaticAnalysis(metaAccess, stampProvider); + StaticAnalysis sa = new StaticAnalysis(providers); sa.addMethod(findMethod(StaticAnalysisTests.class, "test04Entry")); sa.finish(); @@ -192,7 +186,7 @@ } private ResolvedJavaType t(Class clazz) { - return metaAccess.lookupJavaType(clazz); + return providers.getMetaAccess().lookupJavaType(clazz); } private ResolvedJavaMethod findMethod(Class declaringClass, String name) { @@ -204,7 +198,7 @@ } } assert reflectionMethod != null : "No method with name " + name + " in class " + declaringClass.getName(); - return metaAccess.lookupJavaMethod(reflectionMethod); + return providers.getMetaAccess().lookupJavaMethod(reflectionMethod); } private ResolvedJavaField findField(Class declaringClass, String name) { @@ -214,6 +208,6 @@ } catch (NoSuchFieldException | SecurityException ex) { throw new AssertionError(ex); } - return metaAccess.lookupJavaField(reflectionField); + return providers.getMetaAccess().lookupJavaField(reflectionField); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/LIRGenerationPhase.java 2019-03-28 07:36:54.756529642 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/LIRGenerationPhase.java 2019-03-28 07:36:54.376527102 +0100 @@ -67,7 +67,11 @@ NodeLIRBuilderTool nodeLirBuilder = context.nodeLirBuilder; StructuredGraph graph = context.graph; ScheduleResult schedule = context.schedule; - for (AbstractBlockBase b : lirGenRes.getLIR().getControlFlowGraph().getBlocks()) { + AbstractBlockBase[] blocks = lirGenRes.getLIR().getControlFlowGraph().getBlocks(); + for (AbstractBlockBase b : blocks) { + matchBlock(nodeLirBuilder, (Block) b, graph, schedule); + } + for (AbstractBlockBase b : blocks) { emitBlock(nodeLirBuilder, lirGenRes, (Block) b, graph, schedule.getBlockToNodesMap()); } context.lirGen.beforeRegisterAllocation(); @@ -84,6 +88,10 @@ instructionCounter.add(debug, lir.getLIRforBlock(b).size()); } + private static void matchBlock(NodeLIRBuilderTool nodeLirGen, Block b, StructuredGraph graph, ScheduleResult schedule) { + nodeLirGen.matchBlock(b, graph, schedule); + } + private static boolean verifyPredecessors(LIRGenerationResult lirGenRes, Block block) { for (Block pred : block.getPredecessors()) { if (!block.isLoopHeader() || !pred.isLoopEnd()) { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java 2019-03-28 07:36:55.240532877 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java 2019-03-28 07:36:54.860530337 +0100 @@ -48,6 +48,7 @@ import org.graalvm.compiler.core.match.MatchPattern; import org.graalvm.compiler.core.match.MatchRuleRegistry; import org.graalvm.compiler.core.match.MatchStatement; +import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.TTY; @@ -255,7 +256,7 @@ // get ValueKind for input final LIRKind valueKind; - if (value != null) { + if (value != null && !(value instanceof ComplexMatchValue)) { valueKind = value.getValueKind(LIRKind.class); } else { assert isPhiInputFromBackedge(phi, i) : String.format("Input %s to phi node %s is not yet available although it is not coming from a loop back edge", node, phi); @@ -358,10 +359,6 @@ List nodes = blockMap.get(block); - // Allow NodeLIRBuilder subclass to specialize code generation of any interesting groups - // of instructions - matchComplexExpressions(nodes); - boolean trace = traceLIRGeneratorLevel >= 3; for (int i = 0; i < nodes.size(); i++) { Node node = nodes.get(i); @@ -419,11 +416,23 @@ } } + @Override @SuppressWarnings("try") - protected void matchComplexExpressions(List nodes) { + public void matchBlock(Block block, StructuredGraph graph, StructuredGraph.ScheduleResult schedule) { + try (DebugCloseable matchScope = gen.getMatchScope(block)) { + // Allow NodeLIRBuilder subclass to specialize code generation of any interesting groups + // of instructions + matchComplexExpressions(block, schedule); + } + } + + @SuppressWarnings("try") + protected void matchComplexExpressions(Block block, StructuredGraph.ScheduleResult schedule) { + if (matchRules != null) { DebugContext debug = gen.getResult().getLIR().getDebug(); try (DebugContext.Scope s = debug.scope("MatchComplexExpressions")) { + List nodes = schedule.getBlockToNodesMap().get(block); if (LogVerbose.getValue(nodeOperands.graph().getOptions())) { int i = 0; for (Node node : nodes) { @@ -441,7 +450,7 @@ List statements = matchRules.get(node.getClass()); if (statements != null) { for (MatchStatement statement : statements) { - if (statement.generate(this, index, node, nodes)) { + if (statement.generate(this, index, node, block, schedule)) { // Found a match so skip to the next break; } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeMatchRules.java 2019-03-28 07:36:55.744536245 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeMatchRules.java 2019-03-28 07:36:55.360533678 +0100 @@ -67,38 +67,38 @@ import jdk.vm.ci.meta.Value; -@MatchableNode(nodeClass = ConstantNode.class, shareable = true) -@MatchableNode(nodeClass = FloatConvertNode.class, inputs = {"value"}) +@MatchableNode(nodeClass = ConstantNode.class, shareable = true, ignoresSideEffects = true) +@MatchableNode(nodeClass = FloatConvertNode.class, inputs = {"value"}, ignoresSideEffects = true) @MatchableNode(nodeClass = FloatingReadNode.class, inputs = {"address"}) @MatchableNode(nodeClass = IfNode.class, inputs = {"condition"}) -@MatchableNode(nodeClass = SubNode.class, inputs = {"x", "y"}) -@MatchableNode(nodeClass = LeftShiftNode.class, inputs = {"x", "y"}) -@MatchableNode(nodeClass = NarrowNode.class, inputs = {"value"}) +@MatchableNode(nodeClass = SubNode.class, inputs = {"x", "y"}, ignoresSideEffects = true) +@MatchableNode(nodeClass = LeftShiftNode.class, inputs = {"x", "y"}, ignoresSideEffects = true) +@MatchableNode(nodeClass = NarrowNode.class, inputs = {"value"}, ignoresSideEffects = true) @MatchableNode(nodeClass = ReadNode.class, inputs = {"address"}) -@MatchableNode(nodeClass = ReinterpretNode.class, inputs = {"value"}) -@MatchableNode(nodeClass = SignExtendNode.class, inputs = {"value"}) -@MatchableNode(nodeClass = UnsignedRightShiftNode.class, inputs = {"x", "y"}) +@MatchableNode(nodeClass = ReinterpretNode.class, inputs = {"value"}, ignoresSideEffects = true) +@MatchableNode(nodeClass = SignExtendNode.class, inputs = {"value"}, ignoresSideEffects = true) +@MatchableNode(nodeClass = UnsignedRightShiftNode.class, inputs = {"x", "y"}, ignoresSideEffects = true) @MatchableNode(nodeClass = WriteNode.class, inputs = {"address", "value"}) -@MatchableNode(nodeClass = ZeroExtendNode.class, inputs = {"value"}) -@MatchableNode(nodeClass = AndNode.class, inputs = {"x", "y"}, commutative = true) -@MatchableNode(nodeClass = NegateNode.class, inputs = {"value"}) -@MatchableNode(nodeClass = NotNode.class, inputs = {"value"}) -@MatchableNode(nodeClass = FloatEqualsNode.class, inputs = {"x", "y"}, commutative = true) -@MatchableNode(nodeClass = FloatLessThanNode.class, inputs = {"x", "y"}, commutative = true) -@MatchableNode(nodeClass = PointerEqualsNode.class, inputs = {"x", "y"}, commutative = true) -@MatchableNode(nodeClass = AddNode.class, inputs = {"x", "y"}, commutative = true) -@MatchableNode(nodeClass = IntegerBelowNode.class, inputs = {"x", "y"}, commutative = true) -@MatchableNode(nodeClass = IntegerEqualsNode.class, inputs = {"x", "y"}, commutative = true) -@MatchableNode(nodeClass = IntegerLessThanNode.class, inputs = {"x", "y"}, commutative = true) -@MatchableNode(nodeClass = MulNode.class, inputs = {"x", "y"}, commutative = true) -@MatchableNode(nodeClass = IntegerTestNode.class, inputs = {"x", "y"}, commutative = true) -@MatchableNode(nodeClass = ObjectEqualsNode.class, inputs = {"x", "y"}, commutative = true) -@MatchableNode(nodeClass = OrNode.class, inputs = {"x", "y"}, commutative = true) -@MatchableNode(nodeClass = XorNode.class, inputs = {"x", "y"}, commutative = true) -@MatchableNode(nodeClass = PiNode.class, inputs = {"object"}) +@MatchableNode(nodeClass = ZeroExtendNode.class, inputs = {"value"}, ignoresSideEffects = true) +@MatchableNode(nodeClass = AndNode.class, inputs = {"x", "y"}, commutative = true, ignoresSideEffects = true) +@MatchableNode(nodeClass = NegateNode.class, inputs = {"value"}, ignoresSideEffects = true) +@MatchableNode(nodeClass = NotNode.class, inputs = {"value"}, ignoresSideEffects = true) +@MatchableNode(nodeClass = FloatEqualsNode.class, inputs = {"x", "y"}, commutative = true, ignoresSideEffects = true) +@MatchableNode(nodeClass = FloatLessThanNode.class, inputs = {"x", "y"}, commutative = true, ignoresSideEffects = true) +@MatchableNode(nodeClass = PointerEqualsNode.class, inputs = {"x", "y"}, commutative = true, ignoresSideEffects = true) +@MatchableNode(nodeClass = AddNode.class, inputs = {"x", "y"}, commutative = true, ignoresSideEffects = true) +@MatchableNode(nodeClass = IntegerBelowNode.class, inputs = {"x", "y"}, commutative = true, ignoresSideEffects = true) +@MatchableNode(nodeClass = IntegerEqualsNode.class, inputs = {"x", "y"}, commutative = true, ignoresSideEffects = true) +@MatchableNode(nodeClass = IntegerLessThanNode.class, inputs = {"x", "y"}, commutative = true, ignoresSideEffects = true) +@MatchableNode(nodeClass = MulNode.class, inputs = {"x", "y"}, commutative = true, ignoresSideEffects = true) +@MatchableNode(nodeClass = IntegerTestNode.class, inputs = {"x", "y"}, commutative = true, ignoresSideEffects = true) +@MatchableNode(nodeClass = ObjectEqualsNode.class, inputs = {"x", "y"}, commutative = true, ignoresSideEffects = true) +@MatchableNode(nodeClass = OrNode.class, inputs = {"x", "y"}, commutative = true, ignoresSideEffects = true) +@MatchableNode(nodeClass = XorNode.class, inputs = {"x", "y"}, commutative = true, ignoresSideEffects = true) +@MatchableNode(nodeClass = PiNode.class, inputs = {"object"}, ignoresSideEffects = true) @MatchableNode(nodeClass = LogicCompareAndSwapNode.class, inputs = {"address", "expectedValue", "newValue"}) @MatchableNode(nodeClass = ValueCompareAndSwapNode.class, inputs = {"address", "expectedValue", "newValue"}) -@MatchableNode(nodeClass = RightShiftNode.class, inputs = {"x", "y"}) +@MatchableNode(nodeClass = RightShiftNode.class, inputs = {"x", "y"}, ignoresSideEffects = true) public abstract class NodeMatchRules { NodeLIRBuilder lirBuilder; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java 2019-03-28 07:36:56.248539613 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java 2019-03-28 07:36:55.860537020 +0100 @@ -24,40 +24,120 @@ package org.graalvm.compiler.core.match; +import static org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph.dominates; +import static org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph.strictlyDominates; import static org.graalvm.compiler.debug.DebugOptions.LogVerbose; import java.util.ArrayList; import java.util.Arrays; +import java.util.Iterator; import java.util.List; import jdk.internal.vm.compiler.collections.EconomicMap; import jdk.internal.vm.compiler.collections.Equivalence; +import org.graalvm.compiler.core.common.cfg.BlockMap; import org.graalvm.compiler.core.gen.NodeLIRBuilder; import org.graalvm.compiler.core.match.MatchPattern.Result; +import org.graalvm.compiler.debug.CounterKey; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.graph.NodeMap; +import org.graalvm.compiler.nodes.PhiNode; +import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.calc.FloatingNode; +import org.graalvm.compiler.nodes.cfg.Block; import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; /** * Container for state captured during a match. */ public class MatchContext { + private static final CounterKey MatchContextSuccessDifferentBlocks = DebugContext.counter("MatchContextSuccessDifferentBlocks"); private final Node root; - private final List nodes; - private final MatchStatement rule; + private final StructuredGraph.ScheduleResult schedule; private EconomicMap namedNodes; - private ArrayList consumed; + /** + * A node consumed by a match. Keeps track of whether side effects can be ignored. + */ + static final class ConsumedNode { + final Node node; + final boolean ignoresSideEffects; + + ConsumedNode(Node node, boolean ignoresSideEffects) { + this.node = node; + this.ignoresSideEffects = ignoresSideEffects; + } + } + + /** + * The collection of nodes consumed by this match. + */ + static final class ConsumedNodes implements Iterable { + private ArrayList nodes; + + ConsumedNodes() { + this.nodes = null; + } + + public void add(Node node, boolean ignoresSideEffects) { + if (nodes == null) { + nodes = new ArrayList<>(2); + } + nodes.add(new ConsumedNode(node, ignoresSideEffects)); + } - private int startIndex; + public boolean contains(Node node) { + for (ConsumedNode c : nodes) { + if (c.node == node) { + return true; + } + } + return false; + } - private int endIndex; + public ConsumedNode find(Node node) { + for (ConsumedNode c : nodes) { + if (c.node == node) { + return c; + } + } + return null; + } + + @Override + public String toString() { + Node[] arr = new Node[nodes.size()]; + int i = 0; + for (ConsumedNode c : nodes) { + arr[i++] = c.node; + } + return Arrays.toString(arr); + } + + @Override + public Iterator iterator() { + return nodes.iterator(); + } + } + + private ConsumedNodes consumed = new ConsumedNodes(); + + private Block rootBlock; + private int rootIndex; + + /** + * Block and index in the block at which the match should be emitted. Differs from + * rootBlock/rootIndex for (ZeroExtend Read=access) for instance: match should be emitted where + * the Read is. + */ + private int emitIndex; + private Block emitBlock; private final NodeLIRBuilder builder; @@ -71,14 +151,15 @@ } } - public MatchContext(NodeLIRBuilder builder, MatchStatement rule, int index, Node node, List nodes) { + public MatchContext(NodeLIRBuilder builder, MatchStatement rule, int index, Node node, Block rootBlock, StructuredGraph.ScheduleResult schedule) { this.builder = builder; this.rule = rule; this.root = node; - this.nodes = nodes; - assert index == nodes.indexOf(node); + assert index == schedule.getBlockToNodesMap().get(rootBlock).indexOf(node); + this.schedule = schedule; // The root should be the last index since all the inputs must be scheduled before it. - startIndex = endIndex = index; + this.rootBlock = rootBlock; + rootIndex = index; } public Node getRoot() { @@ -103,28 +184,177 @@ } public Result validate() { - // Ensure that there's no unsafe work in between these operations. - for (int i = startIndex; i <= endIndex; i++) { + Result result = findEarlyPosition(); + if (result != Result.OK) { + return result; + } + findLatePosition(); + assert emitIndex == rootIndex || consumed.find(root).ignoresSideEffects; + return verifyInputs(); + } + + private Result findEarlyPosition() { + int startIndexSideEffect = -1; + int endIndexSideEffect = -1; + final NodeMap nodeToBlockMap = schedule.getNodeToBlockMap(); + final BlockMap> blockToNodesMap = schedule.getBlockToNodesMap(); + + // Nodes affected by side effects must be in the same block + for (ConsumedNode cn : consumed) { + if (!cn.ignoresSideEffects) { + Block b = nodeToBlockMap.get(cn.node); + if (emitBlock == null) { + emitBlock = b; + startIndexSideEffect = endIndexSideEffect = blockToNodesMap.get(b).indexOf(cn.node); + } else if (emitBlock == b) { + int index = blockToNodesMap.get(b).indexOf(cn.node); + startIndexSideEffect = Math.min(startIndexSideEffect, index); + endIndexSideEffect = Math.max(endIndexSideEffect, index); + } else { + logFailedMatch("nodes affected by side effects in different blocks %s", cn.node); + return Result.notInBlock(cn.node, rule.getPattern()); + } + } + } + if (emitBlock != null) { + // There must be no side effects between nodes that are affected by side effects + assert startIndexSideEffect != -1 && endIndexSideEffect != -1; + final List nodes = blockToNodesMap.get(emitBlock); + for (int i = startIndexSideEffect; i <= endIndexSideEffect; i++) { + Node node = nodes.get(i); + if (!sideEffectFree(node) && !consumed.contains(node)) { + logFailedMatch("unexpected side effect %s", node); + return Result.notSafe(node, rule.getPattern()); + } + } + // early position is at the node affected by side effects the closest to the root + emitIndex = endIndexSideEffect; + } else { + // Nodes not affected by side effect: early position is at the root + emitBlock = nodeToBlockMap.get(root); + emitIndex = rootIndex; + } + return Result.OK; + } + + private static boolean sideEffectFree(Node node) { + // The order of evaluation of these nodes controlled by data dependence so they + // don't interfere with this match. + return node instanceof VirtualObjectNode || node instanceof FloatingNode; + } + + private void findLatePosition() { + // If emit position is at a node affected by side effects that's followed by side effect + // free nodes, the node can be emitted later. This helps when the match has inputs that are + // late in the block. + int index = rootIndex; + if (emitBlock != rootBlock) { + index = schedule.getBlockToNodesMap().get(emitBlock).size() - 1; + } + final List emitBlockNodes = schedule.getBlockToNodesMap().get(emitBlock); + for (int i = emitIndex + 1; i <= index; i++) { + Node node = emitBlockNodes.get(i); + ConsumedNode cn = consumed.find(node); + if (cn == null) { + if (!sideEffectFree(node)) { + return; + } + } else { + assert cn.ignoresSideEffects; + emitIndex = i; + } + } + } + + private Result verifyInputs() { + DebugContext debug = root.getDebug(); + if (emitBlock != rootBlock) { + assert consumed.find(root).ignoresSideEffects; + Result result = verifyInputsDifferentBlock(root); + if (result == Result.OK) { + MatchContextSuccessDifferentBlocks.increment(debug); + } + return result; + } + // We are going to emit the match at emitIndex. We need to make sure nodes of the match + // between emitIndex and rootIndex don't have inputs after position emitIndex that would + // make emitIndex an illegal position. + final List nodes = schedule.getBlockToNodesMap().get(rootBlock); + for (int i = emitIndex + 1; i <= rootIndex; i++) { Node node = nodes.get(i); - if (node instanceof VirtualObjectNode || node instanceof FloatingNode) { - // The order of evaluation of these nodes controlled by data dependence so they - // don't interfere with this match. - continue; - } else if ((consumed == null || !consumed.contains(node)) && node != root) { - if (LogVerbose.getValue(root.getOptions())) { - DebugContext debug = root.getDebug(); - debug.log("unexpected node %s", node); - for (int j = startIndex; j <= endIndex; j++) { - Node theNode = nodes.get(j); - debug.log("%s(%s) %1s", (consumed != null && consumed.contains(theNode) || theNode == root) ? "*" : " ", theNode.getUsageCount(), theNode); + ConsumedNode cn = consumed.find(node); + if (cn != null) { + assert cn.ignoresSideEffects; + for (Node in : node.inputs()) { + if (!consumed.contains(in)) { + for (int j = emitIndex + 1; j < i; j++) { + if (nodes.get(j) == in) { + logFailedMatch("Earliest position in block is too late %s", in); + assert consumed.find(root).ignoresSideEffects; + assert verifyInputsDifferentBlock(root) != Result.OK; + return Result.tooLate(node, rule.getPattern()); + } + } } } - return Result.notSafe(node, rule.getPattern()); + } + } + assert verifyInputsDifferentBlock(root) == Result.OK; + return Result.OK; + } + + private Result verifyInputsDifferentBlock(Node node) { + // Is there an input that's not part of the match that's after the emit position? + for (Node in : node.inputs()) { + if (in instanceof PhiNode) { + Block b = schedule.getNodeToBlockMap().get(((PhiNode) in).merge()); + if (dominates(b, emitBlock)) { + continue; + } + } else { + Block b = schedule.getNodeToBlockMap().get(in); + if (strictlyDominates(b, emitBlock) || (b == emitBlock && schedule.getBlockToNodesMap().get(emitBlock).indexOf(in) <= emitIndex)) { + continue; + } + } + ConsumedNode cn = consumed.find(in); + if (cn == null) { + logFailedMatch("Earliest position in block is too late %s", in); + return Result.tooLate(node, rule.getPattern()); + } + assert cn.ignoresSideEffects; + Result res = verifyInputsDifferentBlock(in); + if (res != Result.OK) { + return res; } } return Result.OK; } + private void logFailedMatch(String s, Node node) { + if (LogVerbose.getValue(root.getOptions())) { + DebugContext debug = root.getDebug(); + debug.log(s, node); + int startIndex = emitIndex; + if (emitBlock != rootBlock) { + int endIndex = schedule.getBlockToNodesMap().get(emitBlock).size() - 1; + final List emitBlockNodes = schedule.getBlockToNodesMap().get(emitBlock); + debug.log("%s:", emitBlock); + for (int j = startIndex; j <= endIndex; j++) { + Node theNode = emitBlockNodes.get(j); + debug.log("%s(%s) %1s", consumed.contains(theNode) ? "*" : " ", theNode.getUsageCount(), theNode); + } + startIndex = 0; + } + debug.log("%s:", rootBlock); + final List nodes = schedule.getBlockToNodesMap().get(rootBlock); + for (int j = startIndex; j <= rootIndex; j++) { + Node theNode = nodes.get(j); + debug.log("%s(%s) %1s", consumed.contains(theNode) ? "*" : " ", theNode.getUsageCount(), theNode); + } + } + } + /** * Mark the interior nodes with INTERIOR_MATCH and set the Value of the root to be the result. * During final LIR generation it will be evaluated to produce the actual LIR value. @@ -133,20 +363,28 @@ */ public void setResult(ComplexMatchResult result) { ComplexMatchValue value = new ComplexMatchValue(result); + Node emitNode = schedule.getBlockToNodesMap().get(emitBlock).get(emitIndex); DebugContext debug = root.getDebug(); if (debug.isLogEnabled()) { - debug.log("matched %s %s", rule.getName(), rule.getPattern()); + debug.log("matched %s %s%s", rule.getName(), rule.getPattern(), emitIndex != rootIndex ? " skipping side effects" : ""); debug.log("with nodes %s", rule.formatMatch(root)); } - if (consumed != null) { - for (Node node : consumed) { - // All the interior nodes should be skipped during the normal doRoot calls in - // NodeLIRBuilder so mark them as interior matches. The root of the match will get a - // closure which will be evaluated to produce the final LIR. - builder.setMatchResult(node, ComplexMatchValue.INTERIOR_MATCH); + for (ConsumedNode cn : consumed) { + if (cn.node == root || cn.node == emitNode) { + continue; } + // All the interior nodes should be skipped during the normal doRoot calls in + // NodeLIRBuilder so mark them as interior matches. The root of the match will get a + // closure which will be evaluated to produce the final LIR. + builder.setMatchResult(cn.node, ComplexMatchValue.INTERIOR_MATCH); + } + builder.setMatchResult(emitNode, value); + if (root != emitNode) { + // Match is not emitted at the position of root in the block but the uses of root needs + // the result of the match so add a ComplexMatchValue that will simply return the result + // of the actual match above. + builder.setMatchResult(root, new ComplexMatchValue(gen -> gen.operand(emitNode))); } - builder.setMatchResult(root, value); } /** @@ -154,24 +392,18 @@ * * @return Result.OK if the node can be safely consumed. */ - public Result consume(Node node) { - assert MatchPattern.isSingleValueUser(node) : "should have already been checked"; - - // Check NOT_IN_BLOCK first since that usually implies ALREADY_USED - int index = nodes.indexOf(node); - if (index == -1) { - return Result.notInBlock(node, rule.getPattern()); + public Result consume(Node node, boolean ignoresSideEffects, boolean atRoot) { + if (atRoot) { + consumed.add(node, ignoresSideEffects); + return Result.OK; } + assert MatchPattern.isSingleValueUser(node) : "should have already been checked"; if (builder.hasOperand(node)) { return Result.alreadyUsed(node, rule.getPattern()); } - startIndex = Math.min(startIndex, index); - if (consumed == null) { - consumed = new ArrayList<>(2); - } - consumed.add(node); + consumed.add(node, ignoresSideEffects); return Result.OK; } @@ -194,6 +426,6 @@ @Override public String toString() { - return String.format("%s %s (%d, %d) consumed %s", rule, root, startIndex, endIndex, consumed != null ? Arrays.toString(consumed.toArray()) : ""); + return String.format("%s %s (%s/%d, %s/%d) consumed %s", rule, root, rootBlock, rootIndex, emitBlock, emitIndex, consumed); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchPattern.java 2019-03-28 07:36:56.752542981 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchPattern.java 2019-03-28 07:36:56.372540442 +0100 @@ -30,6 +30,7 @@ import org.graalvm.compiler.graph.Position; import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.Verbosity; +import org.graalvm.compiler.nodes.calc.FloatingNode; /** * A simple recursive pattern matcher for a DAG of nodes. @@ -45,6 +46,7 @@ NOT_IN_BLOCK, NOT_SAFE, ALREADY_USED, + TOO_LATE, } /** @@ -70,6 +72,7 @@ private static final CounterKey MatchResult_NOT_IN_BLOCK = DebugContext.counter("MatchResult_NOT_IN_BLOCK"); private static final CounterKey MatchResult_NOT_SAFE = DebugContext.counter("MatchResult_NOT_SAFE"); private static final CounterKey MatchResult_ALREADY_USED = DebugContext.counter("MatchResult_ALREADY_USED"); + private static final CounterKey MatchResult_TOO_LATE = DebugContext.counter("MatchResult_TOO_LATE"); static final Result OK = new Result(MatchResultCode.OK, null, null); private static final Result CACHED_WRONG_CLASS = new Result(MatchResultCode.WRONG_CLASS, null, null); @@ -78,6 +81,7 @@ private static final Result CACHED_NOT_IN_BLOCK = new Result(MatchResultCode.NOT_IN_BLOCK, null, null); private static final Result CACHED_NOT_SAFE = new Result(MatchResultCode.NOT_SAFE, null, null); private static final Result CACHED_ALREADY_USED = new Result(MatchResultCode.ALREADY_USED, null, null); + private static final Result CACHED_TOO_LATE = new Result(MatchResultCode.TOO_LATE, null, null); static Result wrongClass(Node node, MatchPattern matcher) { MatchResult_WRONG_CLASS.increment(node.getDebug()); @@ -109,6 +113,11 @@ return node.getDebug().isLogEnabled() ? new Result(MatchResultCode.ALREADY_USED, node, matcher) : CACHED_ALREADY_USED; } + static Result tooLate(Node node, MatchPattern matcher) { + MatchResult_TOO_LATE.increment(node.getDebug()); + return node.getDebug().isLogEnabled() ? new Result(MatchResultCode.TOO_LATE, node, matcher) : CACHED_TOO_LATE; + } + @Override public String toString() { if (code == MatchResultCode.OK) { @@ -149,39 +158,49 @@ */ private final boolean singleUser; + /** + * Can this node be subsumed into a match even if there are side effecting nodes between this + * node and the match. + */ + private final boolean ignoresSideEffects; + private static final MatchPattern[] EMPTY_PATTERNS = new MatchPattern[0]; - public MatchPattern(String name, boolean singleUser) { - this(null, name, singleUser); + public MatchPattern(String name, boolean singleUser, boolean ignoresSideEffects) { + this(null, name, singleUser, ignoresSideEffects); } - public MatchPattern(Class nodeClass, String name, boolean singleUser) { + public MatchPattern(Class nodeClass, String name, boolean singleUser, boolean ignoresSideEffects) { this.nodeClass = nodeClass; this.name = name; this.singleUser = singleUser; + this.ignoresSideEffects = ignoresSideEffects; this.patterns = EMPTY_PATTERNS; this.inputs = null; + assert !ignoresSideEffects || FloatingNode.class.isAssignableFrom(nodeClass); } - private MatchPattern(Class nodeClass, String name, boolean singleUser, MatchPattern[] patterns, Position[] inputs) { + private MatchPattern(Class nodeClass, String name, boolean singleUser, boolean ignoresSideEffects, MatchPattern[] patterns, Position[] inputs) { assert inputs == null || inputs.length == patterns.length; this.nodeClass = nodeClass; this.name = name; this.singleUser = singleUser; + this.ignoresSideEffects = ignoresSideEffects; this.patterns = patterns; this.inputs = inputs; + assert !ignoresSideEffects || FloatingNode.class.isAssignableFrom(nodeClass); } - public MatchPattern(Class nodeClass, String name, MatchPattern first, Position[] inputs, boolean singleUser) { - this(nodeClass, name, singleUser, new MatchPattern[]{first}, inputs); + public MatchPattern(Class nodeClass, String name, MatchPattern first, Position[] inputs, boolean singleUser, boolean ignoresSideEffects) { + this(nodeClass, name, singleUser, ignoresSideEffects, new MatchPattern[]{first}, inputs); } - public MatchPattern(Class nodeClass, String name, MatchPattern first, MatchPattern second, Position[] inputs, boolean singleUser) { - this(nodeClass, name, singleUser, new MatchPattern[]{first, second}, inputs); + public MatchPattern(Class nodeClass, String name, MatchPattern first, MatchPattern second, Position[] inputs, boolean singleUser, boolean ignoresSideEffects) { + this(nodeClass, name, singleUser, ignoresSideEffects, new MatchPattern[]{first, second}, inputs); } - public MatchPattern(Class nodeClass, String name, MatchPattern first, MatchPattern second, MatchPattern third, Position[] inputs, boolean singleUser) { - this(nodeClass, name, singleUser, new MatchPattern[]{first, second, third}, inputs); + public MatchPattern(Class nodeClass, String name, MatchPattern first, MatchPattern second, MatchPattern third, Position[] inputs, boolean singleUser, boolean ignoresSideEffects) { + this(nodeClass, name, singleUser, ignoresSideEffects, new MatchPattern[]{first, second, third}, inputs); } Class nodeClass() { @@ -215,8 +234,8 @@ if (result != Result.OK) { return result; } - if (singleUser && !atRoot) { - result = context.consume(node); + if (singleUser) { + result = context.consume(node, ignoresSideEffects, atRoot); if (result != Result.OK) { return result; } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchStatement.java 2019-03-28 07:36:57.256546349 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchStatement.java 2019-03-28 07:36:56.872543783 +0100 @@ -26,8 +26,6 @@ import static org.graalvm.compiler.debug.DebugOptions.LogVerbose; -import java.util.List; - import org.graalvm.compiler.core.gen.NodeLIRBuilder; import org.graalvm.compiler.core.match.MatchPattern.MatchResultCode; import org.graalvm.compiler.core.match.MatchPattern.Result; @@ -38,6 +36,8 @@ import org.graalvm.compiler.nodeinfo.Verbosity; import jdk.vm.ci.meta.Value; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.cfg.Block; /** * A named {@link MatchPattern} along with a {@link MatchGenerator} that can be evaluated to replace @@ -80,20 +80,21 @@ * * @param builder the current builder instance. * @param node the node to be matched - * @param nodes the nodes in the current block + * @param block the current block + * @param schedule the schedule that's being used * @return true if the statement matched something and set a {@link ComplexMatchResult} to be * evaluated by the NodeLIRBuilder. */ - public boolean generate(NodeLIRBuilder builder, int index, Node node, List nodes) { + public boolean generate(NodeLIRBuilder builder, int index, Node node, Block block, StructuredGraph.ScheduleResult schedule) { DebugContext debug = node.getDebug(); - assert index == nodes.indexOf(node); + assert index == schedule.getBlockToNodesMap().get(block).indexOf(node); // Check that the basic shape matches Result result = pattern.matchShape(node, this); if (result != Result.OK) { return false; } // Now ensure that the other safety constraints are matched. - MatchContext context = new MatchContext(builder, this, index, node, nodes); + MatchContext context = new MatchContext(builder, this, index, node, block, schedule); result = pattern.matchUsage(node, context); if (result == Result.OK) { // Invoke the generator method and set the result if it's non null. --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchableNode.java 2019-03-28 07:36:57.752549664 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchableNode.java 2019-03-28 07:36:57.376547151 +0100 @@ -64,4 +64,6 @@ * Can a node with multiple uses be safely matched by a rule. */ boolean shareable() default false; + + boolean ignoresSideEffects() default false; } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java 2019-03-28 07:36:58.248552978 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java 2019-03-28 07:36:57.864550412 +0100 @@ -239,15 +239,9 @@ this.unscopedTimers = parseUnscopedMetricSpec(Timers.getValue(options), "".equals(timeValue), true); this.unscopedMemUseTrackers = parseUnscopedMetricSpec(MemUseTrackers.getValue(options), "".equals(trackMemUseValue), true); - if (unscopedTimers != null || timeValue != null) { - if (!GraalServices.isCurrentThreadCpuTimeSupported()) { - throw new IllegalArgumentException("Time and Timers options require VM support for querying CPU time"); - } - } - if (unscopedMemUseTrackers != null || trackMemUseValue != null) { if (!GraalServices.isThreadAllocatedMemorySupported()) { - throw new IllegalArgumentException("MemUseTrackers and TrackMemUse options require VM support for querying thread allocated memory"); + TTY.println("WARNING: Missing VM support for MemUseTrackers and TrackMemUse options so all reported memory usage will be 0"); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/LogStream.java 2019-03-28 07:36:58.768556453 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/LogStream.java 2019-03-28 07:36:58.380553860 +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 @@ -87,7 +87,7 @@ /** * The system dependent line separator. */ - public static final String LINE_SEPARATOR = System.getProperty("line.separator"); + public static final String LINE_SEPARATOR = System.lineSeparator(); /** * Creates a new log stream. --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MemUseTrackerKey.java 2019-03-28 07:36:59.232559554 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MemUseTrackerKey.java 2019-03-28 07:36:58.848556988 +0100 @@ -56,6 +56,6 @@ MemUseTrackerKey doc(String string); static long getCurrentThreadAllocatedBytes() { - return GraalServices.getCurrentThreadAllocatedBytes(); + return GraalServices.isThreadAllocatedMemorySupported() ? GraalServices.getCurrentThreadAllocatedBytes() : 0; } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Versions.java 2019-03-28 07:36:59.696562654 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Versions.java 2019-03-28 07:36:59.308560061 +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 @@ -32,11 +32,13 @@ import java.util.HashMap; import java.util.Map; +import jdk.vm.ci.services.Services; + /** Avoid using directly. Only public for the needs of unit testing. */ public final class Versions { static final Versions VERSIONS; static { - String home = System.getProperty("java.home"); + String home = Services.getSavedProperties().get("java.home"); VERSIONS = new Versions(home == null ? null : new File(home).toPath()); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Edges.java 2019-03-28 07:37:00.152565701 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Edges.java 2019-03-28 07:36:59.772563161 +0100 @@ -26,7 +26,6 @@ import static org.graalvm.compiler.graph.Graph.isModificationCountsEnabled; import static org.graalvm.compiler.graph.Node.NOT_ITERABLE; -import static org.graalvm.compiler.graph.UnsafeAccess.UNSAFE; import java.util.ArrayList; import java.util.Iterator; @@ -34,6 +33,9 @@ import org.graalvm.compiler.core.common.Fields; import org.graalvm.compiler.core.common.FieldsScanner; import org.graalvm.compiler.graph.NodeClass.EdgeInfo; +import org.graalvm.compiler.serviceprovider.GraalUnsafeAccess; + +import sun.misc.Unsafe; /** * Describes {@link Node} fields representing the set of inputs for the node or the set of the @@ -41,6 +43,8 @@ */ public abstract class Edges extends Fields { + private static final Unsafe UNSAFE = GraalUnsafeAccess.getUnsafe(); + /** * Constants denoting whether a set of edges are inputs or successors. */ --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java 2019-03-28 07:37:00.616568801 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java 2019-03-28 07:37:00.236566262 +0100 @@ -27,7 +27,7 @@ import static org.graalvm.compiler.graph.Edges.Type.Inputs; import static org.graalvm.compiler.graph.Edges.Type.Successors; import static org.graalvm.compiler.graph.Graph.isModificationCountsEnabled; -import static org.graalvm.compiler.graph.UnsafeAccess.UNSAFE; +import static org.graalvm.compiler.serviceprovider.GraalUnsafeAccess.getUnsafe; import java.lang.annotation.ElementType; import java.lang.annotation.RetentionPolicy; @@ -61,6 +61,7 @@ import org.graalvm.compiler.nodeinfo.Verbosity; import org.graalvm.compiler.options.OptionValues; +import jdk.vm.ci.services.Services; import sun.misc.Unsafe; /** @@ -86,9 +87,11 @@ @NodeInfo public abstract class Node implements Cloneable, Formattable, NodeInterface { + private static final Unsafe UNSAFE = getUnsafe(); + public static final NodeClass TYPE = null; - public static final boolean TRACK_CREATION_POSITION = Boolean.getBoolean("debug.graal.TrackNodeCreationPosition"); + public static final boolean TRACK_CREATION_POSITION = Boolean.parseBoolean(Services.getSavedProperties().get("debug.graal.TrackNodeCreationPosition")); static final int DELETED_ID_START = -1000000000; static final int INITIAL_ID = -1; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java 2019-03-28 07:37:01.068571820 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java 2019-03-28 07:37:00.704569388 +0100 @@ -24,11 +24,13 @@ 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; -import static org.graalvm.compiler.graph.UnsafeAccess.UNSAFE; +import static org.graalvm.compiler.serviceprovider.GraalUnsafeAccess.getUnsafe; import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; @@ -69,6 +71,8 @@ import org.graalvm.compiler.nodeinfo.NodeSize; import org.graalvm.compiler.nodeinfo.Verbosity; +import sun.misc.Unsafe; + /** * Metadata for every {@link Node} type. The metadata includes: *

    @@ -79,6 +83,7 @@ */ public final class NodeClass extends FieldIntrospection { + private static final Unsafe UNSAFE = getUnsafe(); // Timers for creation of a NodeClass instance private static final TimerKey Init_FieldScanning = DebugContext.timer("NodeClass.Init.FieldScanning"); private static final TimerKey Init_FieldScanningInner = DebugContext.timer("NodeClass.Init.FieldScanning.Inner"); @@ -128,7 +133,7 @@ public static NodeClass get(Class clazz) { int numTries = 0; while (true) { - boolean shouldBeInitializedBefore = UnsafeAccess.UNSAFE.shouldBeInitialized(clazz); + boolean shouldBeInitializedBefore = UNSAFE.shouldBeInitialized(clazz); NodeClass result = getUnchecked(clazz); if (result != null || clazz == NODE_CLASS) { @@ -141,13 +146,13 @@ * information without failing gates. */ numTries++; - boolean shouldBeInitializedAfter = UnsafeAccess.UNSAFE.shouldBeInitialized(clazz); + boolean shouldBeInitializedAfter = UNSAFE.shouldBeInitialized(clazz); String msg = "GR-9537 Reflective field access of TYPE field returned null. This is probably a bug in HotSpot class initialization. " + " clazz: " + clazz.getTypeName() + ", numTries: " + numTries + ", shouldBeInitializedBefore: " + shouldBeInitializedBefore + ", shouldBeInitializedAfter: " + shouldBeInitializedAfter; if (numTries <= 100) { TTY.println(msg); - UnsafeAccess.UNSAFE.ensureClassInitialized(clazz); + UNSAFE.ensureClassInitialized(clazz); } else { throw GraalError.shouldNotReachHere(msg); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeSourcePosition.java 2019-03-28 07:37:01.492574653 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeSourcePosition.java 2019-03-28 07:37:01.148572356 +0100 @@ -40,11 +40,12 @@ import jdk.vm.ci.meta.JavaMethod; import jdk.vm.ci.meta.MetaUtil; import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.services.Services; public class NodeSourcePosition extends BytecodePosition implements Iterable { - private static final boolean STRICT_SOURCE_POSITION = Boolean.getBoolean("debug.graal.SourcePositionStrictChecks"); - private static final boolean SOURCE_POSITION_BYTECODES = Boolean.getBoolean("debug.graal.SourcePositionDisassemble"); + private static final boolean STRICT_SOURCE_POSITION = Boolean.parseBoolean(Services.getSavedProperties().get("debug.graal.SourcePositionStrictChecks")); + private static final boolean SOURCE_POSITION_BYTECODES = Boolean.parseBoolean(Services.getSavedProperties().get("debug.graal.SourcePositionDisassemble")); private final int hashCode; private final Marker marker; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java 2019-03-28 07:37:01.904577407 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java 2019-03-28 07:37:01.560575107 +0100 @@ -166,7 +166,8 @@ HotSpotHostForeignCallsProvider foreignCalls, HotSpotMetaAccessProvider metaAccess, HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes) { Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, replacements); - AArch64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), false); + AArch64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), false, // + /* registerMathPlugins */true); return plugins; } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java 2019-03-28 07:37:02.320580186 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java 2019-03-28 07:37:01.972577861 +0100 @@ -113,7 +113,7 @@ private HotSpotDebugInfoBuilder debugInfoBuilder; protected AArch64HotSpotLIRGenerator(HotSpotProviders providers, GraalHotSpotVMConfig config, LIRGenerationResult lirGenRes) { - this(new AArch64LIRKindTool(), new AArch64ArithmeticLIRGenerator(), new AArch64HotSpotMoveFactory(), providers, config, lirGenRes); + this(new AArch64LIRKindTool(), new AArch64ArithmeticLIRGenerator(null), new AArch64HotSpotMoveFactory(), providers, config, lirGenRes); } protected AArch64HotSpotLIRGenerator(LIRKindTool lirKindTool, AArch64ArithmeticLIRGenerator arithmeticLIRGen, MoveFactory moveFactory, HotSpotProviders providers, GraalHotSpotVMConfig config, --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64IndirectCallOp.java 2019-03-28 07:37:02.740582991 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64IndirectCallOp.java 2019-03-28 07:37:02.396580693 +0100 @@ -73,7 +73,9 @@ crb.recordMark(config.MARKID_INLINE_INVOKE); Register callReg = asRegister(targetAddress); assert !callReg.equals(METHOD); + int pcOffset = masm.position(); AArch64Call.indirectCall(crb, masm, callReg, callTarget, state); + crb.recordInlineInvokeCallOp(pcOffset, getPosition()); } @Override --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64ArrayEqualsStub.java 2019-03-28 07:37:03.148585717 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64ArrayEqualsStub.java 2019-03-28 07:37:02.808583445 +0100 @@ -31,6 +31,7 @@ import org.graalvm.compiler.hotspot.stubs.SnippetStub; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.nodes.ArrayEqualsNode; +import org.graalvm.compiler.replacements.nodes.ArrayRegionEqualsNode; import jdk.internal.vm.compiler.word.Pointer; import jdk.vm.ci.meta.JavaKind; @@ -54,6 +55,13 @@ public static final ForeignCallDescriptor STUB_DOUBLE_ARRAY_EQUALS = new ForeignCallDescriptor( "doubleArraysEquals", boolean.class, Pointer.class, Pointer.class, int.class); + public static final ForeignCallDescriptor STUB_BYTE_ARRAY_EQUALS_DIRECT = new ForeignCallDescriptor( + "byteArraysEqualsDirect", boolean.class, Pointer.class, Pointer.class, int.class); + public static final ForeignCallDescriptor STUB_CHAR_ARRAY_EQUALS_DIRECT = new ForeignCallDescriptor( + "charArraysEqualsDirect", boolean.class, Pointer.class, Pointer.class, int.class); + public static final ForeignCallDescriptor STUB_CHAR_ARRAY_EQUALS_BYTE_ARRAY = new ForeignCallDescriptor( + "charArrayEqualsByteArray", boolean.class, Pointer.class, Pointer.class, int.class); + public AMD64ArrayEqualsStub(ForeignCallDescriptor foreignCallDescriptor, OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { super(foreignCallDescriptor.getName(), options, providers, linkage); } @@ -97,4 +105,19 @@ private static boolean doubleArraysEquals(Pointer array1, Pointer array2, int length) { return ArrayEqualsNode.equals(array1, array2, length, JavaKind.Double); } + + @Snippet + private static boolean byteArraysEqualsDirect(Pointer array1, Pointer array2, int length) { + return ArrayRegionEqualsNode.regionEquals(array1, array2, length, JavaKind.Byte, JavaKind.Byte); + } + + @Snippet + private static boolean charArraysEqualsDirect(Pointer array1, Pointer array2, int length) { + return ArrayRegionEqualsNode.regionEquals(array1, array2, length, JavaKind.Char, JavaKind.Char); + } + + @Snippet + private static boolean charArrayEqualsByteArray(Pointer array1, Pointer array2, int length) { + return ArrayRegionEqualsNode.regionEquals(array1, array2, length, JavaKind.Char, JavaKind.Byte); + } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java 2019-03-28 07:37:03.596588709 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java 2019-03-28 07:37:03.260586464 +0100 @@ -137,6 +137,22 @@ registerStubCall(AMD64ArrayEqualsStub.STUB_FLOAT_ARRAY_EQUALS, LEAF, REEXECUTABLE, NO_LOCATIONS))); link(new AMD64ArrayEqualsStub(AMD64ArrayEqualsStub.STUB_DOUBLE_ARRAY_EQUALS, options, providers, registerStubCall(AMD64ArrayEqualsStub.STUB_DOUBLE_ARRAY_EQUALS, LEAF, REEXECUTABLE, NO_LOCATIONS))); + link(new AMD64ArrayEqualsStub(AMD64ArrayEqualsStub.STUB_BYTE_ARRAY_EQUALS_DIRECT, options, providers, + registerStubCall(AMD64ArrayEqualsStub.STUB_BYTE_ARRAY_EQUALS_DIRECT, LEAF, REEXECUTABLE, NO_LOCATIONS))); + link(new AMD64ArrayEqualsStub(AMD64ArrayEqualsStub.STUB_CHAR_ARRAY_EQUALS_DIRECT, options, providers, + registerStubCall(AMD64ArrayEqualsStub.STUB_CHAR_ARRAY_EQUALS_DIRECT, LEAF, REEXECUTABLE, NO_LOCATIONS))); + link(new AMD64ArrayEqualsStub(AMD64ArrayEqualsStub.STUB_CHAR_ARRAY_EQUALS_BYTE_ARRAY, options, providers, + registerStubCall(AMD64ArrayEqualsStub.STUB_CHAR_ARRAY_EQUALS_BYTE_ARRAY, LEAF, REEXECUTABLE, NO_LOCATIONS))); + + link(new AMD64ArrayCompareToStub(AMD64ArrayCompareToStub.STUB_BYTE_ARRAY_COMPARE_TO_BYTE_ARRAY, options, providers, + registerStubCall(AMD64ArrayCompareToStub.STUB_BYTE_ARRAY_COMPARE_TO_BYTE_ARRAY, LEAF, REEXECUTABLE, NO_LOCATIONS))); + link(new AMD64ArrayCompareToStub(AMD64ArrayCompareToStub.STUB_BYTE_ARRAY_COMPARE_TO_CHAR_ARRAY, options, providers, + registerStubCall(AMD64ArrayCompareToStub.STUB_BYTE_ARRAY_COMPARE_TO_CHAR_ARRAY, LEAF, REEXECUTABLE, NO_LOCATIONS))); + link(new AMD64ArrayCompareToStub(AMD64ArrayCompareToStub.STUB_CHAR_ARRAY_COMPARE_TO_BYTE_ARRAY, options, providers, + registerStubCall(AMD64ArrayCompareToStub.STUB_CHAR_ARRAY_COMPARE_TO_BYTE_ARRAY, LEAF, REEXECUTABLE, NO_LOCATIONS))); + link(new AMD64ArrayCompareToStub(AMD64ArrayCompareToStub.STUB_CHAR_ARRAY_COMPARE_TO_CHAR_ARRAY, options, providers, + registerStubCall(AMD64ArrayCompareToStub.STUB_CHAR_ARRAY_COMPARE_TO_CHAR_ARRAY, LEAF, REEXECUTABLE, NO_LOCATIONS))); + super.initialize(providers, options); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java 2019-03-28 07:37:04.036591648 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java 2019-03-28 07:37:03.692589350 +0100 @@ -676,32 +676,4 @@ protected StrategySwitchOp createStrategySwitchOp(SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Variable key, AllocatableValue temp) { return new AMD64HotSpotStrategySwitchOp(strategy, keyTargets, defaultTarget, key, temp); } - - @Override - public ForeignCallLinkage lookupArrayEqualsStub(JavaKind kind, int constantLength) { - if (constantLength >= 0 && constantLength * kind.getByteCount() < 2 * getMaxVectorSize()) { - // Yield constant-length arrays comparison assembly - return null; - } - switch (kind) { - case Boolean: - return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_BOOLEAN_ARRAY_EQUALS); - case Byte: - return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_BYTE_ARRAY_EQUALS); - case Char: - return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_CHAR_ARRAY_EQUALS); - case Short: - return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_SHORT_ARRAY_EQUALS); - case Int: - return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_INT_ARRAY_EQUALS); - case Long: - return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_LONG_ARRAY_EQUALS); - case Float: - return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_FLOAT_ARRAY_EQUALS); - case Double: - return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_DOUBLE_ARRAY_EQUALS); - default: - return null; - } - } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java 2019-03-28 07:37:04.484594641 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java 2019-03-28 07:37:04.144592370 +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 @@ -28,9 +28,11 @@ import static jdk.vm.ci.code.ValueUtil.isStackSlot; import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER; +import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.core.amd64.AMD64NodeLIRBuilder; import org.graalvm.compiler.core.amd64.AMD64NodeMatchRules; import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.gen.DebugInfoBuilder; import org.graalvm.compiler.hotspot.HotSpotDebugInfoBuilder; @@ -54,6 +56,8 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.NodeValueMap; +import org.graalvm.compiler.replacements.nodes.ArrayCompareToNode; +import org.graalvm.compiler.replacements.nodes.ArrayEqualsNode; import jdk.vm.ci.amd64.AMD64; import jdk.vm.ci.amd64.AMD64Kind; @@ -66,8 +70,11 @@ import jdk.vm.ci.hotspot.HotSpotCallingConventionType; import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import jdk.vm.ci.meta.AllocatableValue; +import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.JavaType; +import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.Value; +import org.graalvm.compiler.replacements.nodes.ArrayRegionEqualsNode; /** * LIR generator specialized for AMD64 HotSpot. @@ -196,4 +203,98 @@ Value[] parameters = visitInvokeArguments(gen.getRegisterConfig().getCallingConvention(HotSpotCallingConventionType.JavaCall, null, sig, gen), node.arguments()); append(new AMD64BreakpointOp(parameters)); } + + private ForeignCallLinkage lookupForeignCall(ForeignCallDescriptor descriptor) { + return getGen().getForeignCalls().lookupForeignCall(descriptor); + } + + @Override + public ForeignCallLinkage lookupGraalStub(ValueNode valueNode) { + ResolvedJavaMethod method = valueNode.graph().method(); + if (method == null || method.getAnnotation(Snippet.class) != null) { + // Emit assembly for snippet stubs + return null; + } + + if (valueNode instanceof ArrayEqualsNode) { + ArrayEqualsNode arrayEqualsNode = (ArrayEqualsNode) valueNode; + JavaKind kind = arrayEqualsNode.getKind(); + ValueNode length = arrayEqualsNode.getLength(); + + if (length.isConstant()) { + int constantLength = length.asJavaConstant().asInt(); + if (constantLength >= 0 && constantLength * kind.getByteCount() < 2 * getGen().getMaxVectorSize()) { + // Yield constant-length arrays comparison assembly + return null; + } + } + + switch (kind) { + case Boolean: + return lookupForeignCall(AMD64ArrayEqualsStub.STUB_BOOLEAN_ARRAY_EQUALS); + case Byte: + return lookupForeignCall(AMD64ArrayEqualsStub.STUB_BYTE_ARRAY_EQUALS); + case Char: + return lookupForeignCall(AMD64ArrayEqualsStub.STUB_CHAR_ARRAY_EQUALS); + case Short: + return lookupForeignCall(AMD64ArrayEqualsStub.STUB_SHORT_ARRAY_EQUALS); + case Int: + return lookupForeignCall(AMD64ArrayEqualsStub.STUB_INT_ARRAY_EQUALS); + case Long: + return lookupForeignCall(AMD64ArrayEqualsStub.STUB_LONG_ARRAY_EQUALS); + case Float: + return lookupForeignCall(AMD64ArrayEqualsStub.STUB_FLOAT_ARRAY_EQUALS); + case Double: + return lookupForeignCall(AMD64ArrayEqualsStub.STUB_DOUBLE_ARRAY_EQUALS); + default: + return null; + } + } else if (valueNode instanceof ArrayCompareToNode) { + ArrayCompareToNode arrayCompareToNode = (ArrayCompareToNode) valueNode; + JavaKind kind1 = arrayCompareToNode.getKind1(); + JavaKind kind2 = arrayCompareToNode.getKind2(); + + if (kind1 == JavaKind.Byte) { + if (kind2 == JavaKind.Byte) { + return lookupForeignCall(AMD64ArrayCompareToStub.STUB_BYTE_ARRAY_COMPARE_TO_BYTE_ARRAY); + } else if (kind2 == JavaKind.Char) { + return lookupForeignCall(AMD64ArrayCompareToStub.STUB_BYTE_ARRAY_COMPARE_TO_CHAR_ARRAY); + } + } else if (kind1 == JavaKind.Char) { + if (kind2 == JavaKind.Byte) { + return lookupForeignCall(AMD64ArrayCompareToStub.STUB_CHAR_ARRAY_COMPARE_TO_BYTE_ARRAY); + } else if (kind2 == JavaKind.Char) { + return lookupForeignCall(AMD64ArrayCompareToStub.STUB_CHAR_ARRAY_COMPARE_TO_CHAR_ARRAY); + } + } + } else if (valueNode instanceof ArrayRegionEqualsNode) { + ArrayRegionEqualsNode arrayRegionEqualsNode = (ArrayRegionEqualsNode) valueNode; + JavaKind kind1 = arrayRegionEqualsNode.getKind1(); + JavaKind kind2 = arrayRegionEqualsNode.getKind2(); + ValueNode length = arrayRegionEqualsNode.getLength(); + + if (length.isConstant()) { + int constantLength = length.asJavaConstant().asInt(); + if (constantLength >= 0 && constantLength * (Math.max(kind1.getByteCount(), kind2.getByteCount())) < 2 * getGen().getMaxVectorSize()) { + // Yield constant-length arrays comparison assembly + return null; + } + } + + if (kind1 == kind2) { + switch (kind1) { + case Byte: + return lookupForeignCall(AMD64ArrayEqualsStub.STUB_BYTE_ARRAY_EQUALS_DIRECT); + case Char: + return lookupForeignCall(AMD64ArrayEqualsStub.STUB_CHAR_ARRAY_EQUALS_DIRECT); + default: + return null; + } + } else if (kind1 == JavaKind.Char && kind2 == JavaKind.Byte) { + return lookupForeignCall(AMD64ArrayEqualsStub.STUB_CHAR_ARRAY_EQUALS_BYTE_ARRAY); + } + } + + return null; + } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/BootstrapWatchDog.java 2019-03-28 07:37:04.940597686 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/BootstrapWatchDog.java 2019-03-28 07:37:04.608595469 +0100 @@ -39,6 +39,7 @@ import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.code.CompilationRequest; +import jdk.vm.ci.services.Services; /** * A watch dog that monitors the duration and compilation rate during a @@ -108,7 +109,7 @@ /** * Set to true to debug the watch dog. */ - private static final boolean DEBUG = Boolean.getBoolean("debug.graal.BootstrapWatchDog"); + private static final boolean DEBUG = Boolean.parseBoolean(Services.getSavedProperties().get("debug.graal.BootstrapWatchDog")); /** * Seconds to delay before starting to measure the compilation rate. --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationStatistics.java 2019-03-28 07:37:05.392600706 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationStatistics.java 2019-03-28 07:37:05.056598462 +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 @@ -48,6 +48,7 @@ import jdk.vm.ci.hotspot.HotSpotInstalledCode; import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; +import jdk.vm.ci.services.Services; @SuppressWarnings("unused") public final class CompilationStatistics { @@ -189,7 +190,7 @@ timeLeft = RESOLUTION; } } - String timelineName = System.getProperty("stats.timeline.name"); + String timelineName = Services.getSavedProperties().get("stats.timeline.name"); if (timelineName != null && !timelineName.isEmpty()) { out.printf("%s%c", CSVUtil.Escape.escape(timelineName), CSVUtil.SEPARATOR); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java 2019-03-28 07:37:05.824603591 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java 2019-03-28 07:37:05.488601347 +0100 @@ -57,7 +57,6 @@ import jdk.vm.ci.hotspot.HotSpotCompilationRequest; import jdk.vm.ci.hotspot.HotSpotCompilationRequestResult; import jdk.vm.ci.hotspot.HotSpotInstalledCode; -import jdk.vm.ci.hotspot.HotSpotJVMCICompilerFactory; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; import jdk.vm.ci.hotspot.HotSpotNmethod; import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; @@ -93,6 +92,7 @@ private final boolean installAsDefault; private final boolean useProfilingInfo; + private final boolean shouldRetainLocalVariables; private final OptionValues options; final class HotSpotCompilationWrapper extends CompilationWrapper { @@ -187,7 +187,7 @@ try (DebugContext.Scope s = debug.scope("Compiling", new DebugDumpScope(getIdString(), true))) { // Begin the compilation event. compilationEvent.begin(); - result = compiler.compile(method, entryBCI, useProfilingInfo, compilationId, options, debug); + result = compiler.compile(method, entryBCI, useProfilingInfo, shouldRetainLocalVariables, compilationId, options, debug); } catch (Throwable e) { throw debug.handle(e); } finally { @@ -213,10 +213,16 @@ public CompilationTask(HotSpotJVMCIRuntime jvmciRuntime, HotSpotGraalCompiler compiler, HotSpotCompilationRequest request, boolean useProfilingInfo, boolean installAsDefault, OptionValues options) { + this(jvmciRuntime, compiler, request, useProfilingInfo, false, installAsDefault, options); + } + + public CompilationTask(HotSpotJVMCIRuntime jvmciRuntime, HotSpotGraalCompiler compiler, HotSpotCompilationRequest request, boolean useProfilingInfo, boolean shouldRetainLocalVariables, + boolean installAsDefault, OptionValues options) { this.jvmciRuntime = jvmciRuntime; this.compiler = compiler; this.compilationId = new HotSpotCompilationIdentifier(request); this.useProfilingInfo = useProfilingInfo; + this.shouldRetainLocalVariables = shouldRetainLocalVariables; this.installAsDefault = installAsDefault; /* @@ -321,15 +327,14 @@ // Log a compilation event. EventProvider.CompilationEvent compilationEvent = eventProvider.newCompilationEvent(); - if (installAsDefault) { + if (installAsDefault || isOSR) { // If there is already compiled code for this method on our level we simply return. // JVMCI compiles are always at the highest compile level, even in non-tiered mode so we // only need to check for that value. if (method.hasCodeAtLevel(entryBCI, config.compilationLevelFullOptimization)) { return HotSpotCompilationRequestResult.failure("Already compiled", false); } - if (HotSpotGraalCompilerFactory.checkGraalCompileOnlyFilter(method.getDeclaringClass().toJavaName(), method.getName(), method.getSignature().toString(), - HotSpotJVMCICompilerFactory.CompilationLevel.FullOptimization) != HotSpotJVMCICompilerFactory.CompilationLevel.FullOptimization) { + if (HotSpotGraalCompilerFactory.shouldExclude(method)) { return HotSpotCompilationRequestResult.failure("GraalCompileOnly excluded", false); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationWatchDog.java 2019-03-28 07:37:06.332606984 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationWatchDog.java 2019-03-28 07:37:05.952604446 +0100 @@ -35,6 +35,7 @@ import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.services.Services; /** * A watch dog for reporting long running compilations. This is designed to be an always on @@ -166,7 +167,7 @@ /** * Set to true to debug the watch dog. */ - private static final boolean DEBUG = Boolean.getBoolean("debug.graal.CompilationWatchDog"); + private static final boolean DEBUG = Boolean.parseBoolean(Services.getSavedProperties().get("debug.graal.CompilationWatchDog")); private void trace(String format, Object... args) { if (DEBUG) { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java 2019-03-28 07:37:06.848610431 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java 2019-03-28 07:37:06.464607866 +0100 @@ -316,14 +316,16 @@ 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 = getJvmciCompileStateCanPostOnExceptionsOffset(); + public final int jvmciCompileStateCanPostOnExceptionsOffset = getJvmciJvmtiCapabilityOffset("_jvmti_can_post_on_exceptions"); + public final int jvmciCompileStateCanPopFrameOffset = getJvmciJvmtiCapabilityOffset("_jvmti_can_pop_frame"); + public final int jvmciCompileStateCanAccessLocalVariablesOffset = getJvmciJvmtiCapabilityOffset("_jvmti_can_access_local_variables"); // Integer.MIN_VALUE if not available - private int getJvmciCompileStateCanPostOnExceptionsOffset() { - int offset = getFieldOffset("JVMCICompileState::_jvmti_can_post_on_exceptions", Integer.class, "jbyte", Integer.MIN_VALUE); + private int getJvmciJvmtiCapabilityOffset(String name) { + int offset = getFieldOffset("JVMCICompileState::" + name, 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); + offset = getFieldOffset("JVMCIEnv::" + name, Integer.class, "jbyte", Integer.MIN_VALUE); } return offset; } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfigBase.java 2019-03-28 07:37:07.352613797 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfigBase.java 2019-03-28 07:37:06.976611286 +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 @@ -36,9 +36,10 @@ import jdk.vm.ci.hotspot.HotSpotVMConfigAccess; import jdk.vm.ci.hotspot.HotSpotVMConfigStore; import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.services.Services; /** - * This is a source with different versions for various JDKs. + * Base class of class hierarchy for accessing HotSpot VM configuration. */ public abstract class GraalHotSpotVMConfigBase extends HotSpotVMConfigAccess { @@ -62,6 +63,18 @@ return true; } + private static String getProperty(String name, String def) { + String value = Services.getSavedProperties().get(name); + if (value == null) { + return def; + } + return value; + } + + private static String getProperty(String name) { + return getProperty(name, null); + } + /** * Contains values that are different between JDK versions. */ @@ -78,14 +91,14 @@ public final String osName = getHostOSName(); public final String osArch = getHostArchitectureName(); - public final boolean windowsOs = System.getProperty("os.name", "").startsWith("Windows"); - public final boolean linuxOs = System.getProperty("os.name", "").startsWith("Linux"); + public final boolean windowsOs = getProperty("os.name", "").startsWith("Windows"); + public final boolean linuxOs = getProperty("os.name", "").startsWith("Linux"); /** * Gets the host operating system name. */ private static String getHostOSName() { - String osName = System.getProperty("os.name"); + String osName = getProperty("os.name"); switch (osName) { case "Linux": osName = "linux"; @@ -108,7 +121,7 @@ } private static String getHostArchitectureName() { - String arch = System.getProperty("os.arch"); + String arch = getProperty("os.arch"); switch (arch) { case "x86_64": arch = "amd64"; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java 2019-03-28 07:37:07.868617243 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java 2019-03-28 07:37:07.480614652 +0100 @@ -25,6 +25,7 @@ package org.graalvm.compiler.hotspot; import static org.graalvm.compiler.core.common.GraalOptions.OptAssumptions; +import org.graalvm.compiler.serviceprovider.GraalUnsafeAccess; import java.io.ByteArrayOutputStream; import java.io.PrintStream; @@ -71,9 +72,11 @@ import jdk.vm.ci.meta.SpeculationLog; import jdk.vm.ci.meta.TriState; import jdk.vm.ci.runtime.JVMCICompiler; +import sun.misc.Unsafe; public class HotSpotGraalCompiler implements GraalJVMCICompiler { + private static final Unsafe UNSAFE = GraalUnsafeAccess.getUnsafe(); private final HotSpotJVMCIRuntime jvmciRuntime; private final HotSpotGraalRuntimeProvider graalRuntime; private final CompilationCounters compilationCounters; @@ -131,7 +134,7 @@ if (compilationCounters != null) { compilationCounters.countCompilation(method); } - CompilationTask task = new CompilationTask(jvmciRuntime, this, hsRequest, true, installAsDefault, options); + CompilationTask task = new CompilationTask(jvmciRuntime, this, hsRequest, true, shouldRetainLocalVariables(hsRequest.getJvmciEnv()), installAsDefault, options); CompilationRequestResult r = null; try (DebugContext debug = graalRuntime.openDebugContext(options, task.getCompilationIdentifier(), method, getDebugHandlersFactories(), DebugContext.DEFAULT_LOG_STREAM); Activation a = debug.activate()) { @@ -142,6 +145,24 @@ } } + private boolean shouldRetainLocalVariables(long envAddress) { + GraalHotSpotVMConfig config = graalRuntime.getVMConfig(); + if (envAddress == 0) { + return false; + } + if (config.jvmciCompileStateCanPopFrameOffset != Integer.MIN_VALUE) { + if ((UNSAFE.getByte(envAddress + config.jvmciCompileStateCanPopFrameOffset) & 0xFF) != 0) { + return true; + } + } + if (config.jvmciCompileStateCanAccessLocalVariablesOffset != Integer.MIN_VALUE) { + if ((UNSAFE.getByte(envAddress + config.jvmciCompileStateCanAccessLocalVariablesOffset) & 0xFF) != 0) { + return true; + } + } + return false; + } + public StructuredGraph createGraph(ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, CompilationIdentifier compilationId, OptionValues options, DebugContext debug) { HotSpotBackend backend = graalRuntime.getHostBackend(); HotSpotProviders providers = backend.getProviders(); @@ -161,6 +182,11 @@ public CompilationResult compileHelper(CompilationResultBuilderFactory crbf, CompilationResult result, StructuredGraph graph, ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, OptionValues options) { + return compileHelper(crbf, result, graph, method, entryBCI, useProfilingInfo, false, options); + } + + public CompilationResult compileHelper(CompilationResultBuilderFactory crbf, CompilationResult result, StructuredGraph graph, ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, + boolean shouldRetainLocalVariables, OptionValues options) { HotSpotBackend backend = graalRuntime.getHostBackend(); HotSpotProviders providers = backend.getProviders(); @@ -181,7 +207,7 @@ result.setEntryBCI(entryBCI); boolean shouldDebugNonSafepoints = providers.getCodeCache().shouldDebugNonSafepoints(); - PhaseSuite graphBuilderSuite = configGraphBuilderSuite(providers.getSuites().getDefaultGraphBuilderSuite(), shouldDebugNonSafepoints, isOSR); + PhaseSuite graphBuilderSuite = configGraphBuilderSuite(providers.getSuites().getDefaultGraphBuilderSuite(), shouldDebugNonSafepoints, shouldRetainLocalVariables, isOSR); GraalCompiler.compileGraph(graph, method, providers, backend, graphBuilderSuite, optimisticOpts, profilingInfo, suites, lirSuites, result, crbf, true); if (!isOSR && useProfilingInfo) { @@ -193,9 +219,14 @@ } public CompilationResult compile(ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, CompilationIdentifier compilationId, OptionValues options, DebugContext debug) { + return compile(method, entryBCI, useProfilingInfo, false, compilationId, options, debug); + } + + public CompilationResult compile(ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, boolean shouldRetainLocalVariables, CompilationIdentifier compilationId, OptionValues options, + DebugContext debug) { StructuredGraph graph = createGraph(method, entryBCI, useProfilingInfo, compilationId, options, debug); CompilationResult result = new CompilationResult(compilationId); - return compileHelper(CompilationResultBuilderFactory.Default, result, graph, method, entryBCI, useProfilingInfo, options); + return compileHelper(CompilationResultBuilderFactory.Default, result, graph, method, entryBCI, useProfilingInfo, shouldRetainLocalVariables, options); } protected OptimisticOptimizations getOptimisticOpts(ProfilingInfo profilingInfo, OptionValues options) { @@ -217,27 +248,26 @@ * @param suite the graph builder suite * @param shouldDebugNonSafepoints specifies if extra debug info should be generated (default is * false) + * @param shouldRetainLocalVariables specifies if local variables should be retained for + * debugging purposes (default is false) * @param isOSR specifies if extra OSR-specific post-processing is required (default is false) * @return a new suite derived from {@code suite} if any of the GBS parameters did not have a * default value otherwise {@code suite} */ - protected PhaseSuite configGraphBuilderSuite(PhaseSuite suite, boolean shouldDebugNonSafepoints, boolean isOSR) { - if (shouldDebugNonSafepoints || isOSR) { + protected PhaseSuite configGraphBuilderSuite(PhaseSuite suite, boolean shouldDebugNonSafepoints, boolean shouldRetainLocalVariables, boolean isOSR) { + if (shouldDebugNonSafepoints || shouldRetainLocalVariables || isOSR) { PhaseSuite newGbs = suite.copy(); - + GraphBuilderPhase graphBuilderPhase = (GraphBuilderPhase) newGbs.findPhase(GraphBuilderPhase.class).previous(); + GraphBuilderConfiguration graphBuilderConfig = graphBuilderPhase.getGraphBuilderConfig(); if (shouldDebugNonSafepoints) { - GraphBuilderPhase graphBuilderPhase = (GraphBuilderPhase) newGbs.findPhase(GraphBuilderPhase.class).previous(); - GraphBuilderConfiguration graphBuilderConfig = graphBuilderPhase.getGraphBuilderConfig(); graphBuilderConfig = graphBuilderConfig.withNodeSourcePosition(true); - GraphBuilderPhase newGraphBuilderPhase = new GraphBuilderPhase(graphBuilderConfig); - newGbs.findPhase(GraphBuilderPhase.class).set(newGraphBuilderPhase); } + if (shouldRetainLocalVariables) { + graphBuilderConfig = graphBuilderConfig.withRetainLocalVariables(true); + } + GraphBuilderPhase newGraphBuilderPhase = new GraphBuilderPhase(graphBuilderConfig); + newGbs.findPhase(GraphBuilderPhase.class).set(newGraphBuilderPhase); if (isOSR) { - // We must not clear non liveness for OSR compilations. - GraphBuilderPhase graphBuilderPhase = (GraphBuilderPhase) newGbs.findPhase(GraphBuilderPhase.class).previous(); - GraphBuilderConfiguration graphBuilderConfig = graphBuilderPhase.getGraphBuilderConfig(); - GraphBuilderPhase newGraphBuilderPhase = new GraphBuilderPhase(graphBuilderConfig); - newGbs.findPhase(GraphBuilderPhase.class).set(newGraphBuilderPhase); newGbs.appendPhase(new OnStackReplacementPhase()); } return newGbs; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompilerFactory.java 2019-03-28 07:37:08.368620582 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompilerFactory.java 2019-03-28 07:37:07.988618044 +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 @@ -25,7 +25,9 @@ package org.graalvm.compiler.hotspot; import static jdk.vm.ci.common.InitTimer.timer; +import static jdk.vm.ci.hotspot.HotSpotJVMCICompilerFactory.CompilationLevelAdjustment.None; 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.hotspot.HotSpotGraalOptionValues.GRAAL_OPTION_PROPERTY_PREFIX; import java.io.PrintStream; @@ -42,8 +44,10 @@ import jdk.vm.ci.common.InitTimer; import jdk.vm.ci.hotspot.HotSpotJVMCICompilerFactory; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; -import jdk.vm.ci.hotspot.HotSpotSignature; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; +import jdk.vm.ci.meta.Signature; import jdk.vm.ci.runtime.JVMCIRuntime; +import jdk.vm.ci.services.Services; public final class HotSpotGraalCompilerFactory extends HotSpotJVMCICompilerFactory { @@ -70,7 +74,7 @@ @Override public void onSelection() { - JVMCIVersionCheck.check(false); + JVMCIVersionCheck.check(Services.getSavedProperties(), false); assert options == null : "cannot select " + getClass() + " service more than once"; options = HotSpotGraalOptionValues.defaultOptions(); initializeGraalCompilePolicyFields(options); @@ -79,8 +83,10 @@ * Exercise this code path early to encourage loading now. This doesn't solve problem of * deadlock during class loading but seems to eliminate it in practice. */ - adjustCompilationLevelInternal(Object.class, "hashCode", "()I", CompilationLevel.FullOptimization); - adjustCompilationLevelInternal(Object.class, "hashCode", "()I", CompilationLevel.Simple); + if (isGraalPredicate != null && isGraalPredicate.getCompilationLevelAdjustment() != None) { + adjustCompilationLevelInternal(Object.class, CompilationLevel.FullOptimization); + adjustCompilationLevelInternal(Object.class, CompilationLevel.Simple); + } if (IS_BUILDING_NATIVE_IMAGE) { // Triggers initialization of all option descriptors Options.CompileGraalWithC1Only.getName(); @@ -88,7 +94,7 @@ } private static void initializeGraalCompilePolicyFields(OptionValues options) { - compileGraalWithC1Only = Options.CompileGraalWithC1Only.getValue(options); + compileGraalWithC1Only = Options.CompileGraalWithC1Only.getValue(options) && !IS_IN_NATIVE_IMAGE; String optionValue = Options.GraalCompileOnly.getValue(options); if (optionValue != null) { MethodFilter[] filter = MethodFilter.parse(optionValue); @@ -123,7 +129,7 @@ public HotSpotGraalCompiler createCompiler(JVMCIRuntime runtime) { CompilerConfigurationFactory factory = CompilerConfigurationFactory.selectFactory(null, options); if (isGraalPredicate != null) { - isGraalPredicate.onCompilerConfigurationFactorySelection(factory); + isGraalPredicate.onCompilerConfigurationFactorySelection((HotSpotJVMCIRuntime) runtime, factory); } HotSpotGraalCompiler compiler = createCompiler("VM", runtime, options, factory); // Only the HotSpotGraalRuntime associated with the compiler created via @@ -154,27 +160,13 @@ @Override public CompilationLevelAdjustment getCompilationLevelAdjustment() { - if (graalCompileOnlyFilter != null) { - return CompilationLevelAdjustment.ByFullSignature; - } - if (compileGraalWithC1Only) { - // We only decide using the class declaring the method - // so no need to have the method name and signature - // symbols converted to a String. - return CompilationLevelAdjustment.ByHolder; - } - return CompilationLevelAdjustment.None; + return isGraalPredicate != null ? isGraalPredicate.getCompilationLevelAdjustment() : None; } @Override public CompilationLevel adjustCompilationLevel(Object declaringClassObject, String name, String signature, boolean isOsr, CompilationLevel level) { - if (declaringClassObject instanceof String) { - // This must be SVM mode in which case only GraalCompileC1Only matters since Graal and - // JVMCI are already compiled. - return checkGraalCompileOnlyFilter((String) declaringClassObject, name, signature, level); - } Class declaringClass = (Class) declaringClassObject; - return adjustCompilationLevelInternal(declaringClass, name, signature, level); + return adjustCompilationLevelInternal(declaringClass, level); } static { @@ -184,32 +176,28 @@ assert HotSpotGraalCompilerFactory.class.getName().equals("org.graalvm.compiler.hotspot.HotSpotGraalCompilerFactory"); } - private CompilationLevel adjustCompilationLevelInternal(Class declaringClass, String name, String signature, CompilationLevel level) { - if (compileGraalWithC1Only) { - if (level.ordinal() > CompilationLevel.Simple.ordinal()) { - if (isGraalPredicate.apply(declaringClass)) { - return CompilationLevel.Simple; - } + private CompilationLevel adjustCompilationLevelInternal(Class declaringClass, CompilationLevel level) { + assert isGraalPredicate != null; + if (level.ordinal() > CompilationLevel.Simple.ordinal()) { + if (isGraalPredicate.apply(declaringClass)) { + return CompilationLevel.Simple; } } - return checkGraalCompileOnlyFilter(declaringClass.getName(), name, signature, level); + return level; } - public static CompilationLevel checkGraalCompileOnlyFilter(String declaringClassName, String name, String signature, CompilationLevel level) { + static boolean shouldExclude(HotSpotResolvedJavaMethod method) { if (graalCompileOnlyFilter != null) { - if (level == CompilationLevel.FullOptimization) { - HotSpotSignature sig = null; - for (MethodFilter filter : graalCompileOnlyFilter) { - if (filter.hasSignature() && sig == null) { - sig = new HotSpotSignature(HotSpotJVMCIRuntime.runtime(), signature); - } - if (filter.matches(declaringClassName, name, sig)) { - return level; - } + String javaClassName = method.getDeclaringClass().toJavaName(); + String name = method.getName(); + Signature signature = method.getSignature(); + for (MethodFilter filter : graalCompileOnlyFilter) { + if (filter.matches(javaClassName, name, signature)) { + return false; } - return CompilationLevel.Simple; } + return true; } - return level; + return false; } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java 2019-03-28 07:37:08.880624001 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java 2019-03-28 07:37:08.496621438 +0100 @@ -87,6 +87,7 @@ import jdk.vm.ci.meta.ResolvedJavaType; import jdk.vm.ci.runtime.JVMCI; import jdk.vm.ci.runtime.JVMCIBackend; +import jdk.vm.ci.services.Services; //JaCoCo Exclude @@ -95,7 +96,7 @@ */ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider { - private static final boolean IS_AOT = Boolean.getBoolean("com.oracle.graalvm.isaot"); + private static final boolean IS_AOT = Boolean.parseBoolean(Services.getSavedProperties().get("com.oracle.graalvm.isaot")); private static boolean checkArrayIndexScaleInvariants(MetaAccessProvider metaAccess) { assert metaAccess.getArrayIndexScale(JavaKind.Byte) == 1; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotTTYStreamProvider.java 2019-03-28 07:37:09.396627447 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotTTYStreamProvider.java 2019-03-28 07:37:09.016624909 +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 @@ -44,6 +44,7 @@ import org.graalvm.compiler.serviceprovider.ServiceProvider; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; +import jdk.vm.ci.services.Services; @ServiceProvider(TTYStreamProvider.class) public class HotSpotTTYStreamProvider implements TTYStreamProvider { @@ -151,7 +152,7 @@ if (inputArguments != null) { ps.println("VM Arguments: " + String.join(" ", inputArguments)); } - String cmd = System.getProperty("sun.java.command"); + String cmd = Services.getSavedProperties().get("sun.java.command"); if (cmd != null) { ps.println("sun.java.command=" + cmd); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/IsGraalPredicate.java 2019-03-28 07:37:09.920630946 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/IsGraalPredicate.java 2019-03-28 07:37:09.536628383 +0100 @@ -25,12 +25,13 @@ package org.graalvm.compiler.hotspot; import jdk.vm.ci.hotspot.HotSpotJVMCICompilerFactory; +import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; /** * Determines if a given class is a JVMCI or Graal class for the purpose of * {@link HotSpotGraalCompilerFactory.Options#CompileGraalWithC1Only}. */ -public class IsGraalPredicate { +class IsGraalPredicate extends IsGraalPredicateBase { /** * Module containing {@link HotSpotJVMCICompilerFactory}. */ @@ -47,15 +48,17 @@ */ private Module compilerConfigurationModule; - public IsGraalPredicate() { + IsGraalPredicate() { jvmciModule = HotSpotJVMCICompilerFactory.class.getModule(); graalModule = HotSpotGraalCompilerFactory.class.getModule(); } - void onCompilerConfigurationFactorySelection(CompilerConfigurationFactory factory) { + @Override + void onCompilerConfigurationFactorySelection(HotSpotJVMCIRuntime runtime, CompilerConfigurationFactory factory) { compilerConfigurationModule = factory.getClass().getModule(); } + @Override boolean apply(Class declaringClass) { Module module = declaringClass.getModule(); return jvmciModule == module || graalModule == module || compilerConfigurationModule == module; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java 2019-03-28 07:37:10.420634285 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java 2019-03-28 07:37:10.028631667 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -25,6 +25,9 @@ package org.graalvm.compiler.hotspot; import java.util.Formatter; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; /** * Mechanism for checking that the current Java runtime environment supports the minimum JVMCI API @@ -38,20 +41,22 @@ */ class JVMCIVersionCheck { - // 0.55 introduces new HotSpotSpeculationLog API + // 0.57 introduces HotSpotJVMCIRuntime.excludeFromJVMCICompilation private static final int JVMCI8_MIN_MAJOR_VERSION = 0; - private static final int JVMCI8_MIN_MINOR_VERSION = 55; + private static final int JVMCI8_MIN_MINOR_VERSION = 57; - private static void failVersionCheck(boolean exit, String reason, Object... args) { + private static void failVersionCheck(Map props, boolean exit, String reason, Object... args) { Formatter errorMessage = new Formatter().format(reason, args); - String javaHome = System.getProperty("java.home"); - String vmName = System.getProperty("java.vm.name"); + String javaHome = props.get("java.home"); + String vmName = props.get("java.vm.name"); errorMessage.format("Set the JVMCI_VERSION_CHECK environment variable to \"ignore\" to suppress "); errorMessage.format("this error or to \"warn\" to emit a warning and continue execution.%n"); errorMessage.format("Currently used Java home directory is %s.%n", javaHome); errorMessage.format("Currently used VM configuration is: %s%n", vmName); - if (System.getProperty("java.specification.version").compareTo("1.9") < 0) { - errorMessage.format("Download the latest JVMCI JDK 8 from http://www.oracle.com/technetwork/oracle-labs/program-languages/downloads/index.html"); + if (props.get("java.specification.version").compareTo("1.9") < 0) { + errorMessage.format("Download the latest JVMCI JDK 8 from " + + "http://www.oracle.com/technetwork/oracle-labs/program-languages/downloads/index.html or " + + "https://github.com/graalvm/openjdk8-jvmci-builder/releases"); } else { errorMessage.format("Download JDK 11 or later."); } @@ -68,10 +73,10 @@ } } - static void check(boolean exitOnFailure) { + static void check(Map props, boolean exitOnFailure) { // Don't use regular expressions to minimize Graal startup time - String javaSpecVersion = System.getProperty("java.specification.version"); - String vmVersion = System.getProperty("java.vm.version"); + String javaSpecVersion = props.get("java.specification.version"); + String vmVersion = props.get("java.vm.version"); if (javaSpecVersion.compareTo("1.9") < 0) { int start = vmVersion.indexOf("-jvmci-"); if (start >= 0) { @@ -82,7 +87,7 @@ try { major = Integer.parseInt(vmVersion.substring(start, end)); } catch (NumberFormatException e) { - failVersionCheck(exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal.%n" + + failVersionCheck(props, exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal.%n" + "Cannot read JVMCI major version from java.vm.version property: %s.%n", vmVersion); return; } @@ -95,22 +100,22 @@ try { minor = Integer.parseInt(vmVersion.substring(start, end)); } catch (NumberFormatException e) { - failVersionCheck(exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal.%n" + + failVersionCheck(props, exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal.%n" + "Cannot read JVMCI minor version from java.vm.version property: %s.%n", vmVersion); return; } if (major >= JVMCI8_MIN_MAJOR_VERSION && minor >= JVMCI8_MIN_MINOR_VERSION) { return; } - failVersionCheck(exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal: %d.%d < %d.%d.%n", + failVersionCheck(props, exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal: %d.%d < %d.%d.%n", major, minor, JVMCI8_MIN_MAJOR_VERSION, JVMCI8_MIN_MINOR_VERSION); return; } } - failVersionCheck(exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal.%n" + + failVersionCheck(props, exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal.%n" + "Cannot read JVMCI version from java.vm.version property: %s.%n", vmVersion); } else if (javaSpecVersion.compareTo("11") < 0) { - failVersionCheck(exitOnFailure, "Graal is not compatible with the JVMCI API in JDK 9 and 10.%n"); + failVersionCheck(props, exitOnFailure, "Graal is not compatible with the JVMCI API in JDK 9 and 10.%n"); } else { if (vmVersion.contains("SNAPSHOT")) { return; @@ -124,11 +129,11 @@ try { int build = Integer.parseInt(buildString); if (build < 20) { - failVersionCheck(exitOnFailure, "Graal requires build 20 or later of JDK 11 early access binary, got build %d.%n", build); + failVersionCheck(props, exitOnFailure, "Graal requires build 20 or later of JDK 11 early access binary, got build %d.%n", build); return; } } catch (NumberFormatException e) { - failVersionCheck(exitOnFailure, "Could not parse the JDK 11 early access build number from java.vm.version property: %s.%n", vmVersion); + failVersionCheck(props, exitOnFailure, "Could not parse the JDK 11 early access build number from java.vm.version property: %s.%n", vmVersion); return; } } else { @@ -141,6 +146,11 @@ * Command line interface for performing the check. */ public static void main(String[] args) { - check(true); + Properties sprops = System.getProperties(); + Map props = new HashMap<>(sprops.size()); + for (String name : sprops.stringPropertyNames()) { + props.put(name, sprops.getProperty(name)); + } + check(props, true); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java 2019-03-28 07:37:10.924637650 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java 2019-03-28 07:37:10.548635140 +0100 @@ -48,7 +48,6 @@ 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; @@ -88,7 +87,6 @@ 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; @@ -112,7 +110,6 @@ 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; @@ -311,10 +308,7 @@ PEGraphDecoder graphDecoder = new PEGraphDecoder( providers.getCodeCache().getTarget().arch, result, - providers.getMetaAccess(), - providers.getConstantReflection(), - providers.getConstantFieldProvider(), - providers.getStampProvider(), + providers, null, // loopExplosionPlugin replacements.getGraphBuilderPlugins().getInvocationPlugins(), new InlineInvokePlugin[0], @@ -407,10 +401,7 @@ PEGraphDecoder graphDecoder = new PEGraphDecoder( architecture, result, - providers.getMetaAccess(), - providers.getConstantReflection(), - providers.getConstantFieldProvider(), - providers.getStampProvider(), + providers, null, replacements.getGraphBuilderPlugins().getInvocationPlugins(), new InlineInvokePlugin[0], @@ -993,17 +984,15 @@ } @Override - protected GraphBuilderPhase.Instance createGraphBuilder(MetaAccessProvider metaAccess, StampProvider stampProvider, ConstantReflectionProvider constantReflection, - ConstantFieldProvider constantFieldProvider, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, IntrinsicContext initialIntrinsicContext) { - return new HotSpotSnippetGraphBuilderPhase(metaAccess, stampProvider, constantReflection, constantFieldProvider, graphBuilderConfig, optimisticOpts, - initialIntrinsicContext); + protected GraphBuilderPhase.Instance createGraphBuilder(Providers providers, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, + IntrinsicContext initialIntrinsicContext) { + return new HotSpotSnippetGraphBuilderPhase(providers, graphBuilderConfig, optimisticOpts, initialIntrinsicContext); } } static class HotSpotSnippetGraphBuilderPhase extends GraphBuilderPhase.Instance { - HotSpotSnippetGraphBuilderPhase(MetaAccessProvider metaAccess, StampProvider stampProvider, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantFieldProvider, - GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, IntrinsicContext initialIntrinsicContext) { - super(metaAccess, stampProvider, constantReflection, constantFieldProvider, graphBuilderConfig, optimisticOpts, initialIntrinsicContext); + HotSpotSnippetGraphBuilderPhase(Providers theProviders, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, IntrinsicContext initialIntrinsicContext) { + super(theProviders, graphBuilderConfig, optimisticOpts, initialIntrinsicContext); } @Override --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/debug/BenchmarkCounters.java 2019-03-28 07:37:11.452641176 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/debug/BenchmarkCounters.java 2019-03-28 07:37:11.064638585 +0100 @@ -416,7 +416,9 @@ if (waitingForEnd) { waitingForEnd = false; running = false; - BenchmarkCounters.dump(options, getPrintStream(options), (System.nanoTime() - startTime) / 1000000000d, jvmciRuntime.collectCounters(), 100); + try (PrintStreamScope scope = getPrintStream(options)) { + BenchmarkCounters.dump(options, scope.out, (System.nanoTime() - startTime) / 1000000000d, jvmciRuntime.collectCounters(), 100); + } } break; } @@ -445,18 +447,19 @@ if (Options.TimedDynamicCounters.getValue(options) > 0) { Thread thread = new Thread() { long lastTime = System.nanoTime(); - PrintStream out = getPrintStream(options); @Override public void run() { - while (true) { - try { - Thread.sleep(Options.TimedDynamicCounters.getValue(options)); - } catch (InterruptedException e) { + try (PrintStreamScope scope = getPrintStream(options)) { + while (true) { + try { + Thread.sleep(Options.TimedDynamicCounters.getValue(options)); + } catch (InterruptedException e) { + } + long time = System.nanoTime(); + dump(options, scope.out, (time - lastTime) / 1000000000d, jvmciRuntime.collectCounters(), 10); + lastTime = time; } - long time = System.nanoTime(); - dump(options, out, (time - lastTime) / 1000000000d, jvmciRuntime.collectCounters(), 10); - lastTime = time; } } }; @@ -472,22 +475,39 @@ public static void shutdown(HotSpotJVMCIRuntime jvmciRuntime, OptionValues options, long compilerStartTime) { if (Options.GenericDynamicCounters.getValue(options)) { - dump(options, getPrintStream(options), (System.nanoTime() - compilerStartTime) / 1000000000d, jvmciRuntime.collectCounters(), 100); + try (PrintStreamScope scope = getPrintStream(options)) { + dump(options, scope.out, (System.nanoTime() - compilerStartTime) / 1000000000d, jvmciRuntime.collectCounters(), 100); + } } } - private static PrintStream getPrintStream(OptionValues options) { - if (Options.BenchmarkCountersFile.getValue(options) != null) { - try { - - File file = new File(Options.BenchmarkCountersFile.getValue(options)); - TTY.println("Writing benchmark counters to '%s'", file.getAbsolutePath()); - return new PrintStream(file); - } catch (IOException e) { - TTY.out().println(e.getMessage()); - TTY.out().println("Fallback to default"); + static class PrintStreamScope implements AutoCloseable { + final PrintStream out; + + PrintStreamScope(OptionValues options) { + PrintStream ps = TTY.out; + if (Options.BenchmarkCountersFile.getValue(options) != null) { + try { + File file = new File(Options.BenchmarkCountersFile.getValue(options)); + TTY.println("Writing benchmark counters to '%s'", file.getAbsolutePath()); + ps = new PrintStream(file); + } catch (IOException e) { + TTY.out().println(e.getMessage()); + TTY.out().println("Fallback to default"); + } + } + this.out = ps; + } + + @Override + public void close() { + if (out != TTY.out) { + this.out.close(); } } - return TTY.out; + } + + private static PrintStreamScope getPrintStream(OptionValues options) { + return new PrintStreamScope(options); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotNodePlugin.java 2019-03-28 07:37:11.952644514 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotNodePlugin.java 2019-03-28 07:37:11.572641978 +0100 @@ -28,8 +28,6 @@ import static jdk.vm.ci.meta.DeoptimizationReason.TransferToInterpreter; import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; -import java.lang.reflect.Field; - import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.StampPair; @@ -56,6 +54,7 @@ import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; import org.graalvm.compiler.nodes.util.ConstantFoldUtil; +import org.graalvm.compiler.serviceprovider.GraalUnsafeAccess; import org.graalvm.compiler.word.Word; import org.graalvm.compiler.word.WordOperationPlugin; import jdk.internal.vm.compiler.word.LocationIdentity; @@ -83,6 +82,7 @@ *
*/ public final class HotSpotNodePlugin implements NodePlugin, TypePlugin { + private static final Unsafe UNSAFE = GraalUnsafeAccess.getUnsafe(); protected final WordOperationPlugin wordOperationPlugin; private final GraalHotSpotVMConfig config; private final HotSpotWordTypes wordTypes; @@ -243,21 +243,5 @@ } private static final LocationIdentity JAVA_THREAD_SHOULD_POST_ON_EXCEPTIONS_FLAG_LOCATION = NamedLocationIdentity.mutable("JavaThread::_should_post_on_exceptions_flag"); - static final Unsafe UNSAFE = initUnsafe(); - - static Unsafe initUnsafe() { - try { - // Fast path when we are trusted. - return Unsafe.getUnsafe(); - } catch (SecurityException se) { - // Slow path when we are not trusted. - try { - Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); - theUnsafe.setAccessible(true); - return (Unsafe) theUnsafe.get(Unsafe.class); - } catch (Exception e) { - throw new RuntimeException("exception while trying to get Unsafe", e); - } - } - } } + --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java 2019-03-28 07:37:12.432647719 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java 2019-03-28 07:37:12.052645183 +0100 @@ -142,8 +142,7 @@ StructuredGraph targetGraph = new StructuredGraph.Builder(graph.getOptions(), graph.getDebug(), AllowAssumptions.YES).method(graph.method()).trackNodeSourcePosition( graph.trackNodeSourcePosition()).build(); - SimplifyingGraphDecoder graphDecoder = new SimplifyingGraphDecoder(runtime.getTarget().arch, targetGraph, context.getMetaAccess(), context.getConstantReflection(), - context.getConstantFieldProvider(), context.getStampProvider(), !ImmutableCode.getValue(graph.getOptions())); + SimplifyingGraphDecoder graphDecoder = new SimplifyingGraphDecoder(runtime.getTarget().arch, targetGraph, context, !ImmutableCode.getValue(graph.getOptions())); graphDecoder.decode(encodedGraph); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/AheadOfTimeVerificationPhase.java 2019-03-28 07:37:12.944651138 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/AheadOfTimeVerificationPhase.java 2019-03-28 07:37:12.564648602 +0100 @@ -44,17 +44,21 @@ public class AheadOfTimeVerificationPhase extends VerifyPhase { @Override - protected boolean verify(StructuredGraph graph, PhaseContext context) { + protected void verify(StructuredGraph graph, PhaseContext context) { for (ConstantNode node : getConstantNodes(graph)) { if (isIllegalObjectConstant(node)) { throw new VerificationError("illegal object constant: " + node); } } - return true; } public static boolean isIllegalObjectConstant(ConstantNode node) { - return isObject(node) && !isNullReference(node) && !isInternedString(node) && !isDirectMethodHandle(node) && !isBoundMethodHandle(node); + return isObject(node) && + !isNullReference(node) && + !isInternedString(node) && + !isDirectMethodHandle(node) && + !isBoundMethodHandle(node) && + !isVarHandle(node); } private static boolean isObject(ConstantNode node) { @@ -79,6 +83,14 @@ return StampTool.typeOrNull(node).getName().startsWith("Ljava/lang/invoke/BoundMethodHandle"); } + private static boolean isVarHandle(ConstantNode node) { + if (!isObject(node)) { + return false; + } + String name = StampTool.typeOrNull(node).getName(); + return name.equals("Ljava/lang/invoke/VarHandle$AccessDescriptor;"); + } + private static boolean isInternedString(ConstantNode node) { if (!isObject(node)) { return false; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java 2019-03-28 07:37:13.460654583 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java 2019-03-28 07:37:13.072651993 +0100 @@ -420,6 +420,8 @@ import org.graalvm.compiler.nodes.java.RegisterFinalizerNode; import org.graalvm.compiler.nodes.java.StoreFieldNode; import org.graalvm.compiler.nodes.java.StoreIndexedNode; +import org.graalvm.compiler.nodes.spi.CoreProviders; +import org.graalvm.compiler.nodes.spi.Replacements; import org.graalvm.compiler.nodes.spi.StampProvider; import org.graalvm.compiler.nodes.type.StampTool; import org.graalvm.compiler.nodes.util.GraphUtil; @@ -714,10 +716,7 @@ this.debug = graph.getDebug(); this.graphBuilderConfig = graphBuilderInstance.graphBuilderConfig; this.optimisticOpts = graphBuilderInstance.optimisticOpts; - this.metaAccess = graphBuilderInstance.metaAccess; - this.stampProvider = graphBuilderInstance.stampProvider; - this.constantReflection = graphBuilderInstance.constantReflection; - this.constantFieldProvider = graphBuilderInstance.constantFieldProvider; + this.providers = graphBuilderInstance.providers; this.stream = new BytecodeStream(code.getCode()); this.profilingInfo = graph.useProfilingInfo() ? code.getProfilingInfo() : null; this.constantPool = code.getConstantPool(); @@ -778,7 +777,7 @@ @SuppressWarnings("try") protected void buildRootMethod() { - FrameStateBuilder startFrameState = new FrameStateBuilder(this, code, graph); + FrameStateBuilder startFrameState = new FrameStateBuilder(this, code, graph, graphBuilderConfig.retainLocalVariables()); startFrameState.initializeForMethodStart(graph.getAssumptions(), graphBuilderConfig.eagerResolving() || intrinsicContext != null, graphBuilderConfig.getPlugins()); try (IntrinsicScope s = intrinsicContext != null ? new IntrinsicScope(this) : null) { @@ -1121,7 +1120,7 @@ AbstractBeginNode dispatchBegin; if (exceptionObject == null) { - ExceptionObjectNode newExceptionObject = graph.add(new ExceptionObjectNode(metaAccess)); + ExceptionObjectNode newExceptionObject = graph.add(new ExceptionObjectNode(getMetaAccess())); dispatchBegin = newExceptionObject; dispatchState.push(JavaKind.Object, dispatchBegin); dispatchState.setRethrowException(true); @@ -1166,7 +1165,7 @@ } protected ValueNode genLoadIndexed(ValueNode array, ValueNode index, GuardingNode boundsCheck, JavaKind kind) { - return LoadIndexedNode.create(graph.getAssumptions(), array, index, boundsCheck, kind, metaAccess, constantReflection); + return LoadIndexedNode.create(graph.getAssumptions(), array, index, boundsCheck, kind, getMetaAccess(), getConstantReflection()); } protected void genStoreIndexed(ValueNode array, ValueNode index, GuardingNode boundsCheck, GuardingNode storeCheck, JavaKind kind, ValueNode value) { @@ -1242,7 +1241,7 @@ } protected ValueNode genNormalizeCompare(ValueNode x, ValueNode y, boolean isUnorderedLess) { - return NormalizeCompareNode.create(x, y, isUnorderedLess, JavaKind.Int, constantReflection); + return NormalizeCompareNode.create(x, y, isUnorderedLess, JavaKind.Int, getConstantReflection()); } protected ValueNode genFloatConvert(FloatConvert op, ValueNode input) { @@ -1273,15 +1272,15 @@ } protected LogicNode genObjectEquals(ValueNode x, ValueNode y) { - return ObjectEqualsNode.create(constantReflection, metaAccess, options, x, y, NodeView.DEFAULT); + return ObjectEqualsNode.create(getConstantReflection(), getMetaAccess(), options, x, y, NodeView.DEFAULT); } protected LogicNode genIntegerEquals(ValueNode x, ValueNode y) { - return IntegerEqualsNode.create(constantReflection, metaAccess, options, null, x, y, NodeView.DEFAULT); + return IntegerEqualsNode.create(getConstantReflection(), getMetaAccess(), options, null, x, y, NodeView.DEFAULT); } protected LogicNode genIntegerLessThan(ValueNode x, ValueNode y) { - return IntegerLessThanNode.create(constantReflection, metaAccess, options, null, x, y, NodeView.DEFAULT); + return IntegerLessThanNode.create(getConstantReflection(), getMetaAccess(), options, null, x, y, NodeView.DEFAULT); } protected ValueNode genUnique(ValueNode x) { @@ -1372,7 +1371,7 @@ return null; } ValueNode length = append(genArrayLength(receiver)); - LogicNode condition = genUnique(IntegerBelowNode.create(constantReflection, metaAccess, options, null, index, length, NodeView.DEFAULT)); + LogicNode condition = genUnique(IntegerBelowNode.create(getConstantReflection(), getMetaAccess(), options, null, index, length, NodeView.DEFAULT)); return emitBytecodeExceptionCheck(condition, true, BytecodeExceptionKind.OUT_OF_BOUNDS, index, length); } @@ -1380,8 +1379,8 @@ if (elementKind != JavaKind.Object || StampTool.isPointerAlwaysNull(value) || !needsExplicitStoreCheckException(array, value)) { return null; } - ValueNode arrayClass = genUnique(LoadHubNode.create(array, stampProvider, metaAccess, constantReflection)); - ValueNode componentHub = append(LoadArrayComponentHubNode.create(arrayClass, stampProvider, metaAccess, constantReflection)); + ValueNode arrayClass = genUnique(LoadHubNode.create(array, getStampProvider(), getMetaAccess(), getConstantReflection())); + ValueNode componentHub = append(LoadArrayComponentHubNode.create(arrayClass, getStampProvider(), getMetaAccess(), getConstantReflection())); LogicNode condition = genUnique(InstanceOfDynamicNode.create(graph.getAssumptions(), getConstantReflection(), componentHub, value, true)); return emitBytecodeExceptionCheck(condition, true, BytecodeExceptionKind.ARRAY_STORE, value); } @@ -1391,7 +1390,7 @@ return null; } ConstantNode zero = ConstantNode.defaultForKind(y.getStackKind(), graph); - LogicNode condition = genUnique(IntegerEqualsNode.create(constantReflection, metaAccess, options, null, y, zero, NodeView.DEFAULT)); + LogicNode condition = genUnique(IntegerEqualsNode.create(getConstantReflection(), getMetaAccess(), options, null, y, zero, NodeView.DEFAULT)); return emitBytecodeExceptionCheck(condition, false, BytecodeExceptionKind.DIVISION_BY_ZERO); } @@ -1400,7 +1399,7 @@ return null; } - BytecodeExceptionNode exception = graph.add(new BytecodeExceptionNode(metaAccess, exceptionKind, arguments)); + BytecodeExceptionNode exception = graph.add(new BytecodeExceptionNode(getMetaAccess(), exceptionKind, arguments)); AbstractBeginNode passingSuccessor = graph.add(new BeginNode()); FixedNode trueSuccessor = passingOnTrue ? passingSuccessor : exception; @@ -1416,7 +1415,7 @@ } protected ValueNode genArrayLength(ValueNode x) { - return ArrayLengthNode.create(x, constantReflection); + return ArrayLengthNode.create(x, getConstantReflection()); } protected void genStoreField(ValueNode receiver, ResolvedJavaField field, ValueNode value) { @@ -1567,7 +1566,7 @@ FrameState stateBefore = createCurrentFrameState(); appendixNode = invokeDynamicPlugin.genAppendixNode(this, cpi, opcode, appendix, stateBefore); } else { - appendixNode = ConstantNode.forConstant(appendix, metaAccess, graph); + appendixNode = ConstantNode.forConstant(appendix, getMetaAccess(), graph); } frameState.push(JavaKind.Object, appendixNode); @@ -1629,10 +1628,7 @@ protected final ProfilingInfo profilingInfo; protected final OptimisticOptimizations optimisticOpts; protected final ConstantPool constantPool; - protected final MetaAccessProvider metaAccess; - private final ConstantReflectionProvider constantReflection; - private final ConstantFieldProvider constantFieldProvider; - private final StampProvider stampProvider; + protected final CoreProviders providers; protected final IntrinsicContext intrinsicContext; @Override @@ -1954,7 +1950,7 @@ } String error(String format, Object... a) { - return String.format(format, a) + String.format("%n\tplugin at %s", plugin.getApplySourceLocation(metaAccess)); + return String.format(format, a) + String.format("%n\tplugin at %s", plugin.getApplySourceLocation(getMetaAccess())); } boolean check(boolean pluginResult) { @@ -2039,11 +2035,12 @@ Mark mark = graph.getMark(); FixedWithNextNode currentLastInstr = lastInstr; ValueNode nonNullReceiver = pluginReceiver.get(); - Stamp methodStamp = stampProvider.createMethodStamp(); - LoadHubNode hub = graph.unique(new LoadHubNode(stampProvider, nonNullReceiver)); + Stamp methodStamp = getStampProvider().createMethodStamp(); + LoadHubNode hub = graph.unique(new LoadHubNode(getStampProvider(), nonNullReceiver)); LoadMethodNode actual = append(new LoadMethodNode(methodStamp, targetMethod, receiverType, method.getDeclaringClass(), hub)); ConstantNode expected = graph.unique(ConstantNode.forConstant(methodStamp, targetMethod.getEncoding(), getMetaAccess())); - LogicNode compare = graph.addOrUniqueWithInputs(CompareNode.createCompareNode(constantReflection, metaAccess, options, null, CanonicalCondition.EQ, actual, expected, NodeView.DEFAULT)); + LogicNode compare = graph.addOrUniqueWithInputs( + CompareNode.createCompareNode(getConstantReflection(), getMetaAccess(), options, null, CanonicalCondition.EQ, actual, expected, NodeView.DEFAULT)); JavaTypeProfile profile = null; if (profilingInfo != null && this.optimisticOpts.useTypeCheckHints(getOptions())) { @@ -2321,7 +2318,7 @@ } return false; } - if (canInlinePartialIntrinsicExit() && InlinePartialIntrinsicExitDuringParsing.getValue(options) && !IS_BUILDING_NATIVE_IMAGE) { + if (canInlinePartialIntrinsicExit()) { // Otherwise inline the original method. Any frame state created // during the inlining will exclude frame(s) in the // intrinsic method (see FrameStateBuilder.create(int bci)). @@ -2384,7 +2381,7 @@ * intrinsic) can be inlined. */ protected boolean canInlinePartialIntrinsicExit() { - return true; + return InlinePartialIntrinsicExitDuringParsing.getValue(options) && !IS_BUILDING_NATIVE_IMAGE && method.getAnnotation(Snippet.class) == null; } private void printInlining(ResolvedJavaMethod targetMethod, ResolvedJavaMethod inlinedMethod, boolean success, String msg) { @@ -2446,7 +2443,7 @@ try (IntrinsicScope s = calleeIntrinsicContext != null && !parsingIntrinsic() ? new IntrinsicScope(this, targetMethod.getSignature().toParameterKinds(!targetMethod.isStatic()), args) : null) { BytecodeParser parser = graphBuilderInstance.createBytecodeParser(graph, this, targetMethod, INVOCATION_ENTRY_BCI, calleeIntrinsicContext); - FrameStateBuilder startFrameState = new FrameStateBuilder(parser, parser.code, graph); + FrameStateBuilder startFrameState = new FrameStateBuilder(parser, parser.code, graph, graphBuilderConfig.retainLocalVariables()); if (!targetMethod.isStatic()) { args[0] = nullCheckedValue(args[0]); } @@ -2679,7 +2676,7 @@ JsrScope scope = currentBlock.getJsrScope(); int retAddress = scope.nextReturnAddress(); ConstantNode returnBciNode = getJsrConstant(retAddress); - LogicNode guard = IntegerEqualsNode.create(constantReflection, metaAccess, options, null, local, returnBciNode, NodeView.DEFAULT); + LogicNode guard = IntegerEqualsNode.create(getConstantReflection(), getMetaAccess(), options, null, local, returnBciNode, NodeView.DEFAULT); guard = graph.addOrUniqueWithInputs(guard); append(new FixedGuardNode(guard, JavaSubroutineMismatch, InvalidateReprofile)); if (!successor.getJsrScope().equals(scope.pop())) { @@ -2731,7 +2728,7 @@ protected ConstantNode appendConstant(JavaConstant constant) { assert constant != null; - return ConstantNode.forConstant(constant, metaAccess, graph); + return ConstantNode.forConstant(constant, getMetaAccess(), graph); } @Override @@ -3602,12 +3599,17 @@ @Override public StampProvider getStampProvider() { - return stampProvider; + return providers.getStampProvider(); } @Override public MetaAccessProvider getMetaAccess() { - return metaAccess; + return providers.getMetaAccess(); + } + + @Override + public Replacements getReplacements() { + return providers.getReplacements(); } @Override @@ -3623,12 +3625,12 @@ @Override public ConstantReflectionProvider getConstantReflection() { - return constantReflection; + return providers.getConstantReflection(); } @Override public ConstantFieldProvider getConstantFieldProvider() { - return constantFieldProvider; + return providers.getConstantFieldProvider(); } /** @@ -3753,7 +3755,7 @@ private JavaKind refineComponentType(ValueNode array, JavaKind kind) { if (kind == JavaKind.Byte) { - JavaType type = array.stamp(NodeView.DEFAULT).javaType(metaAccess); + JavaType type = array.stamp(NodeView.DEFAULT).javaType(getMetaAccess()); if (type.isArray()) { JavaType componentType = type.getComponentType(); if (componentType != null) { @@ -4308,7 +4310,7 @@ } private void genNewPrimitiveArray(int typeCode) { - ResolvedJavaType elementType = metaAccess.lookupJavaType(arrayTypeCodeToClass(typeCode)); + ResolvedJavaType elementType = getMetaAccess().lookupJavaType(arrayTypeCodeToClass(typeCode)); ValueNode length = frameState.pop(JavaKind.Int); for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) { @@ -4492,7 +4494,7 @@ @Override public AbstractBeginNode genExplicitExceptionEdge(BytecodeExceptionKind exceptionKind) { - BytecodeExceptionNode exceptionNode = graph.add(new BytecodeExceptionNode(metaAccess, exceptionKind)); + BytecodeExceptionNode exceptionNode = graph.add(new BytecodeExceptionNode(getMetaAccess(), exceptionKind)); exceptionNode.setStateAfter(createFrameState(bci(), exceptionNode)); AbstractBeginNode exceptionDispatch = handleException(exceptionNode, bci(), false); exceptionNode.setNext(exceptionDispatch); @@ -5113,3 +5115,4 @@ return n == 0 ? "" : format("%" + n + "s", ""); } } + --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java 2019-03-28 07:37:14.036658429 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java 2019-03-28 07:37:13.648655839 +0100 @@ -118,17 +118,18 @@ * @param graph the target graph of Graal nodes created by the builder */ public FrameStateBuilder(GraphBuilderTool tool, ResolvedJavaMethod method, StructuredGraph graph) { - this(tool, new ResolvedJavaMethodBytecode(method), graph); + this(tool, new ResolvedJavaMethodBytecode(method), graph, false); } /** * Creates a new frame state builder for the given code attribute, method and the given target - * graph. + * graph. Additionally specifies if nonLiveLocals should be retained. * * @param code the bytecode in which the frame exists * @param graph the target graph of Graal nodes created by the builder + * @param shouldRetainLocalVariables specifies if nonLiveLocals should be retained in state. */ - public FrameStateBuilder(GraphBuilderTool tool, Bytecode code, StructuredGraph graph) { + public FrameStateBuilder(GraphBuilderTool tool, Bytecode code, StructuredGraph graph, boolean shouldRetainLocalVariables) { this.tool = tool; if (tool instanceof BytecodeParser) { this.parser = (BytecodeParser) tool; @@ -144,7 +145,7 @@ this.monitorIds = EMPTY_MONITOR_ARRAY; this.graph = graph; - this.clearNonLiveLocals = GraalOptions.OptClearNonLiveLocals.getValue(graph.getOptions()); + this.clearNonLiveLocals = GraalOptions.OptClearNonLiveLocals.getValue(graph.getOptions()) && !shouldRetainLocalVariables; this.canVerifyKind = true; } @@ -630,12 +631,12 @@ public void clearNonLiveLocals(BciBlock block, LocalLiveness liveness, boolean liveIn) { /* - * (lstadler) if somebody is tempted to remove/disable this clearing code: it's possible to - * remove it for normal compilations, but not for OSR compilations - otherwise dead object - * slots at the OSR entry aren't cleared. it is also not enough to rely on PiNodes with - * Kind.Illegal, because the conflicting branch might not have been parsed. + * Non-live local clearing is mandatory for the entry block of an OSR compilation so that + * dead object slots at the OSR entry are cleared. It's not sufficient to rely on PiNodes + * with Kind.Illegal, because the conflicting branch might not have been parsed. */ - if (!clearNonLiveLocals) { + boolean isOSREntryBlock = graph.isOSR() && getMethod().equals(graph.method()) && graph.getEntryBCI() == block.startBci; + if (!clearNonLiveLocals && !isOSREntryBlock) { return; } if (liveIn) { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/GraphBuilderPhase.java 2019-03-28 07:37:14.528661713 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/GraphBuilderPhase.java 2019-03-28 07:37:14.148659176 +0100 @@ -24,17 +24,14 @@ package org.graalvm.compiler.java; -import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext; -import org.graalvm.compiler.nodes.spi.StampProvider; +import org.graalvm.compiler.nodes.spi.CoreProviders; import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.tiers.HighTierContext; -import jdk.vm.ci.meta.ConstantReflectionProvider; -import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; /** @@ -55,8 +52,7 @@ @Override protected void run(StructuredGraph graph, HighTierContext context) { - new Instance(context.getMetaAccess(), context.getStampProvider(), context.getConstantReflection(), context.getConstantFieldProvider(), graphBuilderConfig, context.getOptimisticOptimizations(), - null).run(graph); + new Instance(context, graphBuilderConfig, context.getOptimisticOptimizations(), null).run(graph); } public GraphBuilderConfiguration getGraphBuilderConfig() { @@ -66,22 +62,15 @@ // Fully qualified name is a workaround for JDK-8056066 public static class Instance extends org.graalvm.compiler.phases.Phase { - protected final MetaAccessProvider metaAccess; - protected final StampProvider stampProvider; - protected final ConstantReflectionProvider constantReflection; - protected final ConstantFieldProvider constantFieldProvider; + protected final CoreProviders providers; protected final GraphBuilderConfiguration graphBuilderConfig; protected final OptimisticOptimizations optimisticOpts; private final IntrinsicContext initialIntrinsicContext; - public Instance(MetaAccessProvider metaAccess, StampProvider stampProvider, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantFieldProvider, - GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, IntrinsicContext initialIntrinsicContext) { + public Instance(CoreProviders providers, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, IntrinsicContext initialIntrinsicContext) { this.graphBuilderConfig = graphBuilderConfig; this.optimisticOpts = optimisticOpts; - this.metaAccess = metaAccess; - this.stampProvider = stampProvider; - this.constantReflection = constantReflection; - this.constantFieldProvider = constantFieldProvider; + this.providers = providers; this.initialIntrinsicContext = initialIntrinsicContext; } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArithmeticLIRGeneratorTool.java 2019-03-28 07:37:15.040665131 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArithmeticLIRGeneratorTool.java 2019-03-28 07:37:14.656662568 +0100 @@ -24,10 +24,8 @@ package org.graalvm.compiler.lir.aarch64; -import org.graalvm.compiler.lir.Variable; import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; -import jdk.vm.ci.aarch64.AArch64Kind; import jdk.vm.ci.meta.Value; /** @@ -53,6 +51,4 @@ } Value emitRound(Value value, RoundingMode mode); - - void emitCompareOp(AArch64Kind cmpKind, Variable left, Value right); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Call.java 2019-03-28 07:37:15.536668442 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Call.java 2019-03-28 07:37:15.152665879 +0100 @@ -215,7 +215,7 @@ * Offset might not fit into a 28-bit immediate, generate an indirect call with a * 64-bit immediate address which is fixed up by HotSpot. */ - masm.movNativeAddress(scratch, 0L); + masm.movNativeAddress(scratch, 0L, true); masm.blr(scratch); } } else { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Compare.java 2019-03-28 07:37:16.028671727 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Compare.java 2019-03-28 07:37:15.648669191 +0100 @@ -24,22 +24,21 @@ package org.graalvm.compiler.lir.aarch64; +import static jdk.vm.ci.code.ValueUtil.asRegister; +import static jdk.vm.ci.code.ValueUtil.isRegister; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.CONST; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; import static org.graalvm.compiler.lir.LIRValueUtil.asJavaConstant; import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant; -import static jdk.vm.ci.code.ValueUtil.asRegister; -import static jdk.vm.ci.code.ValueUtil.isRegister; -import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.aarch64.AArch64Assembler; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; -import jdk.vm.ci.aarch64.AArch64Kind; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.Value; @@ -53,8 +52,7 @@ public CompareOp(Value x, Value y) { super(TYPE); - assert ((AArch64Kind) x.getPlatformKind()).isInteger() && ((AArch64Kind) y.getPlatformKind()).isInteger(); - assert x.getPlatformKind() == y.getPlatformKind(); + assert x.getPlatformKind() == y.getPlatformKind() : x.getPlatformKind() + " " + y.getPlatformKind(); this.x = x; this.y = y; } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ControlFlow.java 2019-03-28 07:37:16.528675064 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ControlFlow.java 2019-03-28 07:37:16.148672527 +0100 @@ -24,22 +24,24 @@ package org.graalvm.compiler.lir.aarch64; +import static jdk.vm.ci.aarch64.AArch64.lr; import static jdk.vm.ci.code.ValueUtil.asAllocatableValue; import static jdk.vm.ci.code.ValueUtil.asRegister; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; import java.util.function.Function; import jdk.vm.ci.meta.AllocatableValue; import org.graalvm.compiler.asm.Label; -import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.aarch64.AArch64Assembler; import org.graalvm.compiler.asm.aarch64.AArch64Assembler.ConditionFlag; import org.graalvm.compiler.asm.aarch64.AArch64Assembler.ExtendType; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; import org.graalvm.compiler.code.CompilationResult.JumpTable; import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.lir.ConstantValue; @@ -47,6 +49,7 @@ import org.graalvm.compiler.lir.LabelRef; import org.graalvm.compiler.lir.Opcode; import org.graalvm.compiler.lir.StandardOp; +import org.graalvm.compiler.lir.StandardOp.BlockEndOp; import org.graalvm.compiler.lir.SwitchStrategy; import org.graalvm.compiler.lir.SwitchStrategy.BaseSwitchClosure; import org.graalvm.compiler.lir.Variable; @@ -59,6 +62,21 @@ import jdk.vm.ci.meta.Value; public class AArch64ControlFlow { + public static final class ReturnOp extends AArch64BlockEndOp implements BlockEndOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(ReturnOp.class); + @Use({REG, ILLEGAL}) protected Value x; + + public ReturnOp(Value x) { + super(TYPE); + this.x = x; + } + + @Override + protected void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { + crb.frameContext.leave(crb); + masm.ret(lr); + } + } public abstract static class AbstractBranchOp extends AArch64BlockEndOp implements StandardOp.BranchOp { private final LabelRef trueDestination; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java 2019-03-28 07:37:17.032678428 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java 2019-03-28 07:37:16.648675865 +0100 @@ -31,18 +31,25 @@ import static jdk.vm.ci.code.ValueUtil.asStackSlot; import static jdk.vm.ci.code.ValueUtil.isRegister; import static jdk.vm.ci.code.ValueUtil.isStackSlot; +import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.COMPOSITE; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.CONST; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT; +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.LIRInstruction.OperandFlag.UNINITIALIZED; import static org.graalvm.compiler.lir.LIRValueUtil.asJavaConstant; import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant; +import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.asm.aarch64.AArch64Address; +import org.graalvm.compiler.asm.aarch64.AArch64Assembler; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.ScratchRegister; +import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.core.common.spi.LIRKindTool; import org.graalvm.compiler.core.common.type.DataPointerConstant; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.lir.LIRFrameState; @@ -54,6 +61,7 @@ import org.graalvm.compiler.lir.StandardOp.ValueMoveOp; import org.graalvm.compiler.lir.VirtualStackSlot; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.aarch64.AArch64Kind; import jdk.vm.ci.code.MemoryBarriers; @@ -507,10 +515,14 @@ break; case Object: if (input.isNull()) { - masm.mov(dst, 0); + if (crb.mustReplaceWithNullRegister(input)) { + masm.mov(64, dst, crb.nullRegister); + } else { + masm.mov(dst, 0); + } } else if (crb.target.inlineObjects) { crb.recordInlineDataInCode(input); - masm.movNativeAddress(dst, 0xDEADDEADDEADDEADL); + masm.mov(dst, 0xDEADDEADDEADDEADL, true); } else { masm.ldr(64, dst, (AArch64Address) crb.recordDataReferenceInCode(input, 8)); } @@ -561,4 +573,131 @@ return masm.makeAddress(sp, displacement, scratchReg, transferSize, /* allowOverwrite */false); } + public abstract static class PointerCompressionOp extends AArch64LIRInstruction { + + @Def({REG, HINT}) private AllocatableValue result; + @Use({REG, CONST}) private Value input; + @Alive({REG, ILLEGAL, UNINITIALIZED}) private AllocatableValue baseRegister; + + protected final CompressEncoding encoding; + protected final boolean nonNull; + protected final LIRKindTool lirKindTool; + + protected PointerCompressionOp(LIRInstructionClass type, AllocatableValue result, Value input, + AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull, LIRKindTool lirKindTool) { + + super(type); + this.result = result; + this.input = input; + this.baseRegister = baseRegister; + this.encoding = encoding; + this.nonNull = nonNull; + this.lirKindTool = lirKindTool; + } + + public static boolean hasBase(OptionValues options, CompressEncoding encoding) { + return GeneratePIC.getValue(options) || encoding.hasBase(); + } + + public final Value getInput() { + return input; + } + + public final AllocatableValue getResult() { + return result; + } + + protected final Register getResultRegister() { + return asRegister(result); + } + + protected final Register getBaseRegister(CompilationResultBuilder crb) { + return hasBase(crb.getOptions(), encoding) ? asRegister(baseRegister) : Register.None; + } + + protected final int getShift() { + return encoding.getShift(); + } + + protected final void move(CompilationResultBuilder crb, AArch64MacroAssembler masm) { + AArch64Move.move(crb, masm, result, input); + } + } + + public static class CompressPointerOp extends PointerCompressionOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(CompressPointerOp.class); + + public CompressPointerOp(AllocatableValue result, Value input, AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull, LIRKindTool lirKindTool) { + this(TYPE, result, input, baseRegister, encoding, nonNull, lirKindTool); + } + + private CompressPointerOp(LIRInstructionClass type, AllocatableValue result, Value input, + AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull, LIRKindTool lirKindTool) { + + super(type, result, input, baseRegister, encoding, nonNull, lirKindTool); + } + + @Override + protected void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { + Register resultRegister = getResultRegister(); + Register ptr = asRegister(getInput()); + Register base = getBaseRegister(crb); + // result = (ptr - base) >> shift + if (!encoding.hasBase()) { + if (encoding.hasShift()) { + masm.lshr(64, resultRegister, ptr, encoding.getShift()); + } else { + masm.movx(resultRegister, ptr); + } + } else if (nonNull) { + masm.sub(64, resultRegister, ptr, base); + if (encoding.hasShift()) { + masm.lshr(64, resultRegister, resultRegister, encoding.getShift()); + } + } else { + // if ptr is null it still has to be null after compression + masm.cmp(64, ptr, 0); + masm.cmov(64, resultRegister, ptr, base, AArch64Assembler.ConditionFlag.NE); + masm.sub(64, resultRegister, resultRegister, base); + if (encoding.hasShift()) { + masm.lshr(64, resultRegister, resultRegister, encoding.getShift()); + } + } + } + } + + public static class UncompressPointerOp extends PointerCompressionOp { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(UncompressPointerOp.class); + + public UncompressPointerOp(AllocatableValue result, Value input, AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull, LIRKindTool lirKindTool) { + this(TYPE, result, input, baseRegister, encoding, nonNull, lirKindTool); + } + + private UncompressPointerOp(LIRInstructionClass type, AllocatableValue result, Value input, + AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull, LIRKindTool lirKindTool) { + super(type, result, input, baseRegister, encoding, nonNull, lirKindTool); + } + + @Override + protected void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { + Register inputRegister = asRegister(getInput()); + Register resultRegister = getResultRegister(); + Register base = encoding.hasBase() ? getBaseRegister(crb) : null; + + // result = base + (ptr << shift) + if (nonNull || base == null) { + masm.add(64, resultRegister, base == null ? zr : base, inputRegister, AArch64Assembler.ShiftType.LSL, encoding.getShift()); + } else { + // if ptr is null it has to be null after decompression + Label done = new Label(); + if (!resultRegister.equals(inputRegister)) { + masm.mov(32, resultRegister, inputRegister); + } + masm.cbz(32, resultRegister, done); + masm.add(64, resultRegister, base, resultRegister, AArch64Assembler.ShiftType.LSL, encoding.getShift()); + masm.bind(done); + } + } + } + } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayIndexOfOp.java 2019-03-28 07:37:17.536681792 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayIndexOfOp.java 2019-03-28 07:37:17.160679283 +0100 @@ -655,3 +655,4 @@ return ((AMD64) tool.target().arch).getFeatures().contains(cpuFeature); } } + --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Binary.java 2019-03-28 07:37:18.064685318 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Binary.java 2019-03-28 07:37:17.676682727 +0100 @@ -137,6 +137,11 @@ opcode.emit(masm, size, asRegister(result), (AMD64Address) crb.asAddress(input)); } } + + public AMD64RMOp getOpcode() { + return opcode; + } + } /** @@ -263,6 +268,11 @@ } return false; } + + public AMD64RMOp getOpcode() { + return opcode; + } + } /** --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64BinaryConsumer.java 2019-03-28 07:37:18.556688601 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64BinaryConsumer.java 2019-03-28 07:37:18.176686064 +0100 @@ -131,6 +131,10 @@ protected boolean shouldAnnotate() { return false; } + + public AMD64MIOp getOpcode() { + return opcode; + } } /** --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGenerator.java 2019-03-28 07:37:19.056691939 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGenerator.java 2019-03-28 07:37:18.680689428 +0100 @@ -46,6 +46,7 @@ import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; import org.graalvm.compiler.core.common.spi.LIRKindTool; import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.graph.NodeSourcePosition; @@ -386,6 +387,24 @@ return blockScope; } + private final class MatchScope implements DebugCloseable { + + private MatchScope(AbstractBlockBase block) { + currentBlock = block; + } + + @Override + public void close() { + currentBlock = null; + } + + } + + public final DebugCloseable getMatchScope(AbstractBlockBase block) { + MatchScope matchScope = new MatchScope(block); + return matchScope; + } + @Override public void emitIncomingValues(Value[] params) { ((LabelOp) res.getLIR().getLIRforBlock(getCurrentBlock()).get(0)).setIncomingValues(params); @@ -457,7 +476,8 @@ double minDensity = 1 / Math.sqrt(strategy.getAverageEffort()); Optional hasher = hasherFor(keyConstants, minDensity); double hashTableSwitchDensity = hasher.map(h -> keyCount / (double) h.cardinality()).orElse(0d); - long valueRange = keyConstants[keyCount - 1].asLong() - keyConstants[0].asLong() + 1; + // The value range computation below may overflow, so compute it as a long. + long valueRange = (long) keyConstants[keyCount - 1].asInt() - (long) keyConstants[0].asInt() + 1; double tableSwitchDensity = keyCount / (double) valueRange; /* @@ -479,7 +499,7 @@ targets[i] = defaultTarget; } for (int i = 0; i < keyCount; i++) { - int idx = h.hash(keyConstants[i].asLong()); + int idx = h.hash(keyConstants[i].asInt()); keys[idx] = keyConstants[i]; targets[idx] = keyTargets[i]; } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGeneratorTool.java 2019-03-28 07:37:19.556695275 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGeneratorTool.java 2019-03-28 07:37:19.176692740 +0100 @@ -269,11 +269,6 @@ Variable emitArrayEquals(JavaKind kind, Value array1, Value array2, Value length, int constantLength, boolean directPointers); @SuppressWarnings("unused") - default ForeignCallLinkage lookupArrayEqualsStub(JavaKind kind, int constantLength) { - return null; - } - - @SuppressWarnings("unused") default Variable emitArrayEquals(JavaKind kind1, JavaKind kind2, Value array1, Value array2, Value length, int constantLength, boolean directPointers) { throw GraalError.unimplemented("Array.equals with different types substitution is not implemented on this architecture"); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/hashing/HashFunction.java 2019-03-28 07:37:20.048698559 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/hashing/HashFunction.java 2019-03-28 07:37:19.664695997 +0100 @@ -49,7 +49,7 @@ * @param min {@code value} is guaranteed to be greater or equal to this minimum * @return the hash value within int range */ - public abstract int apply(long value, long min); + public abstract int apply(int value, int min); /** * Generates LIR that implements the hash function in terms of value and min. @@ -109,25 +109,25 @@ (gen, prime) -> (val, min) -> gen.emitShr(gen.emitMul(val, prime, false), min)); addWithPrimes("rotateRight(val, prime)", 3, - prime -> (val, min) -> Long.rotateRight(val, prime), + prime -> (val, min) -> Integer.rotateRight(val, prime), (gen, prime) -> (val, min) -> gen.emitRor(val, prime)); addWithPrimes("rotateRight(val, prime) + val", 4, - prime -> (val, min) -> Long.rotateRight(val, prime) + val, + prime -> (val, min) -> Integer.rotateRight(val, prime) + val, (gen, prime) -> (val, min) -> gen.emitAdd(gen.emitRor(val, prime), val, false)); addWithPrimes("rotateRight(val, prime) ^ val", 4, - prime -> (val, min) -> Long.rotateRight(val, prime) ^ val, + prime -> (val, min) -> Integer.rotateRight(val, prime) ^ val, (gen, prime) -> (val, min) -> gen.emitXor(gen.emitRor(val, prime), val)); //@formatter:on } - private static void add(String toString, int effort, BiFunction f, Function> gen) { + private static void add(String toString, int effort, BiFunction f, Function> gen) { instances.add(new HashFunction() { @Override - public int apply(long value, long min) { - return f.apply(value, min).intValue(); + public int apply(int value, int min) { + return f.apply(value, min); } @Override @@ -147,7 +147,7 @@ }); } - private static void addWithPrimes(String toString, int effort, Function> f, + private static void addWithPrimes(String toString, int effort, Function> f, BiFunction> gen) { for (int p : mersennePrimes) { add(toString, effort, f.apply(p), g -> gen.apply(g, g.getLIRGen().emitJavaConstant(JavaConstant.forInt(p)))); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/hashing/Hasher.java 2019-03-28 07:37:20.540701842 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/hashing/Hasher.java 2019-03-28 07:37:20.164699333 +0100 @@ -30,6 +30,7 @@ import java.util.Set; import java.util.TreeSet; +import jdk.vm.ci.meta.JavaKind; import org.graalvm.compiler.lir.gen.ArithmeticLIRGenerator; import jdk.vm.ci.meta.JavaConstant; @@ -51,11 +52,12 @@ * @return an optional hasher */ public static Optional forKeys(JavaConstant[] keys, double minDensity) { + assert checkKeyKind(keys); if (keys.length <= 2) { return Optional.empty(); } else { int maxCardinality = (int) Math.round(keys.length / minDensity); - assertSorted(keys); + assert checkIfSorted(keys); TreeSet candidates = new TreeSet<>(new Comparator() { @Override public int compare(Hasher o1, Hasher o2) { @@ -67,7 +69,7 @@ } } }); - long min = keys[0].asLong(); + int min = keys[0].asInt(); for (HashFunction f : HashFunction.instances()) { for (int cardinality = keys.length; cardinality < maxCardinality; cardinality++) { if (isValid(keys, min, f, cardinality)) { @@ -84,16 +86,28 @@ } } - private static void assertSorted(JavaConstant[] keys) { + private static boolean checkKeyKind(JavaConstant[] keys) { + for (int i = 0; i < keys.length; i++) { + if (keys[i].getJavaKind() != JavaKind.Int) { + throw new AssertionError(String.format("Key at index %d is not an int: %s", i, keys[i])); + } + } + return true; + } + + private static boolean checkIfSorted(JavaConstant[] keys) { for (int i = 1; i < keys.length; i++) { - assert keys[i - 1].asLong() < keys[i].asLong(); + if (keys[i - 1].asInt() >= keys[i].asInt()) { + throw new AssertionError("Keys array is not sorted"); + } } + return true; } - private static boolean isValid(JavaConstant[] keys, long min, HashFunction function, int cardinality) { + private static boolean isValid(JavaConstant[] keys, int min, HashFunction function, int cardinality) { Set seen = new HashSet<>(keys.length); for (JavaConstant key : keys) { - int hash = function.apply(key.asLong(), min) & (cardinality - 1); + int hash = function.apply(key.asInt(), min) & (cardinality - 1); if (!seen.add(hash)) { return false; } @@ -103,9 +117,9 @@ private final HashFunction function; private final int cardinality; - private final long min; + private final int min; - private Hasher(HashFunction function, int cardinality, long min) { + private Hasher(HashFunction function, int cardinality, int min) { this.function = function; this.cardinality = cardinality; this.min = min; @@ -117,7 +131,7 @@ * @param value the value to be hashed * @return the hash value */ - public int hash(long value) { + public int hash(int value) { return function.apply(value, min) & (cardinality - 1); } @@ -129,7 +143,7 @@ * @return the hashed lir value */ public Value hash(Value value, ArithmeticLIRGenerator gen) { - Value h = function.gen(value, gen.getLIRGen().emitJavaConstant(JavaConstant.forLong(min)), gen); + Value h = function.gen(value, gen.getLIRGen().emitJavaConstant(JavaConstant.forInt(min)), gen); return gen.emitAnd(h, gen.getLIRGen().emitJavaConstant(JavaConstant.forInt(cardinality - 1))); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/SimplifyingGraphDecoder.java 2019-03-28 07:37:21.060705313 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/SimplifyingGraphDecoder.java 2019-03-28 07:37:20.676702750 +0100 @@ -44,7 +44,7 @@ import org.graalvm.compiler.nodes.java.ArrayLengthNode; import org.graalvm.compiler.nodes.java.LoadFieldNode; import org.graalvm.compiler.nodes.java.LoadIndexedNode; -import org.graalvm.compiler.nodes.spi.StampProvider; +import org.graalvm.compiler.nodes.spi.CoreProviders; import org.graalvm.compiler.nodes.util.GraphUtil; import org.graalvm.compiler.options.OptionValues; @@ -61,10 +61,7 @@ */ public class SimplifyingGraphDecoder extends GraphDecoder { - protected final MetaAccessProvider metaAccess; - protected final ConstantReflectionProvider constantReflection; - protected final ConstantFieldProvider constantFieldProvider; - protected final StampProvider stampProvider; + protected final CoreProviders providers; protected final boolean canonicalizeReads; protected final CanonicalizerTool canonicalizerTool; @@ -85,17 +82,17 @@ @Override public MetaAccessProvider getMetaAccess() { - return metaAccess; + return providers.getMetaAccess(); } @Override public ConstantReflectionProvider getConstantReflection() { - return constantReflection; + return providers.getConstantReflection(); } @Override public ConstantFieldProvider getConstantFieldProvider() { - return constantFieldProvider; + return providers.getConstantFieldProvider(); } @Override @@ -135,14 +132,9 @@ } } - public SimplifyingGraphDecoder(Architecture architecture, StructuredGraph graph, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, - ConstantFieldProvider constantFieldProvider, StampProvider stampProvider, - boolean canonicalizeReads) { + public SimplifyingGraphDecoder(Architecture architecture, StructuredGraph graph, CoreProviders providers, boolean canonicalizeReads) { super(architecture, graph); - this.metaAccess = metaAccess; - this.constantReflection = constantReflection; - this.constantFieldProvider = constantFieldProvider; - this.stampProvider = stampProvider; + this.providers = providers; this.canonicalizeReads = canonicalizeReads; this.canonicalizerTool = new PECanonicalizerTool(graph.getAssumptions(), graph.getOptions()); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/JavaWriteNode.java 2019-03-28 07:37:21.540708516 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/JavaWriteNode.java 2019-03-28 07:37:21.160705981 +0100 @@ -24,6 +24,8 @@ package org.graalvm.compiler.nodes.extended; +import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.StateSplit; @@ -72,4 +74,9 @@ public boolean isCompressible() { return compressible; } + + @Override + public Stamp getAccessStamp() { + return StampFactory.forKind(writeKind); + } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderConfiguration.java 2019-03-28 07:37:22.064712012 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderConfiguration.java 2019-03-28 07:37:21.684709477 +0100 @@ -201,6 +201,7 @@ private final List skippedExceptionTypes; private final boolean insertFullInfopoints; private final boolean trackNodeSourcePosition; + private final boolean retainLocalVariables; private final Plugins plugins; public enum BytecodeExceptionMode { @@ -229,6 +230,7 @@ boolean omitAssertions, boolean insertFullInfopoints, boolean trackNodeSourcePosition, + boolean retainLocalVariables, List skippedExceptionTypes, Plugins plugins) { this.eagerResolving = eagerResolving; @@ -237,6 +239,7 @@ this.omitAssertions = omitAssertions; this.insertFullInfopoints = insertFullInfopoints; this.trackNodeSourcePosition = trackNodeSourcePosition; + this.retainLocalVariables = retainLocalVariables; this.skippedExceptionTypes = skippedExceptionTypes; this.plugins = plugins; } @@ -255,6 +258,7 @@ omitAssertions, insertFullInfopoints, trackNodeSourcePosition, + retainLocalVariables, skippedExceptionTypes, newPlugins); return result; @@ -274,6 +278,7 @@ omitAssertions, insertFullInfopoints, trackNodeSourcePosition, + retainLocalVariables, skippedExceptionTypes, plugins); } @@ -286,6 +291,7 @@ omitAssertions, insertFullInfopoints, trackNodeSourcePosition, + retainLocalVariables, skippedExceptionTypes, plugins); } @@ -298,6 +304,7 @@ omitAssertions, insertFullInfopoints, trackNodeSourcePosition, + retainLocalVariables, Collections.unmodifiableList(Arrays.asList(newSkippedExceptionTypes)), plugins); } @@ -309,6 +316,7 @@ omitAssertions, insertFullInfopoints, trackNodeSourcePosition, + retainLocalVariables, skippedExceptionTypes, plugins); } @@ -321,6 +329,7 @@ newOmitAssertions, insertFullInfopoints, trackNodeSourcePosition, + retainLocalVariables, skippedExceptionTypes, plugins); } @@ -333,6 +342,7 @@ omitAssertions, newInsertFullInfopoints, trackNodeSourcePosition, + retainLocalVariables, skippedExceptionTypes, plugins); } @@ -345,6 +355,20 @@ omitAssertions, insertFullInfopoints, newTrackNodeSourcePosition, + retainLocalVariables, + skippedExceptionTypes, + plugins); + } + + public GraphBuilderConfiguration withRetainLocalVariables(boolean newRetainLocalVariables) { + return new GraphBuilderConfiguration( + eagerResolving, + unresolvedIsError, + bytecodeExceptionMode, + omitAssertions, + insertFullInfopoints, + trackNodeSourcePosition, + newRetainLocalVariables, skippedExceptionTypes, plugins); } @@ -369,6 +393,10 @@ return trackNodeSourcePosition; } + public boolean retainLocalVariables() { + return retainLocalVariables; + } + public boolean insertFullInfopoints() { return insertFullInfopoints; } @@ -381,6 +409,7 @@ /* omitAssertions: */ false, /* insertFullInfopoints: */ false, /* trackNodeSourcePosition: */ false, + /* retainLocalVariables */ false, Collections.emptyList(), plugins); } @@ -393,6 +422,7 @@ /* omitAssertions: */ false, /* insertFullInfopoints: */ false, /* trackNodeSourcePosition: */ false, + /* retainLocalVariables */ false, Collections.emptyList(), plugins); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderTool.java 2019-03-28 07:37:22.564715349 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderTool.java 2019-03-28 07:37:22.184712813 +0100 @@ -28,6 +28,7 @@ import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.spi.Replacements; import org.graalvm.compiler.nodes.spi.StampProvider; import org.graalvm.compiler.options.OptionValues; @@ -52,6 +53,8 @@ MetaAccessProvider getMetaAccess(); + Replacements getReplacements(); + default Assumptions getAssumptions() { return getGraph().getAssumptions(); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/NodePlugin.java 2019-03-28 07:37:23.064718685 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/NodePlugin.java 2019-03-28 07:37:22.684716150 +0100 @@ -243,3 +243,4 @@ return false; } } + --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/AbstractWriteNode.java 2019-03-28 07:37:23.580722129 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/AbstractWriteNode.java 2019-03-28 07:37:23.200719594 +0100 @@ -27,6 +27,7 @@ import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; +import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; @@ -90,4 +91,6 @@ updateUsages(lastLocationAccess, newLla); lastLocationAccess = newLla; } + + public abstract Stamp getAccessStamp(); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/LoweringTool.java 2019-03-28 07:37:24.084725492 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/LoweringTool.java 2019-03-28 07:37:23.704722956 +0100 @@ -40,6 +40,8 @@ public interface LoweringTool { + CoreProviders getProviders(); + MetaAccessProvider getMetaAccess(); LoweringProvider getLowerer(); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/NodeLIRBuilderTool.java 2019-03-28 07:37:24.564728694 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/NodeLIRBuilderTool.java 2019-03-28 07:37:24.188726185 +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 @@ -28,6 +28,7 @@ import java.util.List; import org.graalvm.compiler.core.common.cfg.BlockMap; +import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeSourcePosition; @@ -96,4 +97,11 @@ } void emitReadExceptionObject(ValueNode node); + + @SuppressWarnings("unused") + default ForeignCallLinkage lookupGraalStub(ValueNode valueNode) { + return null; + } + + void matchBlock(Block b, StructuredGraph graph, StructuredGraph.ScheduleResult blockMap); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionsParser.java 2019-03-28 07:37:25.052731951 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionsParser.java 2019-03-28 07:37:24.676729442 +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 @@ -36,6 +36,8 @@ import jdk.internal.vm.compiler.collections.EconomicMap; import jdk.internal.vm.compiler.collections.MapCursor; +import jdk.vm.ci.services.Services; + /** * This class contains methods for parsing Graal options and matching them against a set of * {@link OptionDescriptors}. The {@link OptionDescriptors} are loaded via a {@link ServiceLoader}. @@ -51,7 +53,7 @@ if (IS_IN_NATIVE_IMAGE || cachedOptionDescriptors != null) { return cachedOptionDescriptors; } - boolean java8OrEarlier = System.getProperty("java.specification.version").compareTo("1.9") < 0; + boolean java8OrEarlier = Services.getSavedProperties().get("java.specification.version").compareTo("1.9") < 0; ClassLoader loader; if (java8OrEarlier) { // On JDK 8, Graal and its extensions are loaded by same class loader. --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LoweringPhase.java 2019-03-28 07:37:25.552735287 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LoweringPhase.java 2019-03-28 07:37:25.172732751 +0100 @@ -38,6 +38,7 @@ import java.util.List; import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; +import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.debug.GraalError; @@ -68,6 +69,7 @@ import org.graalvm.compiler.nodes.extended.GuardedNode; import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; +import org.graalvm.compiler.nodes.spi.CoreProviders; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringProvider; import org.graalvm.compiler.nodes.spi.LoweringTool; @@ -144,6 +146,11 @@ } @Override + public CoreProviders getProviders() { + return context; + } + + @Override public ConstantReflectionProvider getConstantReflection() { return context.getConstantReflection(); } @@ -168,6 +175,10 @@ return context.getReplacements(); } + public ForeignCallsProvider getForeignCalls() { + return context.getForeignCalls(); + } + @Override public AnchoringNode getCurrentGuardAnchor() { return guardAnchor; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ProfileCompiledMethodsPhase.java 2019-03-28 07:37:26.032738490 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ProfileCompiledMethodsPhase.java 2019-03-28 07:37:25.656735981 +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 @@ -69,6 +69,8 @@ import org.graalvm.compiler.phases.Phase; import org.graalvm.compiler.phases.schedule.SchedulePhase; +import jdk.vm.ci.services.Services; + /** * This phase add counters for the dynamically executed number of nodes. Incrementing the counter * for each node would be too costly, so this phase takes the compromise that it trusts split @@ -87,9 +89,17 @@ private static final String GROUP_NAME_WITHOUT = "~profiled weight (invoke-free sections)"; private static final String GROUP_NAME_INVOKES = "~profiled invokes"; - private static final boolean WITH_SECTION_HEADER = Boolean.parseBoolean(System.getProperty("ProfileCompiledMethodsPhase.WITH_SECTION_HEADER", "false")); - private static final boolean WITH_INVOKE_FREE_SECTIONS = Boolean.parseBoolean(System.getProperty("ProfileCompiledMethodsPhase.WITH_FREE_SECTIONS", "false")); - private static final boolean WITH_INVOKES = Boolean.parseBoolean(System.getProperty("ProfileCompiledMethodsPhase.WITH_INVOKES", "true")); + private static String getProperty(String name, String def) { + String value = Services.getSavedProperties().get(name); + if (value == null) { + return def; + } + return value; + } + + private static final boolean WITH_SECTION_HEADER = Boolean.parseBoolean(getProperty("ProfileCompiledMethodsPhase.WITH_SECTION_HEADER", "false")); + private static final boolean WITH_INVOKE_FREE_SECTIONS = Boolean.parseBoolean(getProperty("ProfileCompiledMethodsPhase.WITH_FREE_SECTIONS", "false")); + private static final boolean WITH_INVOKES = Boolean.parseBoolean(getProperty("ProfileCompiledMethodsPhase.WITH_INVOKES", "true")); @Override protected void run(StructuredGraph graph) { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java 2019-03-28 07:37:26.524741771 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java 2019-03-28 07:37:26.144739236 +0100 @@ -154,6 +154,8 @@ return "it is marked non-inlinable"; } else if (countRecursiveInlining(method) > MaximumRecursiveInlining.getValue(options)) { return "it exceeds the maximum recursive inlining depth"; + } else if (!method.hasBytecodes()) { + return "it has no bytecodes to inline"; } else { if (new OptimisticOptimizations(rootGraph.getProfilingInfo(method), options).lessOptimisticThan(context.getOptimisticOptimizations())) { return "the callee uses less optimistic optimizations than caller"; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/VerifyPhase.java 2019-03-28 07:37:27.040745214 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/VerifyPhase.java 2019-03-28 07:37:26.652742625 +0100 @@ -26,11 +26,12 @@ import org.graalvm.compiler.nodes.StructuredGraph; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaType; + /*** - * This phase serves as a verification, in order to check the graph for certain properties. The - * {@link #verify(StructuredGraph, Object)} method will be used as an assertion, and implements the - * actual check. Instead of returning false, it is also valid to throw an {@link VerificationError} - * in the implemented {@link #verify(StructuredGraph, Object)} method. + * Verifies a {@linkplain #verify graph} or {@linkplain #verifyClass class} against one or more + * invariants. */ public abstract class VerifyPhase extends BasePhase { @@ -55,13 +56,23 @@ @Override protected final void run(StructuredGraph graph, C context) { - assert verify(graph, context); + verify(graph, context); } /** - * Performs the actual verification. + * Checks {@code graph} against some invariants. * * @throws VerificationError if the verification fails */ - protected abstract boolean verify(StructuredGraph graph, C context); + protected abstract void verify(StructuredGraph graph, C context); + + /** + * Checks {@code clazz} against some invariants. + * + * @param clazz the class to verify + * @param metaAccess an object to get a {@link ResolvedJavaType} for {@code clazz} + * @throws VerificationError if the class violates some invariant + */ + public void verifyClass(Class clazz, MetaAccessProvider metaAccess) { + } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/tiers/PhaseContext.java 2019-03-28 07:37:27.548748602 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/tiers/PhaseContext.java 2019-03-28 07:37:27.164746041 +0100 @@ -25,66 +25,55 @@ package org.graalvm.compiler.phases.tiers; import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; +import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; +import org.graalvm.compiler.nodes.spi.CoreProviders; import org.graalvm.compiler.nodes.spi.LoweringProvider; import org.graalvm.compiler.nodes.spi.Replacements; import org.graalvm.compiler.nodes.spi.StampProvider; -import org.graalvm.compiler.phases.util.Providers; import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.MetaAccessProvider; -import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; -public class PhaseContext { +public class PhaseContext implements CoreProviders { + + private final CoreProviders providers; - private final MetaAccessProvider metaAccess; - private final ConstantReflectionProvider constantReflection; - private final ConstantFieldProvider constantFieldProvider; - private final LoweringProvider lowerer; - private final Replacements replacements; - private final StampProvider stampProvider; - private final ForeignCallsProvider foreignCalls; - - public PhaseContext(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantFieldProvider, LoweringProvider lowerer, Replacements replacements, - StampProvider stampProvider, ForeignCallsProvider foreignCalls) { - this.metaAccess = metaAccess; - this.constantReflection = constantReflection; - this.constantFieldProvider = constantFieldProvider; - this.lowerer = lowerer; - this.replacements = replacements; - this.stampProvider = stampProvider; - this.foreignCalls = foreignCalls; - } - - public PhaseContext(Providers providers) { - this(providers.getMetaAccess(), providers.getConstantReflection(), providers.getConstantFieldProvider(), providers.getLowerer(), providers.getReplacements(), providers.getStampProvider(), - providers.getForeignCalls()); + public PhaseContext(CoreProviders providers) { + this.providers = providers; } + @Override public MetaAccessProvider getMetaAccess() { - return metaAccess; + return providers.getMetaAccess(); } + @Override public ConstantReflectionProvider getConstantReflection() { - return constantReflection; + return providers.getConstantReflection(); } + @Override public ConstantFieldProvider getConstantFieldProvider() { - return constantFieldProvider; + return providers.getConstantFieldProvider(); } + @Override public LoweringProvider getLowerer() { - return lowerer; + return providers.getLowerer(); } + @Override public Replacements getReplacements() { - return replacements; + return providers.getReplacements(); } + @Override public StampProvider getStampProvider() { - return stampProvider; + return providers.getStampProvider(); } + @Override public ForeignCallsProvider getForeignCalls() { - return foreignCalls; + return providers.getForeignCalls(); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/Providers.java 2019-03-28 07:37:28.080752152 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/Providers.java 2019-03-28 07:37:27.696749590 +0100 @@ -27,6 +27,7 @@ import org.graalvm.compiler.core.common.spi.CodeGenProviders; import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; +import org.graalvm.compiler.nodes.spi.CoreProvidersImpl; import org.graalvm.compiler.nodes.spi.LoweringProvider; import org.graalvm.compiler.nodes.spi.Replacements; import org.graalvm.compiler.nodes.spi.StampProvider; @@ -39,27 +40,14 @@ /** * A set of providers, some of which may not be present (i.e., null). */ -public class Providers implements CodeGenProviders { +public class Providers extends CoreProvidersImpl implements CodeGenProviders { - private final MetaAccessProvider metaAccess; private final CodeCacheProvider codeCache; - private final LoweringProvider lowerer; - private final ConstantReflectionProvider constantReflection; - private final ConstantFieldProvider constantFieldProvider; - private final ForeignCallsProvider foreignCalls; - private final Replacements replacements; - private final StampProvider stampProvider; public Providers(MetaAccessProvider metaAccess, CodeCacheProvider codeCache, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantFieldProvider, ForeignCallsProvider foreignCalls, LoweringProvider lowerer, Replacements replacements, StampProvider stampProvider) { - this.metaAccess = metaAccess; + super(metaAccess, constantReflection, constantFieldProvider, lowerer, replacements, stampProvider, foreignCalls); this.codeCache = codeCache; - this.constantReflection = constantReflection; - this.constantFieldProvider = constantFieldProvider; - this.foreignCalls = foreignCalls; - this.lowerer = lowerer; - this.replacements = replacements; - this.stampProvider = stampProvider; } public Providers(Providers copyFrom) { @@ -73,41 +61,10 @@ } @Override - public MetaAccessProvider getMetaAccess() { - return metaAccess; - } - - @Override public CodeCacheProvider getCodeCache() { return codeCache; } - @Override - public ForeignCallsProvider getForeignCalls() { - return foreignCalls; - } - - public LoweringProvider getLowerer() { - return lowerer; - } - - @Override - public ConstantReflectionProvider getConstantReflection() { - return constantReflection; - } - - public ConstantFieldProvider getConstantFieldProvider() { - return constantFieldProvider; - } - - public Replacements getReplacements() { - return replacements; - } - - public StampProvider getStampProvider() { - return stampProvider; - } - public Providers copyWith(MetaAccessProvider substitution) { assert this.getClass() == Providers.class : "must override"; return new Providers(substitution, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, stampProvider); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinterObserver.java 2019-03-28 07:37:28.592755567 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinterObserver.java 2019-03-28 07:37:28.208753006 +0100 @@ -64,6 +64,7 @@ import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.meta.JavaMethod; import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.services.Services; /** * Observes compilation events and uses {@link CFGPrinter} to produce a control flow graph for the @@ -256,11 +257,19 @@ static { DisassemblerProvider selected = null; + String arch = Services.getSavedProperties().get("os.arch"); for (DisassemblerProvider d : GraalServices.load(DisassemblerProvider.class)) { String name = d.getName().toLowerCase(); - if (name.contains("hcf") || name.contains("hexcodefile")) { - selected = d; - break; + if (arch.equals("aarch64")) { + if (name.contains("hsdis-objdump")) { + selected = d; + break; + } + } else { + if (name.contains("hcf") || name.contains("hexcodefile")) { + selected = d; + break; + } } } if (selected == null) { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinterDumpHandler.java 2019-03-28 07:37:29.108759009 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinterDumpHandler.java 2019-03-28 07:37:28.720756421 +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 @@ -52,6 +52,7 @@ import jdk.vm.ci.meta.JavaMethod; import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.services.Services; //JaCoCo Exclude @@ -86,7 +87,7 @@ this.printerSupplier = printerSupplier; /* Add the JVM and Java arguments to the graph properties to help identify it. */ this.jvmArguments = jvmArguments(); - this.sunJavaCommand = System.getProperty("sun.java.command"); + this.sunJavaCommand = Services.getSavedProperties().get("sun.java.command"); } private static String jvmArguments() { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java 2019-03-28 07:37:29.600762292 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java 2019-03-28 07:37:29.220759756 +0100 @@ -59,14 +59,16 @@ public class AArch64GraphBuilderPlugins { - public static void register(Plugins plugins, BytecodeProvider bytecodeProvider, boolean explicitUnsafeNullChecks) { + public static void register(Plugins plugins, BytecodeProvider bytecodeProvider, boolean explicitUnsafeNullChecks, boolean registerMathPlugins) { InvocationPlugins invocationPlugins = plugins.getInvocationPlugins(); invocationPlugins.defer(new Runnable() { @Override public void run() { registerIntegerLongPlugins(invocationPlugins, AArch64IntegerSubstitutions.class, JavaKind.Int, bytecodeProvider); registerIntegerLongPlugins(invocationPlugins, AArch64LongSubstitutions.class, JavaKind.Long, bytecodeProvider); - registerMathPlugins(invocationPlugins); + if (registerMathPlugins) { + registerMathPlugins(invocationPlugins); + } registerStringLatin1Plugins(invocationPlugins, bytecodeProvider); registerStringUTF16Plugins(invocationPlugins, bytecodeProvider); registerUnsafePlugins(invocationPlugins, bytecodeProvider); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java 2019-03-28 07:37:30.088765547 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java 2019-03-28 07:37:29.712763038 +0100 @@ -31,6 +31,7 @@ import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.SourceLanguagePositionProvider; import org.graalvm.compiler.java.GraphBuilderPhase; +import org.graalvm.compiler.loop.phases.ConvertDeoptimizeToGuardPhase; import org.graalvm.compiler.nodes.EncodedGraph; import org.graalvm.compiler.nodes.GraphEncoder; import org.graalvm.compiler.nodes.StructuredGraph; @@ -44,7 +45,6 @@ import org.graalvm.compiler.nodes.graphbuilderconf.ParameterPlugin; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.common.CanonicalizerPhase; -import org.graalvm.compiler.loop.phases.ConvertDeoptimizeToGuardPhase; import org.graalvm.compiler.phases.tiers.PhaseContext; import org.graalvm.compiler.phases.util.Providers; @@ -67,7 +67,7 @@ AllowAssumptions allowAssumptions, LoopExplosionPlugin loopExplosionPlugin, InvocationPlugins invocationPlugins, InlineInvokePlugin[] inlineInvokePlugins, ParameterPlugin parameterPlugin, NodePlugin[] nodePlugins, ResolvedJavaMethod callInlinedMethod, SourceLanguagePositionProvider sourceLanguagePositionProvider) { - super(architecture, graph, providers.getMetaAccess(), providers.getConstantReflection(), providers.getConstantFieldProvider(), providers.getStampProvider(), loopExplosionPlugin, + super(architecture, graph, providers, loopExplosionPlugin, invocationPlugins, inlineInvokePlugins, parameterPlugin, nodePlugins, callInlinedMethod, sourceLanguagePositionProvider); this.providers = providers; @@ -78,8 +78,7 @@ } protected GraphBuilderPhase.Instance createGraphBuilderPhaseInstance(IntrinsicContext initialIntrinsicContext) { - return new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), providers.getConstantReflection(), providers.getConstantFieldProvider(), graphBuilderConfig, - optimisticOpts, initialIntrinsicContext); + return new GraphBuilderPhase.Instance(providers, graphBuilderConfig, optimisticOpts, initialIntrinsicContext); } @SuppressWarnings("try") --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ConstantStringIndexOfSnippets.java 2019-03-28 07:37:30.592768908 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ConstantStringIndexOfSnippets.java 2019-03-28 07:37:30.208766347 +0100 @@ -25,6 +25,7 @@ package org.graalvm.compiler.replacements; import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER; +import static org.graalvm.compiler.serviceprovider.GraalUnsafeAccess.getUnsafe; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.Fold.InjectedParameter; @@ -44,8 +45,11 @@ import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.MetaAccessProvider; +import sun.misc.Unsafe; public class ConstantStringIndexOfSnippets implements Snippets { + private static final Unsafe UNSAFE = getUnsafe(); + public static class Templates extends AbstractTemplates { private final SnippetInfo indexOfConstant = snippet(ConstantStringIndexOfSnippets.class, "indexOfConstant"); @@ -157,10 +161,10 @@ return 0; } long base = metaAccess.getArrayBaseOffset(JavaKind.Byte); - char lastChar = UnsafeAccess.UNSAFE.getChar(target, base + (c - 1) * 2); + char lastChar = UNSAFE.getChar(target, base + (c - 1) * 2); int md2 = c; for (int i = 0; i < c - 1; i++) { - char currChar = UnsafeAccess.UNSAFE.getChar(target, base + i * 2); + char currChar = UNSAFE.getChar(target, base + i * 2); if (currChar == lastChar) { md2 = (c - 1) - i; } @@ -174,7 +178,7 @@ int i; long base = metaAccess.getArrayBaseOffset(JavaKind.Byte); for (i = 0; i < c - 1; i++) { - char currChar = UnsafeAccess.UNSAFE.getChar(s, base + i * 2); + char currChar = UNSAFE.getChar(s, base + i * 2); cache |= (1 << (currChar & 63)); } return cache; @@ -212,10 +216,10 @@ int sourceEnd = sourceCount - targetCountLess1; long base = charArrayBaseOffset(INJECTED); - int lastChar = UnsafeAccess.UNSAFE.getChar(target, base + targetCountLess1 * 2); + int lastChar = UNSAFE.getChar(target, base + targetCountLess1 * 2); outer_loop: for (long i = sourceOffset + fromIndex; i < sourceEnd;) { - int src = UnsafeAccess.UNSAFE.getChar(source, base + (i + targetCountLess1) * 2); + int src = UNSAFE.getChar(source, base + (i + targetCountLess1) * 2); if (src == lastChar) { // With random strings and a 4-character alphabet, // reverse matching at this point sets up 0.8% fewer @@ -229,8 +233,8 @@ ExplodeLoopNode.explodeLoop(); } for (long j = 0; j < targetCountLess1; j++) { - char sourceChar = UnsafeAccess.UNSAFE.getChar(source, base + (i + j) * 2); - if (UnsafeAccess.UNSAFE.getChar(target, base + (targetOffset + j) * 2) != sourceChar) { + char sourceChar = UNSAFE.getChar(source, base + (i + j) * 2); + if (UNSAFE.getChar(target, base + (targetOffset + j) * 2) != sourceChar) { if ((cache & (1 << sourceChar)) == 0) { if (md2 < j + 1) { i += j + 1; @@ -270,10 +274,10 @@ int sourceEnd = sourceCount - targetCountLess1; long base = byteArrayBaseOffset(INJECTED); - int lastChar = UnsafeAccess.UNSAFE.getChar(target, base + targetCountLess1 * 2); + int lastChar = UNSAFE.getChar(target, base + targetCountLess1 * 2); outer_loop: for (long i = fromIndex; i < sourceEnd;) { - int src = UnsafeAccess.UNSAFE.getChar(source, base + (i + targetCountLess1) * 2); + int src = UNSAFE.getChar(source, base + (i + targetCountLess1) * 2); if (src == lastChar) { // With random strings and a 4-character alphabet, // reverse matching at this point sets up 0.8% fewer @@ -287,8 +291,8 @@ ExplodeLoopNode.explodeLoop(); } for (long j = 0; j < targetCountLess1; j++) { - char sourceChar = UnsafeAccess.UNSAFE.getChar(source, base + (i + j) * 2); - if (UnsafeAccess.UNSAFE.getChar(target, base + j * 2) != sourceChar) { + char sourceChar = UNSAFE.getChar(source, base + (i + j) * 2); + if (UNSAFE.getChar(target, base + j * 2) != sourceChar) { if ((cache & (1 << sourceChar)) == 0) { if (md2 < j + 1) { i += j + 1; @@ -328,10 +332,10 @@ int sourceEnd = sourceCount - targetCountLess1; long base = byteArrayBaseOffset(INJECTED); - int lastByte = UnsafeAccess.UNSAFE.getByte(target, base + targetCountLess1); + int lastByte = UNSAFE.getByte(target, base + targetCountLess1); outer_loop: for (long i = fromIndex; i < sourceEnd;) { - int src = UnsafeAccess.UNSAFE.getByte(source, base + i + targetCountLess1); + int src = UNSAFE.getByte(source, base + i + targetCountLess1); if (src == lastByte) { // With random strings and a 4-character alphabet, // reverse matching at this point sets up 0.8% fewer @@ -345,8 +349,8 @@ ExplodeLoopNode.explodeLoop(); } for (long j = 0; j < targetCountLess1; j++) { - byte sourceByte = UnsafeAccess.UNSAFE.getByte(source, base + i + j); - if (UnsafeAccess.UNSAFE.getByte(target, base + j) != sourceByte) { + byte sourceByte = UNSAFE.getByte(source, base + i + j); + if (UNSAFE.getByte(target, base + j) != sourceByte) { if ((cache & (1 << sourceByte)) == 0) { if (md2 < j + 1) { i += j + 1; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/GraphKit.java 2019-03-28 07:37:31.108772349 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/GraphKit.java 2019-03-28 07:37:30.720769762 +0100 @@ -68,6 +68,7 @@ import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext; import org.graalvm.compiler.nodes.java.ExceptionObjectNode; import org.graalvm.compiler.nodes.java.MethodCallTargetNode; +import org.graalvm.compiler.nodes.spi.Replacements; import org.graalvm.compiler.nodes.spi.StampProvider; import org.graalvm.compiler.nodes.type.StampTool; import org.graalvm.compiler.phases.OptimisticOptimizations; @@ -152,6 +153,11 @@ } @Override + public Replacements getReplacements() { + return providers.getReplacements(); + } + + @Override public StampProvider getStampProvider() { return providers.getStampProvider(); } @@ -355,7 +361,6 @@ public void inline(InvokeNode invoke, String reason, String phase) { ResolvedJavaMethod method = ((MethodCallTargetNode) invoke.callTarget()).targetMethod(); - MetaAccessProvider metaAccess = providers.getMetaAccess(); Plugins plugins = new Plugins(graphBuilderPlugins); GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(plugins); @@ -366,9 +371,7 @@ calleeGraph = new StructuredGraph.Builder(invoke.getOptions(), invoke.getDebug()).method(method).trackNodeSourcePosition(invoke.graph().trackNodeSourcePosition()).setIsSubstitution( true).build(); IntrinsicContext initialReplacementContext = new IntrinsicContext(method, method, providers.getReplacements().getDefaultReplacementBytecodeProvider(), INLINE_AFTER_PARSING); - GraphBuilderPhase.Instance instance = createGraphBuilderInstance(metaAccess, providers.getStampProvider(), providers.getConstantReflection(), providers.getConstantFieldProvider(), config, - OptimisticOptimizations.NONE, - initialReplacementContext); + GraphBuilderPhase.Instance instance = createGraphBuilderInstance(providers, config, OptimisticOptimizations.NONE, initialReplacementContext); instance.apply(calleeGraph); } @@ -379,9 +382,9 @@ InliningUtil.inline(invoke, calleeGraph, false, method, reason, phase); } - protected GraphBuilderPhase.Instance createGraphBuilderInstance(MetaAccessProvider metaAccess, StampProvider stampProvider, ConstantReflectionProvider constantReflection, - ConstantFieldProvider constantFieldProvider, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, IntrinsicContext initialIntrinsicContext) { - return new GraphBuilderPhase.Instance(metaAccess, stampProvider, constantReflection, constantFieldProvider, graphBuilderConfig, optimisticOpts, initialIntrinsicContext); + protected GraphBuilderPhase.Instance createGraphBuilderInstance(Providers theProviders, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, + IntrinsicContext initialIntrinsicContext) { + return new GraphBuilderPhase.Instance(theProviders, graphBuilderConfig, optimisticOpts, initialIntrinsicContext); } protected void pushStructure(Structure structure) { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/InlineDuringParsingPlugin.java 2019-03-28 07:37:31.616775738 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/InlineDuringParsingPlugin.java 2019-03-28 07:37:31.232773176 +0100 @@ -35,17 +35,26 @@ import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin; import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.services.Services; public final class InlineDuringParsingPlugin implements InlineInvokePlugin { + private static int getInteger(String name, int def) { + String value = Services.getSavedProperties().get(name); + if (value != null) { + return Integer.parseInt(value); + } + return def; + } + /** * Budget which when exceeded reduces the effective value of * {@link BytecodeParserOptions#InlineDuringParsingMaxDepth} to * {@link #MaxDepthAfterBudgetExceeded}. */ - private static final int NodeBudget = Integer.getInteger("InlineDuringParsingPlugin.NodeBudget", 2000); + private static final int NodeBudget = getInteger("InlineDuringParsingPlugin.NodeBudget", 2000); - private static final int MaxDepthAfterBudgetExceeded = Integer.getInteger("InlineDuringParsingPlugin.MaxDepthAfterBudgetExceeded", 3); + private static final int MaxDepthAfterBudgetExceeded = getInteger("InlineDuringParsingPlugin.MaxDepthAfterBudgetExceeded", 3); @Override public InlineInfo shouldInlineInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/IntrinsicGraphBuilder.java 2019-03-28 07:37:32.124779127 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/IntrinsicGraphBuilder.java 2019-03-28 07:37:31.740776565 +0100 @@ -51,6 +51,8 @@ import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.Receiver; +import org.graalvm.compiler.nodes.spi.CoreProviders; +import org.graalvm.compiler.nodes.spi.Replacements; import org.graalvm.compiler.nodes.spi.StampProvider; import org.graalvm.compiler.options.OptionValues; @@ -70,10 +72,7 @@ */ public class IntrinsicGraphBuilder implements GraphBuilderContext, Receiver { - protected final MetaAccessProvider metaAccess; - protected final ConstantReflectionProvider constantReflection; - protected final ConstantFieldProvider constantFieldProvider; - protected final StampProvider stampProvider; + protected final CoreProviders providers; protected final StructuredGraph graph; protected final Bytecode code; protected final ResolvedJavaMethod method; @@ -82,17 +81,12 @@ protected ValueNode[] arguments; protected ValueNode returnValue; - public IntrinsicGraphBuilder(OptionValues options, DebugContext debug, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantFieldProvider, - StampProvider stampProvider, Bytecode code, int invokeBci) { - this(options, debug, metaAccess, constantReflection, constantFieldProvider, stampProvider, code, invokeBci, AllowAssumptions.YES); + public IntrinsicGraphBuilder(OptionValues options, DebugContext debug, CoreProviders providers, Bytecode code, int invokeBci) { + this(options, debug, providers, code, invokeBci, AllowAssumptions.YES); } - protected IntrinsicGraphBuilder(OptionValues options, DebugContext debug, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantFieldProvider, - StampProvider stampProvider, Bytecode code, int invokeBci, AllowAssumptions allowAssumptions) { - this.metaAccess = metaAccess; - this.constantReflection = constantReflection; - this.constantFieldProvider = constantFieldProvider; - this.stampProvider = stampProvider; + protected IntrinsicGraphBuilder(OptionValues options, DebugContext debug, CoreProviders providers, Bytecode code, int invokeBci, AllowAssumptions allowAssumptions) { + this.providers = providers; this.code = code; this.method = code.getMethod(); this.graph = new StructuredGraph.Builder(options, debug, allowAssumptions).method(method).setIsSubstitution(true).trackNodeSourcePosition(true).build(); @@ -133,7 +127,9 @@ private void updateLastInstruction(T v) { if (v instanceof FixedNode) { FixedNode fixedNode = (FixedNode) v; - lastInstr.setNext(fixedNode); + if (lastInstr != null) { + lastInstr.setNext(fixedNode); + } if (fixedNode instanceof FixedWithNextNode) { FixedWithNextNode fixedWithNextNode = (FixedWithNextNode) fixedNode; assert fixedWithNextNode.next() == null : "cannot append instruction to instruction which isn't end"; @@ -175,22 +171,27 @@ @Override public StampProvider getStampProvider() { - return stampProvider; + return providers.getStampProvider(); } @Override public MetaAccessProvider getMetaAccess() { - return metaAccess; + return providers.getMetaAccess(); } @Override public ConstantReflectionProvider getConstantReflection() { - return constantReflection; + return providers.getConstantReflection(); } @Override public ConstantFieldProvider getConstantFieldProvider() { - return constantFieldProvider; + return providers.getConstantFieldProvider(); + } + + @Override + public Replacements getReplacements() { + return providers.getReplacements(); } @Override --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java 2019-03-28 07:37:32.640782568 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java 2019-03-28 07:37:32.256780006 +0100 @@ -106,6 +106,8 @@ import org.graalvm.compiler.nodes.java.NewMultiArrayNode; import org.graalvm.compiler.nodes.java.StoreFieldNode; import org.graalvm.compiler.nodes.java.StoreIndexedNode; +import org.graalvm.compiler.nodes.spi.CoreProviders; +import org.graalvm.compiler.nodes.spi.Replacements; import org.graalvm.compiler.nodes.spi.StampProvider; import org.graalvm.compiler.nodes.type.StampTool; import org.graalvm.compiler.nodes.util.GraphUtil; @@ -309,22 +311,27 @@ @Override public StampProvider getStampProvider() { - return stampProvider; + return providers.getStampProvider(); } @Override public MetaAccessProvider getMetaAccess() { - return metaAccess; + return providers.getMetaAccess(); } @Override public ConstantReflectionProvider getConstantReflection() { - return constantReflection; + return providers.getConstantReflection(); } @Override public ConstantFieldProvider getConstantFieldProvider() { - return constantFieldProvider; + return providers.getConstantFieldProvider(); + } + + @Override + public Replacements getReplacements() { + return providers.getReplacements(); } @Override @@ -565,11 +572,11 @@ private final ResolvedJavaMethod callInlinedMethod; protected final SourceLanguagePositionProvider sourceLanguagePositionProvider; - public PEGraphDecoder(Architecture architecture, StructuredGraph graph, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantFieldProvider, - StampProvider stampProvider, LoopExplosionPlugin loopExplosionPlugin, InvocationPlugins invocationPlugins, InlineInvokePlugin[] inlineInvokePlugins, + public PEGraphDecoder(Architecture architecture, StructuredGraph graph, CoreProviders providers, LoopExplosionPlugin loopExplosionPlugin, InvocationPlugins invocationPlugins, + InlineInvokePlugin[] inlineInvokePlugins, ParameterPlugin parameterPlugin, NodePlugin[] nodePlugins, ResolvedJavaMethod callInlinedMethod, SourceLanguagePositionProvider sourceLanguagePositionProvider) { - super(architecture, graph, metaAccess, constantReflection, constantFieldProvider, stampProvider, true); + super(architecture, graph, providers, true); this.loopExplosionPlugin = loopExplosionPlugin; this.invocationPlugins = invocationPlugins; this.inlineInvokePlugins = inlineInvokePlugins; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java 2019-03-28 07:37:33.160786035 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java 2019-03-28 07:37:32.772783448 +0100 @@ -52,7 +52,6 @@ import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode; import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.common.GraalOptions; -import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugContext.Description; @@ -64,6 +63,7 @@ import org.graalvm.compiler.graph.NodeSourcePosition; import org.graalvm.compiler.java.GraphBuilderPhase; import org.graalvm.compiler.java.GraphBuilderPhase.Instance; +import org.graalvm.compiler.loop.phases.ConvertDeoptimizeToGuardPhase; import org.graalvm.compiler.nodes.CallTargetNode; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.StateSplit; @@ -80,14 +80,12 @@ import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin; import org.graalvm.compiler.nodes.java.MethodCallTargetNode; import org.graalvm.compiler.nodes.spi.Replacements; -import org.graalvm.compiler.nodes.spi.StampProvider; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.common.CanonicalizerPhase; -import org.graalvm.compiler.loop.phases.ConvertDeoptimizeToGuardPhase; import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; import org.graalvm.compiler.phases.tiers.PhaseContext; import org.graalvm.compiler.phases.util.Providers; @@ -95,7 +93,6 @@ import org.graalvm.compiler.word.WordOperationPlugin; import jdk.vm.ci.code.TargetDescription; -import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; @@ -322,11 +319,8 @@ result = graph; } else { Bytecode code = new ResolvedJavaMethodBytecode(method); - ConstantReflectionProvider constantReflection = providers.getConstantReflection(); - ConstantFieldProvider constantFieldProvider = providers.getConstantFieldProvider(); - StampProvider stampProvider = providers.getStampProvider(); try (DebugContext debug = openDebugContext("Substitution_", method)) { - result = new IntrinsicGraphBuilder(options, debug, metaAccess, constantReflection, constantFieldProvider, stampProvider, code, invokeBci).buildGraph(plugin); + result = new IntrinsicGraphBuilder(options, debug, providers, code, invokeBci).buildGraph(plugin); } } } else { @@ -355,8 +349,7 @@ Plugins plugins = new Plugins(getGraphBuilderPlugins()); GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(plugins); IntrinsicContext initialReplacementContext = new IntrinsicContext(method, substMethod, bytecodeProvider, ROOT_COMPILATION); - new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), providers.getConstantReflection(), providers.getConstantFieldProvider(), config, - OptimisticOptimizations.NONE, initialReplacementContext).apply(graph); + new GraphBuilderPhase.Instance(providers, config, OptimisticOptimizations.NONE, initialReplacementContext).apply(graph); assert !graph.isFrozen(); return graph; } catch (Throwable e) { @@ -521,8 +514,7 @@ snippetAnnotation != null ? snippetAnnotation.allowPartialIntrinsicArgumentMismatch() : true); } - createGraphBuilder(metaAccess, replacements.providers.getStampProvider(), replacements.providers.getConstantReflection(), replacements.providers.getConstantFieldProvider(), config, - OptimisticOptimizations.NONE, initialIntrinsicContext).apply(graph); + createGraphBuilder(replacements.providers, config, OptimisticOptimizations.NONE, initialIntrinsicContext).apply(graph); new CanonicalizerPhase().apply(graph, new PhaseContext(replacements.providers)); } catch (Throwable e) { @@ -531,10 +523,8 @@ return graph; } - protected Instance createGraphBuilder(MetaAccessProvider metaAccess, StampProvider stampProvider, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantFieldProvider, - GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, IntrinsicContext initialIntrinsicContext) { - return new GraphBuilderPhase.Instance(metaAccess, stampProvider, constantReflection, constantFieldProvider, graphBuilderConfig, optimisticOpts, - initialIntrinsicContext); + protected Instance createGraphBuilder(Providers providers, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, IntrinsicContext initialIntrinsicContext) { + return new GraphBuilderPhase.Instance(providers, graphBuilderConfig, optimisticOpts, initialIntrinsicContext); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetCounterNode.java 2019-03-28 07:37:33.656789343 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetCounterNode.java 2019-03-28 07:37:33.276786810 +0100 @@ -28,7 +28,6 @@ import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED; import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER; -import java.lang.reflect.Field; import java.util.Arrays; import org.graalvm.compiler.api.replacements.Fold; @@ -51,6 +50,7 @@ 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.serviceprovider.GraalUnsafeAccess; import org.graalvm.compiler.word.ObjectAccess; import jdk.internal.vm.compiler.word.LocationIdentity; @@ -129,6 +129,8 @@ static class SnippetCounterSnippets implements Snippets { + private static final Unsafe UNSAFE = GraalUnsafeAccess.getUnsafe(); + @Fold static int countOffset() { try { @@ -162,20 +164,4 @@ } } } - - private static final Unsafe UNSAFE = initUnsafe(); - - private static Unsafe initUnsafe() { - try { - return Unsafe.getUnsafe(); - } catch (SecurityException se) { - try { - Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); - theUnsafe.setAccessible(true); - return (Unsafe) theUnsafe.get(Unsafe.class); - } catch (Exception e) { - throw new RuntimeException("exception while trying to get Unsafe", e); - } - } - } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java 2019-03-28 07:37:34.172792785 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java 2019-03-28 07:37:33.792790250 +0100 @@ -212,6 +212,20 @@ return false; } }); + r.register1("intern", Receiver.class, new InvocationPlugin() { + @Override + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { + if (receiver.isConstant()) { + String s = snippetReflection.asObject(String.class, (JavaConstant) receiver.get().asConstant()); + if (s != null) { + JavaConstant interned = snippetReflection.forObject(s.intern()); + b.addPush(JavaKind.Object, b.add(ConstantNode.forConstant(interned, b.getMetaAccess(), b.getGraph()))); + return true; + } + } + return false; + } + }); if (Java8OrEarlier) { r.registerMethodSubstitution(StringSubstitutions.class, "equals", Receiver.class, Object.class); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileBytecodeProvider.java 2019-03-28 07:37:34.664796065 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileBytecodeProvider.java 2019-03-28 07:37:34.288793558 +0100 @@ -108,12 +108,13 @@ if (classfile == null) { try { ResolvedJavaType type = metaAccess.lookupJavaType(c); - InputStream in = GraalServices.getClassfileAsStream(c); - if (in != null) { - DataInputStream stream = new DataInputStream(in); - classfile = new Classfile(type, stream, this); - classfiles.put(c, classfile); - return classfile; + try (InputStream in = GraalServices.getClassfileAsStream(c)) { + if (in != null) { + DataInputStream stream = new DataInputStream(in); + classfile = new Classfile(type, stream, this); + classfiles.put(c, classfile); + return classfile; + } } throw new NoClassDefFoundError(c.getName()); } catch (IOException e) { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ArrayCompareToNode.java 2019-03-28 07:37:35.152799320 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ArrayCompareToNode.java 2019-03-28 07:37:34.772796785 +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 @@ -24,10 +24,12 @@ package org.graalvm.compiler.replacements.nodes; +import static org.graalvm.compiler.core.common.GraalOptions.UseGraalStubs; import static org.graalvm.compiler.nodeinfo.InputType.Memory; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1024; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1024; +import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; @@ -117,8 +119,25 @@ @NodeIntrinsic public static native int compareTo(Object array1, Object array2, int length1, int length2, @ConstantNodeParameter JavaKind kind1, @ConstantNodeParameter JavaKind kind2); + public JavaKind getKind1() { + return kind1; + } + + public JavaKind getKind2() { + return kind2; + } + @Override public void generate(NodeLIRBuilderTool gen) { + if (UseGraalStubs.getValue(graph().getOptions())) { + ForeignCallLinkage linkage = gen.lookupGraalStub(this); + if (linkage != null) { + Value result = gen.getLIRGeneratorTool().emitForeignCall(linkage, null, gen.operand(array1), gen.operand(array2), gen.operand(length1), gen.operand(length2)); + gen.setResult(this, result); + return; + } + } + Value result = gen.getLIRGeneratorTool().emitArrayCompareTo(kind1, kind2, gen.operand(array1), gen.operand(array2), gen.operand(length1), gen.operand(length2)); gen.setResult(this, result); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ArrayEqualsNode.java 2019-03-28 07:37:35.648802628 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ArrayEqualsNode.java 2019-03-28 07:37:35.268800093 +0100 @@ -24,16 +24,15 @@ package org.graalvm.compiler.replacements.nodes; +import static org.graalvm.compiler.core.common.GraalOptions.UseGraalStubs; import static org.graalvm.compiler.nodeinfo.InputType.Memory; -import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.Canonicalizable; import org.graalvm.compiler.graph.spi.CanonicalizerTool; -import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeCycles; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodeinfo.NodeSize; @@ -51,14 +50,11 @@ import org.graalvm.compiler.nodes.spi.VirtualizerTool; import org.graalvm.compiler.nodes.util.GraphUtil; import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; -import org.graalvm.compiler.options.Option; -import org.graalvm.compiler.options.OptionKey; import jdk.internal.vm.compiler.word.LocationIdentity; import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.Value; // JaCoCo Exclude @@ -69,13 +65,6 @@ @NodeInfo(cycles = NodeCycles.CYCLES_UNKNOWN, size = NodeSize.SIZE_128) public final class ArrayEqualsNode extends FixedWithNextNode implements LIRLowerable, Canonicalizable, Virtualizable, MemoryAccess { - public static class Options { - // @formatter:off - @Option(help = "Use Array equals stubs instead of embedding all the emitted code.") - public static final OptionKey ArrayEqualsStubs = new OptionKey<>(true); - // @formatter:on - } - public static final NodeClass TYPE = NodeClass.create(ArrayEqualsNode.class); /** {@link JavaKind} of the arrays to compare. */ protected final JavaKind kind; @@ -225,27 +214,30 @@ return equals(array1, array2, length, JavaKind.Double); } + public ValueNode getLength() { + return length; + } + + public JavaKind getKind() { + return kind; + } + @Override public void generate(NodeLIRBuilderTool gen) { - LIRGeneratorTool tool = gen.getLIRGeneratorTool(); + if (UseGraalStubs.getValue(graph().getOptions())) { + ForeignCallLinkage linkage = gen.lookupGraalStub(this); + if (linkage != null) { + Value result = gen.getLIRGeneratorTool().emitForeignCall(linkage, null, gen.operand(array1), gen.operand(array2), gen.operand(length)); + gen.setResult(this, result); + return; + } + } + int constantLength = -1; if (length.isConstant()) { constantLength = length.asJavaConstant().asInt(); } - - if (Options.ArrayEqualsStubs.getValue(graph().getOptions())) { - ResolvedJavaMethod method = graph().method(); - if (method != null && method.getAnnotation(Snippet.class) == null) { - ForeignCallLinkage linkage = tool.lookupArrayEqualsStub(kind, constantLength); - if (linkage != null) { - Value result = tool.emitForeignCall(linkage, null, gen.operand(array1), gen.operand(array2), gen.operand(length)); - gen.setResult(this, result); - return; - } - } - } - - Value result = tool.emitArrayEquals(kind, gen.operand(array1), gen.operand(array2), gen.operand(length), constantLength, false); + Value result = gen.getLIRGeneratorTool().emitArrayEquals(kind, gen.operand(array1), gen.operand(array2), gen.operand(length), constantLength, false); gen.setResult(this, result); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ArrayRegionEqualsNode.java 2019-03-28 07:37:36.152805988 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ArrayRegionEqualsNode.java 2019-03-28 07:37:35.772803454 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -24,8 +24,10 @@ package org.graalvm.compiler.replacements.nodes; -import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.Value; +import static org.graalvm.compiler.core.common.GraalOptions.UseGraalStubs; +import static org.graalvm.compiler.nodeinfo.InputType.Memory; + +import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeCycles; @@ -42,7 +44,8 @@ import jdk.internal.vm.compiler.word.LocationIdentity; import jdk.internal.vm.compiler.word.Pointer; -import static org.graalvm.compiler.nodeinfo.InputType.Memory; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.Value; // JaCoCo Exclude @@ -85,8 +88,29 @@ @NodeIntrinsic public static native boolean regionEquals(Pointer array1, Pointer array2, int length, @ConstantNodeParameter JavaKind kind1, @ConstantNodeParameter JavaKind kind2); + public JavaKind getKind1() { + return kind1; + } + + public JavaKind getKind2() { + return kind2; + } + + public ValueNode getLength() { + return length; + } + @Override public void generate(NodeLIRBuilderTool gen) { + if (UseGraalStubs.getValue(graph().getOptions())) { + ForeignCallLinkage linkage = gen.lookupGraalStub(this); + if (linkage != null) { + Value result = gen.getLIRGeneratorTool().emitForeignCall(linkage, null, gen.operand(array1), gen.operand(array2), gen.operand(length)); + gen.setResult(this, result); + return; + } + } + int constantLength = -1; if (length.isConstant()) { constantLength = length.asJavaConstant().asInt(); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroNode.java 2019-03-28 07:37:36.664809402 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroNode.java 2019-03-28 07:37:36.280806842 +0100 @@ -41,9 +41,9 @@ import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind; import org.graalvm.compiler.nodes.FixedNode; -import org.graalvm.compiler.nodes.Invokable; import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.FrameState; +import org.graalvm.compiler.nodes.Invokable; import org.graalvm.compiler.nodes.InvokeNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.GuardsStage; @@ -58,10 +58,10 @@ import org.graalvm.compiler.phases.common.RemoveValueProxyPhase; import org.graalvm.compiler.phases.common.inlining.InliningUtil; import org.graalvm.compiler.phases.tiers.PhaseContext; +import jdk.internal.vm.compiler.word.LocationIdentity; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.internal.vm.compiler.word.LocationIdentity; /** * Macro nodes can be used to temporarily replace an invoke. They can, for example, be used to @@ -160,8 +160,7 @@ */ @SuppressWarnings("try") protected StructuredGraph lowerReplacement(final StructuredGraph replacementGraph, LoweringTool tool) { - final PhaseContext c = new PhaseContext(tool.getMetaAccess(), tool.getConstantReflection(), tool.getConstantFieldProvider(), tool.getLowerer(), tool.getReplacements(), - tool.getStampProvider(), null); + final PhaseContext c = new PhaseContext(tool.getProviders()); if (!graph().hasValueProxies()) { new RemoveValueProxyPhase().apply(replacementGraph); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/JavaVersionUtil.java 2019-03-28 07:37:37.196812950 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/JavaVersionUtil.java 2019-03-28 07:37:36.808810362 +0100 @@ -24,13 +24,15 @@ package org.graalvm.compiler.serviceprovider; +import jdk.vm.ci.services.Services; + /** * Interface to query which JDK version Graal is running on. */ public final class JavaVersionUtil { private static int getJavaSpecificationVersion() { - String value = System.getProperty("java.specification.version"); + String value = Services.getSavedProperties().get("java.specification.version"); if (value.startsWith("1.")) { value = value.substring(2); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsClosure.java 2019-03-28 07:37:37.668816097 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsClosure.java 2019-03-28 07:37:37.288813562 +0100 @@ -428,7 +428,7 @@ protected abstract class MergeProcessor { private final Block mergeBlock; - private final AbstractMergeNode merge; + protected final AbstractMergeNode merge; protected final GraphEffectList mergeEffects; protected final GraphEffectList afterMergeEffects; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapeClosure.java 2019-03-28 07:37:38.148819296 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapeClosure.java 2019-03-28 07:37:37.772816790 +0100 @@ -59,6 +59,7 @@ import org.graalvm.compiler.nodes.ProxyNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; +import org.graalvm.compiler.nodes.UnwindNode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.ValuePhiNode; import org.graalvm.compiler.nodes.ValueProxyNode; @@ -105,7 +106,6 @@ * The indexes into this array correspond to {@link VirtualObjectNode#getObjectId()}. */ public final ArrayList virtualObjects = new ArrayList<>(); - public final DebugContext debug; @Override public boolean needsApplyEffects() { @@ -189,7 +189,6 @@ super(schedule, schedule.getCFG()); StructuredGraph graph = schedule.getCFG().graph; this.hasVirtualInputs = graph.createNodeBitMap(); - this.debug = graph.getDebug(); this.tool = new VirtualizerToolImpl(metaAccess, constantReflection, constantFieldProvider, this, graph.getAssumptions(), graph.getOptions(), debug, loweringProvider); } @@ -687,16 +686,44 @@ // calculate the set of virtual objects that exist in all predecessors int[] virtualObjTemp = intersectVirtualObjects(states); + boolean forceMaterialization = false; + ValueNode forcedMaterializationValue = null; + FrameState frameState = merge.stateAfter(); + if (frameState != null && frameState.isExceptionHandlingBCI()) { + // We can not go below merges with an exception handling bci + // it could create allocations whose slow-path has an invalid framestate + forceMaterialization = true; + // check if we can reduce the scope of forced materialization to one phi node + if (frameState.stackSize() == 1 && merge.next() instanceof UnwindNode) { + assert frameState.outerFrameState() == null; + UnwindNode unwind = (UnwindNode) merge.next(); + if (unwind.exception() == frameState.stackAt(0)) { + boolean nullLocals = true; + for (int i = 0; i < frameState.localsSize(); i++) { + if (frameState.localAt(i) != null) { + nullLocals = false; + break; + } + } + if (nullLocals) { + // We found that the merge is directly followed by an unwind + // the Framestate only has the thrown value on the stack and no locals + forcedMaterializationValue = unwind.exception(); + } + } + } + } + boolean materialized; do { materialized = false; - if (PartialEscapeBlockState.identicalObjectStates(states)) { + if (!forceMaterialization && PartialEscapeBlockState.identicalObjectStates(states)) { newState.adoptAddObjectStates(states[0]); } else { for (int object : virtualObjTemp) { - if (PartialEscapeBlockState.identicalObjectStates(states, object)) { + if (!forceMaterialization && PartialEscapeBlockState.identicalObjectStates(states, object)) { newState.addObject(object, states[0].getObjectState(object).share()); continue; } @@ -710,6 +737,22 @@ for (int i = 0; i < states.length; i++) { ObjectState obj = states[i].getObjectState(object); ensureVirtual &= obj.getEnsureVirtualized(); + if (forceMaterialization) { + if (forcedMaterializationValue == null) { + uniqueMaterializedValue = null; + continue; + } else { + ValueNode value = forcedMaterializationValue; + if (merge.isPhiAtMerge(value)) { + value = ((ValuePhiNode) value).valueAt(i); + } + ValueNode alias = getAlias(value); + if (alias instanceof VirtualObjectNode && ((VirtualObjectNode) alias).getObjectId() == object) { + uniqueMaterializedValue = null; + continue; + } + } + } if (obj.isVirtual()) { virtualCount++; uniqueMaterializedValue = null; @@ -1029,6 +1072,7 @@ */ if (virtual.hasIdentity() && !isSingleUsageAllocation(getPhiValueAt(phi, i), virtualObjs, states[i])) { compatible = false; + break; } } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/Word.java 2019-03-28 07:37:38.664822737 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/Word.java 2019-03-28 07:37:38.284820203 +0100 @@ -24,7 +24,7 @@ package org.graalvm.compiler.word; -import static org.graalvm.compiler.word.UnsafeAccess.UNSAFE; +import static org.graalvm.compiler.serviceprovider.GraalUnsafeAccess.getUnsafe; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -59,8 +59,12 @@ import jdk.internal.vm.compiler.word.WordFactory; import jdk.internal.vm.compiler.word.impl.WordBoxFactory; +import sun.misc.Unsafe; + public abstract class Word implements SignedWord, UnsignedWord, Pointer { + private static final Unsafe UNSAFE = getUnsafe(); + static { BoxFactoryImpl.initialize(); } --- /dev/null 2017-11-16 08:17:56.803999947 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SwitchTest.java 2019-03-28 07:37:38.772823457 +0100 @@ -0,0 +1,55 @@ +/* + * 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 jdk.vm.ci.meta.ResolvedJavaMethod; +import org.junit.Test; + +// Regression test for JDK-8220643 (GR-14583) +public class SwitchTest extends GraalCompilerTest { + public static boolean test1(int arg) { + switch (arg) { + case -2139290527: + case -1466249004: + case -1063407861: + case 125135499: + case 425995464: + case 786490581: + case 1180611932: + case 1790655921: + case 1970660086: + return true; + default: + return false; + } + } + + @Test + public void run1() throws Throwable { + ResolvedJavaMethod method = getResolvedJavaMethod("test1"); + Result compiled = executeActual(method, null, -2139290527); + assertEquals(new Result(true, null), compiled); + } +} --- /dev/null 2017-11-16 08:17:56.803999947 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifySystemPropertyUsage.java 2019-03-28 07:37:39.284826870 +0100 @@ -0,0 +1,125 @@ +/* + * 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 java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.java.MethodCallTargetNode; +import org.graalvm.compiler.phases.VerifyPhase; +import org.graalvm.compiler.phases.tiers.PhaseContext; + +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.services.Services; + +/** + * Checks against calls to {@link System#getProperty(String)}, + * {@link System#getProperty(String, String)} and {@link System#getProperties()}. System properties + * can be modified by application code so {@link Services#getSavedProperties()} should be used + * instead. + */ +public class VerifySystemPropertyUsage extends VerifyPhase { + + static final Class[] BOXES = {Integer.class, Long.class, Boolean.class, Float.class, Double.class}; + static final int JVMCI_VERSION_MAJOR; + static final int JVMCI_VERSION_MINOR; + static { + int major = -1; + int minor = -1; + String vmVersion = System.getProperty("java.vm.version"); + if (System.getProperty("java.specification.version").compareTo("1.9") < 0) { + Pattern re = Pattern.compile(".*-jvmci-(\\d+)\\.(\\d+).*"); + Matcher matcher = re.matcher(vmVersion); + if (matcher.matches()) { + major = Integer.parseInt(matcher.group(1)); + minor = Integer.parseInt(matcher.group(2)); + } + } + JVMCI_VERSION_MAJOR = major; + JVMCI_VERSION_MINOR = minor; + } + + @Override + protected void verify(StructuredGraph graph, PhaseContext context) { + MetaAccessProvider metaAccess = context.getMetaAccess(); + final ResolvedJavaType systemType = metaAccess.lookupJavaType(System.class); + final ResolvedJavaType[] boxTypes = new ResolvedJavaType[BOXES.length]; + for (int i = 0; i < boxTypes.length; i++) { + boxTypes[i] = metaAccess.lookupJavaType(BOXES[i]); + } + + ResolvedJavaMethod caller = graph.method(); + String holderQualified = caller.format("%H"); + String holderUnqualified = caller.format("%h"); + String packageName = holderQualified.equals(holderUnqualified) ? "" : holderQualified.substring(0, holderQualified.length() - holderUnqualified.length() - 1); + if (packageName.startsWith("jdk.vm.ci")) { + if (JVMCI_VERSION_MAJOR >= 0 && JVMCI_VERSION_MINOR > 56) { + // This JVMCI version should not use non-saved system properties + } else { + // This JVMCI version still has some calls that need to be removed + return; + } + } else if (holderQualified.equals("org.graalvm.compiler.hotspot.JVMCIVersionCheck") && caller.getName().equals("main")) { + // The main method in JVMCIVersionCheck is only called from the shell + return; + } else if (packageName.startsWith("com.oracle.truffle") || packageName.startsWith("org.graalvm.polyglot")) { + // Truffle and Polyglot do not depend on JVMCI so cannot use + // Services.getSavedProperties() + return; + } else if (packageName.startsWith("com.oracle.svm")) { + // SVM must read system properties in: + // * its JDK substitutions to mimic required JDK semantics + // * native-image for config info + return; + } + for (MethodCallTargetNode t : graph.getNodes(MethodCallTargetNode.TYPE)) { + ResolvedJavaMethod callee = t.targetMethod(); + if (callee.getDeclaringClass().equals(systemType)) { + if (callee.getName().equals("getProperty") || callee.getName().equals("getProperties")) { + throw new VerificationError("Call to %s at callsite %s is prohibited. Call Services.getSavedProperties().get(String) instead.", + callee.format("%H.%n(%p)"), + caller.format("%H.%n(%p)")); + } + } else { + for (int i = 0; i < boxTypes.length; i++) { + ResolvedJavaType boxType = boxTypes[i]; + if (callee.getDeclaringClass().equals(boxType)) { + String simpleName = boxType.toJavaName(false); + if (callee.getName().equals("get" + simpleName)) { + throw new VerificationError("Call to %s at callsite %s is prohibited. Call %s.parse%s(Services.getSavedProperties().get(String)) instead.", + callee.format("%H.%n(%p)"), + caller.format("%H.%n(%p)"), + simpleName, simpleName); + } + } + } + } + } + } + +} --- /dev/null 2017-11-16 08:17:56.803999947 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyUnsafeAccess.java 2019-03-28 07:37:39.800830310 +0100 @@ -0,0 +1,116 @@ +/* + * 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 static java.lang.reflect.Modifier.isProtected; +import static java.lang.reflect.Modifier.isPublic; + +import java.lang.reflect.Field; + +import org.graalvm.compiler.core.common.type.TypeReference; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.java.InstanceOfNode; +import org.graalvm.compiler.nodes.java.MethodCallTargetNode; +import org.graalvm.compiler.phases.VerifyPhase; +import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.graalvm.compiler.serviceprovider.GraalUnsafeAccess; + +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; +import sun.misc.Unsafe; + +/** + * Checks that the {@link Unsafe} singleton instance is only accessed via well known classes such as + * {@link GraalUnsafeAccess}. + */ +public class VerifyUnsafeAccess extends VerifyPhase { + + @Override + protected void verify(StructuredGraph graph, PhaseContext context) { + MetaAccessProvider metaAccess = context.getMetaAccess(); + final ResolvedJavaType unsafeType = metaAccess.lookupJavaType(Unsafe.class); + + ResolvedJavaMethod caller = graph.method(); + String holderQualified = caller.format("%H"); + String holderUnqualified = caller.format("%h"); + String packageName = holderQualified.equals(holderUnqualified) ? "" : holderQualified.substring(0, holderQualified.length() - holderUnqualified.length() - 1); + if ((holderQualified.equals(GraalUnsafeAccess.class.getName()) || + holderQualified.equals("jdk.vm.ci.hotspot.UnsafeAccess")) && + caller.getName().equals("initUnsafe")) { + // This is the blessed way access Unsafe in Graal and JVMCI + return; + } else if (packageName.startsWith("com.oracle.truffle") || packageName.startsWith("org.graalvm.compiler.truffle.runtime")) { + // Truffle and GraalTruffleRuntime do not depend on Graal and so cannot use + // GraalUnsafeAccess + return; + } + + if (caller.getSignature().getReturnType(caller.getDeclaringClass()).equals(unsafeType)) { + if (caller.isPublic()) { + if (holderQualified.equals(GraalUnsafeAccess.class.getName()) && caller.getName().equals("getUnsafe")) { + // pass + } else { + throw new VerificationError("Cannot leak Unsafe from public method %s", + caller.format("%H.%n(%p)")); + } + } + } + + for (InstanceOfNode node : graph.getNodes().filter(InstanceOfNode.class)) { + TypeReference typeRef = node.type(); + if (typeRef != null) { + if (unsafeType.isAssignableFrom(typeRef.getType())) { + throw new VerificationError("Cast to %s in %s is prohibited as it implies accessing Unsafe.theUnsafe via reflection. Use %s.getUnsafe() instead.", + unsafeType.toJavaName(), + caller.format("%H.%n(%p)"), + GraalUnsafeAccess.class.getName()); + + } + } + } + for (MethodCallTargetNode t : graph.getNodes(MethodCallTargetNode.TYPE)) { + ResolvedJavaMethod callee = t.targetMethod(); + if (callee.getDeclaringClass().equals(unsafeType)) { + if (callee.getName().equals("getUnsafe")) { + throw new VerificationError("Call to %s at callsite %s is prohibited. Use %s.getUnsafe() instead.", + callee.format("%H.%n(%p)"), + caller.format("%H.%n(%p)"), + GraalUnsafeAccess.class.getName()); + } + } + } + } + + @Override + public void verifyClass(Class c, MetaAccessProvider metaAccess) { + for (Field field : c.getDeclaredFields()) { + int modifiers = field.getModifiers(); + if (field.getType() == Unsafe.class && (isPublic(modifiers) || isProtected(modifiers))) { + throw new VerificationError("Field of type %s must be private or package-private: %s", Unsafe.class.getName(), field); + } + } + } +} --- /dev/null 2017-11-16 08:17:56.803999947 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64ArrayCompareToStub.java 2019-03-28 07:37:40.308833697 +0100 @@ -0,0 +1,72 @@ +/* + * 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.hotspot.amd64; + +import org.graalvm.compiler.api.replacements.Snippet; +import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; +import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; +import org.graalvm.compiler.hotspot.meta.HotSpotProviders; +import org.graalvm.compiler.hotspot.stubs.SnippetStub; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.replacements.nodes.ArrayCompareToNode; +import jdk.internal.vm.compiler.word.Pointer; + +import jdk.vm.ci.meta.JavaKind; + +public final class AMD64ArrayCompareToStub extends SnippetStub { + + public static final ForeignCallDescriptor STUB_BYTE_ARRAY_COMPARE_TO_BYTE_ARRAY = new ForeignCallDescriptor( + "byteArrayCompareToByteArray", int.class, Pointer.class, Pointer.class, int.class, int.class); + public static final ForeignCallDescriptor STUB_BYTE_ARRAY_COMPARE_TO_CHAR_ARRAY = new ForeignCallDescriptor( + "byteArrayCompareToCharArray", int.class, Pointer.class, Pointer.class, int.class, int.class); + public static final ForeignCallDescriptor STUB_CHAR_ARRAY_COMPARE_TO_BYTE_ARRAY = new ForeignCallDescriptor( + "charArrayCompareToByteArray", int.class, Pointer.class, Pointer.class, int.class, int.class); + public static final ForeignCallDescriptor STUB_CHAR_ARRAY_COMPARE_TO_CHAR_ARRAY = new ForeignCallDescriptor( + "charArrayCompareToCharArray", int.class, Pointer.class, Pointer.class, int.class, int.class); + + public AMD64ArrayCompareToStub(ForeignCallDescriptor foreignCallDescriptor, OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super(foreignCallDescriptor.getName(), options, providers, linkage); + } + + @Snippet + private static int byteArrayCompareToByteArray(Pointer array1, Pointer array2, int length1, int length2) { + return ArrayCompareToNode.compareTo(array1, array2, length1, length2, JavaKind.Byte, JavaKind.Byte); + } + + @Snippet + private static int byteArrayCompareToCharArray(Pointer array1, Pointer array2, int length1, int length2) { + return ArrayCompareToNode.compareTo(array1, array2, length1, length2, JavaKind.Byte, JavaKind.Char); + } + + @Snippet + private static int charArrayCompareToByteArray(Pointer array1, Pointer array2, int length1, int length2) { + return ArrayCompareToNode.compareTo(array1, array2, length1, length2, JavaKind.Char, JavaKind.Byte); + } + + @Snippet + private static int charArrayCompareToCharArray(Pointer array1, Pointer array2, int length1, int length2) { + return ArrayCompareToNode.compareTo(array1, array2, length1, length2, JavaKind.Char, JavaKind.Char); + } +} --- /dev/null 2017-11-16 08:17:56.803999947 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/NodeCostDumpUtil.java 2019-03-28 07:37:40.808837030 +0100 @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2016, 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.hotspot.test; + +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; +import java.util.stream.Collectors; + +import org.graalvm.compiler.debug.CSVUtil; +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.graph.spi.Canonicalizable; +import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; +import org.graalvm.compiler.nodes.spi.Virtualizable; + +public class NodeCostDumpUtil { + + private static final String prefix1 = "com.oracle."; + private static final String prefix2 = "org.graalvm."; + private static final String FMT = CSVUtil.buildFormatString("%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s"); + + private static String getArgumentRegex(String arg) { + if (arg.length() == 0) { + return null; + } + try { + Pattern.compile(arg); + return arg; + } catch (PatternSyntaxException e) { + // silently ignore + System.err.println("Invalid regex given, defaulting to \".*\" regex.."); + return null; + } + } + + public static void main(String[] args) { + if (args.length != 1) { + System.err.println("NodeCostDumpUtil expects exactly one argument, the node name regex to match against."); + System.exit(-1); + } + final String pattern = getArgumentRegex(args[0]); + String version = System.getProperty("java.specification.version"); + if (version.compareTo("1.9") >= 0) { + System.err.printf("NodeCostDumpUtil does not support JDK versions greater than 1.8, current version is %s.\n", version); + System.exit(-1); + } + String[] jvmciCP = System.getProperty("jvmci.class.path.append").split(File.pathSeparator); + String[] primarySuiteCP = System.getProperty("primary.suite.cp").split(File.pathSeparator); + ClassLoader applicationClassLoader = Thread.currentThread().getContextClassLoader(); + HashSet> classes = new HashSet<>(); + try { + Set uniquePaths = new HashSet<>(Arrays.asList(primarySuiteCP)); + uniquePaths.addAll(Arrays.asList(jvmciCP)); + for (String path : uniquePaths) { + if (new File(path).exists()) { + if (path.endsWith(".jar")) { + try (FileSystem jarFileSystem = FileSystems.newFileSystem(URI.create("jar:file:" + path), Collections.emptyMap())) { + initAllClasses(jarFileSystem.getPath("/"), applicationClassLoader, classes); + } + } else { + initAllClasses(FileSystems.getDefault().getPath(path), applicationClassLoader, classes); + } + } + } + } catch (IOException ex) { + GraalError.shouldNotReachHere(); + } + System.err.printf("Loaded %d classes...\n", classes.size()); + List> nodeClasses = new ArrayList<>(); + for (Class loaded : classes) { + if (Node.class.isAssignableFrom(loaded) && !loaded.isArray()) { + nodeClasses.add(loaded); + } + } + System.err.printf("Loaded %s node classes...\n", nodeClasses.size()); + List> nc = new ArrayList<>(); + for (Class c : nodeClasses) { + try { + nc.add(NodeClass.get(c)); + } catch (Throwable t) { + // Silently ignore problems here + } + } + System.err.printf("Read TYPE field from %s node classes...\n", nc.size()); + nc = nc.stream().filter(x -> x != null).collect(Collectors.toList()); + nc.sort((x, y) -> { + String a = x.getJavaClass().getName(); + String b = y.getJavaClass().getName(); + return a.compareTo(b); + }); + CSVUtil.Escape.println(System.out, FMT, "NodeName", "Size", "Overrides Size Method", "Cycles", "Overrides Cycles Method", "Canonicalizable", "MemoryCheckPoint", "Virtualizable"); + for (NodeClass nodeclass : nc) { + String packageStrippedName = null; + try { + packageStrippedName = nodeclass.getJavaClass().getCanonicalName().replace(prefix1, "").replace(prefix2, ""); + } catch (Throwable t) { + // do nothing + continue; + } + if (pattern != null && !packageStrippedName.matches(pattern)) { + continue; + } + boolean overridesSizeMethod = false; + boolean overridesCyclesMethod = false; + Class c = nodeclass.getJavaClass(); + try { + c.getDeclaredMethod("estimatedNodeSize"); + overridesSizeMethod = true; + } catch (Throwable t) { + // do nothing + } + try { + c.getDeclaredMethod("estimatedNodeCycles"); + overridesCyclesMethod = true; + } catch (Throwable t) { + // do nothing + } + CSVUtil.Escape.println(System.out, FMT, packageStrippedName, nodeclass.size(), overridesSizeMethod, nodeclass.cycles(), overridesCyclesMethod, canonicalizable(c), memoryCheckPoint(c), + virtualizable(c)); + } + } + + private static boolean canonicalizable(Class c) { + return Canonicalizable.class.isAssignableFrom(c); + } + + private static boolean virtualizable(Class c) { + return Virtualizable.class.isAssignableFrom(c); + } + + private static boolean memoryCheckPoint(Class c) { + return MemoryCheckpoint.class.isAssignableFrom(c); + } + + private static void initAllClasses(final Path root, ClassLoader classLoader, HashSet> classes) { + try { + Files.walkFileTree(root, new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + String className = root.relativize(file).toString(); + ClassLoader c = classLoader; + if (className.endsWith(".class")) { + String prefix = prefixed(className); + if (prefix != null) { + String stripped = stripClassName(className); + c = new URLClassLoader(new URL[]{new File(constructURLPart(stripped, className, prefix)).toURI().toURL()}, classLoader); + className = constructClazzPart(stripped, prefix); + } else { + String clazzPart = className.replace('/', '.'); + className = clazzPart.substring(0, clazzPart.length() - ".class".length()); + } + try { + Class systemClass = Class.forName(className, false, c); + if (systemClass.getEnclosingClass() != null) { + try { + classes.add(systemClass.getEnclosingClass()); + } catch (Throwable t) { + // do nothing + } + } + classes.add(systemClass); + } catch (Throwable ignored) { + } + } + return FileVisitResult.CONTINUE; + } + }); + } catch (IOException ex) { + GraalError.shouldNotReachHere(); + } + } + + private static String prefixed(String className) { + if (className.contains(prefix1) && className.indexOf(prefix1) > 0) { + return prefix1; + } else if (className.contains(prefix2) && className.indexOf(prefix2) > 0) { + return prefix2; + } + return null; + } + + private static String stripClassName(String className) { + return className.replace('/', '.'); + } + + private static String constructClazzPart(String stripped, String prefix) { + String clazzPart = stripped.substring(stripped.lastIndexOf(prefix), stripped.length()); + return clazzPart.substring(0, clazzPart.length() - ".class".length()); + } + + private static String constructURLPart(String stripped, String className, String prefix) { + return className.substring(0, stripped.lastIndexOf(prefix)); + } + +} + --- /dev/null 2017-11-16 08:17:56.803999947 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/StringInternConstantTest.java 2019-03-28 07:37:41.320840443 +0100 @@ -0,0 +1,73 @@ +/* + * 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.hotspot.test; + +import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.FixedNode; +import org.graalvm.compiler.nodes.ReturnNode; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.junit.Test; + +import jdk.vm.ci.hotspot.HotSpotObjectConstant; +import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import static org.hamcrest.CoreMatchers.instanceOf; +import org.junit.Assert; + +/** + * Tests constant folding of {@link String#intern()}. + */ +public class StringInternConstantTest extends GraalCompilerTest { + + private static final String A_CONSTANT_STRING = "a constant string"; + + @Test + public void test1() { + ResolvedJavaMethod method = getResolvedJavaMethod("constantIntern"); + StructuredGraph graph = parseForCompile(method); + + FixedNode firstFixed = graph.start().next(); + Assert.assertThat(firstFixed, instanceOf(ReturnNode.class)); + + ReturnNode ret = (ReturnNode) firstFixed; + if (ret.result() instanceof ConstantNode) { + String expected = A_CONSTANT_STRING.intern(); + Constant constant = ((ConstantNode) ret.result()).getValue(); + if (constant instanceof HotSpotObjectConstant) { + String returnedString = ((HotSpotObjectConstant) constant).asObject(String.class); + Assert.assertSame("result", expected, returnedString); + } else { + Assert.fail("expected HotSpotObjectConstant, got: " + constant.getClass()); + } + } else { + Assert.fail("result not constant: " + ret.result()); + } + } + + public static String constantIntern() { + return A_CONSTANT_STRING.intern(); + } +} --- /dev/null 2017-11-16 08:17:56.803999947 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/IsGraalPredicateBase.java 2019-03-28 07:37:41.820843777 +0100 @@ -0,0 +1,46 @@ +/* + * 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 + * 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 jdk.vm.ci.hotspot.HotSpotJVMCICompilerFactory; +import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; + +/** + * Determines if a given class is a JVMCI or Graal class for the purpose of + * {@link HotSpotGraalCompilerFactory.Options#CompileGraalWithC1Only}. + */ +abstract class IsGraalPredicateBase { + + @SuppressWarnings("unused") + void onCompilerConfigurationFactorySelection(HotSpotJVMCIRuntime runtime, CompilerConfigurationFactory factory) { + } + + abstract boolean apply(Class declaringClass); + + HotSpotJVMCICompilerFactory.CompilationLevelAdjustment getCompilationLevelAdjustment() { + return HotSpotJVMCICompilerFactory.CompilationLevelAdjustment.ByHolder; + } +} + --- /dev/null 2017-11-16 08:17:56.803999947 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotObjdumpDisassemblerProvider.java 2019-03-28 07:37:42.324847137 +0100 @@ -0,0 +1,167 @@ +/* + * 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.hotspot.meta; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.graalvm.compiler.code.CompilationResult; +import org.graalvm.compiler.code.CompilationResult.CodeAnnotation; +import org.graalvm.compiler.code.DisassemblerProvider; +import org.graalvm.compiler.serviceprovider.ServiceProvider; + +import jdk.vm.ci.code.CodeCacheProvider; +import jdk.vm.ci.code.CodeUtil; +import jdk.vm.ci.code.CodeUtil.DefaultRefMapFormatter; +import jdk.vm.ci.code.CodeUtil.RefMapFormatter; +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.site.Call; +import jdk.vm.ci.code.site.DataPatch; +import jdk.vm.ci.code.site.Infopoint; +import jdk.vm.ci.code.site.Mark; +import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; +import jdk.vm.ci.services.Services; + +/** + * This disassembles the code immediatly with objdump. + */ +@ServiceProvider(DisassemblerProvider.class) +public class HotSpotObjdumpDisassemblerProvider extends HotSpotDisassemblerProvider { + + /** + * Uses objdump to disassemble the compiled code. + */ + @Override + public String disassembleCompiledCode(CodeCacheProvider codeCache, CompilationResult compResult) { + File tmp = null; + try { + tmp = File.createTempFile("compiledBinary", ".bin"); + try (FileOutputStream fos = new FileOutputStream(tmp)) { + fos.write(compResult.getTargetCode()); + } + String[] cmdline; + String arch = Services.getSavedProperties().get("os.arch"); + if (arch.equals("amd64")) { + cmdline = new String[]{"objdump", "-D", "-b", "binary", "-M", "x86-64", "-m", "i386", tmp.getAbsolutePath()}; + } else if (arch.equals("aarch64")) { + cmdline = new String[]{"objdump", "-D", "-b", "binary", "-m", "aarch64", tmp.getAbsolutePath()}; + } else { + return null; + } + + Pattern p = Pattern.compile(" *(([0-9a-fA-F]+):\t.*)"); + + TargetDescription target = codeCache.getTarget(); + RegisterConfig regConfig = codeCache.getRegisterConfig(); + Register fp = regConfig.getFrameRegister(); + RefMapFormatter slotFormatter = new DefaultRefMapFormatter(target.wordSize, fp, 0); + + Map annotations = new HashMap<>(); + for (DataPatch site : compResult.getDataPatches()) { + putAnnotation(annotations, site.pcOffset, "{" + site.reference.toString() + "}"); + } + for (Mark mark : compResult.getMarks()) { + putAnnotation(annotations, mark.pcOffset, codeCache.getMarkName(mark)); + } + for (CodeAnnotation a : compResult.getCodeAnnotations()) { + putAnnotation(annotations, a.position, a.toString()); + } + for (Infopoint infopoint : compResult.getInfopoints()) { + if (infopoint instanceof Call) { + Call call = (Call) infopoint; + if (call.debugInfo != null) { + putAnnotation(annotations, call.pcOffset + call.size, CodeUtil.append(new StringBuilder(100), call.debugInfo, slotFormatter).toString()); + } + putAnnotation(annotations, call.pcOffset, "{" + codeCache.getTargetName(call) + "}"); + } else { + if (infopoint.debugInfo != null) { + putAnnotation(annotations, infopoint.pcOffset, CodeUtil.append(new StringBuilder(100), infopoint.debugInfo, slotFormatter).toString()); + } + putAnnotation(annotations, infopoint.pcOffset, "{infopoint: " + infopoint.reason + "}"); + } + } + + Process proc = Runtime.getRuntime().exec(cmdline); + InputStream is = proc.getInputStream(); + + InputStreamReader isr = new InputStreamReader(is); + BufferedReader br = new BufferedReader(isr); + String line; + + StringBuilder sb = new StringBuilder(); + while ((line = br.readLine()) != null) { + Matcher m = p.matcher(line); + if (m.find()) { + int address = Integer.parseInt(m.group(2), 16); + String annotation = annotations.get(address); + if (annotation != null) { + annotation = annotation.replace("\n", "\n; "); + sb.append("; ").append(annotation).append('\n'); + } + line = m.replaceAll("0x$1"); + } + sb.append(line).append("\n"); + } + BufferedReader ebr = new BufferedReader(new InputStreamReader(proc.getErrorStream())); + while ((line = ebr.readLine()) != null) { + System.err.println(line); + } + ebr.close(); + return sb.toString(); + } catch (IOException e) { + if (tmp != null) { + tmp.delete(); + } + e.printStackTrace(); + return null; + } + } + + private static void putAnnotation(Map annotations, int idx, String txt) { + String newAnnoation = annotations.getOrDefault(idx, "") + "\n" + txt; + annotations.put(idx, newAnnoation); + } + + @Override + public String disassembleInstalledCode(CodeCacheProvider codeCache, CompilationResult compResult, InstalledCode code) { + return ((HotSpotCodeCacheProvider) codeCache).disassemble(code); + } + + @Override + public String getName() { + return "hsdis-objdump"; + } +} --- /dev/null 2017-11-16 08:17:56.803999947 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64MathIntrinsicBinaryOp.java 2019-03-28 07:37:42.816850416 +0100 @@ -0,0 +1,84 @@ +/* + * 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.lir.aarch64; + +import static jdk.vm.ci.aarch64.AArch64.v0; +import static jdk.vm.ci.aarch64.AArch64.v1; + +import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.lir.LIRInstructionClass; +import org.graalvm.compiler.lir.Variable; +import org.graalvm.compiler.lir.gen.LIRGenerator; + +import jdk.vm.ci.aarch64.AArch64; +import jdk.vm.ci.aarch64.AArch64Kind; +import jdk.vm.ci.code.Register; +import jdk.vm.ci.code.RegisterValue; +import jdk.vm.ci.meta.Value; + +public abstract class AArch64MathIntrinsicBinaryOp extends AArch64LIRInstruction { + + @Def protected Value output; + @Use protected Value input0; + @Use protected Value input1; + @Temp protected Value[] temps; + + public AArch64MathIntrinsicBinaryOp(LIRInstructionClass type, Register... registers) { + super(type); + input0 = v0.asValue(LIRKind.value(AArch64Kind.V64_WORD)); + input1 = v0.asValue(LIRKind.value(AArch64Kind.V64_WORD)); + output = v0.asValue(LIRKind.value(AArch64Kind.V64_WORD)); + + temps = registersToValues(registers); + } + + protected static Value[] registersToValues(Register[] registers) { + Value[] temps = new Value[registers.length]; + for (int i = 0; i < registers.length; i++) { + Register register = registers[i]; + if (AArch64.CPU.equals(register.getRegisterCategory())) { + temps[i] = register.asValue(LIRKind.value(AArch64Kind.V64_WORD)); + } else if (AArch64.SIMD.equals(register.getRegisterCategory())) { + temps[i] = register.asValue(LIRKind.value(AArch64Kind.V64_WORD)); + } else { + throw GraalError.shouldNotReachHere("Unsupported register type in math stubs."); + } + } + return temps; + } + + public final Variable emitLIRWrapper(LIRGenerator gen, Value x, Value y) { + LIRKind kind = LIRKind.combine(x, y); + RegisterValue v0value = v0.asValue(kind); + gen.emitMove(v0value, x); + RegisterValue v1value = v1.asValue(kind); + gen.emitMove(v1value, y); + gen.append(this); + Variable result = gen.newVariable(kind); + gen.emitMove(result, v0value); + return result; + } +} --- /dev/null 2017-11-16 08:17:56.803999947 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/CoreProviders.java 2019-03-28 07:37:43.300853643 +0100 @@ -0,0 +1,48 @@ +/* + * 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.nodes.spi; + +import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; +import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; + +import jdk.vm.ci.meta.ConstantReflectionProvider; +import jdk.vm.ci.meta.MetaAccessProvider; + +public interface CoreProviders { + + MetaAccessProvider getMetaAccess(); + + ConstantReflectionProvider getConstantReflection(); + + ConstantFieldProvider getConstantFieldProvider(); + + LoweringProvider getLowerer(); + + Replacements getReplacements(); + + StampProvider getStampProvider(); + + ForeignCallsProvider getForeignCalls(); +} --- /dev/null 2017-11-16 08:17:56.803999947 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/CoreProvidersImpl.java 2019-03-28 07:37:43.788856895 +0100 @@ -0,0 +1,87 @@ +/* + * 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.nodes.spi; + +import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; +import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; + +import jdk.vm.ci.meta.ConstantReflectionProvider; +import jdk.vm.ci.meta.MetaAccessProvider; + +public class CoreProvidersImpl implements CoreProviders { + protected final MetaAccessProvider metaAccess; + protected final ConstantReflectionProvider constantReflection; + protected final ConstantFieldProvider constantFieldProvider; + protected final LoweringProvider lowerer; + protected final Replacements replacements; + protected final StampProvider stampProvider; + protected final ForeignCallsProvider foreignCalls; + + protected CoreProvidersImpl(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantFieldProvider, LoweringProvider lowerer, + Replacements replacements, StampProvider stampProvider, ForeignCallsProvider foreignCalls) { + this.metaAccess = metaAccess; + this.constantReflection = constantReflection; + this.constantFieldProvider = constantFieldProvider; + this.lowerer = lowerer; + this.replacements = replacements; + this.stampProvider = stampProvider; + this.foreignCalls = foreignCalls; + } + + @Override + public MetaAccessProvider getMetaAccess() { + return metaAccess; + } + + @Override + public ConstantReflectionProvider getConstantReflection() { + return constantReflection; + } + + @Override + public ConstantFieldProvider getConstantFieldProvider() { + return constantFieldProvider; + } + + @Override + public LoweringProvider getLowerer() { + return lowerer; + } + + @Override + public Replacements getReplacements() { + return replacements; + } + + @Override + public StampProvider getStampProvider() { + return stampProvider; + } + + @Override + public ForeignCallsProvider getForeignCalls() { + return foreignCalls; + } +} --- /dev/null 2017-11-16 08:17:56.803999947 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/GraalUnsafeAccess.java 2019-03-28 07:37:44.288860227 +0100 @@ -0,0 +1,70 @@ +/* + * 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 + * 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.serviceprovider; + +import java.lang.reflect.Field; + +import sun.misc.Unsafe; + +/** + * Access to the {@link Unsafe} capability. Care must be taken not to leak the {@link #UNSAFE} value + * of out code loaded by the JVMCI class loader or encapsulated in the JVMCI or Graal modules into + * other code (e.g. via the Polyglot API). + */ +public class GraalUnsafeAccess { + + private static final Unsafe UNSAFE = initUnsafe(); + + private static Unsafe initUnsafe() { + try { + // Fast path when we are trusted. + return Unsafe.getUnsafe(); + } catch (SecurityException se) { + // Slow path when we are not trusted. + try { + Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); + theUnsafe.setAccessible(true); + return (Unsafe) theUnsafe.get(Unsafe.class); + } catch (Exception e) { + throw new RuntimeException("exception while trying to get Unsafe", e); + } + } + } + + /** + * Gets the {@link Unsafe} singleton. + * + * @throws SecurityException if a security manager is present and it denies + * {@link RuntimePermission}("accessUnsafe") + */ + public static Unsafe getUnsafe() { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new RuntimePermission("accessUnsafe")); + } + return UNSAFE; + } +} + --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/UnsafeAccess.java 2019-03-28 07:37:45.164866066 +0100 +++ /dev/null 2017-11-16 08:17:56.803999947 +0100 @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2012, 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; - -import java.lang.reflect.Field; - -import sun.misc.Unsafe; - -/** - * Package private access to the {@link Unsafe} capability. - */ -class UnsafeAccess { - - static final Unsafe UNSAFE = initUnsafe(); - - private static Unsafe initUnsafe() { - try { - // Fast path when we are trusted. - return Unsafe.getUnsafe(); - } catch (SecurityException se) { - // Slow path when we are not trusted. - try { - Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); - theUnsafe.setAccessible(true); - return (Unsafe) theUnsafe.get(Unsafe.class); - } catch (Exception e) { - throw new RuntimeException("exception while trying to get Unsafe", e); - } - } - } -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/UnsafeAccess.java 2019-03-28 07:37:45.596868945 +0100 +++ /dev/null 2017-11-16 08:17:56.803999947 +0100 @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2012, 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.util; - -import java.lang.reflect.Field; - -import sun.misc.Unsafe; - -/** - * Package private access to the {@link Unsafe} capability. - */ -class UnsafeAccess { - - static final Unsafe UNSAFE = initUnsafe(); - - private static Unsafe initUnsafe() { - try { - // Fast path when we are trusted. - return Unsafe.getUnsafe(); - } catch (SecurityException se) { - // Slow path when we are not trusted. - try { - Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); - theUnsafe.setAccessible(true); - return (Unsafe) theUnsafe.get(Unsafe.class); - } catch (Exception e) { - throw new RuntimeException("exception while trying to get Unsafe", e); - } - } - } -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/UnsafeAccess.java 2019-03-28 07:37:46.016871745 +0100 +++ /dev/null 2017-11-16 08:17:56.803999947 +0100 @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2012, 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.graph; - -import java.lang.reflect.Field; - -import sun.misc.Unsafe; - -/** - * Package private access to the {@link Unsafe} capability. - */ -class UnsafeAccess { - - static final Unsafe UNSAFE = initUnsafe(); - - private static Unsafe initUnsafe() { - try { - // Fast path when we are trusted. - return Unsafe.getUnsafe(); - } catch (SecurityException se) { - // Slow path when we are not trusted. - try { - Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); - theUnsafe.setAccessible(true); - return (Unsafe) theUnsafe.get(Unsafe.class); - } catch (Exception e) { - throw new RuntimeException("exception while trying to get Unsafe", e); - } - } - } -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/NodeCostDumpUtil.java 2019-03-28 07:37:46.444874596 +0100 +++ /dev/null 2017-11-16 08:17:56.803999947 +0100 @@ -1,236 +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; - -import java.io.File; -import java.io.IOException; -import java.net.URI; -import java.net.URL; -import java.net.URLClassLoader; -import java.nio.file.FileSystem; -import java.nio.file.FileSystems; -import java.nio.file.FileVisitResult; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.attribute.BasicFileAttributes; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.regex.Pattern; -import java.util.regex.PatternSyntaxException; -import java.util.stream.Collectors; - -import org.graalvm.compiler.debug.CSVUtil; -import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.graph.spi.Canonicalizable; -import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; -import org.graalvm.compiler.nodes.spi.Virtualizable; - -public class NodeCostDumpUtil { - - private static final String prefix1 = "com.oracle."; - private static final String prefix2 = "org.graalvm."; - private static final String FMT = CSVUtil.buildFormatString("%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s"); - - private static String getArgumentRegex(String arg) { - if (arg.length() == 0) { - return null; - } - try { - Pattern.compile(arg); - return arg; - } catch (PatternSyntaxException e) { - // silently ignore - System.err.println("Invalid regex given, defaulting to \".*\" regex.."); - return null; - } - } - - public static void main(String[] args) { - if (args.length != 1) { - System.err.println("NodeCostDumpUtil expects exactly one argument, the node name regex to match against."); - System.exit(-1); - } - final String pattern = getArgumentRegex(args[0]); - String version = System.getProperty("java.specification.version"); - if (version.compareTo("1.9") >= 0) { - System.err.printf("NodeCostDumpUtil does not support JDK versions greater than 1.8, current version is %s.\n", version); - System.exit(-1); - } - String[] jvmciCP = System.getProperty("jvmci.class.path.append").split(File.pathSeparator); - String[] primarySuiteCP = System.getProperty("primary.suite.cp").split(File.pathSeparator); - ClassLoader applicationClassLoader = Thread.currentThread().getContextClassLoader(); - HashSet> classes = new HashSet<>(); - try { - Set uniquePaths = new HashSet<>(Arrays.asList(primarySuiteCP)); - uniquePaths.addAll(Arrays.asList(jvmciCP)); - for (String path : uniquePaths) { - if (new File(path).exists()) { - if (path.endsWith(".jar")) { - try (FileSystem jarFileSystem = FileSystems.newFileSystem(URI.create("jar:file:" + path), Collections.emptyMap())) { - initAllClasses(jarFileSystem.getPath("/"), applicationClassLoader, classes); - } - } else { - initAllClasses(FileSystems.getDefault().getPath(path), applicationClassLoader, classes); - } - } - } - } catch (IOException ex) { - GraalError.shouldNotReachHere(); - } - System.err.printf("Loaded %d classes...\n", classes.size()); - List> nodeClasses = new ArrayList<>(); - for (Class loaded : classes) { - if (Node.class.isAssignableFrom(loaded) && !loaded.isArray()) { - nodeClasses.add(loaded); - } - } - System.err.printf("Loaded %s node classes...\n", nodeClasses.size()); - List> nc = new ArrayList<>(); - for (Class c : nodeClasses) { - try { - nc.add(NodeClass.get(c)); - } catch (Throwable t) { - // Silently ignore problems here - } - } - System.err.printf("Read TYPE field from %s node classes...\n", nc.size()); - nc = nc.stream().filter(x -> x != null).collect(Collectors.toList()); - nc.sort((x, y) -> { - String a = x.getJavaClass().getName(); - String b = y.getJavaClass().getName(); - return a.compareTo(b); - }); - CSVUtil.Escape.println(System.out, FMT, "NodeName", "Size", "Overrides Size Method", "Cycles", "Overrides Cycles Method", "Canonicalizable", "MemoryCheckPoint", "Virtualizable"); - for (NodeClass nodeclass : nc) { - String packageStrippedName = null; - try { - packageStrippedName = nodeclass.getJavaClass().getCanonicalName().replace(prefix1, "").replace(prefix2, ""); - } catch (Throwable t) { - // do nothing - continue; - } - if (pattern != null && !packageStrippedName.matches(pattern)) { - continue; - } - boolean overridesSizeMethod = false; - boolean overridesCyclesMethod = false; - Class c = nodeclass.getJavaClass(); - try { - c.getDeclaredMethod("estimatedNodeSize"); - overridesSizeMethod = true; - } catch (Throwable t) { - // do nothing - } - try { - c.getDeclaredMethod("estimatedNodeCycles"); - overridesCyclesMethod = true; - } catch (Throwable t) { - // do nothing - } - CSVUtil.Escape.println(System.out, FMT, packageStrippedName, nodeclass.size(), overridesSizeMethod, nodeclass.cycles(), overridesCyclesMethod, canonicalizable(c), memoryCheckPoint(c), - virtualizable(c)); - } - } - - private static boolean canonicalizable(Class c) { - return Canonicalizable.class.isAssignableFrom(c); - } - - private static boolean virtualizable(Class c) { - return Virtualizable.class.isAssignableFrom(c); - } - - private static boolean memoryCheckPoint(Class c) { - return MemoryCheckpoint.class.isAssignableFrom(c); - } - - private static void initAllClasses(final Path root, ClassLoader classLoader, HashSet> classes) { - try { - Files.walkFileTree(root, new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - String className = root.relativize(file).toString(); - ClassLoader c = classLoader; - if (className.endsWith(".class")) { - String prefix = prefixed(className); - if (prefix != null) { - String stripped = stripClassName(className); - c = new URLClassLoader(new URL[]{new File(constructURLPart(stripped, className, prefix)).toURI().toURL()}, classLoader); - className = constructClazzPart(stripped, prefix); - } else { - String clazzPart = className.replace('/', '.'); - className = clazzPart.substring(0, clazzPart.length() - ".class".length()); - } - try { - Class systemClass = Class.forName(className, false, c); - if (systemClass.getEnclosingClass() != null) { - try { - classes.add(systemClass.getEnclosingClass()); - } catch (Throwable t) { - // do nothing - } - } - classes.add(systemClass); - } catch (Throwable ignored) { - } - } - return FileVisitResult.CONTINUE; - } - }); - } catch (IOException ex) { - GraalError.shouldNotReachHere(); - } - } - - private static String prefixed(String className) { - if (className.contains(prefix1) && className.indexOf(prefix1) > 0) { - return prefix1; - } else if (className.contains(prefix2) && className.indexOf(prefix2) > 0) { - return prefix2; - } - return null; - } - - private static String stripClassName(String className) { - return className.replace('/', '.'); - } - - private static String constructClazzPart(String stripped, String prefix) { - String clazzPart = stripped.substring(stripped.lastIndexOf(prefix), stripped.length()); - return clazzPart.substring(0, clazzPart.length() - ".class".length()); - } - - private static String constructURLPart(String stripped, String className, String prefix) { - return className.substring(0, stripped.lastIndexOf(prefix)); - } - -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/UnsafeAccess.java 2019-03-28 07:37:46.872877449 +0100 +++ /dev/null 2017-11-16 08:17:56.803999947 +0100 @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2012, 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.replacements; - -import java.lang.reflect.Field; - -import sun.misc.Unsafe; - -/** - * Package private access to the {@link Unsafe} capability. - */ -class UnsafeAccess { - - private static final Unsafe THE_UNSAFE = initUnsafe(); - - static final UnsafeAccess UNSAFE = new UnsafeAccess(); - - private static Unsafe initUnsafe() { - try { - // Fast path when we are trusted. - return Unsafe.getUnsafe(); - } catch (SecurityException se) { - // Slow path when we are not trusted. - try { - Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); - theUnsafe.setAccessible(true); - return (Unsafe) theUnsafe.get(Unsafe.class); - } catch (Exception e) { - throw new RuntimeException("exception while trying to get Unsafe", e); - } - } - } - - public char getChar(Object target, long l) { - return THE_UNSAFE.getChar(target, l); - } - - public byte getByte(Object target, long l) { - return THE_UNSAFE.getByte(target, l); - } -} --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/UnsafeAccess.java 2019-03-28 07:37:47.284880194 +0100 +++ /dev/null 2017-11-16 08:17:56.803999947 +0100 @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2012, 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.word; - -import java.lang.reflect.Field; - -import sun.misc.Unsafe; - -/** - * Package private access to the {@link Unsafe} capability. - */ -class UnsafeAccess { - - static final Unsafe UNSAFE = initUnsafe(); - - private static Unsafe initUnsafe() { - try { - // Fast path when we are trusted. - return Unsafe.getUnsafe(); - } catch (SecurityException se) { - // Slow path when we are not trusted. - try { - Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); - theUnsafe.setAccessible(true); - return (Unsafe) theUnsafe.get(Unsafe.class); - } catch (Exception e) { - throw new RuntimeException("exception while trying to get Unsafe", e); - } - } - } -}