Mercurial > hg > openjdk > jdk9 > hotspot
changeset 12605:b2d0a906afd7 jdk-9+157
Merge
author | jwilhelm |
---|---|
date | Thu, 09 Feb 2017 23:35:22 +0100 |
parents | 8c7769a2e1fe (current diff) e64d5880a8be (diff) |
children | 4e78f3093522 47a72295aa68 |
files | |
diffstat | 34 files changed, 643 insertions(+), 259 deletions(-) [+] |
line wrap: on
line diff
--- a/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp Fri Feb 10 09:03:55 2017 +0000 +++ b/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp Thu Feb 09 23:35:22 2017 +0100 @@ -1922,12 +1922,17 @@ } if (opr2->is_constant()) { + bool is_32bit = false; // width of register operand jlong imm; + switch(opr2->type()) { + case T_INT: + imm = opr2->as_constant_ptr()->as_jint(); + is_32bit = true; + break; case T_LONG: imm = opr2->as_constant_ptr()->as_jlong(); break; - case T_INT: case T_ADDRESS: imm = opr2->as_constant_ptr()->as_jint(); break; @@ -1942,14 +1947,14 @@ } if (Assembler::operand_valid_for_add_sub_immediate(imm)) { - if (type2aelembytes(opr1->type()) <= 4) + if (is_32bit) __ cmpw(reg1, imm); else __ cmp(reg1, imm); return; } else { __ mov(rscratch1, imm); - if (type2aelembytes(opr1->type()) <= 4) + if (is_32bit) __ cmpw(reg1, rscratch1); else __ cmp(reg1, rscratch1);
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTStub.java Fri Feb 10 09:03:55 2017 +0000 +++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTStub.java Thu Feb 09 23:35:22 2017 +0100 @@ -25,6 +25,7 @@ import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.target.Backend; +import org.graalvm.compiler.hotspot.HotSpotCompiledCodeBuilder; import org.graalvm.compiler.hotspot.stubs.Stub; import jdk.vm.ci.hotspot.HotSpotCompiledCode; @@ -48,7 +49,7 @@ } public HotSpotCompiledCode compiledCode(CompilationResult result) { - return stub.getCompiledCode(backend); + return HotSpotCompiledCodeBuilder.createCompiledCode(null, null, result); } }
--- a/src/jdk.hotspot.agent/linux/native/libsaproc/libproc_impl.c Fri Feb 10 09:03:55 2017 +0000 +++ b/src/jdk.hotspot.agent/linux/native/libsaproc/libproc_impl.c Thu Feb 09 23:35:22 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,7 +50,7 @@ } - if (strlen(alt_root) + strlen(name) < PATH_MAX) { + if (strlen(alt_root) + strlen(name) > PATH_MAX) { // Buffer too small. return -1; }
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/AbstractHeapGraphWriter.java Fri Feb 10 09:03:55 2017 +0000 +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/AbstractHeapGraphWriter.java Thu Feb 09 23:35:22 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -114,6 +114,8 @@ } }); + writeHeapRecordPrologue(); + // write JavaThreads writeJavaThreads();
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java Fri Feb 10 09:03:55 2017 +0000 +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java Thu Feb 09 23:35:22 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,8 +45,8 @@ * WARNING: This format is still under development, and is subject to * change without notice. * - * header "JAVA PROFILE 1.0.1" or "JAVA PROFILE 1.0.2" (0-terminated) - * u4 size of identifiers. Identifiers are used to represent + * header "JAVA PROFILE 1.0.2" (0-terminated) + * u4 size of identifiers. Identifiers are used to represent * UTF8 strings, objects, stack traces, etc. They usually * have the same size as host pointers. For example, on * Solaris and Win32, the size is 4. @@ -294,10 +294,9 @@ * u2 stack trace depth * * - * When the header is "JAVA PROFILE 1.0.2" a heap dump can optionally - * be generated as a sequence of heap dump segments. This sequence is - * terminated by an end record. The additional tags allowed by format - * "JAVA PROFILE 1.0.2" are: + * A heap dump can optionally be generated as a sequence of heap dump + * segments. This sequence is terminated by an end record. The additional + * tags allowed by format "JAVA PROFILE 1.0.2" are: * * HPROF_HEAP_DUMP_SEGMENT denote a heap dump segment * @@ -310,8 +309,6 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter { - // The heap size threshold used to determine if segmented format - // ("JAVA PROFILE 1.0.2") should be used. private static final long HPROF_SEGMENTED_HEAP_DUMP_THRESHOLD = 2L * 0x40000000; // The approximate size of a heap segment. Used to calculate when to create @@ -319,7 +316,6 @@ private static final long HPROF_SEGMENTED_HEAP_DUMP_SEGMENT_SIZE = 1L * 0x40000000; // hprof binary file header - private static final String HPROF_HEADER_1_0_1 = "JAVA PROFILE 1.0.1"; private static final String HPROF_HEADER_1_0_2 = "JAVA PROFILE 1.0.2"; // constants in enum HprofTag @@ -380,6 +376,7 @@ private static final int JVM_SIGNATURE_ARRAY = '['; private static final int JVM_SIGNATURE_CLASS = 'L'; + private static final long MAX_U4_VALUE = 0xFFFFFFFFL; int serialNum = 1; public synchronized void write(String fileName) throws IOException { @@ -469,7 +466,6 @@ // length later - hprof format requires length. out.flush(); currentSegmentStart = fos.getChannel().position(); - // write dummy length of 0 and we'll fix it later. out.writeInt(0); } @@ -479,7 +475,7 @@ protected void writeHeapRecordEpilogue() throws IOException { if (useSegmentedHeapDump) { out.flush(); - if ((fos.getChannel().position() - currentSegmentStart - 4) >= HPROF_SEGMENTED_HEAP_DUMP_SEGMENT_SIZE) { + if ((fos.getChannel().position() - currentSegmentStart - 4L) >= HPROF_SEGMENTED_HEAP_DUMP_SEGMENT_SIZE) { fillInHeapRecordLength(); currentSegmentStart = 0; } @@ -488,14 +484,14 @@ private void fillInHeapRecordLength() throws IOException { - // now get current position to calculate length + // now get the current position to calculate length long dumpEnd = fos.getChannel().position(); - // calculate length of heap data + // calculate the length of heap data long dumpLenLong = (dumpEnd - currentSegmentStart - 4L); // Check length boundary, overflow could happen but is _very_ unlikely - if(dumpLenLong >= (4L * 0x40000000)){ + if (dumpLenLong >= (4L * 0x40000000)) { throw new RuntimeException("Heap segment size overflow."); } @@ -517,6 +513,71 @@ fos.getChannel().position(currentPosition); } + // get the size in bytes for the requested type + private long getSizeForType(int type) throws IOException { + switch (type) { + case TypeArrayKlass.T_BOOLEAN: + return BOOLEAN_SIZE; + case TypeArrayKlass.T_INT: + return INT_SIZE; + case TypeArrayKlass.T_CHAR: + return CHAR_SIZE; + case TypeArrayKlass.T_SHORT: + return SHORT_SIZE; + case TypeArrayKlass.T_BYTE: + return BYTE_SIZE; + case TypeArrayKlass.T_LONG: + return LONG_SIZE; + case TypeArrayKlass.T_FLOAT: + return FLOAT_SIZE; + case TypeArrayKlass.T_DOUBLE: + return DOUBLE_SIZE; + default: + throw new RuntimeException( + "Should not reach here: Unknown type: " + type); + } + } + + private int getArrayHeaderSize(boolean isObjectAarray) { + return isObjectAarray? + ((int) BYTE_SIZE + 2 * (int) INT_SIZE + 2 * (int) OBJ_ID_SIZE): + (2 * (int) BYTE_SIZE + 2 * (int) INT_SIZE + (int) OBJ_ID_SIZE); + } + + // Check if we need to truncate an array + private int calculateArrayMaxLength(long originalArrayLength, + int headerSize, + long typeSize, + String typeName) throws IOException { + + long length = originalArrayLength; + + // now get the current position to calculate length + long dumpEnd = fos.getChannel().position(); + long originalLengthInBytes = originalArrayLength * typeSize; + + // calculate the length of heap data + long currentRecordLength = (dumpEnd - currentSegmentStart - 4L); + if (currentRecordLength > 0 && + (currentRecordLength + headerSize + originalLengthInBytes) > MAX_U4_VALUE) { + fillInHeapRecordLength(); + currentSegmentStart = 0; + writeHeapRecordPrologue(); + currentRecordLength = 0; + } + + // Calculate the max bytes we can use. + long maxBytes = (MAX_U4_VALUE - (headerSize + currentRecordLength)); + + if (originalLengthInBytes > maxBytes) { + length = maxBytes/typeSize; + System.err.println("WARNING: Cannot dump array of type " + typeName + + " with length " + originalArrayLength + + "; truncating to length " + length); + } + return (int) length; + } + private void writeClassDumpRecords() throws IOException { SystemDictionary sysDict = VM.getVM().getSystemDictionary(); ClassLoaderDataGraph cldGraph = VM.getVM().getClassLoaderDataGraph(); @@ -694,12 +755,16 @@ } protected void writeObjectArray(ObjArray array) throws IOException { + int headerSize = getArrayHeaderSize(true); + final int length = calculateArrayMaxLength(array.getLength(), + headerSize, + OBJ_ID_SIZE, + "Object"); out.writeByte((byte) HPROF_GC_OBJ_ARRAY_DUMP); writeObjectID(array); out.writeInt(DUMMY_STACK_TRACE_ID); - out.writeInt((int) array.getLength()); + out.writeInt(length); writeObjectID(array.getKlass().getJavaMirror()); - final int length = (int) array.getLength(); for (int index = 0; index < length; index++) { OopHandle handle = array.getOopHandleAt(index); writeObjectID(getAddressValue(handle)); @@ -707,101 +772,101 @@ } protected void writePrimitiveArray(TypeArray array) throws IOException { + int headerSize = getArrayHeaderSize(false); + TypeArrayKlass tak = (TypeArrayKlass) array.getKlass(); + final int type = (int) tak.getElementType(); + final String typeName = tak.getElementTypeName(); + final long typeSize = getSizeForType(type); + final int length = calculateArrayMaxLength(array.getLength(), + headerSize, + typeSize, + typeName); out.writeByte((byte) HPROF_GC_PRIM_ARRAY_DUMP); writeObjectID(array); out.writeInt(DUMMY_STACK_TRACE_ID); - out.writeInt((int) array.getLength()); - TypeArrayKlass tak = (TypeArrayKlass) array.getKlass(); - final int type = (int) tak.getElementType(); + out.writeInt(length); out.writeByte((byte) type); switch (type) { case TypeArrayKlass.T_BOOLEAN: - writeBooleanArray(array); + writeBooleanArray(array, length); break; case TypeArrayKlass.T_CHAR: - writeCharArray(array); + writeCharArray(array, length); break; case TypeArrayKlass.T_FLOAT: - writeFloatArray(array); + writeFloatArray(array, length); break; case TypeArrayKlass.T_DOUBLE: - writeDoubleArray(array); + writeDoubleArray(array, length); break; case TypeArrayKlass.T_BYTE: - writeByteArray(array); + writeByteArray(array, length); break; case TypeArrayKlass.T_SHORT: - writeShortArray(array); + writeShortArray(array, length); break; case TypeArrayKlass.T_INT: - writeIntArray(array); + writeIntArray(array, length); break; case TypeArrayKlass.T_LONG: - writeLongArray(array); + writeLongArray(array, length); break; default: - throw new RuntimeException("should not reach here"); + throw new RuntimeException( + "Should not reach here: Unknown type: " + type); } } - private void writeBooleanArray(TypeArray array) throws IOException { - final int length = (int) array.getLength(); + private void writeBooleanArray(TypeArray array, int length) throws IOException { for (int index = 0; index < length; index++) { long offset = BOOLEAN_BASE_OFFSET + index * BOOLEAN_SIZE; out.writeBoolean(array.getHandle().getJBooleanAt(offset)); } } - private void writeByteArray(TypeArray array) throws IOException { - final int length = (int) array.getLength(); + private void writeByteArray(TypeArray array, int length) throws IOException { for (int index = 0; index < length; index++) { long offset = BYTE_BASE_OFFSET + index * BYTE_SIZE; out.writeByte(array.getHandle().getJByteAt(offset)); } } - private void writeShortArray(TypeArray array) throws IOException { - final int length = (int) array.getLength(); + private void writeShortArray(TypeArray array, int length) throws IOException { for (int index = 0; index < length; index++) { long offset = SHORT_BASE_OFFSET + index * SHORT_SIZE; out.writeShort(array.getHandle().getJShortAt(offset)); } } - private void writeIntArray(TypeArray array) throws IOException { - final int length = (int) array.getLength(); + private void writeIntArray(TypeArray array, int length) throws IOException { for (int index = 0; index < length; index++) { long offset = INT_BASE_OFFSET + index * INT_SIZE; out.writeInt(array.getHandle().getJIntAt(offset)); } } - private void writeLongArray(TypeArray array) throws IOException { - final int length = (int) array.getLength(); + private void writeLongArray(TypeArray array, int length) throws IOException { for (int index = 0; index < length; index++) { long offset = LONG_BASE_OFFSET + index * LONG_SIZE; out.writeLong(array.getHandle().getJLongAt(offset)); } } - private void writeCharArray(TypeArray array) throws IOException { - final int length = (int) array.getLength(); + private void writeCharArray(TypeArray array, int length) throws IOException { for (int index = 0; index < length; index++) { long offset = CHAR_BASE_OFFSET + index * CHAR_SIZE; out.writeChar(array.getHandle().getJCharAt(offset)); } } - private void writeFloatArray(TypeArray array) throws IOException { - final int length = (int) array.getLength(); + private void writeFloatArray(TypeArray array, int length) throws IOException { for (int index = 0; index < length; index++) { long offset = FLOAT_BASE_OFFSET + index * FLOAT_SIZE; out.writeFloat(array.getHandle().getJFloatAt(offset)); } } - private void writeDoubleArray(TypeArray array) throws IOException { - final int length = (int) array.getLength(); + private void writeDoubleArray(TypeArray array, int length) throws IOException { for (int index = 0; index < length; index++) { long offset = DOUBLE_BASE_OFFSET + index * DOUBLE_SIZE; out.writeDouble(array.getHandle().getJDoubleAt(offset)); @@ -996,12 +1061,7 @@ // writes hprof binary file header private void writeFileHeader() throws IOException { // version string - if(useSegmentedHeapDump) { - out.writeBytes(HPROF_HEADER_1_0_2); - } - else { - out.writeBytes(HPROF_HEADER_1_0_1); - } + out.writeBytes(HPROF_HEADER_1_0_2); out.writeByte((byte)'\0'); // write identifier size. we use pointers as identifiers.
--- a/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIMetaAccessContext.java Fri Feb 10 09:03:55 2017 +0000 +++ b/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIMetaAccessContext.java Thu Feb 09 23:35:22 2017 +0100 @@ -27,8 +27,6 @@ import java.lang.ref.WeakReference; import java.util.Arrays; import java.util.Iterator; -import java.util.Map; -import java.util.WeakHashMap; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaType; @@ -147,21 +145,34 @@ } } - private final Map<Class<?>, WeakReference<ResolvedJavaType>> typeMap = new WeakHashMap<>(); + private final ClassValue<WeakReference<ResolvedJavaType>> resolvedJavaType = new ClassValue<WeakReference<ResolvedJavaType>>() { + @Override + protected WeakReference<ResolvedJavaType> computeValue(Class<?> type) { + return new WeakReference<>(createClass(type)); + } + }; /** * Gets the JVMCI mirror for a {@link Class} object. * * @return the {@link ResolvedJavaType} corresponding to {@code javaClass} */ - public synchronized ResolvedJavaType fromClass(Class<?> javaClass) { - WeakReference<ResolvedJavaType> typeRef = typeMap.get(javaClass); - ResolvedJavaType type = typeRef != null ? typeRef.get() : null; - if (type == null) { - type = createClass(javaClass); - typeMap.put(javaClass, new WeakReference<>(type)); + public ResolvedJavaType fromClass(Class<?> javaClass) { + ResolvedJavaType javaType = null; + while (javaType == null) { + WeakReference<ResolvedJavaType> type = resolvedJavaType.get(javaClass); + javaType = type.get(); + if (javaType == null) { + /* + * If the referent has become null, clear out the current value + * and let computeValue above create a new value. Reload the + * value in a loop because in theory the WeakReference referent + * can be reclaimed at any point. + */ + resolvedJavaType.remove(javaClass); + } } - return type; + return javaType; } /**
--- a/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java Fri Feb 10 09:03:55 2017 +0000 +++ b/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java Thu Feb 09 23:35:22 2017 +0100 @@ -90,17 +90,10 @@ protected InstalledCode code; /** - * Compilation result from which {@link #code} was created. - */ - protected CompilationResult compResult; - - /** * The registers destroyed by this stub (from the caller's perspective). */ private Set<Register> destroyedCallerRegisters; - private HotSpotCompiledCode compiledCode; - public void initDestroyedCallerRegisters(Set<Register> registers) { assert registers != null; assert destroyedCallerRegisters == null || registers.equals(destroyedCallerRegisters) : "cannot redefine"; @@ -184,35 +177,13 @@ public synchronized InstalledCode getCode(final Backend backend) { if (code == null) { try (Scope d = Debug.sandbox("CompilingStub", DebugScope.getConfig(), providers.getCodeCache(), debugScopeContext())) { - final StructuredGraph graph = getGraph(getStubCompilationId()); - - // Stubs cannot be recompiled so they cannot be compiled with assumptions - assert graph.getAssumptions() == null; - - if (!(graph.start() instanceof StubStartNode)) { - StubStartNode newStart = graph.add(new StubStartNode(Stub.this)); - newStart.setStateAfter(graph.start().stateAfter()); - graph.replaceFixed(graph.start(), newStart); - } - CodeCacheProvider codeCache = providers.getCodeCache(); - - compResult = new CompilationResult(toString(), GeneratePIC.getValue()); - try (Scope s0 = Debug.scope("StubCompilation", graph, providers.getCodeCache())) { - Suites suites = createSuites(); - emitFrontEnd(providers, backend, graph, providers.getSuites().getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL, DefaultProfilingInfo.get(TriState.UNKNOWN), suites); - LIRSuites lirSuites = createLIRSuites(); - emitBackEnd(graph, Stub.this, getInstalledCodeOwner(), backend, compResult, CompilationResultBuilderFactory.Default, getRegisterConfig(), lirSuites); - assert checkStubInvariants(); - } catch (Throwable e) { - throw Debug.handle(e); - } - - assert destroyedCallerRegisters != null; + CompilationResult compResult = buildCompilationResult(backend); try (Scope s = Debug.scope("CodeInstall", compResult)) { + assert destroyedCallerRegisters != null; // Add a GeneratePIC check here later, we don't want to install // code if we don't have a corresponding VM global symbol. - compiledCode = HotSpotCompiledCodeBuilder.createCompiledCode(null, null, compResult); + HotSpotCompiledCode compiledCode = HotSpotCompiledCodeBuilder.createCompiledCode(null, null, compResult); code = codeCache.installCode(null, compiledCode, null, null, false); } catch (Throwable e) { throw Debug.handle(e); @@ -226,6 +197,44 @@ return code; } + @SuppressWarnings("try") + private CompilationResult buildCompilationResult(final Backend backend) { + CompilationResult compResult = new CompilationResult(toString(), GeneratePIC.getValue()); + final StructuredGraph graph = getGraph(getStubCompilationId()); + + // Stubs cannot be recompiled so they cannot be compiled with assumptions + assert graph.getAssumptions() == null; + + if (!(graph.start() instanceof StubStartNode)) { + StubStartNode newStart = graph.add(new StubStartNode(Stub.this)); + newStart.setStateAfter(graph.start().stateAfter()); + graph.replaceFixed(graph.start(), newStart); + } + + try (Scope s0 = Debug.scope("StubCompilation", graph, providers.getCodeCache())) { + Suites suites = createSuites(); + emitFrontEnd(providers, backend, graph, providers.getSuites().getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL, DefaultProfilingInfo.get(TriState.UNKNOWN), suites); + LIRSuites lirSuites = createLIRSuites(); + emitBackEnd(graph, Stub.this, getInstalledCodeOwner(), backend, compResult, CompilationResultBuilderFactory.Default, getRegisterConfig(), lirSuites); + assert checkStubInvariants(compResult); + } catch (Throwable e) { + throw Debug.handle(e); + } + return compResult; + } + + /** + * Gets a {@link CompilationResult} that can be used for code generation. Required for AOT. + */ + @SuppressWarnings("try") + public CompilationResult getCompilationResult(final Backend backend) { + try (Scope d = Debug.sandbox("CompilingStub", DebugScope.getConfig(), providers.getCodeCache(), debugScopeContext())) { + return buildCompilationResult(backend); + } catch (Throwable e) { + throw Debug.handle(e); + } + } + public CompilationIdentifier getStubCompilationId() { return new StubCompilationIdentifier(this); } @@ -233,7 +242,7 @@ /** * Checks the conditions a compilation must satisfy to be installed as a RuntimeStub. */ - private boolean checkStubInvariants() { + private boolean checkStubInvariants(CompilationResult compResult) { assert compResult.getExceptionHandlers().isEmpty() : this; // Stubs cannot be recompiled so they cannot be compiled with @@ -278,24 +287,4 @@ } return lirSuites; } - - /** - * Gets the HotSpotCompiledCode that was created during installation. - */ - public synchronized HotSpotCompiledCode getCompiledCode(final Backend backend) { - getCompilationResult(backend); - assert compiledCode != null; - return compiledCode; - } - - /** - * Gets the compilation result for this stub, compiling it first if necessary, and installing it - * in code. - */ - public synchronized CompilationResult getCompilationResult(final Backend backend) { - if (code == null) { - getCode(backend); - } - return compResult; - } }
--- a/src/share/vm/c1/c1_Canonicalizer.cpp Fri Feb 10 09:03:55 2017 +0000 +++ b/src/share/vm/c1/c1_Canonicalizer.cpp Thu Feb 09 23:35:22 2017 +0100 @@ -248,7 +248,9 @@ } else if ((lf = x->array()->as_LoadField()) != NULL) { ciField* field = lf->field(); if (field->is_static_constant()) { - assert(PatchALot || ScavengeRootsInCode < 2, "Constant field loads are folded during parsing"); + // Constant field loads are usually folded during parsing. + // But it doesn't happen with PatchALot, ScavengeRootsInCode < 2, or when + // holder class is being initialized during parsing (for static fields). ciObject* c = field->constant_value().as_object(); if (!c->is_null_object()) { set_constant(c->as_array()->length());
--- a/src/share/vm/c1/c1_LIR.cpp Fri Feb 10 09:03:55 2017 +0000 +++ b/src/share/vm/c1/c1_LIR.cpp Thu Feb 09 23:35:22 2017 +0100 @@ -1413,6 +1413,17 @@ append(c); } +void LIR_List::null_check(LIR_Opr opr, CodeEmitInfo* info, bool deoptimize_on_null) { + if (deoptimize_on_null) { + // Emit an explicit null check and deoptimize if opr is null + CodeStub* deopt = new DeoptimizeStub(info, Deoptimization::Reason_null_check, Deoptimization::Action_none); + cmp(lir_cond_equal, opr, LIR_OprFact::oopConst(NULL)); + branch(lir_cond_equal, T_OBJECT, deopt); + } else { + // Emit an implicit null check + append(new LIR_Op1(lir_null_check, opr, info)); + } +} void LIR_List::cas_long(LIR_Opr addr, LIR_Opr cmp_value, LIR_Opr new_value, LIR_Opr t1, LIR_Opr t2, LIR_Opr result) {
--- a/src/share/vm/c1/c1_LIR.hpp Fri Feb 10 09:03:55 2017 +0000 +++ b/src/share/vm/c1/c1_LIR.hpp Thu Feb 09 23:35:22 2017 +0100 @@ -2113,7 +2113,7 @@ void pack64(LIR_Opr src, LIR_Opr dst) { append(new LIR_Op1(lir_pack64, src, dst, T_LONG, lir_patch_none, NULL)); } void unpack64(LIR_Opr src, LIR_Opr dst) { append(new LIR_Op1(lir_unpack64, src, dst, T_LONG, lir_patch_none, NULL)); } - void null_check(LIR_Opr opr, CodeEmitInfo* info) { append(new LIR_Op1(lir_null_check, opr, info)); } + void null_check(LIR_Opr opr, CodeEmitInfo* info, bool deoptimize_on_null = false); void throw_exception(LIR_Opr exceptionPC, LIR_Opr exceptionOop, CodeEmitInfo* info) { append(new LIR_Op2(lir_throw, exceptionPC, exceptionOop, LIR_OprFact::illegalOpr, info)); }
--- a/src/share/vm/c1/c1_LIRGenerator.cpp Fri Feb 10 09:03:55 2017 +0000 +++ b/src/share/vm/c1/c1_LIRGenerator.cpp Thu Feb 09 23:35:22 2017 +0100 @@ -1752,8 +1752,10 @@ if (x->needs_null_check() && (needs_patching || MacroAssembler::needs_explicit_null_check(x->offset()))) { - // emit an explicit null check because the offset is too large - __ null_check(object.result(), new CodeEmitInfo(info)); + // Emit an explicit null check because the offset is too large. + // If the class is not loaded and the object is NULL, we need to deoptimize to throw a + // NoClassDefFoundError in the interpreter instead of an implicit NPE from compiled code. + __ null_check(object.result(), new CodeEmitInfo(info), /* deoptimize */ needs_patching); } LIR_Address* address; @@ -1838,8 +1840,10 @@ obj = new_register(T_OBJECT); __ move(LIR_OprFact::oopConst(NULL), obj); } - // emit an explicit null check because the offset is too large - __ null_check(obj, new CodeEmitInfo(info)); + // Emit an explicit null check because the offset is too large. + // If the class is not loaded and the object is NULL, we need to deoptimize to throw a + // NoClassDefFoundError in the interpreter instead of an implicit NPE from compiled code. + __ null_check(obj, new CodeEmitInfo(info), /* deoptimize */ needs_patching); } LIR_Opr reg = rlock_result(x, field_type);
--- a/src/share/vm/ci/ciEnv.cpp Fri Feb 10 09:03:55 2017 +0000 +++ b/src/share/vm/ci/ciEnv.cpp Thu Feb 09 23:35:22 2017 +0100 @@ -101,6 +101,7 @@ _debug_info = NULL; _dependencies = NULL; _failure_reason = NULL; + _inc_decompile_count_on_failure = true; _compilable = MethodCompilable; _break_at_compile = false; _compiler_data = NULL; @@ -161,6 +162,7 @@ _debug_info = NULL; _dependencies = NULL; _failure_reason = NULL; + _inc_decompile_count_on_failure = true; _compilable = MethodCompilable_never; _break_at_compile = false; _compiler_data = NULL; @@ -902,7 +904,12 @@ if (deps.is_klass_type()) continue; // skip klass dependencies Klass* witness = deps.check_dependency(); if (witness != NULL) { - record_failure("invalid non-klass dependency"); + if (deps.type() == Dependencies::call_site_target_value) { + _inc_decompile_count_on_failure = false; + record_failure("call site target change"); + } else { + record_failure("invalid non-klass dependency"); + } return; } } @@ -1017,7 +1024,7 @@ if (failing()) { // While not a true deoptimization, it is a preemptive decompile. MethodData* mdo = method()->method_data(); - if (mdo != NULL) { + if (mdo != NULL && _inc_decompile_count_on_failure) { mdo->inc_decompile_count(); }
--- a/src/share/vm/ci/ciEnv.hpp Fri Feb 10 09:03:55 2017 +0000 +++ b/src/share/vm/ci/ciEnv.hpp Thu Feb 09 23:35:22 2017 +0100 @@ -55,6 +55,7 @@ DebugInformationRecorder* _debug_info; Dependencies* _dependencies; const char* _failure_reason; + bool _inc_decompile_count_on_failure; int _compilable; bool _break_at_compile; int _num_inlined_bytecodes;
--- a/src/share/vm/classfile/javaClasses.cpp Fri Feb 10 09:03:55 2017 +0000 +++ b/src/share/vm/classfile/javaClasses.cpp Thu Feb 09 23:35:22 2017 +0100 @@ -2269,6 +2269,7 @@ compute_offset(_monitors_offset, k, vmSymbols::monitors_name(), vmSymbols::object_array_signature()); compute_offset(_locals_offset, k, vmSymbols::locals_name(), vmSymbols::object_array_signature()); compute_offset(_operands_offset, k, vmSymbols::operands_name(), vmSymbols::object_array_signature()); + compute_offset(_mode_offset, k, vmSymbols::mode_name(), vmSymbols::int_signature()); } void java_lang_reflect_AccessibleObject::compute_offsets() { @@ -3658,6 +3659,7 @@ int java_lang_LiveStackFrameInfo::_monitors_offset; int java_lang_LiveStackFrameInfo::_locals_offset; int java_lang_LiveStackFrameInfo::_operands_offset; +int java_lang_LiveStackFrameInfo::_mode_offset; int java_lang_AssertionStatusDirectives::classes_offset; int java_lang_AssertionStatusDirectives::classEnabled_offset; int java_lang_AssertionStatusDirectives::packages_offset; @@ -3728,6 +3730,10 @@ element->obj_field_put(_operands_offset, value); } +void java_lang_LiveStackFrameInfo::set_mode(oop element, int value) { + element->int_field_put(_mode_offset, value); +} + // Support for java Assertions - java_lang_AssertionStatusDirectives. void java_lang_AssertionStatusDirectives::set_classes(oop o, oop val) {
--- a/src/share/vm/classfile/javaClasses.hpp Fri Feb 10 09:03:55 2017 +0000 +++ b/src/share/vm/classfile/javaClasses.hpp Thu Feb 09 23:35:22 2017 +0100 @@ -1380,11 +1380,13 @@ static int _monitors_offset; static int _locals_offset; static int _operands_offset; + static int _mode_offset; public: static void set_monitors(oop info, oop value); static void set_locals(oop info, oop value); static void set_operands(oop info, oop value); + static void set_mode(oop info, int value); static void compute_offsets();
--- a/src/share/vm/classfile/vmSymbols.hpp Fri Feb 10 09:03:55 2017 +0000 +++ b/src/share/vm/classfile/vmSymbols.hpp Thu Feb 09 23:35:22 2017 +0100 @@ -325,14 +325,8 @@ template(java_lang_StackStreamFactory_AbstractStackWalker, "java/lang/StackStreamFactory$AbstractStackWalker") \ template(doStackWalk_signature, "(JIIII)Ljava/lang/Object;") \ template(asPrimitive_name, "asPrimitive") \ - template(asPrimitive_int_signature, "(I)Ljava/lang/LiveStackFrame$PrimitiveValue;") \ - template(asPrimitive_long_signature, "(J)Ljava/lang/LiveStackFrame$PrimitiveValue;") \ - template(asPrimitive_short_signature, "(S)Ljava/lang/LiveStackFrame$PrimitiveValue;") \ - template(asPrimitive_byte_signature, "(B)Ljava/lang/LiveStackFrame$PrimitiveValue;") \ - template(asPrimitive_char_signature, "(C)Ljava/lang/LiveStackFrame$PrimitiveValue;") \ - template(asPrimitive_float_signature, "(F)Ljava/lang/LiveStackFrame$PrimitiveValue;") \ - template(asPrimitive_double_signature, "(D)Ljava/lang/LiveStackFrame$PrimitiveValue;") \ - template(asPrimitive_boolean_signature, "(Z)Ljava/lang/LiveStackFrame$PrimitiveValue;") \ + template(asPrimitive_int_signature, "(I)Ljava/lang/LiveStackFrame$PrimitiveSlot;") \ + template(asPrimitive_long_signature, "(J)Ljava/lang/LiveStackFrame$PrimitiveSlot;") \ \ /* common method and field names */ \ template(object_initializer_name, "<init>") \ @@ -444,6 +438,7 @@ template(monitors_name, "monitors") \ template(locals_name, "locals") \ template(operands_name, "operands") \ + template(mode_name, "mode") \ template(oop_size_name, "oop_size") \ template(static_oop_field_count_name, "static_oop_field_count") \ template(protection_domain_name, "protection_domain") \
--- a/src/share/vm/code/codeCache.cpp Fri Feb 10 09:03:55 2017 +0000 +++ b/src/share/vm/code/codeCache.cpp Thu Feb 09 23:35:22 2017 +0100 @@ -1211,7 +1211,7 @@ CompiledMethodIterator iter; while(iter.next_alive()) { CompiledMethod* nm = iter.method(); - if (nm->is_marked_for_deoptimization()) { + if (nm->is_marked_for_deoptimization() && !nm->is_not_entrant()) { nm->make_not_entrant(); } }
--- a/src/share/vm/code/nmethod.cpp Fri Feb 10 09:03:55 2017 +0000 +++ b/src/share/vm/code/nmethod.cpp Thu Feb 09 23:35:22 2017 +0100 @@ -1146,6 +1146,14 @@ assert(state == zombie || state == not_entrant, "must be zombie or not_entrant"); assert(!is_zombie(), "should not already be a zombie"); + if (_state == state) { + // Avoid taking the lock if already in required state. + // This is safe from races because the state is an end-state, + // which the nmethod cannot back out of once entered. + // No need for fencing either. + return false; + } + // Make sure neither the nmethod nor the method is flushed in case of a safepoint in code below. nmethodLocker nml(this); methodHandle the_method(method());
--- a/src/share/vm/gc/g1/heapRegionRemSet.cpp Fri Feb 10 09:03:55 2017 +0000 +++ b/src/share/vm/gc/g1/heapRegionRemSet.cpp Thu Feb 09 23:35:22 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -711,29 +711,6 @@ guarantee(G1RSetSparseRegionEntries > 0 && G1RSetRegionEntries > 0 , "Sanity"); } -#ifndef PRODUCT -void HeapRegionRemSet::print() { - HeapRegionRemSetIterator iter(this); - size_t card_index; - while (iter.has_next(card_index)) { - HeapWord* card_start = _bot->address_for_index(card_index); - tty->print_cr(" Card " PTR_FORMAT, p2i(card_start)); - } - if (iter.n_yielded() != occupied()) { - tty->print_cr("Yielded disagrees with occupied:"); - tty->print_cr(" " SIZE_FORMAT_W(6) " yielded (" SIZE_FORMAT_W(6) - " coarse, " SIZE_FORMAT_W(6) " fine).", - iter.n_yielded(), - iter.n_yielded_coarse(), iter.n_yielded_fine()); - tty->print_cr(" " SIZE_FORMAT_W(6) " occ (" SIZE_FORMAT_W(6) - " coarse, " SIZE_FORMAT_W(6) " fine).", - occupied(), occ_coarse(), occ_fine()); - } - guarantee(iter.n_yielded() == occupied(), - "We should have yielded all the represented cards."); -} -#endif - void HeapRegionRemSet::cleanup() { SparsePRT::cleanup_all(); } @@ -917,10 +894,6 @@ // Otherwise... break; } - assert(ParallelGCThreads > 1 || - n_yielded() == _hrrs->occupied(), - "Should have yielded all the cards in the rem set " - "(in the non-par case)."); return false; }
--- a/src/share/vm/gc/g1/heapRegionRemSet.hpp Fri Feb 10 09:03:55 2017 +0000 +++ b/src/share/vm/gc/g1/heapRegionRemSet.hpp Thu Feb 09 23:35:22 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -290,8 +290,6 @@ // consumed by the strong code roots. size_t strong_code_roots_mem_size(); - void print() PRODUCT_RETURN; - // Called during a stop-world phase to perform any deferred cleanups. static void cleanup();
--- a/src/share/vm/opto/type.cpp Fri Feb 10 09:03:55 2017 +0000 +++ b/src/share/vm/opto/type.cpp Thu Feb 09 23:35:22 2017 +0100 @@ -373,7 +373,7 @@ if (con_type != NULL && field->is_call_site_target()) { ciCallSite* call_site = holder->as_call_site(); if (!call_site->is_constant_call_site()) { - ciMethodHandle* target = call_site->get_target(); + ciMethodHandle* target = con.as_object()->as_method_handle(); Compile::current()->dependencies()->assert_call_site_target_value(call_site, target); } }
--- a/src/share/vm/prims/jvmtiExport.cpp Fri Feb 10 09:03:55 2017 +0000 +++ b/src/share/vm/prims/jvmtiExport.cpp Thu Feb 09 23:35:22 2017 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1230,8 +1230,12 @@ assert(thread->is_VM_thread(), "wrong thread"); // get JavaThread for whom we are proxy - JavaThread *real_thread = - (JavaThread *)((VMThread *)thread)->vm_operation()->calling_thread(); + Thread *calling_thread = ((VMThread *)thread)->vm_operation()->calling_thread(); + if (!calling_thread->is_Java_thread()) { + // cannot post an event to a non-JavaThread + return; + } + JavaThread *real_thread = (JavaThread *)calling_thread; JvmtiEnvIterator it; for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
--- a/src/share/vm/prims/stackwalk.cpp Fri Feb 10 09:03:55 2017 +0000 +++ b/src/share/vm/prims/stackwalk.cpp Thu Feb 09 23:35:22 2017 +0100 @@ -173,7 +173,11 @@ } } -oop LiveFrameStream::create_primitive_value_instance(StackValueCollection* values, int i, TRAPS) { +// Create and return a LiveStackFrame.PrimitiveSlot (if needed) for the +// StackValue at the given index. 'type' is expected to be T_INT, T_LONG, +// T_OBJECT, or T_CONFLICT. +oop LiveFrameStream::create_primitive_slot_instance(StackValueCollection* values, + int i, BasicType type, TRAPS) { Klass* k = SystemDictionary::resolve_or_null(vmSymbols::java_lang_LiveStackFrameInfo(), CHECK_NULL); instanceKlassHandle ik (THREAD, k); @@ -182,8 +186,8 @@ Symbol* signature = NULL; // ## TODO: type is only available in LocalVariable table, if present. - // ## StackValue type is T_INT or T_OBJECT. - switch (values->at(i)->type()) { + // ## StackValue type is T_INT or T_OBJECT (or converted to T_LONG on 64-bit) + switch (type) { case T_INT: args.push_int(values->int_at(i)); signature = vmSymbols::asPrimitive_int_signature(); @@ -195,42 +199,26 @@ break; case T_FLOAT: - args.push_float(values->float_at(i)); - signature = vmSymbols::asPrimitive_float_signature(); - break; - case T_DOUBLE: - args.push_double(values->double_at(i)); - signature = vmSymbols::asPrimitive_double_signature(); - break; - case T_BYTE: - args.push_int(values->int_at(i)); - signature = vmSymbols::asPrimitive_byte_signature(); - break; - case T_SHORT: - args.push_int(values->int_at(i)); - signature = vmSymbols::asPrimitive_short_signature(); - break; - case T_CHAR: - args.push_int(values->int_at(i)); - signature = vmSymbols::asPrimitive_char_signature(); - break; - case T_BOOLEAN: - args.push_int(values->int_at(i)); - signature = vmSymbols::asPrimitive_boolean_signature(); - break; + THROW_MSG_(vmSymbols::java_lang_InternalError(), "Unexpected StackValue type", NULL); case T_OBJECT: return values->obj_at(i)(); case T_CONFLICT: // put a non-null slot - args.push_int(0); - signature = vmSymbols::asPrimitive_int_signature(); + #ifdef _LP64 + args.push_long(0); + signature = vmSymbols::asPrimitive_long_signature(); + #else + args.push_int(0); + signature = vmSymbols::asPrimitive_int_signature(); + #endif + break; default: ShouldNotReachHere(); @@ -252,9 +240,19 @@ objArrayHandle array_h(THREAD, array_oop); for (int i = 0; i < values->size(); i++) { StackValue* st = values->at(i); - oop obj = create_primitive_value_instance(values, i, CHECK_(empty)); - if (obj != NULL) + BasicType type = st->type(); + int index = i; +#ifdef _LP64 + if (type != T_OBJECT && type != T_CONFLICT) { + intptr_t ret = st->get_int(); // read full 64-bit slot + type = T_LONG; // treat as long + index--; // undo +1 in StackValueCollection::long_at + } +#endif + oop obj = create_primitive_slot_instance(values, index, type, CHECK_(empty)); + if (obj != NULL) { array_h->obj_at_put(i, obj); + } } return array_h; } @@ -286,6 +284,13 @@ StackValueCollection* expressions = _jvf->expressions(); GrowableArray<MonitorInfo*>* monitors = _jvf->monitors(); + int mode = 0; + if (_jvf->is_interpreted_frame()) { + mode = MODE_INTERPRETED; + } else if (_jvf->is_compiled_frame()) { + mode = MODE_COMPILED; + } + if (!locals->is_empty()) { objArrayHandle locals_h = values_to_object_array(locals, CHECK); java_lang_LiveStackFrameInfo::set_locals(stackFrame(), locals_h()); @@ -298,6 +303,7 @@ objArrayHandle monitors_h = monitors_to_object_array(monitors, CHECK); java_lang_LiveStackFrameInfo::set_monitors(stackFrame(), monitors_h()); } + java_lang_LiveStackFrameInfo::set_mode(stackFrame(), mode); } }
--- a/src/share/vm/prims/stackwalk.hpp Fri Feb 10 09:03:55 2017 +0000 +++ b/src/share/vm/prims/stackwalk.hpp Thu Feb 09 23:35:22 2017 +0100 @@ -92,11 +92,16 @@ class LiveFrameStream : public BaseFrameStream { private: + enum { + MODE_INTERPRETED = 0x01, + MODE_COMPILED = 0x02 + }; + javaVFrame* _jvf; void fill_live_stackframe(Handle stackFrame, const methodHandle& method, TRAPS); - static oop create_primitive_value_instance(StackValueCollection* values, - int i, TRAPS); + static oop create_primitive_slot_instance(StackValueCollection* values, + int i, BasicType type, TRAPS); static objArrayHandle monitors_to_object_array(GrowableArray<MonitorInfo*>* monitors, TRAPS); static objArrayHandle values_to_object_array(StackValueCollection* values, TRAPS);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/c1/TestUnresolvedField.jasm Thu Feb 09 23:35:22 2017 +0100 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +public class compiler/c1/TestUnresolvedField version 52:0 { + public static Method testGetField:"()V" stack 1 locals 1 { + aconst_null; + getfield Field T.f:I; // T does not exist + return; + } + + public static Method testPutField:"()V" stack 2 locals 1 { + aconst_null; + iconst_0; + putfield Field T.f:I; // T does not exist + return; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/c1/TestUnresolvedFieldMain.java Thu Feb 09 23:35:22 2017 +0100 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8173373 + * @compile TestUnresolvedField.jasm + * @run main/othervm -XX:TieredStopAtLevel=1 -Xcomp + * -XX:CompileCommand=compileonly,compiler.c1.TestUnresolvedField::test* + * compiler.c1.TestUnresolvedFieldMain + */ + +package compiler.c1; + +public class TestUnresolvedFieldMain { + public static void main(String[] args) { + try { + TestUnresolvedField.testGetField(); + } catch (java.lang.NoClassDefFoundError error) { + // Expected + } + try { + TestUnresolvedField.testPutField(); + } catch (java.lang.NoClassDefFoundError error) { + // Expected + } + } +}
--- a/test/compiler/jsr292/ContinuousCallSiteTargetChange.java Fri Feb 10 09:03:55 2017 +0000 +++ b/test/compiler/jsr292/ContinuousCallSiteTargetChange.java Thu Feb 09 23:35:22 2017 +0100 @@ -23,7 +23,6 @@ /** * @test - * @modules java.base/jdk.internal.misc * @library /test/lib / * * @run driver compiler.jsr292.ContinuousCallSiteTargetChange @@ -31,6 +30,7 @@ package compiler.jsr292; +import jdk.test.lib.Asserts; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; @@ -39,15 +39,26 @@ import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.lang.invoke.MutableCallSite; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; public class ContinuousCallSiteTargetChange { - static void testServer() throws Exception { + static final int ITERATIONS = Integer.parseInt(System.getProperty("iterations", "50")); + + static void runTest(Class<?> test, String... extraArgs) throws Exception { + List<String> argsList = new ArrayList<>( + List.of("-XX:+IgnoreUnrecognizedVMOptions", + "-XX:PerBytecodeRecompilationCutoff=10", "-XX:PerMethodRecompilationCutoff=10", + "-XX:+PrintCompilation", "-XX:+UnlockDiagnosticVMOptions", "-XX:+PrintInlining")); + + argsList.addAll(Arrays.asList(extraArgs)); + + argsList.add(test.getName()); + argsList.add(Integer.toString(ITERATIONS)); + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( - "-XX:+IgnoreUnrecognizedVMOptions", - "-server", "-XX:-TieredCompilation", "-Xbatch", - "-XX:PerBytecodeRecompilationCutoff=10", "-XX:PerMethodRecompilationCutoff=10", - "-XX:+PrintCompilation", "-XX:+UnlockDiagnosticVMOptions", "-XX:+PrintInlining", - Test.class.getName(), "100"); + argsList.toArray(new String[argsList.size()])); OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); @@ -55,30 +66,42 @@ analyzer.shouldNotContain("made not compilable"); analyzer.shouldNotContain("decompile_count > PerMethodRecompilationCutoff"); + } - static void testClient() throws Exception { - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( - "-XX:+IgnoreUnrecognizedVMOptions", - "-client", "-XX:+TieredCompilation", "-XX:TieredStopAtLevel=1", "-Xbatch", - "-XX:PerBytecodeRecompilationCutoff=10", "-XX:PerMethodRecompilationCutoff=10", - "-XX:+PrintCompilation", "-XX:+UnlockDiagnosticVMOptions", "-XX:+PrintInlining", - Test.class.getName(), "100"); + static void testServer(Class<?> test, String... args) throws Exception { + List<String> extraArgsList = new ArrayList<>( + List.of("-server", "-XX:-TieredCompilation")); + extraArgsList.addAll(Arrays.asList(args)); - OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); + runTest(test, extraArgsList.toArray(new String[extraArgsList.size()])); + } - analyzer.shouldHaveExitValue(0); + static void testClient(Class<?> test, String... args) throws Exception { + List<String> extraArgsList = new ArrayList<>( + List.of("-client", "-XX:+TieredCompilation", "-XX:TieredStopAtLevel=1")); + extraArgsList.addAll(Arrays.asList(args)); - analyzer.shouldNotContain("made not compilable"); - analyzer.shouldNotContain("decompile_count > PerMethodRecompilationCutoff"); + runTest(test, extraArgsList.toArray(new String[extraArgsList.size()])); } public static void main(String[] args) throws Exception { - testServer(); - testClient(); + testServer(RecompilationTest.class, "-Xbatch"); + testClient(RecompilationTest.class, "-Xbatch"); + + testServer(PingPongTest.class); + testClient(PingPongTest.class); } - static class Test { + static MethodHandle findStatic(Class<?> cls, String name, MethodType mt) { + try { + return MethodHandles.lookup().findStatic(cls, name, mt); + } catch (Exception e) { + throw new Error(e); + } + } + + static class RecompilationTest { static final MethodType mt = MethodType.methodType(void.class); static final CallSite cs = new MutableCallSite(mt); @@ -96,7 +119,7 @@ } static void iteration() throws Throwable { - MethodHandle mh1 = MethodHandles.lookup().findStatic(ContinuousCallSiteTargetChange.Test.class, "f", mt); + MethodHandle mh1 = findStatic(RecompilationTest.class, "f", mt); cs.setTarget(mh1); for (int i = 0; i < 20_000; i++) { test1(); @@ -111,4 +134,38 @@ } } } + + static class PingPongTest { + static final MethodType mt = MethodType.methodType(void.class); + static final CallSite cs = new MutableCallSite(mt); + + static final MethodHandle mh = cs.dynamicInvoker(); + + static final MethodHandle ping = findStatic(PingPongTest.class, "ping", mt); + static final MethodHandle pong = findStatic(PingPongTest.class, "pong", mt); + + static void ping() { + Asserts.assertEQ(cs.getTarget(), ping, "wrong call site target"); + cs.setTarget(pong); + } + + static void pong() { + Asserts.assertEQ(cs.getTarget(), pong, "wrong call site target"); + cs.setTarget(ping); + } + + static void iteration() throws Throwable { + cs.setTarget(ping); + for (int i = 0; i < 20_000; i++) { + mh.invokeExact(); + } + } + + public static void main(String[] args) throws Throwable { + int iterations = Integer.parseInt(args[0]); + for (int i = 0; i < iterations; i++) { + iteration(); + } + } + } }
--- a/test/compiler/jvmci/compilerToVM/MaterializeVirtualObjectTest.java Fri Feb 10 09:03:55 2017 +0000 +++ b/test/compiler/jvmci/compilerToVM/MaterializeVirtualObjectTest.java Thu Feb 09 23:35:22 2017 +0100 @@ -44,6 +44,8 @@ * -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI * -XX:CompileCommand=exclude,*::check * -XX:+DoEscapeAnalysis -XX:-UseCounterDecay + * -XX:CompileCommand=dontinline,compiler/jvmci/compilerToVM/MaterializeVirtualObjectTest,testFrame + * -XX:CompileCommand=inline,compiler/jvmci/compilerToVM/MaterializeVirtualObjectTest,recurse * -Xbatch * -Dcompiler.jvmci.compilerToVM.MaterializeVirtualObjectTest.invalidate=false * compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest @@ -119,14 +121,25 @@ } Asserts.assertTrue(WB.isMethodCompiled(METHOD), getName() + "Method unexpectedly not compiled"); + Asserts.assertTrue(WB.getMethodCompilationLevel(METHOD) == 4, getName() + + "Method not compiled at level 4"); testFrame("someString", COMPILE_THRESHOLD); } private void testFrame(String str, int iteration) { Helper helper = new Helper(str); - check(iteration); + recurse(2, iteration); Asserts.assertTrue((helper.string != null) && (this != null) - && (helper != null), getName() + " : some locals are null"); + && (helper != null), String.format("%s : some locals are null", getName())); + } + private void recurse(int depth, int iteration) { + if (depth == 0) { + check(iteration); + } else { + Integer s = new Integer(depth); + recurse(depth - 1, iteration); + Asserts.assertEQ(s.intValue(), depth, String.format("different values: %s != %s", s.intValue(), depth)); + } } private void check(int iteration) {
--- a/test/runtime/LocalLong/LocalLongHelper.java Fri Feb 10 09:03:55 2017 +0000 +++ b/test/runtime/LocalLong/LocalLongHelper.java Thu Feb 09 23:35:22 2017 +0100 @@ -30,10 +30,10 @@ public class LocalLongHelper { static StackWalker sw; - static Method intValue; + static Method longValue; static Method getLocals; static Class<?> primitiveValueClass; - static Method primitiveType; + static Method primitiveSize; static Method getMethodType; static Field memberName; static Field offset; @@ -43,27 +43,29 @@ new LocalLongHelper().longArg(0xC0FFEE, 0x1234567890ABCDEFL); } - // locals[2] contains the high byte of the long argument. + // locals[2] contains the unused slot of the long argument. public long longArg(int i, long l) throws Throwable { List<StackFrame> frames = sw.walk(s -> s.collect(Collectors.toList())); Object[] locals = (Object[]) getLocals.invoke(frames.get(0)); - int locals_2 = (int) intValue.invoke(locals[2]); - if (locals_2 != 0){ - throw new RuntimeException("Expected locals_2 == 0"); + if (8 == (int) primitiveSize.invoke(locals[2])) { // Only test 64-bit + long locals_2 = (long) longValue.invoke(locals[2]); + if (locals_2 != 0){ + throw new RuntimeException("Expected locals_2 == 0"); + } } return l; // Don't want l to become a dead var } private static void setupReflectionStatics() throws Throwable { Class<?> liveStackFrameClass = Class.forName("java.lang.LiveStackFrame"); - primitiveValueClass = Class.forName("java.lang.LiveStackFrame$PrimitiveValue"); + primitiveValueClass = Class.forName("java.lang.LiveStackFrame$PrimitiveSlot"); getLocals = liveStackFrameClass.getDeclaredMethod("getLocals"); getLocals.setAccessible(true); - intValue = primitiveValueClass.getDeclaredMethod("intValue"); - intValue.setAccessible(true); + longValue = primitiveValueClass.getDeclaredMethod("longValue"); + longValue.setAccessible(true); Class<?> stackFrameInfoClass = Class.forName("java.lang.StackFrameInfo"); memberName = stackFrameInfoClass.getDeclaredField("memberName"); @@ -80,20 +82,8 @@ f.setAccessible(true); Object localsAndOperandsOption = f.get(null); - primitiveType = primitiveValueClass.getDeclaredMethod("type"); - primitiveType.setAccessible(true); - + primitiveSize = primitiveValueClass.getDeclaredMethod("size"); + primitiveSize.setAccessible(true); sw = (StackWalker) ewsNI.invoke(null, java.util.Collections.emptySet(), localsAndOperandsOption); } - - private static String type(Object o) throws Throwable { - if (primitiveValueClass.isInstance(o)) { - final char c = (char) primitiveType.invoke(o); - return String.valueOf(c); - } else if (o != null) { - return o.getClass().getName(); - } else { - return "null"; - } - } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/serviceability/sa/LingeredAppWithLargeArray.java Thu Feb 09 23:35:22 2017 +0100 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import jdk.test.lib.apps.LingeredApp; + +public class LingeredAppWithLargeArray extends LingeredApp { + public static void main(String args[]) { + int[] hugeArray = new int[Integer.MAX_VALUE/2]; + LingeredApp.main(args); + } + }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/serviceability/sa/TestHeapDumpForLargeArray.java Thu Feb 09 23:35:22 2017 +0100 @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.ArrayList; +import java.util.List; +import java.io.File; +import java.nio.file.Files; +import java.io.IOException; +import java.io.BufferedInputStream; +import java.util.stream.Collectors; +import java.io.FileInputStream; + +import sun.jvm.hotspot.HotSpotAgent; +import sun.jvm.hotspot.debugger.*; + +import jdk.test.lib.apps.LingeredApp; +import jdk.test.lib.JDKToolLauncher; +import jdk.test.lib.JDKToolFinder; +import jdk.test.lib.Platform; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.Utils; +import jdk.test.lib.Asserts; + +/* + * @test + * @library /test/lib + * @bug 8171084 + * @requires (vm.bits == "64" & os.maxMemory > 8g) + * @modules java.base/jdk.internal.misc + * jdk.hotspot.agent/sun.jvm.hotspot + * jdk.hotspot.agent/sun.jvm.hotspot.utilities + * jdk.hotspot.agent/sun.jvm.hotspot.oops + * jdk.hotspot.agent/sun.jvm.hotspot.debugger + * @run main/timeout=1800/othervm -Xmx8g TestHeapDumpForLargeArray + */ + +public class TestHeapDumpForLargeArray { + + private static LingeredAppWithLargeArray theApp = null; + + private static void attachAndDump(String heapDumpFileName, + long lingeredAppPid) throws Exception { + + JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jhsdb"); + launcher.addToolArg("jmap"); + launcher.addToolArg("--binaryheap"); + launcher.addToolArg("--dumpfile"); + launcher.addToolArg(heapDumpFileName); + launcher.addToolArg("--pid"); + launcher.addToolArg(Long.toString(lingeredAppPid)); + + ProcessBuilder processBuilder = new ProcessBuilder(); + processBuilder.command(launcher.getCommand()); + System.out.println( + processBuilder.command().stream().collect(Collectors.joining(" "))); + + OutputAnalyzer SAOutput = ProcessTools.executeProcess(processBuilder); + SAOutput.shouldHaveExitValue(0); + SAOutput.shouldNotContain("Heap segment size overflow"); + SAOutput.shouldContain("truncating to"); + SAOutput.shouldContain("heap written to"); + SAOutput.shouldContain(heapDumpFileName); + System.out.println(SAOutput.getOutput()); + + } + + public static void main (String... args) throws Exception { + + String heapDumpFileName = "LargeArrayHeapDump.bin"; + + if (!Platform.shouldSAAttach()) { + System.out.println( + "SA attach not expected to work - test skipped."); + return; + } + + File heapDumpFile = new File(heapDumpFileName); + if (heapDumpFile.exists()) { + heapDumpFile.delete(); + } + + try { + List<String> vmArgs = new ArrayList<String>(); + vmArgs.add("-XX:+UsePerfData"); + vmArgs.add("-Xmx8g"); + vmArgs.addAll(Utils.getVmOptions()); + + theApp = new LingeredAppWithLargeArray(); + LingeredApp.startApp(vmArgs, theApp); + attachAndDump(heapDumpFileName, theApp.getPid()); + } finally { + LingeredApp.stopApp(theApp); + heapDumpFile.delete(); + } + } +}
--- a/test/serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java Fri Feb 10 09:03:55 2017 +0000 +++ b/test/serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java Thu Feb 09 23:35:22 2017 +0100 @@ -53,7 +53,6 @@ public class JMapHProfLargeHeapTest { private static final String HEAP_DUMP_FILE_NAME = "heap.bin"; - private static final String HPROF_HEADER_1_0_1 = "JAVA PROFILE 1.0.1"; private static final String HPROF_HEADER_1_0_2 = "JAVA PROFILE 1.0.2"; private static final long M = 1024L; private static final long G = 1024L * M; @@ -65,9 +64,7 @@ } // All heap dumps should create 1.0.2 file format - // Hotspot internal heapdumper always use HPROF_HEADER_1_0_2 format, - // but SA heapdumper still use HPROF_HEADER_1_0_1 for small heaps - testHProfFileFormat("-Xmx1g", 22 * M, HPROF_HEADER_1_0_1); + testHProfFileFormat("-Xmx1g", 22 * M, HPROF_HEADER_1_0_2); /** * This test was deliberately commented out since the test system lacks
--- a/test/testlibrary/jittester/Makefile Fri Feb 10 09:03:55 2017 +0000 +++ b/test/testlibrary/jittester/Makefile Thu Feb 09 23:35:22 2017 +0100 @@ -108,7 +108,7 @@ $(shell if [ ! -d $(CLASSES_DIR) ]; then mkdir -p $(CLASSES_DIR); fi) install: clean_testbase testgroup testroot copytestlibrary copyaot JAR cleantmp - $(JAVA) --add-exports=java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED -ea -jar $(DIST_JAR) $(APPLICATION_ARGS) + $(JAVA) --add-exports=java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED -ea -jar $(DIST_JAR) $(APPLICATION_ARGS) clean_testbase: @rm -rf $(TESTBASE_DIR)
--- a/test/testlibrary/jittester/src/jdk/test/lib/jittester/TestsGenerator.java Fri Feb 10 09:03:55 2017 +0000 +++ b/test/testlibrary/jittester/src/jdk/test/lib/jittester/TestsGenerator.java Thu Feb 09 23:35:22 2017 +0100 @@ -43,6 +43,7 @@ protected final Path generatorDir; protected final Function<String, String[]> preRunActions; protected final String jtDriverOptions; + private static final String DISABLE_WARNINGS = "-XX:-PrintWarnings"; protected TestsGenerator(String suffix) { this(suffix, s -> new String[0], ""); @@ -57,8 +58,8 @@ protected void generateGoldenOut(String mainClassName) { String classPath = getRoot() + File.pathSeparator + generatorDir; - ProcessBuilder pb = new ProcessBuilder(JAVA, "-Xint", "-Xverify", "-cp", classPath, - mainClassName); + ProcessBuilder pb = new ProcessBuilder(JAVA, "-Xint", DISABLE_WARNINGS, "-Xverify", + "-cp", classPath, mainClassName); String goldFile = mainClassName + ".gold"; try { runProcess(pb, generatorDir.resolve(goldFile).toString()); @@ -128,6 +129,8 @@ .append("\n"); } header.append(" * @run driver jdk.test.lib.jittester.jtreg.JitTesterDriver ") + .append(DISABLE_WARNINGS) + .append(" ") .append(jtDriverOptions) .append(" ") .append(mainClassName)