--- a/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -277,6 +277,8 @@
// Add in the index
add(result, result, tmp);
load_heap_oop(result, Address(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
+ // The resulting oop is null if the reference is not yet resolved.
+ // It is Universe::the_null_sentinel() if the reference resolved to NULL via condy.
}
void InterpreterMacroAssembler::load_resolved_klass_at_offset(
@@ -399,6 +401,13 @@
str(val, Address(esp, Interpreter::expr_offset_in_bytes(n)));
}
+void InterpreterMacroAssembler::load_float(Address src) {
+ ldrs(v0, src);
+}
+
+void InterpreterMacroAssembler::load_double(Address src) {
+ ldrd(v0, src);
+}
void InterpreterMacroAssembler::prepare_to_jump_from_interpreted() {
// set sender sp
--- a/src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -158,6 +158,10 @@
void load_ptr(int n, Register val);
void store_ptr(int n, Register val);
+// Load float value from 'address'. The value is loaded onto the FPU register v0.
+ void load_float(Address src);
+ void load_double(Address src);
+
// Generate a subtype check: branch to ok_is_subtype if sub_klass is
// a subtype of super_klass.
void gen_subtype_check( Register sub_klass, Label &ok_is_subtype );
--- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -2056,9 +2056,14 @@
}
void MacroAssembler::unimplemented(const char* what) {
- char* b = new char[1024];
- jio_snprintf(b, 1024, "unimplemented: %s", what);
- stop(b);
+ const char* buf = NULL;
+ {
+ ResourceMark rm;
+ stringStream ss;
+ ss.print("unimplemented: %s", what);
+ buf = code_string(ss.as_string());
+ }
+ stop(buf);
}
// If a constant does not fit in an immediate field, generate some
--- a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -370,7 +370,7 @@
void TemplateTable::ldc(bool wide)
{
transition(vtos, vtos);
- Label call_ldc, notFloat, notClass, Done;
+ Label call_ldc, notFloat, notClass, notInt, Done;
if (wide) {
__ get_unsigned_2_byte_index_at_bcp(r1, 1);
@@ -417,20 +417,19 @@
__ b(Done);
__ bind(notFloat);
-#ifdef ASSERT
- {
- Label L;
- __ cmp(r3, JVM_CONSTANT_Integer);
- __ br(Assembler::EQ, L);
- // String and Object are rewritten to fast_aldc
- __ stop("unexpected tag type in ldc");
- __ bind(L);
- }
-#endif
- // itos JVM_CONSTANT_Integer only
+
+ __ cmp(r3, JVM_CONSTANT_Integer);
+ __ br(Assembler::NE, notInt);
+
+ // itos
__ adds(r1, r2, r1, Assembler::LSL, 3);
__ ldrw(r0, Address(r1, base_offset));
__ push_i(r0);
+ __ b(Done);
+
+ __ bind(notInt);
+ condy_helper(Done);
+
__ bind(Done);
}
@@ -441,6 +440,8 @@
Register result = r0;
Register tmp = r1;
+ Register rarg = r2;
+
int index_size = wide ? sizeof(u2) : sizeof(u1);
Label resolved;
@@ -455,12 +456,27 @@
address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc);
// first time invocation - must resolve first
- __ mov(tmp, (int)bytecode());
- __ call_VM(result, entry, tmp);
+ __ mov(rarg, (int)bytecode());
+ __ call_VM(result, entry, rarg);
__ bind(resolved);
+ { // Check for the null sentinel.
+ // If we just called the VM, that already did the mapping for us,
+ // but it's harmless to retry.
+ Label notNull;
+
+ // Stash null_sentinel address to get its value later
+ __ movptr(rarg, (uintptr_t)Universe::the_null_sentinel_addr());
+ __ ldr(tmp, Address(rarg));
+ __ cmp(result, tmp);
+ __ br(Assembler::NE, notNull);
+ __ mov(result, 0); // NULL object reference
+ __ bind(notNull);
+ }
+
if (VerifyOops) {
+ // Safe to call with 0 result
__ verify_oop(result);
}
}
@@ -468,7 +484,7 @@
void TemplateTable::ldc2_w()
{
transition(vtos, vtos);
- Label Long, Done;
+ Label notDouble, notLong, Done;
__ get_unsigned_2_byte_index_at_bcp(r0, 1);
__ get_cpool_and_tags(r1, r2);
@@ -479,22 +495,143 @@
__ lea(r2, Address(r2, r0, Address::lsl(0)));
__ load_unsigned_byte(r2, Address(r2, tags_offset));
__ cmpw(r2, (int)JVM_CONSTANT_Double);
- __ br(Assembler::NE, Long);
+ __ br(Assembler::NE, notDouble);
+
// dtos
__ lea (r2, Address(r1, r0, Address::lsl(3)));
__ ldrd(v0, Address(r2, base_offset));
__ push_d();
__ b(Done);
- __ bind(Long);
+ __ bind(notDouble);
+ __ cmpw(r2, (int)JVM_CONSTANT_Long);
+ __ br(Assembler::NE, notLong);
+
// ltos
__ lea(r0, Address(r1, r0, Address::lsl(3)));
__ ldr(r0, Address(r0, base_offset));
__ push_l();
+ __ b(Done);
+
+ __ bind(notLong);
+ condy_helper(Done);
__ bind(Done);
}
+void TemplateTable::condy_helper(Label& Done)
+{
+ Register obj = r0;
+ Register rarg = r1;
+ Register flags = r2;
+ Register off = r3;
+
+ address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc);
+
+ __ mov(rarg, (int) bytecode());
+ __ call_VM(obj, entry, rarg);
+
+ __ get_vm_result_2(flags, rthread);
+
+ // VMr = obj = base address to find primitive value to push
+ // VMr2 = flags = (tos, off) using format of CPCE::_flags
+ __ mov(off, flags);
+ __ andw(off, off, ConstantPoolCacheEntry::field_index_mask);
+
+ const Address field(obj, off);
+
+ // What sort of thing are we loading?
+ // x86 uses a shift and mask or wings it with a shift plus assert
+ // the mask is not needed. aarch64 just uses bitfield extract
+ __ ubfxw(flags, flags, ConstantPoolCacheEntry::tos_state_shift,
+ ConstantPoolCacheEntry::tos_state_bits);
+
+ switch (bytecode()) {
+ case Bytecodes::_ldc:
+ case Bytecodes::_ldc_w:
+ {
+ // tos in (itos, ftos, stos, btos, ctos, ztos)
+ Label notInt, notFloat, notShort, notByte, notChar, notBool;
+ __ cmpw(flags, itos);
+ __ br(Assembler::NE, notInt);
+ // itos
+ __ ldrw(r0, field);
+ __ push(itos);
+ __ b(Done);
+
+ __ bind(notInt);
+ __ cmpw(flags, ftos);
+ __ br(Assembler::NE, notFloat);
+ // ftos
+ __ load_float(field);
+ __ push(ftos);
+ __ b(Done);
+
+ __ bind(notFloat);
+ __ cmpw(flags, stos);
+ __ br(Assembler::NE, notShort);
+ // stos
+ __ load_signed_short(r0, field);
+ __ push(stos);
+ __ b(Done);
+
+ __ bind(notShort);
+ __ cmpw(flags, btos);
+ __ br(Assembler::NE, notByte);
+ // btos
+ __ load_signed_byte(r0, field);
+ __ push(btos);
+ __ b(Done);
+
+ __ bind(notByte);
+ __ cmpw(flags, ctos);
+ __ br(Assembler::NE, notChar);
+ // ctos
+ __ load_unsigned_short(r0, field);
+ __ push(ctos);
+ __ b(Done);
+
+ __ bind(notChar);
+ __ cmpw(flags, ztos);
+ __ br(Assembler::NE, notBool);
+ // ztos
+ __ load_signed_byte(r0, field);
+ __ push(ztos);
+ __ b(Done);
+
+ __ bind(notBool);
+ break;
+ }
+
+ case Bytecodes::_ldc2_w:
+ {
+ Label notLong, notDouble;
+ __ cmpw(flags, ltos);
+ __ br(Assembler::NE, notLong);
+ // ltos
+ __ ldr(r0, field);
+ __ push(ltos);
+ __ b(Done);
+
+ __ bind(notLong);
+ __ cmpw(flags, dtos);
+ __ br(Assembler::NE, notDouble);
+ // dtos
+ __ load_double(field);
+ __ push(dtos);
+ __ b(Done);
+
+ __ bind(notDouble);
+ break;
+ }
+
+ default:
+ ShouldNotReachHere();
+ }
+
+ __ stop("bad ldc/condy");
+}
+
void TemplateTable::locals_index(Register reg, int offset)
{
__ ldrb(reg, at_bcp(offset));
--- a/src/hotspot/cpu/ppc/copy_ppc.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/cpu/ppc/copy_ppc.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2013 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -32,11 +32,11 @@
// Inline functions for memory copy and fill.
-static void pd_conjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
(void)memmove(to, from, count * HeapWordSize);
}
-static void pd_disjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
switch (count) {
case 8: to[7] = from[7];
case 7: to[6] = from[6];
@@ -52,7 +52,7 @@
}
}
-static void pd_disjoint_words_atomic(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_disjoint_words_atomic(const HeapWord* from, HeapWord* to, size_t count) {
switch (count) {
case 8: to[7] = from[7];
case 7: to[6] = from[6];
@@ -70,25 +70,25 @@
}
}
-static void pd_aligned_conjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_aligned_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
(void)memmove(to, from, count * HeapWordSize);
}
-static void pd_aligned_disjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_aligned_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
pd_disjoint_words(from, to, count);
}
-static void pd_conjoint_bytes(void* from, void* to, size_t count) {
+static void pd_conjoint_bytes(const void* from, void* to, size_t count) {
(void)memmove(to, from, count);
}
-static void pd_conjoint_bytes_atomic(void* from, void* to, size_t count) {
+static void pd_conjoint_bytes_atomic(const void* from, void* to, size_t count) {
(void)memmove(to, from, count);
}
// Template for atomic, element-wise copy.
template <class T>
-static void copy_conjoint_atomic(T* from, T* to, size_t count) {
+static void copy_conjoint_atomic(const T* from, T* to, size_t count) {
if (from > to) {
while (count-- > 0) {
// Copy forwards
@@ -104,44 +104,44 @@
}
}
-static void pd_conjoint_jshorts_atomic(jshort* from, jshort* to, size_t count) {
+static void pd_conjoint_jshorts_atomic(const jshort* from, jshort* to, size_t count) {
// TODO: contribute optimized version.
copy_conjoint_atomic<jshort>(from, to, count);
}
-static void pd_conjoint_jints_atomic(jint* from, jint* to, size_t count) {
+static void pd_conjoint_jints_atomic(const jint* from, jint* to, size_t count) {
// TODO: contribute optimized version.
copy_conjoint_atomic<jint>(from, to, count);
}
-static void pd_conjoint_jlongs_atomic(jlong* from, jlong* to, size_t count) {
+static void pd_conjoint_jlongs_atomic(const jlong* from, jlong* to, size_t count) {
copy_conjoint_atomic<jlong>(from, to, count);
}
-static void pd_conjoint_oops_atomic(oop* from, oop* to, size_t count) {
+static void pd_conjoint_oops_atomic(const oop* from, oop* to, size_t count) {
copy_conjoint_atomic<oop>(from, to, count);
}
-static void pd_arrayof_conjoint_bytes(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_arrayof_conjoint_bytes(const HeapWord* from, HeapWord* to, size_t count) {
pd_conjoint_bytes_atomic(from, to, count);
}
-static void pd_arrayof_conjoint_jshorts(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_arrayof_conjoint_jshorts(const HeapWord* from, HeapWord* to, size_t count) {
// TODO: contribute optimized version.
- pd_conjoint_jshorts_atomic((jshort*)from, (jshort*)to, count);
+ pd_conjoint_jshorts_atomic((const jshort*)from, (jshort*)to, count);
}
-static void pd_arrayof_conjoint_jints(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_arrayof_conjoint_jints(const HeapWord* from, HeapWord* to, size_t count) {
// TODO: contribute optimized version.
- pd_conjoint_jints_atomic((jint*)from, (jint*)to, count);
+ pd_conjoint_jints_atomic((const jint*)from, (jint*)to, count);
}
-static void pd_arrayof_conjoint_jlongs(HeapWord* from, HeapWord* to, size_t count) {
- pd_conjoint_jlongs_atomic((jlong*)from, (jlong*)to, count);
+static void pd_arrayof_conjoint_jlongs(const HeapWord* from, HeapWord* to, size_t count) {
+ pd_conjoint_jlongs_atomic((const jlong*)from, (jlong*)to, count);
}
-static void pd_arrayof_conjoint_oops(HeapWord* from, HeapWord* to, size_t count) {
- pd_conjoint_oops_atomic((oop*)from, (oop*)to, count);
+static void pd_arrayof_conjoint_oops(const HeapWord* from, HeapWord* to, size_t count) {
+ pd_conjoint_oops_atomic((const oop*)from, (oop*)to, count);
}
static void pd_fill_to_words(HeapWord* tohw, size_t count, juint value) {
--- a/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -492,6 +492,8 @@
// Add in the index.
add(result, tmp, result);
load_heap_oop(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT), result, is_null);
+ // The resulting oop is null if the reference is not yet resolved.
+ // It is Universe::the_null_sentinel() if the reference resolved to NULL via condy.
}
// load cpool->resolved_klass_at(index)
--- a/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -314,7 +314,7 @@
Rcpool = R3_ARG1;
transition(vtos, vtos);
- Label notInt, notClass, exit;
+ Label notInt, notFloat, notClass, exit;
__ get_cpool_and_tags(Rcpool, Rscratch2); // Set Rscratch2 = &tags.
if (wide) { // Read index.
@@ -356,13 +356,16 @@
__ align(32, 12);
__ bind(notInt);
-#ifdef ASSERT
- // String and Object are rewritten to fast_aldc
__ cmpdi(CCR0, Rscratch2, JVM_CONSTANT_Float);
- __ asm_assert_eq("unexpected type", 0x8765);
-#endif
+ __ bne(CCR0, notFloat);
__ lfsx(F15_ftos, Rcpool, Rscratch1);
__ push(ftos);
+ __ b(exit);
+
+ __ align(32, 12);
+ // assume the tag is for condy; if not, the VM runtime will tell us
+ __ bind(notFloat);
+ condy_helper(exit);
__ align(32, 12);
__ bind(exit);
@@ -380,6 +383,19 @@
// non-null object (CallSite, etc.)
__ get_cache_index_at_bcp(Rscratch, 1, index_size); // Load index.
__ load_resolved_reference_at_index(R17_tos, Rscratch, &is_null);
+
+ // Convert null sentinel to NULL.
+ int simm16_rest = __ load_const_optimized(Rscratch, Universe::the_null_sentinel_addr(), R0, true);
+ __ ld(Rscratch, simm16_rest, Rscratch);
+ __ cmpld(CCR0, R17_tos, Rscratch);
+ if (VM_Version::has_isel()) {
+ __ isel_0(R17_tos, CCR0, Assembler::equal);
+ } else {
+ Label not_sentinel;
+ __ bne(CCR0, not_sentinel);
+ __ li(R17_tos, 0);
+ __ bind(not_sentinel);
+ }
__ verify_oop(R17_tos);
__ dispatch_epilog(atos, Bytecodes::length_for(bytecode()));
@@ -395,7 +411,7 @@
void TemplateTable::ldc2_w() {
transition(vtos, vtos);
- Label Llong, Lexit;
+ Label not_double, not_long, exit;
Register Rindex = R11_scratch1,
Rcpool = R12_scratch2,
@@ -410,23 +426,129 @@
__ addi(Rtag, Rtag, tags_offset);
__ lbzx(Rtag, Rtag, Rindex);
-
__ sldi(Rindex, Rindex, LogBytesPerWord);
+
__ cmpdi(CCR0, Rtag, JVM_CONSTANT_Double);
- __ bne(CCR0, Llong);
- // A double can be placed at word-aligned locations in the constant pool.
- // Check out Conversions.java for an example.
- // Also ConstantPool::header_size() is 20, which makes it very difficult
- // to double-align double on the constant pool. SG, 11/7/97
+ __ bne(CCR0, not_double);
__ lfdx(F15_ftos, Rcpool, Rindex);
__ push(dtos);
- __ b(Lexit);
-
- __ bind(Llong);
+ __ b(exit);
+
+ __ bind(not_double);
+ __ cmpdi(CCR0, Rtag, JVM_CONSTANT_Long);
+ __ bne(CCR0, not_long);
__ ldx(R17_tos, Rcpool, Rindex);
__ push(ltos);
-
- __ bind(Lexit);
+ __ b(exit);
+
+ __ bind(not_long);
+ condy_helper(exit);
+
+ __ align(32, 12);
+ __ bind(exit);
+}
+
+void TemplateTable::condy_helper(Label& Done) {
+ const Register obj = R31;
+ const Register off = R11_scratch1;
+ const Register flags = R12_scratch2;
+ const Register rarg = R4_ARG2;
+ __ li(rarg, (int)bytecode());
+ call_VM(obj, CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc), rarg);
+ __ get_vm_result_2(flags);
+
+ // VMr = obj = base address to find primitive value to push
+ // VMr2 = flags = (tos, off) using format of CPCE::_flags
+ __ andi(off, flags, ConstantPoolCacheEntry::field_index_mask);
+
+ // What sort of thing are we loading?
+ __ rldicl(flags, flags, 64-ConstantPoolCacheEntry::tos_state_shift, 64-ConstantPoolCacheEntry::tos_state_bits);
+
+ switch (bytecode()) {
+ case Bytecodes::_ldc:
+ case Bytecodes::_ldc_w:
+ {
+ // tos in (itos, ftos, stos, btos, ctos, ztos)
+ Label notInt, notFloat, notShort, notByte, notChar, notBool;
+ __ cmplwi(CCR0, flags, itos);
+ __ bne(CCR0, notInt);
+ // itos
+ __ lwax(R17_tos, obj, off);
+ __ push(itos);
+ __ b(Done);
+
+ __ bind(notInt);
+ __ cmplwi(CCR0, flags, ftos);
+ __ bne(CCR0, notFloat);
+ // ftos
+ __ lfsx(F15_ftos, obj, off);
+ __ push(ftos);
+ __ b(Done);
+
+ __ bind(notFloat);
+ __ cmplwi(CCR0, flags, stos);
+ __ bne(CCR0, notShort);
+ // stos
+ __ lhax(R17_tos, obj, off);
+ __ push(stos);
+ __ b(Done);
+
+ __ bind(notShort);
+ __ cmplwi(CCR0, flags, btos);
+ __ bne(CCR0, notByte);
+ // btos
+ __ lbzx(R17_tos, obj, off);
+ __ extsb(R17_tos, R17_tos);
+ __ push(btos);
+ __ b(Done);
+
+ __ bind(notByte);
+ __ cmplwi(CCR0, flags, ctos);
+ __ bne(CCR0, notChar);
+ // ctos
+ __ lhzx(R17_tos, obj, off);
+ __ push(ctos);
+ __ b(Done);
+
+ __ bind(notChar);
+ __ cmplwi(CCR0, flags, ztos);
+ __ bne(CCR0, notBool);
+ // ztos
+ __ lbzx(R17_tos, obj, off);
+ __ push(ztos);
+ __ b(Done);
+
+ __ bind(notBool);
+ break;
+ }
+
+ case Bytecodes::_ldc2_w:
+ {
+ Label notLong, notDouble;
+ __ cmplwi(CCR0, flags, ltos);
+ __ bne(CCR0, notLong);
+ // ltos
+ __ ldx(R17_tos, obj, off);
+ __ push(ltos);
+ __ b(Done);
+
+ __ bind(notLong);
+ __ cmplwi(CCR0, flags, dtos);
+ __ bne(CCR0, notDouble);
+ // dtos
+ __ lfdx(F15_ftos, obj, off);
+ __ push(dtos);
+ __ b(Done);
+
+ __ bind(notDouble);
+ break;
+ }
+
+ default:
+ ShouldNotReachHere();
+ }
+
+ __ stop("bad ldc/condy");
}
// Get the locals index located in the bytecode stream at bcp + offset.
--- a/src/hotspot/cpu/s390/copy_s390.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/cpu/s390/copy_s390.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -73,7 +73,7 @@
#undef USE_INLINE_ASM
-static void copy_conjoint_jshorts_atomic(jshort* from, jshort* to, size_t count) {
+static void copy_conjoint_jshorts_atomic(const jshort* from, jshort* to, size_t count) {
if (from > to) {
while (count-- > 0) {
// Copy forwards
@@ -89,7 +89,7 @@
}
}
-static void copy_conjoint_jints_atomic(jint* from, jint* to, size_t count) {
+static void copy_conjoint_jints_atomic(const jint* from, jint* to, size_t count) {
if (from > to) {
while (count-- > 0) {
// Copy forwards
@@ -105,7 +105,7 @@
}
}
-static bool has_destructive_overlap(char* from, char* to, size_t byte_count) {
+static bool has_destructive_overlap(const char* from, char* to, size_t byte_count) {
return (from < to) && ((to-from) < (ptrdiff_t)byte_count);
}
@@ -662,7 +662,7 @@
// D I S J O I N T C O P Y I N G //
//*************************************//
-static void pd_aligned_disjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_aligned_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
// JVM2008: very frequent, some tests frequent.
// Copy HeapWord (=DW) aligned storage. Use MVCLE in inline-asm code.
@@ -740,13 +740,13 @@
#endif
}
-static void pd_disjoint_words_atomic(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_disjoint_words_atomic(const HeapWord* from, HeapWord* to, size_t count) {
// JVM2008: < 4k calls.
assert(((((size_t)from) & 0x07L) | (((size_t)to) & 0x07L)) == 0, "No atomic copy w/o aligned data");
pd_aligned_disjoint_words(from, to, count); // Rare calls -> just delegate.
}
-static void pd_disjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
// JVM2008: very rare.
pd_aligned_disjoint_words(from, to, count); // Rare calls -> just delegate.
}
@@ -756,7 +756,7 @@
// C O N J O I N T C O P Y I N G //
//*************************************//
-static void pd_aligned_conjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_aligned_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
// JVM2008: between some and lower end of frequent.
#ifdef USE_INLINE_ASM
@@ -836,13 +836,13 @@
#endif
}
-static void pd_conjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
// Just delegate. HeapWords are optimally aligned anyway.
pd_aligned_conjoint_words(from, to, count);
}
-static void pd_conjoint_bytes(void* from, void* to, size_t count) {
+static void pd_conjoint_bytes(const void* from, void* to, size_t count) {
#ifdef USE_INLINE_ASM
size_t count_in = count;
@@ -866,16 +866,16 @@
// C O N J O I N T A T O M I C C O P Y I N G //
//**************************************************//
-static void pd_conjoint_bytes_atomic(void* from, void* to, size_t count) {
+static void pd_conjoint_bytes_atomic(const void* from, void* to, size_t count) {
// Call arraycopy stubs to do the job.
pd_conjoint_bytes(from, to, count); // bytes are always accessed atomically.
}
-static void pd_conjoint_jshorts_atomic(jshort* from, jshort* to, size_t count) {
+static void pd_conjoint_jshorts_atomic(const jshort* from, jshort* to, size_t count) {
#ifdef USE_INLINE_ASM
size_t count_in = count;
- if (has_destructive_overlap((char*)from, (char*)to, count_in*BytesPerShort)) {
+ if (has_destructive_overlap((const char*)from, (char*)to, count_in*BytesPerShort)) {
// Use optimizations from shared code where no z-specific optimization exists.
copy_conjoint_jshorts_atomic(from, to, count);
} else {
@@ -890,11 +890,11 @@
#endif
}
-static void pd_conjoint_jints_atomic(jint* from, jint* to, size_t count) {
+static void pd_conjoint_jints_atomic(const jint* from, jint* to, size_t count) {
#ifdef USE_INLINE_ASM
size_t count_in = count;
- if (has_destructive_overlap((char*)from, (char*)to, count_in*BytesPerInt)) {
+ if (has_destructive_overlap((const char*)from, (char*)to, count_in*BytesPerInt)) {
switch (count_in) {
case 4: COPY4_ATOMIC_4(to,from)
return;
@@ -922,7 +922,7 @@
#endif
}
-static void pd_conjoint_jlongs_atomic(jlong* from, jlong* to, size_t count) {
+static void pd_conjoint_jlongs_atomic(const jlong* from, jlong* to, size_t count) {
#ifdef USE_INLINE_ASM
size_t count_in = count;
@@ -970,11 +970,11 @@
}
}
else
- pd_aligned_disjoint_words((HeapWord*)from, (HeapWord*)to, count_in); // rare calls -> just delegate.
+ pd_aligned_disjoint_words((const HeapWord*)from, (HeapWord*)to, count_in); // rare calls -> just delegate.
#endif
}
-static void pd_conjoint_oops_atomic(oop* from, oop* to, size_t count) {
+static void pd_conjoint_oops_atomic(const oop* from, oop* to, size_t count) {
#ifdef USE_INLINE_ASM
size_t count_in = count;
@@ -1011,24 +1011,24 @@
#endif
}
-static void pd_arrayof_conjoint_bytes(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_arrayof_conjoint_bytes(const HeapWord* from, HeapWord* to, size_t count) {
pd_conjoint_bytes_atomic(from, to, count);
}
-static void pd_arrayof_conjoint_jshorts(HeapWord* from, HeapWord* to, size_t count) {
- pd_conjoint_jshorts_atomic((jshort*)from, (jshort*)to, count);
+static void pd_arrayof_conjoint_jshorts(const HeapWord* from, HeapWord* to, size_t count) {
+ pd_conjoint_jshorts_atomic((const jshort*)from, (jshort*)to, count);
}
-static void pd_arrayof_conjoint_jints(HeapWord* from, HeapWord* to, size_t count) {
- pd_conjoint_jints_atomic((jint*)from, (jint*)to, count);
+static void pd_arrayof_conjoint_jints(const HeapWord* from, HeapWord* to, size_t count) {
+ pd_conjoint_jints_atomic((const jint*)from, (jint*)to, count);
}
-static void pd_arrayof_conjoint_jlongs(HeapWord* from, HeapWord* to, size_t count) {
- pd_conjoint_jlongs_atomic((jlong*)from, (jlong*)to, count);
+static void pd_arrayof_conjoint_jlongs(const HeapWord* from, HeapWord* to, size_t count) {
+ pd_conjoint_jlongs_atomic((const jlong*)from, (jlong*)to, count);
}
-static void pd_arrayof_conjoint_oops(HeapWord* from, HeapWord* to, size_t count) {
- pd_conjoint_oops_atomic((oop*)from, (oop*)to, count);
+static void pd_arrayof_conjoint_oops(const HeapWord* from, HeapWord* to, size_t count) {
+ pd_conjoint_oops_atomic((const oop*)from, (oop*)to, count);
}
//**********************************************//
--- a/src/hotspot/cpu/s390/interp_masm_s390.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/cpu/s390/interp_masm_s390.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -389,6 +389,8 @@
#endif
z_agr(result, index); // Address of indexed array element.
load_heap_oop(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT), result);
+ // The resulting oop is null if the reference is not yet resolved.
+ // It is Universe::the_null_sentinel() if the reference resolved to NULL via condy.
}
// load cpool->resolved_klass_at(index)
--- a/src/hotspot/cpu/s390/templateTable_s390.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/cpu/s390/templateTable_s390.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -450,7 +450,7 @@
void TemplateTable::ldc(bool wide) {
transition(vtos, vtos);
- Label call_ldc, notFloat, notClass, Done;
+ Label call_ldc, notFloat, notClass, notInt, Done;
const Register RcpIndex = Z_tmp_1;
const Register Rtags = Z_ARG2;
@@ -500,22 +500,17 @@
__ z_bru(Done);
__ bind(notFloat);
-#ifdef ASSERT
- {
- Label L;
-
- __ z_cli(0, Raddr_type, JVM_CONSTANT_Integer);
- __ z_bre(L);
- // String and Object are rewritten to fast_aldc.
- __ stop("unexpected tag type in ldc");
-
- __ bind(L);
- }
-#endif
+ __ z_cli(0, Raddr_type, JVM_CONSTANT_Integer);
+ __ z_brne(notInt);
// itos
__ mem2reg_opt(Z_tos, Address(Z_tmp_2, RcpOffset, base_offset), false);
__ push_i(Z_tos);
+ __ z_bru(Done);
+
+ // assume the tag is for condy; if not, the VM runtime will tell us
+ __ bind(notInt);
+ condy_helper(Done);
__ bind(Done);
}
@@ -528,15 +523,23 @@
const Register index = Z_tmp_2;
int index_size = wide ? sizeof(u2) : sizeof(u1);
- Label L_resolved;
+ Label L_do_resolve, L_resolved;
// We are resolved if the resolved reference cache entry contains a
// non-null object (CallSite, etc.).
__ get_cache_index_at_bcp(index, 1, index_size); // Load index.
__ load_resolved_reference_at_index(Z_tos, index);
__ z_ltgr(Z_tos, Z_tos);
+ __ z_bre(L_do_resolve);
+
+ // Convert null sentinel to NULL.
+ __ load_const_optimized(Z_R1_scratch, (intptr_t)Universe::the_null_sentinel_addr());
+ __ z_cg(Z_tos, Address(Z_R1_scratch));
__ z_brne(L_resolved);
-
+ __ clear_reg(Z_tos);
+ __ z_bru(L_resolved);
+
+ __ bind(L_do_resolve);
// First time invocation - must resolve first.
address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc);
__ load_const_optimized(Z_ARG1, (int)bytecode());
@@ -548,7 +551,7 @@
void TemplateTable::ldc2_w() {
transition(vtos, vtos);
- Label Long, Done;
+ Label notDouble, notLong, Done;
// Z_tmp_1 = index of cp entry
__ get_2_byte_integer_at_bcp(Z_tmp_1, 1, InterpreterMacroAssembler::Unsigned);
@@ -566,21 +569,132 @@
// Check type.
__ z_cli(0, Z_tos, JVM_CONSTANT_Double);
- __ z_brne(Long);
-
+ __ z_brne(notDouble);
// dtos
__ mem2freg_opt(Z_ftos, Address(Z_tmp_2, Z_tmp_1, base_offset));
__ push_d();
__ z_bru(Done);
- __ bind(Long);
+ __ bind(notDouble);
+ __ z_cli(0, Z_tos, JVM_CONSTANT_Long);
+ __ z_brne(notLong);
// ltos
__ mem2reg_opt(Z_tos, Address(Z_tmp_2, Z_tmp_1, base_offset));
__ push_l();
+ __ z_bru(Done);
+
+ __ bind(notLong);
+ condy_helper(Done);
__ bind(Done);
}
+void TemplateTable::condy_helper(Label& Done) {
+ const Register obj = Z_tmp_1;
+ const Register off = Z_tmp_2;
+ const Register flags = Z_ARG1;
+ const Register rarg = Z_ARG2;
+ __ load_const_optimized(rarg, (int)bytecode());
+ call_VM(obj, CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc), rarg);
+ __ get_vm_result_2(flags);
+
+ // VMr = obj = base address to find primitive value to push
+ // VMr2 = flags = (tos, off) using format of CPCE::_flags
+ assert(ConstantPoolCacheEntry::field_index_mask == 0xffff, "or use other instructions");
+ __ z_llghr(off, flags);
+ const Address field(obj, off);
+
+ // What sort of thing are we loading?
+ __ z_srl(flags, ConstantPoolCacheEntry::tos_state_shift);
+ // Make sure we don't need to mask flags for tos_state after the above shift.
+ ConstantPoolCacheEntry::verify_tos_state_shift();
+
+ switch (bytecode()) {
+ case Bytecodes::_ldc:
+ case Bytecodes::_ldc_w:
+ {
+ // tos in (itos, ftos, stos, btos, ctos, ztos)
+ Label notInt, notFloat, notShort, notByte, notChar, notBool;
+ __ z_cghi(flags, itos);
+ __ z_brne(notInt);
+ // itos
+ __ z_l(Z_tos, field);
+ __ push(itos);
+ __ z_bru(Done);
+
+ __ bind(notInt);
+ __ z_cghi(flags, ftos);
+ __ z_brne(notFloat);
+ // ftos
+ __ z_le(Z_ftos, field);
+ __ push(ftos);
+ __ z_bru(Done);
+
+ __ bind(notFloat);
+ __ z_cghi(flags, stos);
+ __ z_brne(notShort);
+ // stos
+ __ z_lh(Z_tos, field);
+ __ push(stos);
+ __ z_bru(Done);
+
+ __ bind(notShort);
+ __ z_cghi(flags, btos);
+ __ z_brne(notByte);
+ // btos
+ __ z_lb(Z_tos, field);
+ __ push(btos);
+ __ z_bru(Done);
+
+ __ bind(notByte);
+ __ z_cghi(flags, ctos);
+ __ z_brne(notChar);
+ // ctos
+ __ z_llh(Z_tos, field);
+ __ push(ctos);
+ __ z_bru(Done);
+
+ __ bind(notChar);
+ __ z_cghi(flags, ztos);
+ __ z_brne(notBool);
+ // ztos
+ __ z_lb(Z_tos, field);
+ __ push(ztos);
+ __ z_bru(Done);
+
+ __ bind(notBool);
+ break;
+ }
+
+ case Bytecodes::_ldc2_w:
+ {
+ Label notLong, notDouble;
+ __ z_cghi(flags, ltos);
+ __ z_brne(notLong);
+ // ltos
+ __ z_lg(Z_tos, field);
+ __ push(ltos);
+ __ z_bru(Done);
+
+ __ bind(notLong);
+ __ z_cghi(flags, dtos);
+ __ z_brne(notDouble);
+ // dtos
+ __ z_ld(Z_ftos, field);
+ __ push(dtos);
+ __ z_bru(Done);
+
+ __ bind(notDouble);
+ break;
+ }
+
+ default:
+ ShouldNotReachHere();
+ }
+
+ __ stop("bad ldc/condy");
+}
+
void TemplateTable::locals_index(Register reg, int offset) {
__ z_llgc(reg, at_bcp(offset));
__ z_lcgr(reg);
--- a/src/hotspot/cpu/sparc/copy_sparc.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/cpu/sparc/copy_sparc.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -27,11 +27,11 @@
// Inline functions for memory copy and fill.
-static void pd_conjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
(void)memmove(to, from, count * HeapWordSize);
}
-static void pd_disjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
switch (count) {
case 8: to[7] = from[7];
case 7: to[6] = from[6];
@@ -47,7 +47,7 @@
}
}
-static void pd_disjoint_words_atomic(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_disjoint_words_atomic(const HeapWord* from, HeapWord* to, size_t count) {
switch (count) {
case 8: to[7] = from[7];
case 7: to[6] = from[6];
@@ -65,23 +65,23 @@
}
}
-static void pd_aligned_conjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_aligned_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
(void)memmove(to, from, count * HeapWordSize);
}
-static void pd_aligned_disjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_aligned_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
pd_disjoint_words(from, to, count);
}
-static void pd_conjoint_bytes(void* from, void* to, size_t count) {
+static void pd_conjoint_bytes(const void* from, void* to, size_t count) {
(void)memmove(to, from, count);
}
-static void pd_conjoint_bytes_atomic(void* from, void* to, size_t count) {
+static void pd_conjoint_bytes_atomic(const void* from, void* to, size_t count) {
(void)memmove(to, from, count);
}
-static void pd_conjoint_jshorts_atomic(jshort* from, jshort* to, size_t count) {
+static void pd_conjoint_jshorts_atomic(const jshort* from, jshort* to, size_t count) {
if (from > to) {
while (count-- > 0) {
// Copy forwards
@@ -97,7 +97,7 @@
}
}
-static void pd_conjoint_jints_atomic(jint* from, jint* to, size_t count) {
+static void pd_conjoint_jints_atomic(const jint* from, jint* to, size_t count) {
if (from > to) {
while (count-- > 0) {
// Copy forwards
@@ -113,12 +113,12 @@
}
}
-static void pd_conjoint_jlongs_atomic(jlong* from, jlong* to, size_t count) {
+static void pd_conjoint_jlongs_atomic(const jlong* from, jlong* to, size_t count) {
assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size");
- pd_conjoint_oops_atomic((oop*)from, (oop*)to, count);
+ pd_conjoint_oops_atomic((const oop*)from, (oop*)to, count);
}
-static void pd_conjoint_oops_atomic(oop* from, oop* to, size_t count) {
+static void pd_conjoint_oops_atomic(const oop* from, oop* to, size_t count) {
// Do better than this: inline memmove body NEEDS CLEANUP
if (from > to) {
while (count-- > 0) {
@@ -135,24 +135,24 @@
}
}
-static void pd_arrayof_conjoint_bytes(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_arrayof_conjoint_bytes(const HeapWord* from, HeapWord* to, size_t count) {
pd_conjoint_bytes_atomic(from, to, count);
}
-static void pd_arrayof_conjoint_jshorts(HeapWord* from, HeapWord* to, size_t count) {
- pd_conjoint_jshorts_atomic((jshort*)from, (jshort*)to, count);
+static void pd_arrayof_conjoint_jshorts(const HeapWord* from, HeapWord* to, size_t count) {
+ pd_conjoint_jshorts_atomic((const jshort*)from, (jshort*)to, count);
}
-static void pd_arrayof_conjoint_jints(HeapWord* from, HeapWord* to, size_t count) {
- pd_conjoint_jints_atomic((jint*)from, (jint*)to, count);
+static void pd_arrayof_conjoint_jints(const HeapWord* from, HeapWord* to, size_t count) {
+ pd_conjoint_jints_atomic((const jint*)from, (jint*)to, count);
}
-static void pd_arrayof_conjoint_jlongs(HeapWord* from, HeapWord* to, size_t count) {
- pd_conjoint_jlongs_atomic((jlong*)from, (jlong*)to, count);
+static void pd_arrayof_conjoint_jlongs(const HeapWord* from, HeapWord* to, size_t count) {
+ pd_conjoint_jlongs_atomic((const jlong*)from, (jlong*)to, count);
}
-static void pd_arrayof_conjoint_oops(HeapWord* from, HeapWord* to, size_t count) {
- pd_conjoint_oops_atomic((oop*)from, (oop*)to, count);
+static void pd_arrayof_conjoint_oops(const HeapWord* from, HeapWord* to, size_t count) {
+ pd_conjoint_oops_atomic((const oop*)from, (oop*)to, count);
}
static void pd_fill_to_words(HeapWord* tohw, size_t count, juint value) {
--- a/src/hotspot/cpu/sparc/macroAssembler_sparc.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/cpu/sparc/macroAssembler_sparc.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -1411,9 +1411,14 @@
void MacroAssembler::unimplemented(const char* what) {
- char* b = new char[1024];
- jio_snprintf(b, 1024, "unimplemented: %s", what);
- stop(b);
+ const char* buf = NULL;
+ {
+ ResourceMark rm;
+ stringStream ss;
+ ss.print("unimplemented: %s", what);
+ buf = code_string(ss.as_string());
+ }
+ stop(buf);
}
--- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -3660,9 +3660,14 @@
}
void MacroAssembler::unimplemented(const char* what) {
- char* b = new char[1024];
- jio_snprintf(b, 1024, "unimplemented: %s", what);
- stop(b);
+ const char* buf = NULL;
+ {
+ ResourceMark rm;
+ stringStream ss;
+ ss.print("unimplemented: %s", what);
+ buf = code_string(ss.as_string());
+ }
+ stop(buf);
}
#ifdef _LP64
--- a/src/hotspot/cpu/zero/copy_zero.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/cpu/zero/copy_zero.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright 2007 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -28,11 +28,11 @@
// Inline functions for memory copy and fill.
-static void pd_conjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
memmove(to, from, count * HeapWordSize);
}
-static void pd_disjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
switch (count) {
case 8: to[7] = from[7];
case 7: to[6] = from[6];
@@ -49,7 +49,7 @@
}
}
-static void pd_disjoint_words_atomic(HeapWord* from,
+static void pd_disjoint_words_atomic(const HeapWord* from,
HeapWord* to,
size_t count) {
switch (count) {
@@ -70,73 +70,73 @@
}
}
-static void pd_aligned_conjoint_words(HeapWord* from,
+static void pd_aligned_conjoint_words(const HeapWord* from,
HeapWord* to,
size_t count) {
memmove(to, from, count * HeapWordSize);
}
-static void pd_aligned_disjoint_words(HeapWord* from,
+static void pd_aligned_disjoint_words(const HeapWord* from,
HeapWord* to,
size_t count) {
pd_disjoint_words(from, to, count);
}
-static void pd_conjoint_bytes(void* from, void* to, size_t count) {
+static void pd_conjoint_bytes(const void* from, void* to, size_t count) {
memmove(to, from, count);
}
-static void pd_conjoint_bytes_atomic(void* from, void* to, size_t count) {
+static void pd_conjoint_bytes_atomic(const void* from, void* to, size_t count) {
memmove(to, from, count);
}
-static void pd_conjoint_jshorts_atomic(jshort* from, jshort* to, size_t count) {
+static void pd_conjoint_jshorts_atomic(const jshort* from, jshort* to, size_t count) {
_Copy_conjoint_jshorts_atomic(from, to, count);
}
-static void pd_conjoint_jints_atomic(jint* from, jint* to, size_t count) {
+static void pd_conjoint_jints_atomic(const jint* from, jint* to, size_t count) {
_Copy_conjoint_jints_atomic(from, to, count);
}
-static void pd_conjoint_jlongs_atomic(jlong* from, jlong* to, size_t count) {
+static void pd_conjoint_jlongs_atomic(const jlong* from, jlong* to, size_t count) {
_Copy_conjoint_jlongs_atomic(from, to, count);
}
-static void pd_conjoint_oops_atomic(oop* from, oop* to, size_t count) {
+static void pd_conjoint_oops_atomic(const oop* from, oop* to, size_t count) {
#ifdef _LP64
assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size");
- _Copy_conjoint_jlongs_atomic((jlong*)from, (jlong*)to, count);
+ _Copy_conjoint_jlongs_atomic((const jlong*)from, (jlong*)to, count);
#else
assert(BytesPerInt == BytesPerOop, "jints and oops must be the same size");
- _Copy_conjoint_jints_atomic((jint*)from, (jint*)to, count);
+ _Copy_conjoint_jints_atomic((const jint*)from, (jint*)to, count);
#endif // _LP64
}
-static void pd_arrayof_conjoint_bytes(HeapWord* from,
+static void pd_arrayof_conjoint_bytes(const HeapWord* from,
HeapWord* to,
size_t count) {
_Copy_arrayof_conjoint_bytes(from, to, count);
}
-static void pd_arrayof_conjoint_jshorts(HeapWord* from,
+static void pd_arrayof_conjoint_jshorts(const HeapWord* from,
HeapWord* to,
size_t count) {
_Copy_arrayof_conjoint_jshorts(from, to, count);
}
-static void pd_arrayof_conjoint_jints(HeapWord* from,
+static void pd_arrayof_conjoint_jints(const HeapWord* from,
HeapWord* to,
size_t count) {
_Copy_arrayof_conjoint_jints(from, to, count);
}
-static void pd_arrayof_conjoint_jlongs(HeapWord* from,
+static void pd_arrayof_conjoint_jlongs(const HeapWord* from,
HeapWord* to,
size_t count) {
_Copy_arrayof_conjoint_jlongs(from, to, count);
}
-static void pd_arrayof_conjoint_oops(HeapWord* from,
+static void pd_arrayof_conjoint_oops(const HeapWord* from,
HeapWord* to,
size_t count) {
#ifdef _LP64
--- a/src/hotspot/os/linux/decoder_linux.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/os/linux/decoder_linux.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -24,6 +24,7 @@
#include "jvm.h"
#include "utilities/decoder_elf.hpp"
+#include "utilities/elfFile.hpp"
#include <cxxabi.h>
@@ -50,3 +51,38 @@
return false;
}
+// Returns true if the elf file is marked NOT to require an executable stack,
+// or if the file could not be opened.
+// Returns false if the elf file requires an executable stack, the stack flag
+// is not set at all, or if the file can not be read.
+bool ElfFile::specifies_noexecstack(const char* filepath) {
+ if (filepath == NULL) return true;
+
+ FILE* file = fopen(filepath, "r");
+ if (file == NULL) return true;
+
+ // AARCH64 defaults to noexecstack. All others default to execstack.
+ bool result = AARCH64_ONLY(true) NOT_AARCH64(false);
+
+ // Read file header
+ Elf_Ehdr head;
+ if (fread(&head, sizeof(Elf_Ehdr), 1, file) == 1 &&
+ is_elf_file(head) &&
+ fseek(file, head.e_phoff, SEEK_SET) == 0) {
+
+ // Read program header table
+ Elf_Phdr phdr;
+ for (int index = 0; index < head.e_phnum; index ++) {
+ if (fread((void*)&phdr, sizeof(Elf_Phdr), 1, file) != 1) {
+ result = false;
+ break;
+ }
+ if (phdr.p_type == PT_GNU_STACK) {
+ result = (phdr.p_flags == (PF_R | PF_W));
+ break;
+ }
+ }
+ }
+ fclose(file);
+ return result;
+}
--- a/src/hotspot/os/windows/globals_windows.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/os/windows/globals_windows.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -37,10 +37,7 @@
notproduct, \
range, \
constraint, \
- writeable) \
- \
- product(bool, UseUTCFileTimestamp, true, \
- "Adjust the timestamp returned from stat() to be UTC")
+ writeable)
//
--- a/src/hotspot/os_cpu/bsd_x86/copy_bsd_x86.inline.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/os_cpu/bsd_x86/copy_bsd_x86.inline.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -25,7 +25,7 @@
#ifndef OS_CPU_BSD_X86_VM_COPY_BSD_X86_INLINE_HPP
#define OS_CPU_BSD_X86_VM_COPY_BSD_X86_INLINE_HPP
-static void pd_conjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
#ifdef AMD64
(void)memmove(to, from, count * HeapWordSize);
#else
@@ -70,7 +70,7 @@
#endif // AMD64
}
-static void pd_disjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
#ifdef AMD64
switch (count) {
case 8: to[7] = from[7];
@@ -108,7 +108,7 @@
#endif // AMD64
}
-static void pd_disjoint_words_atomic(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_disjoint_words_atomic(const HeapWord* from, HeapWord* to, size_t count) {
#ifdef AMD64
switch (count) {
case 8: to[7] = from[7];
@@ -132,15 +132,15 @@
#endif // AMD64
}
-static void pd_aligned_conjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_aligned_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
pd_conjoint_words(from, to, count);
}
-static void pd_aligned_disjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_aligned_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
pd_disjoint_words(from, to, count);
}
-static void pd_conjoint_bytes(void* from, void* to, size_t count) {
+static void pd_conjoint_bytes(const void* from, void* to, size_t count) {
#ifdef AMD64
(void)memmove(to, from, count);
#else
@@ -219,25 +219,25 @@
#endif // AMD64
}
-static void pd_conjoint_bytes_atomic(void* from, void* to, size_t count) {
+static void pd_conjoint_bytes_atomic(const void* from, void* to, size_t count) {
pd_conjoint_bytes(from, to, count);
}
-static void pd_conjoint_jshorts_atomic(jshort* from, jshort* to, size_t count) {
+static void pd_conjoint_jshorts_atomic(const jshort* from, jshort* to, size_t count) {
_Copy_conjoint_jshorts_atomic(from, to, count);
}
-static void pd_conjoint_jints_atomic(jint* from, jint* to, size_t count) {
+static void pd_conjoint_jints_atomic(const jint* from, jint* to, size_t count) {
#ifdef AMD64
_Copy_conjoint_jints_atomic(from, to, count);
#else
assert(HeapWordSize == BytesPerInt, "heapwords and jints must be the same size");
// pd_conjoint_words is word-atomic in this implementation.
- pd_conjoint_words((HeapWord*)from, (HeapWord*)to, count);
+ pd_conjoint_words((const HeapWord*)from, (HeapWord*)to, count);
#endif // AMD64
}
-static void pd_conjoint_jlongs_atomic(jlong* from, jlong* to, size_t count) {
+static void pd_conjoint_jlongs_atomic(const jlong* from, jlong* to, size_t count) {
#ifdef AMD64
_Copy_conjoint_jlongs_atomic(from, to, count);
#else
@@ -262,47 +262,47 @@
#endif // AMD64
}
-static void pd_conjoint_oops_atomic(oop* from, oop* to, size_t count) {
+static void pd_conjoint_oops_atomic(const oop* from, oop* to, size_t count) {
#ifdef AMD64
assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size");
- _Copy_conjoint_jlongs_atomic((jlong*)from, (jlong*)to, count);
+ _Copy_conjoint_jlongs_atomic((const jlong*)from, (jlong*)to, count);
#else
assert(HeapWordSize == BytesPerOop, "heapwords and oops must be the same size");
// pd_conjoint_words is word-atomic in this implementation.
- pd_conjoint_words((HeapWord*)from, (HeapWord*)to, count);
+ pd_conjoint_words((const HeapWord*)from, (HeapWord*)to, count);
#endif // AMD64
}
-static void pd_arrayof_conjoint_bytes(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_arrayof_conjoint_bytes(const HeapWord* from, HeapWord* to, size_t count) {
_Copy_arrayof_conjoint_bytes(from, to, count);
}
-static void pd_arrayof_conjoint_jshorts(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_arrayof_conjoint_jshorts(const HeapWord* from, HeapWord* to, size_t count) {
_Copy_arrayof_conjoint_jshorts(from, to, count);
}
-static void pd_arrayof_conjoint_jints(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_arrayof_conjoint_jints(const HeapWord* from, HeapWord* to, size_t count) {
#ifdef AMD64
_Copy_arrayof_conjoint_jints(from, to, count);
#else
- pd_conjoint_jints_atomic((jint*)from, (jint*)to, count);
+ pd_conjoint_jints_atomic((const jint*)from, (jint*)to, count);
#endif // AMD64
}
-static void pd_arrayof_conjoint_jlongs(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_arrayof_conjoint_jlongs(const HeapWord* from, HeapWord* to, size_t count) {
#ifdef AMD64
_Copy_arrayof_conjoint_jlongs(from, to, count);
#else
- pd_conjoint_jlongs_atomic((jlong*)from, (jlong*)to, count);
+ pd_conjoint_jlongs_atomic((const jlong*)from, (jlong*)to, count);
#endif // AMD64
}
-static void pd_arrayof_conjoint_oops(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_arrayof_conjoint_oops(const HeapWord* from, HeapWord* to, size_t count) {
#ifdef AMD64
assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size");
_Copy_arrayof_conjoint_jlongs(from, to, count);
#else
- pd_conjoint_oops_atomic((oop*)from, (oop*)to, count);
+ pd_conjoint_oops_atomic((const oop*)from, (oop*)to, count);
#endif // AMD64
}
--- a/src/hotspot/os_cpu/linux_aarch64/copy_linux_aarch64.inline.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/os_cpu/linux_aarch64/copy_linux_aarch64.inline.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -99,7 +99,7 @@
: "memory", "cc"); \
}
-static void pd_conjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
__asm volatile( "prfm pldl1strm, [%[s], #0];" :: [s]"r"(from) : "memory");
if (__builtin_expect(count <= 8, 1)) {
COPY_SMALL(from, to, count);
@@ -108,7 +108,7 @@
_Copy_conjoint_words(from, to, count);
}
-static void pd_disjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
if (__builtin_constant_p(count)) {
memcpy(to, from, count * sizeof(HeapWord));
return;
@@ -121,7 +121,7 @@
_Copy_disjoint_words(from, to, count);
}
-static void pd_disjoint_words_atomic(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_disjoint_words_atomic(const HeapWord* from, HeapWord* to, size_t count) {
__asm volatile( "prfm pldl1strm, [%[s], #0];" :: [s]"r"(from) : "memory");
if (__builtin_expect(count <= 8, 1)) {
COPY_SMALL(from, to, count);
@@ -130,56 +130,56 @@
_Copy_disjoint_words(from, to, count);
}
-static void pd_aligned_conjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_aligned_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
pd_conjoint_words(from, to, count);
}
-static void pd_aligned_disjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_aligned_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
pd_disjoint_words(from, to, count);
}
-static void pd_conjoint_bytes(void* from, void* to, size_t count) {
+static void pd_conjoint_bytes(const void* from, void* to, size_t count) {
(void)memmove(to, from, count);
}
-static void pd_conjoint_bytes_atomic(void* from, void* to, size_t count) {
+static void pd_conjoint_bytes_atomic(const void* from, void* to, size_t count) {
pd_conjoint_bytes(from, to, count);
}
-static void pd_conjoint_jshorts_atomic(jshort* from, jshort* to, size_t count) {
+static void pd_conjoint_jshorts_atomic(const jshort* from, jshort* to, size_t count) {
_Copy_conjoint_jshorts_atomic(from, to, count);
}
-static void pd_conjoint_jints_atomic(jint* from, jint* to, size_t count) {
+static void pd_conjoint_jints_atomic(const jint* from, jint* to, size_t count) {
_Copy_conjoint_jints_atomic(from, to, count);
}
-static void pd_conjoint_jlongs_atomic(jlong* from, jlong* to, size_t count) {
+static void pd_conjoint_jlongs_atomic(const jlong* from, jlong* to, size_t count) {
_Copy_conjoint_jlongs_atomic(from, to, count);
}
-static void pd_conjoint_oops_atomic(oop* from, oop* to, size_t count) {
+static void pd_conjoint_oops_atomic(const oop* from, oop* to, size_t count) {
assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size");
- _Copy_conjoint_jlongs_atomic((jlong*)from, (jlong*)to, count);
+ _Copy_conjoint_jlongs_atomic((const jlong*)from, (jlong*)to, count);
}
-static void pd_arrayof_conjoint_bytes(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_arrayof_conjoint_bytes(const HeapWord* from, HeapWord* to, size_t count) {
_Copy_arrayof_conjoint_bytes(from, to, count);
}
-static void pd_arrayof_conjoint_jshorts(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_arrayof_conjoint_jshorts(const HeapWord* from, HeapWord* to, size_t count) {
_Copy_arrayof_conjoint_jshorts(from, to, count);
}
-static void pd_arrayof_conjoint_jints(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_arrayof_conjoint_jints(const HeapWord* from, HeapWord* to, size_t count) {
_Copy_arrayof_conjoint_jints(from, to, count);
}
-static void pd_arrayof_conjoint_jlongs(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_arrayof_conjoint_jlongs(const HeapWord* from, HeapWord* to, size_t count) {
_Copy_arrayof_conjoint_jlongs(from, to, count);
}
-static void pd_arrayof_conjoint_oops(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_arrayof_conjoint_oops(const HeapWord* from, HeapWord* to, size_t count) {
assert(!UseCompressedOops, "foo!");
assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size");
_Copy_arrayof_conjoint_jlongs(from, to, count);
--- a/src/hotspot/os_cpu/linux_arm/copy_linux_arm.inline.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/os_cpu/linux_arm/copy_linux_arm.inline.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -25,7 +25,7 @@
#ifndef OS_CPU_LINUX_ARM_VM_COPY_LINUX_ARM_INLINE_HPP
#define OS_CPU_LINUX_ARM_VM_COPY_LINUX_ARM_INLINE_HPP
-static void pd_conjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
#ifdef AARCH64
_Copy_conjoint_words(from, to, count * HeapWordSize);
#else
@@ -34,7 +34,7 @@
#endif
}
-static void pd_disjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
#ifdef AARCH64
_Copy_disjoint_words(from, to, count * HeapWordSize);
#else
@@ -42,27 +42,27 @@
#endif // AARCH64
}
-static void pd_disjoint_words_atomic(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_disjoint_words_atomic(const HeapWord* from, HeapWord* to, size_t count) {
pd_disjoint_words(from, to, count);
}
-static void pd_aligned_conjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_aligned_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
pd_conjoint_words(from, to, count);
}
-static void pd_aligned_disjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_aligned_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
pd_disjoint_words(from, to, count);
}
-static void pd_conjoint_bytes(void* from, void* to, size_t count) {
+static void pd_conjoint_bytes(const void* from, void* to, size_t count) {
memmove(to, from, count);
}
-static void pd_conjoint_bytes_atomic(void* from, void* to, size_t count) {
+static void pd_conjoint_bytes_atomic(const void* from, void* to, size_t count) {
pd_conjoint_bytes(from, to, count);
}
-static void pd_conjoint_jshorts_atomic(jshort* from, jshort* to, size_t count) {
+static void pd_conjoint_jshorts_atomic(const jshort* from, jshort* to, size_t count) {
#ifdef AARCH64
_Copy_conjoint_jshorts_atomic(from, to, count * BytesPerShort);
#else
@@ -70,58 +70,58 @@
#endif
}
-static void pd_conjoint_jints_atomic(jint* from, jint* to, size_t count) {
+static void pd_conjoint_jints_atomic(const jint* from, jint* to, size_t count) {
#ifdef AARCH64
_Copy_conjoint_jints_atomic(from, to, count * BytesPerInt);
#else
assert(HeapWordSize == BytesPerInt, "heapwords and jints must be the same size");
// pd_conjoint_words is word-atomic in this implementation.
- pd_conjoint_words((HeapWord*)from, (HeapWord*)to, count);
+ pd_conjoint_words((const HeapWord*)from, (HeapWord*)to, count);
#endif
}
-static void pd_conjoint_jlongs_atomic(jlong* from, jlong* to, size_t count) {
+static void pd_conjoint_jlongs_atomic(const jlong* from, jlong* to, size_t count) {
#ifdef AARCH64
assert(HeapWordSize == BytesPerLong, "64-bit architecture");
- pd_conjoint_words((HeapWord*)from, (HeapWord*)to, count);
+ pd_conjoint_words((const HeapWord*)from, (HeapWord*)to, count);
#else
_Copy_conjoint_jlongs_atomic(to, from, count * BytesPerLong);
#endif
}
-static void pd_conjoint_oops_atomic(oop* from, oop* to, size_t count) {
+static void pd_conjoint_oops_atomic(const oop* from, oop* to, size_t count) {
#ifdef AARCH64
if (UseCompressedOops) {
assert(BytesPerHeapOop == BytesPerInt, "compressed oops");
- pd_conjoint_jints_atomic((jint*)from, (jint*)to, count);
+ pd_conjoint_jints_atomic((const jint*)from, (jint*)to, count);
} else {
assert(BytesPerHeapOop == BytesPerLong, "64-bit architecture");
- pd_conjoint_jlongs_atomic((jlong*)from, (jlong*)to, count);
+ pd_conjoint_jlongs_atomic((const jlong*)from, (jlong*)to, count);
}
#else
assert(BytesPerHeapOop == BytesPerInt, "32-bit architecture");
- pd_conjoint_jints_atomic((jint*)from, (jint*)to, count);
+ pd_conjoint_jints_atomic((const jint*)from, (jint*)to, count);
#endif
}
-static void pd_arrayof_conjoint_bytes(HeapWord* from, HeapWord* to, size_t count) {
- pd_conjoint_bytes_atomic((void*)from, (void*)to, count);
+static void pd_arrayof_conjoint_bytes(const HeapWord* from, HeapWord* to, size_t count) {
+ pd_conjoint_bytes_atomic((const void*)from, (void*)to, count);
}
-static void pd_arrayof_conjoint_jshorts(HeapWord* from, HeapWord* to, size_t count) {
- pd_conjoint_jshorts_atomic((jshort*)from, (jshort*)to, count);
+static void pd_arrayof_conjoint_jshorts(const HeapWord* from, HeapWord* to, size_t count) {
+ pd_conjoint_jshorts_atomic((const jshort*)from, (jshort*)to, count);
}
-static void pd_arrayof_conjoint_jints(HeapWord* from, HeapWord* to, size_t count) {
- pd_conjoint_jints_atomic((jint*)from, (jint*)to, count);
+static void pd_arrayof_conjoint_jints(const HeapWord* from, HeapWord* to, size_t count) {
+ pd_conjoint_jints_atomic((const jint*)from, (jint*)to, count);
}
-static void pd_arrayof_conjoint_jlongs(HeapWord* from, HeapWord* to, size_t count) {
- pd_conjoint_jlongs_atomic((jlong*)from, (jlong*)to, count);
+static void pd_arrayof_conjoint_jlongs(const HeapWord* from, HeapWord* to, size_t count) {
+ pd_conjoint_jlongs_atomic((const jlong*)from, (jlong*)to, count);
}
-static void pd_arrayof_conjoint_oops(HeapWord* from, HeapWord* to, size_t count) {
- pd_conjoint_oops_atomic((oop*)from, (oop*)to, count);
+static void pd_arrayof_conjoint_oops(const HeapWord* from, HeapWord* to, size_t count) {
+ pd_conjoint_oops_atomic((const oop*)from, (oop*)to, count);
}
#endif // OS_CPU_LINUX_ARM_VM_COPY_LINUX_ARM_INLINE_HPP
--- a/src/hotspot/os_cpu/linux_x86/copy_linux_x86.inline.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/os_cpu/linux_x86/copy_linux_x86.inline.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -25,7 +25,7 @@
#ifndef OS_CPU_LINUX_X86_VM_COPY_LINUX_X86_INLINE_HPP
#define OS_CPU_LINUX_X86_VM_COPY_LINUX_X86_INLINE_HPP
-static void pd_conjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
#ifdef AMD64
(void)memmove(to, from, count * HeapWordSize);
#else
@@ -70,7 +70,7 @@
#endif // AMD64
}
-static void pd_disjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
#ifdef AMD64
switch (count) {
case 8: to[7] = from[7];
@@ -108,7 +108,7 @@
#endif // AMD64
}
-static void pd_disjoint_words_atomic(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_disjoint_words_atomic(const HeapWord* from, HeapWord* to, size_t count) {
#ifdef AMD64
switch (count) {
case 8: to[7] = from[7];
@@ -132,15 +132,15 @@
#endif // AMD64
}
-static void pd_aligned_conjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_aligned_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
pd_conjoint_words(from, to, count);
}
-static void pd_aligned_disjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_aligned_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
pd_disjoint_words(from, to, count);
}
-static void pd_conjoint_bytes(void* from, void* to, size_t count) {
+static void pd_conjoint_bytes(const void* from, void* to, size_t count) {
#ifdef AMD64
(void)memmove(to, from, count);
#else
@@ -219,25 +219,25 @@
#endif // AMD64
}
-static void pd_conjoint_bytes_atomic(void* from, void* to, size_t count) {
+static void pd_conjoint_bytes_atomic(const void* from, void* to, size_t count) {
pd_conjoint_bytes(from, to, count);
}
-static void pd_conjoint_jshorts_atomic(jshort* from, jshort* to, size_t count) {
+static void pd_conjoint_jshorts_atomic(const jshort* from, jshort* to, size_t count) {
_Copy_conjoint_jshorts_atomic(from, to, count);
}
-static void pd_conjoint_jints_atomic(jint* from, jint* to, size_t count) {
+static void pd_conjoint_jints_atomic(const jint* from, jint* to, size_t count) {
#ifdef AMD64
_Copy_conjoint_jints_atomic(from, to, count);
#else
assert(HeapWordSize == BytesPerInt, "heapwords and jints must be the same size");
// pd_conjoint_words is word-atomic in this implementation.
- pd_conjoint_words((HeapWord*)from, (HeapWord*)to, count);
+ pd_conjoint_words((const HeapWord*)from, (HeapWord*)to, count);
#endif // AMD64
}
-static void pd_conjoint_jlongs_atomic(jlong* from, jlong* to, size_t count) {
+static void pd_conjoint_jlongs_atomic(const jlong* from, jlong* to, size_t count) {
#ifdef AMD64
_Copy_conjoint_jlongs_atomic(from, to, count);
#else
@@ -262,47 +262,47 @@
#endif // AMD64
}
-static void pd_conjoint_oops_atomic(oop* from, oop* to, size_t count) {
+static void pd_conjoint_oops_atomic(const oop* from, oop* to, size_t count) {
#ifdef AMD64
assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size");
- _Copy_conjoint_jlongs_atomic((jlong*)from, (jlong*)to, count);
+ _Copy_conjoint_jlongs_atomic((const jlong*)from, (jlong*)to, count);
#else
assert(HeapWordSize == BytesPerOop, "heapwords and oops must be the same size");
// pd_conjoint_words is word-atomic in this implementation.
- pd_conjoint_words((HeapWord*)from, (HeapWord*)to, count);
+ pd_conjoint_words((const HeapWord*)from, (HeapWord*)to, count);
#endif // AMD64
}
-static void pd_arrayof_conjoint_bytes(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_arrayof_conjoint_bytes(const HeapWord* from, HeapWord* to, size_t count) {
_Copy_arrayof_conjoint_bytes(from, to, count);
}
-static void pd_arrayof_conjoint_jshorts(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_arrayof_conjoint_jshorts(const HeapWord* from, HeapWord* to, size_t count) {
_Copy_arrayof_conjoint_jshorts(from, to, count);
}
-static void pd_arrayof_conjoint_jints(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_arrayof_conjoint_jints(const HeapWord* from, HeapWord* to, size_t count) {
#ifdef AMD64
_Copy_arrayof_conjoint_jints(from, to, count);
#else
- pd_conjoint_jints_atomic((jint*)from, (jint*)to, count);
+ pd_conjoint_jints_atomic((const jint*)from, (jint*)to, count);
#endif // AMD64
}
-static void pd_arrayof_conjoint_jlongs(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_arrayof_conjoint_jlongs(const HeapWord* from, HeapWord* to, size_t count) {
#ifdef AMD64
_Copy_arrayof_conjoint_jlongs(from, to, count);
#else
- pd_conjoint_jlongs_atomic((jlong*)from, (jlong*)to, count);
+ pd_conjoint_jlongs_atomic((const jlong*)from, (jlong*)to, count);
#endif // AMD64
}
-static void pd_arrayof_conjoint_oops(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_arrayof_conjoint_oops(const HeapWord* from, HeapWord* to, size_t count) {
#ifdef AMD64
assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size");
_Copy_arrayof_conjoint_jlongs(from, to, count);
#else
- pd_conjoint_oops_atomic((oop*)from, (oop*)to, count);
+ pd_conjoint_oops_atomic((const oop*)from, (oop*)to, count);
#endif // AMD64
}
--- a/src/hotspot/os_cpu/solaris_x86/copy_solaris_x86.inline.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/os_cpu/solaris_x86/copy_solaris_x86.inline.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -25,11 +25,11 @@
#ifndef OS_CPU_SOLARIS_X86_VM_COPY_SOLARIS_X86_INLINE_HPP
#define OS_CPU_SOLARIS_X86_VM_COPY_SOLARIS_X86_INLINE_HPP
-static void pd_conjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
(void)memmove(to, from, count * HeapWordSize);
}
-static void pd_disjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
#ifndef AMD64
(void)memcpy(to, from, count * HeapWordSize);
#else
@@ -50,7 +50,7 @@
#endif // AMD64
}
-static void pd_disjoint_words_atomic(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_disjoint_words_atomic(const HeapWord* from, HeapWord* to, size_t count) {
switch (count) {
case 8: to[7] = from[7];
case 7: to[6] = from[6];
@@ -68,15 +68,15 @@
}
}
-static void pd_aligned_conjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_aligned_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
(void)memmove(to, from, count * HeapWordSize);
}
-static void pd_aligned_disjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_aligned_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
pd_disjoint_words(from, to, count);
}
-static void pd_conjoint_bytes(void* from, void* to, size_t count) {
+static void pd_conjoint_bytes(const void* from, void* to, size_t count) {
#ifdef AMD64
(void)memmove(to, from, count);
#else
@@ -84,53 +84,53 @@
#endif // AMD64
}
-static void pd_conjoint_bytes_atomic(void* from, void* to, size_t count) {
+static void pd_conjoint_bytes_atomic(const void* from, void* to, size_t count) {
pd_conjoint_bytes(from, to, count);
}
-static void pd_conjoint_jshorts_atomic(jshort* from, jshort* to, size_t count) {
+static void pd_conjoint_jshorts_atomic(const jshort* from, jshort* to, size_t count) {
_Copy_conjoint_jshorts_atomic(from, to, count);
}
-static void pd_conjoint_jints_atomic(jint* from, jint* to, size_t count) {
+static void pd_conjoint_jints_atomic(const jint* from, jint* to, size_t count) {
_Copy_conjoint_jints_atomic(from, to, count);
}
-static void pd_conjoint_jlongs_atomic(jlong* from, jlong* to, size_t count) {
+static void pd_conjoint_jlongs_atomic(const jlong* from, jlong* to, size_t count) {
// Guarantee use of fild/fistp or xmm regs via some asm code, because compilers won't.
_Copy_conjoint_jlongs_atomic(from, to, count);
}
-static void pd_conjoint_oops_atomic(oop* from, oop* to, size_t count) {
+static void pd_conjoint_oops_atomic(const oop* from, oop* to, size_t count) {
#ifdef AMD64
assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size");
- _Copy_conjoint_jlongs_atomic((jlong*)from, (jlong*)to, count);
+ _Copy_conjoint_jlongs_atomic((const jlong*)from, (jlong*)to, count);
#else
- _Copy_conjoint_jints_atomic((jint*)from, (jint*)to, count);
+ _Copy_conjoint_jints_atomic((const jint*)from, (jint*)to, count);
#endif // AMD64
}
-static void pd_arrayof_conjoint_bytes(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_arrayof_conjoint_bytes(const HeapWord* from, HeapWord* to, size_t count) {
_Copy_arrayof_conjoint_bytes(from, to, count);
}
-static void pd_arrayof_conjoint_jshorts(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_arrayof_conjoint_jshorts(const HeapWord* from, HeapWord* to, size_t count) {
_Copy_arrayof_conjoint_jshorts(from, to, count);
}
-static void pd_arrayof_conjoint_jints(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_arrayof_conjoint_jints(const HeapWord* from, HeapWord* to, size_t count) {
_Copy_arrayof_conjoint_jints(from, to, count);
}
-static void pd_arrayof_conjoint_jlongs(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_arrayof_conjoint_jlongs(const HeapWord* from, HeapWord* to, size_t count) {
#ifdef AMD64
_Copy_arrayof_conjoint_jlongs(from, to, count);
#else
- pd_conjoint_jlongs_atomic((jlong*)from, (jlong*)to, count);
+ pd_conjoint_jlongs_atomic((const jlong*)from, (jlong*)to, count);
#endif // AMD64
}
-static void pd_arrayof_conjoint_oops(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_arrayof_conjoint_oops(const HeapWord* from, HeapWord* to, size_t count) {
#ifdef AMD64
assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size");
_Copy_arrayof_conjoint_jlongs(from, to, count);
--- a/src/hotspot/os_cpu/windows_x86/copy_windows_x86.inline.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/os_cpu/windows_x86/copy_windows_x86.inline.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -25,11 +25,11 @@
#ifndef OS_CPU_WINDOWS_X86_VM_COPY_WINDOWS_X86_INLINE_HPP
#define OS_CPU_WINDOWS_X86_VM_COPY_WINDOWS_X86_INLINE_HPP
-static void pd_conjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
(void)memmove(to, from, count * HeapWordSize);
}
-static void pd_disjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
#ifdef AMD64
switch (count) {
case 8: to[7] = from[7];
@@ -50,7 +50,7 @@
#endif // AMD64
}
-static void pd_disjoint_words_atomic(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_disjoint_words_atomic(const HeapWord* from, HeapWord* to, size_t count) {
switch (count) {
case 8: to[7] = from[7];
case 7: to[6] = from[6];
@@ -68,23 +68,23 @@
}
}
-static void pd_aligned_conjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_aligned_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
(void)memmove(to, from, count * HeapWordSize);
}
-static void pd_aligned_disjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_aligned_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
pd_disjoint_words(from, to, count);
}
-static void pd_conjoint_bytes(void* from, void* to, size_t count) {
+static void pd_conjoint_bytes(const void* from, void* to, size_t count) {
(void)memmove(to, from, count);
}
-static void pd_conjoint_bytes_atomic(void* from, void* to, size_t count) {
+static void pd_conjoint_bytes_atomic(const void* from, void* to, size_t count) {
pd_conjoint_bytes(from, to, count);
}
-static void pd_conjoint_jshorts_atomic(jshort* from, jshort* to, size_t count) {
+static void pd_conjoint_jshorts_atomic(const jshort* from, jshort* to, size_t count) {
if (from > to) {
while (count-- > 0) {
// Copy forwards
@@ -100,7 +100,7 @@
}
}
-static void pd_conjoint_jints_atomic(jint* from, jint* to, size_t count) {
+static void pd_conjoint_jints_atomic(const jint* from, jint* to, size_t count) {
if (from > to) {
while (count-- > 0) {
// Copy forwards
@@ -116,10 +116,10 @@
}
}
-static void pd_conjoint_jlongs_atomic(jlong* from, jlong* to, size_t count) {
+static void pd_conjoint_jlongs_atomic(const jlong* from, jlong* to, size_t count) {
#ifdef AMD64
assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size");
- pd_conjoint_oops_atomic((oop*)from, (oop*)to, count);
+ pd_conjoint_oops_atomic((const oop*)from, (oop*)to, count);
#else
// Guarantee use of fild/fistp or xmm regs via some asm code, because compilers won't.
__asm {
@@ -149,7 +149,7 @@
#endif // AMD64
}
-static void pd_conjoint_oops_atomic(oop* from, oop* to, size_t count) {
+static void pd_conjoint_oops_atomic(const oop* from, oop* to, size_t count) {
// Do better than this: inline memmove body NEEDS CLEANUP
if (from > to) {
while (count-- > 0) {
@@ -166,7 +166,7 @@
}
}
-static void pd_arrayof_conjoint_bytes(HeapWord* from, HeapWord* to, size_t count) {
+static void pd_arrayof_conjoint_bytes(const HeapWord* from, HeapWord* to, size_t count) {
#ifdef AMD64
pd_conjoint_bytes_atomic(from, to, count);
#else
@@ -174,20 +174,20 @@
#endif // AMD64
}
-static void pd_arrayof_conjoint_jshorts(HeapWord* from, HeapWord* to, size_t count) {
- pd_conjoint_jshorts_atomic((jshort*)from, (jshort*)to, count);
+static void pd_arrayof_conjoint_jshorts(const HeapWord* from, HeapWord* to, size_t count) {
+ pd_conjoint_jshorts_atomic((const jshort*)from, (jshort*)to, count);
}
-static void pd_arrayof_conjoint_jints(HeapWord* from, HeapWord* to, size_t count) {
- pd_conjoint_jints_atomic((jint*)from, (jint*)to, count);
+static void pd_arrayof_conjoint_jints(const HeapWord* from, HeapWord* to, size_t count) {
+ pd_conjoint_jints_atomic((const jint*)from, (jint*)to, count);
}
-static void pd_arrayof_conjoint_jlongs(HeapWord* from, HeapWord* to, size_t count) {
- pd_conjoint_jlongs_atomic((jlong*)from, (jlong*)to, count);
+static void pd_arrayof_conjoint_jlongs(const HeapWord* from, HeapWord* to, size_t count) {
+ pd_conjoint_jlongs_atomic((const jlong*)from, (jlong*)to, count);
}
-static void pd_arrayof_conjoint_oops(HeapWord* from, HeapWord* to, size_t count) {
- pd_conjoint_oops_atomic((oop*)from, (oop*)to, count);
+static void pd_arrayof_conjoint_oops(const HeapWord* from, HeapWord* to, size_t count) {
+ pd_conjoint_oops_atomic((const oop*)from, (oop*)to, count);
}
#endif // OS_CPU_WINDOWS_X86_VM_COPY_WINDOWS_X86_INLINE_HPP
--- a/src/hotspot/share/classfile/compactHashtable.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/classfile/compactHashtable.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -146,27 +146,23 @@
cht->init(base_address, _num_entries, _num_buckets,
_compact_buckets->data(), _compact_entries->data());
- if (log_is_enabled(Info, cds, hashtables)) {
- ResourceMark rm;
- LogMessage(cds, hashtables) msg;
- stringStream info_stream;
-
+ LogMessage(cds, hashtables) msg;
+ if (msg.is_info()) {
double avg_cost = 0.0;
if (_num_entries > 0) {
avg_cost = double(table_bytes)/double(_num_entries);
}
- info_stream.print_cr("Shared %s table stats -------- base: " PTR_FORMAT,
+ msg.info("Shared %s table stats -------- base: " PTR_FORMAT,
table_name, (intptr_t)base_address);
- info_stream.print_cr("Number of entries : %9d", _num_entries);
- info_stream.print_cr("Total bytes used : %9d", table_bytes);
- info_stream.print_cr("Average bytes per entry : %9.3f", avg_cost);
- info_stream.print_cr("Average bucket size : %9.3f", summary.avg());
- info_stream.print_cr("Variance of bucket size : %9.3f", summary.variance());
- info_stream.print_cr("Std. dev. of bucket size: %9.3f", summary.sd());
- info_stream.print_cr("Empty buckets : %9d", _num_empty_buckets);
- info_stream.print_cr("Value_Only buckets : %9d", _num_value_only_buckets);
- info_stream.print_cr("Other buckets : %9d", _num_other_buckets);
- msg.info("%s", info_stream.as_string());
+ msg.info("Number of entries : %9d", _num_entries);
+ msg.info("Total bytes used : %9d", table_bytes);
+ msg.info("Average bytes per entry : %9.3f", avg_cost);
+ msg.info("Average bucket size : %9.3f", summary.avg());
+ msg.info("Variance of bucket size : %9.3f", summary.variance());
+ msg.info("Std. dev. of bucket size: %9.3f", summary.sd());
+ msg.info("Empty buckets : %9d", _num_empty_buckets);
+ msg.info("Value_Only buckets : %9d", _num_value_only_buckets);
+ msg.info("Other buckets : %9d", _num_other_buckets);
}
}
--- a/src/hotspot/share/code/compiledMethod.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/code/compiledMethod.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -439,11 +439,11 @@
}
void CompiledMethod::set_unloading_clock(unsigned char unloading_clock) {
- OrderAccess::release_store((volatile jubyte*)&_unloading_clock, unloading_clock);
+ OrderAccess::release_store(&_unloading_clock, unloading_clock);
}
unsigned char CompiledMethod::unloading_clock() {
- return (unsigned char)OrderAccess::load_acquire((volatile jubyte*)&_unloading_clock);
+ return OrderAccess::load_acquire(&_unloading_clock);
}
// Processing of oop references should have been sufficient to keep
--- a/src/hotspot/share/code/dependencyContext.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/code/dependencyContext.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -270,5 +270,5 @@
#endif //PRODUCT
int nmethodBucket::decrement() {
- return Atomic::add(-1, (volatile int *)&_count);
+ return Atomic::sub(1, &_count);
}
--- a/src/hotspot/share/gc/cms/cmsHeap.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/cms/cmsHeap.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -75,10 +75,6 @@
// supports. Caller does not hold the Heap_lock on entry.
void collect(GCCause::Cause cause);
- bool card_mark_must_follow_store() const {
- return true;
- }
-
void stop();
void safepoint_synchronize_begin();
void safepoint_synchronize_end();
--- a/src/hotspot/share/gc/g1/collectionSetChooser.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/g1/collectionSetChooser.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -138,7 +138,7 @@
G1PrintRegionLivenessInfoClosure cl("Post-Sorting");
for (uint i = 0; i < _end; ++i) {
HeapRegion* r = regions_at(i);
- cl.doHeapRegion(r);
+ cl.do_heap_region(r);
}
}
verify();
@@ -220,7 +220,7 @@
_g1h(G1CollectedHeap::heap()),
_cset_updater(hrSorted, true /* parallel */, chunk_size) { }
- bool doHeapRegion(HeapRegion* r) {
+ bool do_heap_region(HeapRegion* r) {
// Do we have any marking information for this region?
if (r->is_marked()) {
// We will skip any region that's currently used as an old GC
--- a/src/hotspot/share/gc/g1/g1Allocator.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/g1/g1Allocator.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -134,9 +134,6 @@
_old_is_full = true;
}
-G1PLAB::G1PLAB(size_t gclab_word_size) :
- PLAB(gclab_word_size), _retired(true) { }
-
size_t G1Allocator::unsafe_max_tlab_alloc(AllocationContext_t context) {
// Return the remaining space in the cur alloc region, but not less than
// the min TLAB size.
@@ -253,7 +250,7 @@
if ((required_in_plab <= plab_word_size) &&
may_throw_away_buffer(required_in_plab, plab_word_size)) {
- G1PLAB* alloc_buf = alloc_buffer(dest, context);
+ PLAB* alloc_buf = alloc_buffer(dest, context);
alloc_buf->retire();
size_t actual_plab_size = 0;
@@ -304,7 +301,7 @@
void G1DefaultPLABAllocator::flush_and_retire_stats() {
for (uint state = 0; state < InCSetState::Num; state++) {
- G1PLAB* const buf = _alloc_buffers[state];
+ PLAB* const buf = _alloc_buffers[state];
if (buf != NULL) {
G1EvacStats* stats = _g1h->alloc_buffer_stats(state);
buf->flush_and_retire_stats(stats);
@@ -318,7 +315,7 @@
wasted = 0;
undo_wasted = 0;
for (uint state = 0; state < InCSetState::Num; state++) {
- G1PLAB * const buf = _alloc_buffers[state];
+ PLAB * const buf = _alloc_buffers[state];
if (buf != NULL) {
wasted += buf->waste();
undo_wasted += buf->undo_waste();
--- a/src/hotspot/share/gc/g1/g1Allocator.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/g1/g1Allocator.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -178,39 +178,6 @@
}
};
-class G1PLAB: public PLAB {
-private:
- bool _retired;
-
-public:
- G1PLAB(size_t gclab_word_size);
- virtual ~G1PLAB() {
- guarantee(_retired, "Allocation buffer has not been retired");
- }
-
- // The amount of space in words wasted within the PLAB including
- // waste due to refills and alignment.
- size_t wasted() const { return _wasted; }
-
- virtual void set_buf(HeapWord* buf, size_t word_size) {
- PLAB::set_buf(buf, word_size);
- _retired = false;
- }
-
- virtual void retire() {
- if (_retired) {
- return;
- }
- PLAB::retire();
- _retired = true;
- }
-
- virtual void flush_and_retire_stats(PLABStats* stats) {
- PLAB::flush_and_retire_stats(stats);
- _retired = true;
- }
-};
-
// Manages the PLABs used during garbage collection. Interface for allocation from PLABs.
// Needs to handle multiple contexts, extra alignment in any "survivor" area and some
// statistics.
@@ -231,7 +198,7 @@
size_t _direct_allocated[InCSetState::Num];
virtual void flush_and_retire_stats() = 0;
- virtual G1PLAB* alloc_buffer(InCSetState dest, AllocationContext_t context) = 0;
+ virtual PLAB* alloc_buffer(InCSetState dest, AllocationContext_t context) = 0;
// Calculate the survivor space object alignment in bytes. Returns that or 0 if
// there are no restrictions on survivor alignment.
@@ -292,14 +259,14 @@
// The default PLAB allocator for G1. Keeps the current (single) PLAB for survivor
// and old generation allocation.
class G1DefaultPLABAllocator : public G1PLABAllocator {
- G1PLAB _surviving_alloc_buffer;
- G1PLAB _tenured_alloc_buffer;
- G1PLAB* _alloc_buffers[InCSetState::Num];
+ PLAB _surviving_alloc_buffer;
+ PLAB _tenured_alloc_buffer;
+ PLAB* _alloc_buffers[InCSetState::Num];
public:
G1DefaultPLABAllocator(G1Allocator* _allocator);
- virtual G1PLAB* alloc_buffer(InCSetState dest, AllocationContext_t context) {
+ virtual PLAB* alloc_buffer(InCSetState dest, AllocationContext_t context) {
assert(dest.is_valid(),
"Allocation buffer index out-of-bounds: " CSETSTATE_FORMAT, dest.value());
assert(_alloc_buffers[dest.value()] != NULL,
--- a/src/hotspot/share/gc/g1/g1Allocator.inline.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/g1/g1Allocator.inline.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -47,7 +47,7 @@
inline HeapWord* G1PLABAllocator::plab_allocate(InCSetState dest,
size_t word_sz,
AllocationContext_t context) {
- G1PLAB* buffer = alloc_buffer(dest, context);
+ PLAB* buffer = alloc_buffer(dest, context);
if (_survivor_alignment_bytes == 0 || !dest.is_young()) {
return buffer->allocate(word_sz);
} else {
--- a/src/hotspot/share/gc/g1/g1CardCounts.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/g1/g1CardCounts.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -144,7 +144,7 @@
HeapRegionClosure(), _card_counts(card_counts) { }
- virtual bool doHeapRegion(HeapRegion* r) {
+ virtual bool do_heap_region(HeapRegion* r) {
_card_counts->clear_region(r);
return false;
}
--- a/src/hotspot/share/gc/g1/g1CardLiveData.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/g1/g1CardLiveData.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -285,7 +285,7 @@
_mark_bitmap(mark_bitmap),
_cm(cm) { }
- bool doHeapRegion(HeapRegion* hr) {
+ bool do_heap_region(HeapRegion* hr) {
size_t marked_bytes = _helper.mark_marked_during_marking(_mark_bitmap, hr);
if (marked_bytes > 0) {
hr->add_to_marked_bytes(marked_bytes);
@@ -352,7 +352,7 @@
_helper(live_data, g1h->reserved_region().start()),
_gc_timestamp_at_create(live_data->gc_timestamp_at_create()) { }
- bool doHeapRegion(HeapRegion* hr) {
+ bool do_heap_region(HeapRegion* hr) {
if (has_been_reclaimed(hr)) {
_helper.reset_live_data(hr);
}
@@ -478,7 +478,7 @@
int failures() const { return _failures; }
- bool doHeapRegion(HeapRegion* hr) {
+ bool do_heap_region(HeapRegion* hr) {
int failures = 0;
// Walk the marking bitmap for this region and set the corresponding bits
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -1010,7 +1010,7 @@
private:
G1HRPrinter* _hr_printer;
public:
- bool doHeapRegion(HeapRegion* hr) {
+ bool do_heap_region(HeapRegion* hr) {
assert(!hr->is_young(), "not expecting to find young regions");
_hr_printer->post_compaction(hr);
return false;
@@ -1573,7 +1573,6 @@
}
jint G1CollectedHeap::initialize() {
- CollectedHeap::pre_initialize();
os::enable_vtime();
// Necessary to satisfy locking discipline assertions.
@@ -1917,7 +1916,7 @@
CheckGCTimeStampsHRClosure(unsigned gc_time_stamp) :
_gc_time_stamp(gc_time_stamp), _failures(false) { }
- virtual bool doHeapRegion(HeapRegion* hr) {
+ virtual bool do_heap_region(HeapRegion* hr) {
unsigned region_gc_time_stamp = hr->get_gc_time_stamp();
if (_gc_time_stamp != region_gc_time_stamp) {
log_error(gc, verify)("Region " HR_FORMAT " has GC time stamp = %d, expected %d", HR_FORMAT_PARAMS(hr),
@@ -1969,7 +1968,7 @@
size_t _used;
public:
SumUsedClosure() : _used(0) {}
- bool doHeapRegion(HeapRegion* r) {
+ bool do_heap_region(HeapRegion* r) {
_used += r->used();
return false;
}
@@ -2188,7 +2187,7 @@
ObjectClosure* _cl;
public:
IterateObjectClosureRegionClosure(ObjectClosure* cl) : _cl(cl) {}
- bool doHeapRegion(HeapRegion* r) {
+ bool do_heap_region(HeapRegion* r) {
if (!r->is_continues_humongous()) {
r->object_iterate(_cl);
}
@@ -2303,7 +2302,7 @@
outputStream* _st;
public:
PrintRegionClosure(outputStream* st) : _st(st) {}
- bool doHeapRegion(HeapRegion* r) {
+ bool do_heap_region(HeapRegion* r) {
r->print_on(_st);
return false;
}
@@ -2422,7 +2421,7 @@
size_t _occupied_sum;
public:
- bool doHeapRegion(HeapRegion* r) {
+ bool do_heap_region(HeapRegion* r) {
HeapRegionRemSet* hrrs = r->rem_set();
size_t occupied = hrrs->occupied();
_occupied_sum += occupied;
@@ -2669,7 +2668,7 @@
_dcq(&JavaThread::dirty_card_queue_set()) {
}
- virtual bool doHeapRegion(HeapRegion* r) {
+ virtual bool do_heap_region(HeapRegion* r) {
if (!r->is_starts_humongous()) {
return false;
}
@@ -2745,7 +2744,7 @@
class VerifyRegionRemSetClosure : public HeapRegionClosure {
public:
- bool doHeapRegion(HeapRegion* hr) {
+ bool do_heap_region(HeapRegion* hr) {
if (!hr->is_archive() && !hr->is_continues_humongous()) {
hr->verify_rem_set();
}
@@ -2815,7 +2814,7 @@
public:
G1PrintCollectionSetClosure(G1HRPrinter* hr_printer) : HeapRegionClosure(), _hr_printer(hr_printer) { }
- virtual bool doHeapRegion(HeapRegion* r) {
+ virtual bool do_heap_region(HeapRegion* r) {
_hr_printer->cset(r);
return false;
}
@@ -4505,7 +4504,7 @@
_local_free_list("Local Region List for CSet Freeing") {
}
- virtual bool doHeapRegion(HeapRegion* r) {
+ virtual bool do_heap_region(HeapRegion* r) {
G1CollectedHeap* g1h = G1CollectedHeap::heap();
assert(r->in_collection_set(), "Region %u should be in collection set.", r->hrm_index());
@@ -4628,7 +4627,7 @@
public:
G1PrepareFreeCollectionSetClosure(WorkItem* work_items) : HeapRegionClosure(), _cur_idx(0), _work_items(work_items) { }
- virtual bool doHeapRegion(HeapRegion* r) {
+ virtual bool do_heap_region(HeapRegion* r) {
_work_items[_cur_idx++] = WorkItem(r);
return false;
}
@@ -4762,7 +4761,7 @@
_free_region_list(free_region_list), _humongous_objects_reclaimed(0), _humongous_regions_reclaimed(0), _freed_bytes(0) {
}
- virtual bool doHeapRegion(HeapRegion* r) {
+ virtual bool do_heap_region(HeapRegion* r) {
if (!r->is_starts_humongous()) {
return false;
}
@@ -4897,7 +4896,7 @@
class G1AbandonCollectionSetClosure : public HeapRegionClosure {
public:
- virtual bool doHeapRegion(HeapRegion* r) {
+ virtual bool do_heap_region(HeapRegion* r) {
assert(r->in_collection_set(), "Region %u must have been in collection set", r->hrm_index());
G1CollectedHeap::heap()->clear_in_cset(r);
r->set_young_index_in_cset(-1);
@@ -4967,7 +4966,7 @@
bool _success;
public:
NoYoungRegionsClosure() : _success(true) { }
- bool doHeapRegion(HeapRegion* r) {
+ bool do_heap_region(HeapRegion* r) {
if (r->is_young()) {
log_error(gc, verify)("Region [" PTR_FORMAT ", " PTR_FORMAT ") tagged as young",
p2i(r->bottom()), p2i(r->end()));
@@ -4997,7 +4996,7 @@
public:
TearDownRegionSetsClosure(HeapRegionSet* old_set) : _old_set(old_set) { }
- bool doHeapRegion(HeapRegion* r) {
+ bool do_heap_region(HeapRegion* r) {
if (r->is_old()) {
_old_set->remove(r);
} else if(r->is_young()) {
@@ -5065,7 +5064,7 @@
}
}
- bool doHeapRegion(HeapRegion* r) {
+ bool do_heap_region(HeapRegion* r) {
if (r->is_empty()) {
// Add free regions to the free list
r->set_free();
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1197,7 +1197,7 @@
}
// Iterate over heap regions, in address order, terminating the
- // iteration early if the "doHeapRegion" method returns "true".
+ // iteration early if the "do_heap_region" method returns "true".
void heap_region_iterate(HeapRegionClosure* blk) const;
// Return the region with the given index. It assumes the index is valid.
@@ -1272,36 +1272,8 @@
size_t max_tlab_size() const;
size_t unsafe_max_tlab_alloc(Thread* ignored) const;
- // Can a compiler initialize a new object without store barriers?
- // This permission only extends from the creation of a new object
- // via a TLAB up to the first subsequent safepoint. If such permission
- // is granted for this heap type, the compiler promises to call
- // defer_store_barrier() below on any slow path allocation of
- // a new object for which such initializing store barriers will
- // have been elided. G1, like CMS, allows this, but should be
- // ready to provide a compensating write barrier as necessary
- // if that storage came out of a non-young region. The efficiency
- // of this implementation depends crucially on being able to
- // answer very efficiently in constant time whether a piece of
- // storage in the heap comes from a young region or not.
- // See ReduceInitialCardMarks.
- virtual bool can_elide_tlab_store_barriers() const {
- return true;
- }
-
- virtual bool card_mark_must_follow_store() const {
- return true;
- }
-
inline bool is_in_young(const oop obj);
- // We don't need barriers for initializing stores to objects
- // in the young gen: for the SATB pre-barrier, there is no
- // pre-value that needs to be remembered; for the remembered-set
- // update logging post-barrier, we don't maintain remembered set
- // information for young gen objects.
- virtual inline bool can_elide_initializing_store_barrier(oop new_obj);
-
// Returns "true" iff the given word_size is "very large".
static bool is_humongous(size_t word_size) {
// Note this has to be strictly greater-than as the TLABs
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -241,15 +241,6 @@
return heap_region_containing(obj)->is_young();
}
-// We don't need barriers for initializing stores to objects
-// in the young gen: for the SATB pre-barrier, there is no
-// pre-value that needs to be remembered; for the remembered-set
-// update logging post-barrier, we don't maintain remembered set
-// information for young gen objects.
-inline bool G1CollectedHeap::can_elide_initializing_store_barrier(oop new_obj) {
- return is_in_young(new_obj);
-}
-
inline bool G1CollectedHeap::is_obj_dead(const oop obj) const {
if (obj == NULL) {
return false;
--- a/src/hotspot/share/gc/g1/g1CollectionSet.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/g1/g1CollectionSet.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -186,9 +186,9 @@
do {
HeapRegion* r = G1CollectedHeap::heap()->region_at(_collection_set_regions[cur_pos]);
- bool result = cl->doHeapRegion(r);
+ bool result = cl->do_heap_region(r);
if (result) {
- cl->incomplete();
+ cl->set_incomplete();
return;
}
cur_pos++;
@@ -292,7 +292,7 @@
public:
G1VerifyYoungAgesClosure() : HeapRegionClosure(), _valid(true) { }
- virtual bool doHeapRegion(HeapRegion* r) {
+ virtual bool do_heap_region(HeapRegion* r) {
guarantee(r->is_young(), "Region must be young but is %s", r->get_type_str());
SurvRateGroup* group = r->surv_rate_group();
@@ -332,7 +332,7 @@
public:
G1PrintCollectionSetClosure(outputStream* st) : HeapRegionClosure(), _st(st) { }
- virtual bool doHeapRegion(HeapRegion* r) {
+ virtual bool do_heap_region(HeapRegion* r) {
assert(r->in_collection_set(), "Region %u should be in collection set", r->hrm_index());
_st->print_cr(" " HR_FORMAT ", P: " PTR_FORMAT "N: " PTR_FORMAT ", age: %4d",
HR_FORMAT_PARAMS(r),
@@ -524,7 +524,7 @@
FREE_C_HEAP_ARRAY(int, _heap_region_indices);
}
- virtual bool doHeapRegion(HeapRegion* r) {
+ virtual bool do_heap_region(HeapRegion* r) {
const int idx = r->young_index_in_cset();
assert(idx > -1, "Young index must be set for all regions in the incremental collection set but is not for region %u.", r->hrm_index());
--- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -591,7 +591,7 @@
G1ClearBitmapHRClosure(G1CMBitMap* bitmap, G1ConcurrentMark* cm) : HeapRegionClosure(), _cm(cm), _bitmap(bitmap) {
}
- virtual bool doHeapRegion(HeapRegion* r) {
+ virtual bool do_heap_region(HeapRegion* r) {
size_t const chunk_size_in_words = G1ClearBitMapTask::chunk_size() / HeapWordSize;
HeapWord* cur = r->bottom();
@@ -638,7 +638,7 @@
}
bool is_complete() {
- return _cl.complete();
+ return _cl.is_complete();
}
};
@@ -694,7 +694,7 @@
CheckBitmapClearHRClosure(G1CMBitMap* bitmap) : _bitmap(bitmap) {
}
- virtual bool doHeapRegion(HeapRegion* r) {
+ virtual bool do_heap_region(HeapRegion* r) {
// This closure can be called concurrently to the mutator, so we must make sure
// that the result of the getNextMarkedWordAddress() call is compared to the
// value passed to it as limit to detect any found bits.
@@ -707,12 +707,12 @@
bool G1ConcurrentMark::next_mark_bitmap_is_clear() {
CheckBitmapClearHRClosure cl(_next_mark_bitmap);
_g1h->heap_region_iterate(&cl);
- return cl.complete();
+ return cl.is_complete();
}
class NoteStartOfMarkHRClosure: public HeapRegionClosure {
public:
- bool doHeapRegion(HeapRegion* r) {
+ bool do_heap_region(HeapRegion* r) {
r->note_start_of_marking();
return false;
}
@@ -1094,7 +1094,7 @@
const uint old_regions_removed() { return _old_regions_removed; }
const uint humongous_regions_removed() { return _humongous_regions_removed; }
- bool doHeapRegion(HeapRegion *hr) {
+ bool do_heap_region(HeapRegion *hr) {
_g1->reset_gc_time_stamps(hr);
hr->note_end_of_marking();
@@ -1135,7 +1135,7 @@
G1NoteEndOfConcMarkClosure g1_note_end(_g1h, &local_cleanup_list,
&hrrs_cleanup_task);
_g1h->heap_region_par_iterate_from_worker_offset(&g1_note_end, &_hrclaimer, worker_id);
- assert(g1_note_end.complete(), "Shouldn't have yielded!");
+ assert(g1_note_end.is_complete(), "Shouldn't have yielded!");
// Now update the lists
_g1h->remove_from_old_sets(g1_note_end.old_regions_removed(), g1_note_end.humongous_regions_removed());
@@ -2922,7 +2922,7 @@
"(bytes)", "(bytes)");
}
-bool G1PrintRegionLivenessInfoClosure::doHeapRegion(HeapRegion* r) {
+bool G1PrintRegionLivenessInfoClosure::do_heap_region(HeapRegion* r) {
const char* type = r->get_type_str();
HeapWord* bottom = r->bottom();
HeapWord* end = r->end();
--- a/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -848,7 +848,7 @@
// The header and footer are printed in the constructor and
// destructor respectively.
G1PrintRegionLivenessInfoClosure(const char* phase_name);
- virtual bool doHeapRegion(HeapRegion* r);
+ virtual bool do_heap_region(HeapRegion* r);
~G1PrintRegionLivenessInfoClosure();
};
--- a/src/hotspot/share/gc/g1/g1EvacFailure.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/g1/g1EvacFailure.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -220,7 +220,7 @@
return rspc.marked_bytes();
}
- bool doHeapRegion(HeapRegion *hr) {
+ bool do_heap_region(HeapRegion *hr) {
assert(!hr->is_pinned(), "Unexpected pinned region at index %u", hr->hrm_index());
assert(hr->in_collection_set(), "bad CS");
--- a/src/hotspot/share/gc/g1/g1FullGCAdjustTask.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/g1/g1FullGCAdjustTask.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -56,7 +56,7 @@
_bitmap(bitmap),
_worker_id(worker_id) { }
- bool doHeapRegion(HeapRegion* r) {
+ bool do_heap_region(HeapRegion* r) {
G1AdjustAndRebuildClosure cl(_worker_id);
if (r->is_humongous()) {
oop obj = oop(r->humongous_start_region()->bottom());
--- a/src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -40,7 +40,7 @@
G1ResetHumongousClosure(G1CMBitMap* bitmap) :
_bitmap(bitmap) { }
- bool doHeapRegion(HeapRegion* current) {
+ bool do_heap_region(HeapRegion* current) {
if (current->is_humongous()) {
if (current->is_starts_humongous()) {
oop obj = oop(current->bottom());
--- a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -37,7 +37,7 @@
#include "logging/log.hpp"
#include "utilities/ticks.inline.hpp"
-bool G1FullGCPrepareTask::G1CalculatePointersClosure::doHeapRegion(HeapRegion* hr) {
+bool G1FullGCPrepareTask::G1CalculatePointersClosure::do_heap_region(HeapRegion* hr) {
if (hr->is_humongous()) {
oop obj = oop(hr->humongous_start_region()->bottom());
if (_bitmap->is_marked(obj)) {
--- a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -67,7 +67,7 @@
G1FullGCCompactionPoint* cp);
void update_sets();
- bool doHeapRegion(HeapRegion* hr);
+ bool do_heap_region(HeapRegion* hr);
bool freed_regions();
};
--- a/src/hotspot/share/gc/g1/g1HeapTransition.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/g1/g1HeapTransition.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -58,7 +58,7 @@
class DetailedUsageClosure: public HeapRegionClosure {
public:
DetailedUsage _usage;
- bool doHeapRegion(HeapRegion* r) {
+ bool do_heap_region(HeapRegion* r) {
if (r->is_old()) {
_usage._old_used += r->used();
_usage._old_region_count++;
--- a/src/hotspot/share/gc/g1/g1HeapVerifier.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/g1/g1HeapVerifier.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -273,7 +273,7 @@
G1CollectedHeap* _g1h;
public:
VerifyArchivePointerRegionClosure(G1CollectedHeap* g1h) { }
- virtual bool doHeapRegion(HeapRegion* r) {
+ virtual bool do_heap_region(HeapRegion* r) {
if (r->is_archive()) {
VerifyObjectInArchiveRegionClosure verify_oop_pointers(r, false);
r->object_iterate(&verify_oop_pointers);
@@ -306,7 +306,7 @@
return _failures;
}
- bool doHeapRegion(HeapRegion* r) {
+ bool do_heap_region(HeapRegion* r) {
// For archive regions, verify there are no heap pointers to
// non-pinned regions. For all others, verify liveness info.
if (r->is_closed_archive()) {
@@ -498,7 +498,7 @@
_old_set(old_set), _humongous_set(humongous_set), _hrm(hrm),
_old_count(), _humongous_count(), _free_count(){ }
- bool doHeapRegion(HeapRegion* hr) {
+ bool do_heap_region(HeapRegion* hr) {
if (hr->is_young()) {
// TODO
} else if (hr->is_humongous()) {
@@ -608,7 +608,7 @@
public:
G1VerifyCardTableCleanup(G1HeapVerifier* verifier, G1SATBCardTableModRefBS* ct_bs)
: _verifier(verifier), _ct_bs(ct_bs) { }
- virtual bool doHeapRegion(HeapRegion* r) {
+ virtual bool do_heap_region(HeapRegion* r) {
if (r->is_survivor()) {
_verifier->verify_dirty_region(r);
} else {
@@ -654,7 +654,7 @@
G1HeapVerifier* _verifier;
public:
G1VerifyDirtyYoungListClosure(G1HeapVerifier* verifier) : HeapRegionClosure(), _verifier(verifier) { }
- virtual bool doHeapRegion(HeapRegion* r) {
+ virtual bool do_heap_region(HeapRegion* r) {
_verifier->verify_dirty_region(r);
return false;
}
@@ -721,7 +721,7 @@
bool failures() { return _failures; }
- virtual bool doHeapRegion(HeapRegion* hr) {
+ virtual bool do_heap_region(HeapRegion* hr) {
bool result = _verifier->verify_bitmaps(_caller, hr);
if (!result) {
_failures = true;
@@ -744,7 +744,7 @@
public:
G1CheckCSetFastTableClosure() : HeapRegionClosure(), _failures(false) { }
- virtual bool doHeapRegion(HeapRegion* hr) {
+ virtual bool do_heap_region(HeapRegion* hr) {
uint i = hr->hrm_index();
InCSetState cset_state = (InCSetState) G1CollectedHeap::heap()->_in_cset_fast_test.get_by_index(i);
if (hr->is_humongous()) {
--- a/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -206,7 +206,7 @@
oop const old, size_t word_sz, uint age,
HeapWord * const obj_ptr,
const AllocationContext_t context) const {
- G1PLAB* alloc_buf = _plab_allocator->alloc_buffer(dest_state, context);
+ PLAB* alloc_buf = _plab_allocator->alloc_buffer(dest_state, context);
if (alloc_buf->contains(obj_ptr)) {
_g1h->_gc_tracer_stw->report_promotion_in_new_plab_event(old->klass(), word_sz, age,
dest_state.value() == InCSetState::Old,
--- a/src/hotspot/share/gc/g1/g1RemSet.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/g1/g1RemSet.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -127,7 +127,7 @@
public:
G1ResetScanTopClosure(HeapWord** scan_top) : _scan_top(scan_top) { }
- virtual bool doHeapRegion(HeapRegion* r) {
+ virtual bool do_heap_region(HeapRegion* r) {
uint hrm_index = r->hrm_index();
if (!r->in_collection_set() && r->is_old_or_humongous()) {
_scan_top[hrm_index] = r->top();
@@ -204,7 +204,7 @@
if (_iter_states[region] != Unclaimed) {
return false;
}
- jint res = Atomic::cmpxchg(Claimed, (jint*)(&_iter_states[region]), Unclaimed);
+ G1RemsetIterState res = Atomic::cmpxchg(Claimed, &_iter_states[region], Unclaimed);
return (res == Unclaimed);
}
@@ -214,7 +214,7 @@
if (iter_is_complete(region)) {
return false;
}
- jint res = Atomic::cmpxchg(Complete, (jint*)(&_iter_states[region]), Claimed);
+ G1RemsetIterState res = Atomic::cmpxchg(Complete, &_iter_states[region], Claimed);
return (res == Claimed);
}
@@ -349,7 +349,7 @@
_scan_state->add_dirty_region(region_idx_for_card);
}
-bool G1ScanRSForRegionClosure::doHeapRegion(HeapRegion* r) {
+bool G1ScanRSForRegionClosure::do_heap_region(HeapRegion* r) {
assert(r->in_collection_set(), "should only be called on elements of CS.");
uint region_idx = r->hrm_index();
@@ -522,7 +522,7 @@
_g1h(G1CollectedHeap::heap()),
_live_data(live_data) { }
- bool doHeapRegion(HeapRegion* r) {
+ bool do_heap_region(HeapRegion* r) {
if (!r->is_continues_humongous()) {
r->rem_set()->scrub(_live_data);
}
--- a/src/hotspot/share/gc/g1/g1RemSet.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/g1/g1RemSet.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -176,7 +176,7 @@
CodeBlobClosure* code_root_cl,
uint worker_i);
- bool doHeapRegion(HeapRegion* r);
+ bool do_heap_region(HeapRegion* r);
double strong_code_root_scan_time_sec() {
return _strong_code_root_scan_time_sec;
--- a/src/hotspot/share/gc/g1/g1RemSetSummary.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/g1/g1RemSetSummary.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -252,7 +252,7 @@
_max_rs_mem_sz(0), _max_code_root_mem_sz(0)
{}
- bool doHeapRegion(HeapRegion* r) {
+ bool do_heap_region(HeapRegion* r) {
HeapRegionRemSet* hrrs = r->rem_set();
// HeapRegionRemSet::mem_size() includes the
--- a/src/hotspot/share/gc/g1/g1SATBCardTableModRefBS.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/g1/g1SATBCardTableModRefBS.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -131,6 +131,7 @@
}
void G1SATBCardTableLoggingModRefBS::initialize(G1RegionToSpaceMapper* mapper) {
+ initialize_deferred_card_mark_barriers();
mapper->set_mapping_changed_listener(&_listener);
_byte_map_size = mapper->reserved().byte_size();
@@ -213,3 +214,14 @@
}
}
}
+
+bool G1SATBCardTableModRefBS::is_in_young(oop obj) const {
+ volatile jbyte* p = byte_for((void*)obj);
+ return *p == g1_young_card_val();
+}
+
+void G1SATBCardTableLoggingModRefBS::flush_deferred_barriers(JavaThread* thread) {
+ CardTableModRefBS::flush_deferred_barriers(thread);
+ thread->satb_mark_queue().flush();
+ thread->dirty_card_queue().flush();
+}
--- a/src/hotspot/share/gc/g1/g1SATBCardTableModRefBS.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/g1/g1SATBCardTableModRefBS.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -92,6 +92,8 @@
jbyte val = _byte_map[card_index];
return (val & (clean_card_mask_val() | deferred_card_val())) == deferred_card_val();
}
+
+ virtual bool is_in_young(oop obj) const;
};
template<>
@@ -145,13 +147,19 @@
// above no longer applies.
void invalidate(MemRegion mr);
- void write_region_work(MemRegion mr) { invalidate(mr); }
+ void write_region(MemRegion mr) { invalidate(mr); }
void write_ref_array_work(MemRegion mr) { invalidate(mr); }
template <DecoratorSet decorators, typename T>
void write_ref_field_post(T* field, oop new_val);
void write_ref_field_post_slow(volatile jbyte* byte);
+ virtual void flush_deferred_barriers(JavaThread* thread);
+
+ virtual bool card_mark_must_follow_store() const {
+ return true;
+ }
+
// Callbacks for runtime accesses.
template <DecoratorSet decorators, typename BarrierSetT = G1SATBCardTableLoggingModRefBS>
class AccessBarrier: public ModRefBarrierSet::AccessBarrier<decorators, BarrierSetT> {
--- a/src/hotspot/share/gc/g1/g1SATBCardTableModRefBS.inline.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/g1/g1SATBCardTableModRefBS.inline.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -30,7 +30,7 @@
template <DecoratorSet decorators, typename T>
inline void G1SATBCardTableModRefBS::write_ref_field_pre(T* field) {
- if (HasDecorator<decorators, ARRAYCOPY_DEST_NOT_INITIALIZED>::value ||
+ if (HasDecorator<decorators, AS_DEST_NOT_INITIALIZED>::value ||
HasDecorator<decorators, AS_NO_KEEPALIVE>::value) {
return;
}
--- a/src/hotspot/share/gc/g1/g1YoungRemSetSamplingThread.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/g1/g1YoungRemSetSamplingThread.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -79,7 +79,7 @@
G1YoungRemSetSamplingClosure(SuspendibleThreadSetJoiner* sts) :
HeapRegionClosure(), _sts(sts), _regions_visited(0), _sampled_rs_lengths(0) { }
- virtual bool doHeapRegion(HeapRegion* r) {
+ virtual bool do_heap_region(HeapRegion* r) {
size_t rs_length = r->rem_set()->occupied();
_sampled_rs_lengths += rs_length;
@@ -114,7 +114,7 @@
G1CollectionSet* g1cs = g1h->collection_set();
g1cs->iterate(&cl);
- if (cl.complete()) {
+ if (cl.is_complete()) {
g1p->revise_young_list_target_length_if_necessary(cl.sampled_rs_lengths());
}
}
--- a/src/hotspot/share/gc/g1/heapRegion.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/g1/heapRegion.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -719,23 +719,23 @@
};
// HeapRegionClosure is used for iterating over regions.
-// Terminates the iteration when the "doHeapRegion" method returns "true".
+// Terminates the iteration when the "do_heap_region" method returns "true".
class HeapRegionClosure : public StackObj {
friend class HeapRegionManager;
friend class G1CollectionSet;
- bool _complete;
- void incomplete() { _complete = false; }
+ bool _is_complete;
+ void set_incomplete() { _is_complete = false; }
public:
- HeapRegionClosure(): _complete(true) {}
+ HeapRegionClosure(): _is_complete(true) {}
// Typically called on each region until it returns true.
- virtual bool doHeapRegion(HeapRegion* r) = 0;
+ virtual bool do_heap_region(HeapRegion* r) = 0;
// True after iteration if the closure was applied to all heap regions
// and returned "false" in all cases.
- bool complete() { return _complete; }
+ bool is_complete() { return _is_complete; }
};
#endif // SHARE_VM_GC_G1_HEAPREGION_HPP
--- a/src/hotspot/share/gc/g1/heapRegionManager.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/g1/heapRegionManager.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -242,9 +242,9 @@
continue;
}
guarantee(at(i) != NULL, "Tried to access region %u that has a NULL HeapRegion*", i);
- bool res = blk->doHeapRegion(at(i));
+ bool res = blk->do_heap_region(at(i));
if (res) {
- blk->incomplete();
+ blk->set_incomplete();
return;
}
}
@@ -353,7 +353,7 @@
if (!hrclaimer->claim_region(index)) {
continue;
}
- bool res = blk->doHeapRegion(r);
+ bool res = blk->do_heap_region(r);
if (res) {
return;
}
--- a/src/hotspot/share/gc/g1/heapRegionManager.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/g1/heapRegionManager.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -236,8 +236,8 @@
// and not free, and return the number of regions newly committed in commit_count.
bool allocate_containing_regions(MemRegion range, size_t* commit_count, WorkGang* pretouch_workers);
- // Apply blk->doHeapRegion() on all committed regions in address order,
- // terminating the iteration early if doHeapRegion() returns true.
+ // Apply blk->do_heap_region() on all committed regions in address order,
+ // terminating the iteration early if do_heap_region() returns true.
void iterate(HeapRegionClosure* blk) const;
void par_iterate(HeapRegionClosure* blk, HeapRegionClaimer* hrclaimer, const uint start_index) const;
--- a/src/hotspot/share/gc/parallel/cardTableExtension.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/parallel/cardTableExtension.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -26,7 +26,7 @@
#include "gc/parallel/cardTableExtension.hpp"
#include "gc/parallel/gcTaskManager.hpp"
#include "gc/parallel/objectStartArray.inline.hpp"
-#include "gc/parallel/parallelScavengeHeap.hpp"
+#include "gc/parallel/parallelScavengeHeap.inline.hpp"
#include "gc/parallel/psPromotionManager.inline.hpp"
#include "gc/parallel/psScavenge.hpp"
#include "gc/parallel/psTasks.hpp"
@@ -677,3 +677,7 @@
}
return min_start;
}
+
+bool CardTableExtension::is_in_young(oop obj) const {
+ return ParallelScavengeHeap::heap()->is_in_young(obj);
+}
--- a/src/hotspot/share/gc/parallel/cardTableExtension.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/parallel/cardTableExtension.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -108,6 +108,13 @@
}
#endif // ASSERT
+
+ // ReduceInitialCardMarks support
+ virtual bool is_in_young(oop obj) const;
+
+ virtual bool card_mark_must_follow_store() const {
+ return false;
+ }
};
template<>
--- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -57,8 +57,6 @@
GCTaskManager* ParallelScavengeHeap::_gc_task_manager = NULL;
jint ParallelScavengeHeap::initialize() {
- CollectedHeap::pre_initialize();
-
const size_t heap_size = _collector_policy->max_heap_byte_size();
ReservedSpace heap_rs = Universe::reserve_heap(heap_size, _collector_policy->heap_alignment());
@@ -490,13 +488,6 @@
CollectedHeap::resize_all_tlabs();
}
-bool ParallelScavengeHeap::can_elide_initializing_store_barrier(oop new_obj) {
- // We don't need barriers for stores to objects in the
- // young gen and, a fortiori, for initializing stores to
- // objects therein.
- return is_in_young(new_obj);
-}
-
// This method is used by System.gc() and JVMTI.
void ParallelScavengeHeap::collect(GCCause::Cause cause) {
assert(!Heap_lock->owned_by_self(),
@@ -719,4 +710,3 @@
memory_pools.append(_old_pool);
return memory_pools;
}
-
--- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -205,21 +205,6 @@
size_t tlab_used(Thread* thr) const;
size_t unsafe_max_tlab_alloc(Thread* thr) const;
- // Can a compiler initialize a new object without store barriers?
- // This permission only extends from the creation of a new object
- // via a TLAB up to the first subsequent safepoint.
- virtual bool can_elide_tlab_store_barriers() const {
- return true;
- }
-
- virtual bool card_mark_must_follow_store() const {
- return false;
- }
-
- // Return true if we don't we need a store barrier for
- // initializing stores to an object at this address.
- virtual bool can_elide_initializing_store_barrier(oop new_obj);
-
void object_iterate(ObjectClosure* cl);
void safe_object_iterate(ObjectClosure* cl) { object_iterate(cl); }
--- a/src/hotspot/share/gc/parallel/psParallelCompact.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/parallel/psParallelCompact.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -538,7 +538,7 @@
{
assert(_dc_and_los < dc_claimed, "already claimed");
assert(_dc_and_los >= dc_one, "count would go negative");
- Atomic::add((int)dc_mask, (volatile int*)&_dc_and_los);
+ Atomic::add(dc_mask, &_dc_and_los);
}
inline HeapWord* ParallelCompactData::RegionData::data_location() const
@@ -578,7 +578,7 @@
inline void ParallelCompactData::RegionData::add_live_obj(size_t words)
{
assert(words <= (size_t)los_mask - live_obj_size(), "overflow");
- Atomic::add((int) words, (volatile int*) &_dc_and_los);
+ Atomic::add(static_cast<region_sz_t>(words), &_dc_and_los);
}
inline void ParallelCompactData::RegionData::set_highest_ref(HeapWord* addr)
--- a/src/hotspot/share/gc/serial/serialHeap.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/serial/serialHeap.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -61,10 +61,6 @@
virtual bool is_in_closed_subset(const void* p) const {
return is_in(p);
}
-
- virtual bool card_mark_must_follow_store() const {
- return false;
- }
};
#endif // SHARE_VM_GC_CMS_CMSHEAP_HPP
--- a/src/hotspot/share/gc/shared/barrierSet.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/shared/barrierSet.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -32,6 +32,8 @@
#include "oops/oopsHierarchy.hpp"
#include "utilities/fakeRttiSupport.hpp"
+class JavaThread;
+
// This class provides the interface between a barrier implementation and
// the rest of the system.
@@ -107,19 +109,19 @@
static void static_write_ref_array_pre(HeapWord* start, size_t count);
static void static_write_ref_array_post(HeapWord* start, size_t count);
+ // Support for optimizing compilers to call the barrier set on slow path allocations
+ // that did not enter a TLAB. Used for e.g. ReduceInitialCardMarks.
+ // The allocation is safe to use iff it returns true. If not, the slow-path allocation
+ // is redone until it succeeds. This can e.g. prevent allocations from the slow path
+ // to be in old.
+ virtual void on_slowpath_allocation_exit(JavaThread* thread, oop new_obj) {}
+ virtual void flush_deferred_barriers(JavaThread* thread) {}
+ virtual void make_parsable(JavaThread* thread) {}
+
protected:
virtual void write_ref_array_work(MemRegion mr) = 0;
public:
- // (For efficiency reasons, this operation is specialized for certain
- // barrier types. Semantically, it should be thought of as a call to the
- // virtual "_work" function below, which must implement the barrier.)
- void write_region(MemRegion mr);
-
-protected:
- virtual void write_region_work(MemRegion mr) = 0;
-
-public:
// Inform the BarrierSet that the the covered heap region that starts
// with "base" has been changed to have the given size (possibly from 0,
// for initialization.)
--- a/src/hotspot/share/gc/shared/barrierSet.inline.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/shared/barrierSet.inline.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -52,8 +52,4 @@
write_ref_array_work(MemRegion(aligned_start, aligned_end));
}
-inline void BarrierSet::write_region(MemRegion mr) {
- write_region_work(mr);
-}
-
#endif // SHARE_VM_GC_SHARED_BARRIERSET_INLINE_HPP
--- a/src/hotspot/share/gc/shared/cardTableModRefBS.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/shared/cardTableModRefBS.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -30,6 +30,7 @@
#include "logging/log.hpp"
#include "memory/virtualspace.hpp"
#include "oops/oop.inline.hpp"
+#include "runtime/thread.hpp"
#include "services/memTracker.hpp"
#include "utilities/align.hpp"
#include "utilities/macros.hpp"
@@ -61,7 +62,8 @@
_committed(NULL),
_cur_covered_regions(0),
_byte_map(NULL),
- byte_map_base(NULL)
+ byte_map_base(NULL),
+ _defer_initial_card_mark(false)
{
assert((uintptr_t(_whole_heap.start()) & (card_size - 1)) == 0, "heap must start at card boundary");
assert((uintptr_t(_whole_heap.end()) & (card_size - 1)) == 0, "heap must end at card boundary");
@@ -75,6 +77,7 @@
}
void CardTableModRefBS::initialize() {
+ initialize_deferred_card_mark_barriers();
_guard_index = cards_required(_whole_heap.word_size()) - 1;
_last_valid_index = _guard_index - 1;
@@ -521,3 +524,112 @@
st->print_cr("Card table byte_map: [" INTPTR_FORMAT "," INTPTR_FORMAT "] byte_map_base: " INTPTR_FORMAT,
p2i(_byte_map), p2i(_byte_map + _byte_map_size), p2i(byte_map_base));
}
+
+// Helper for ReduceInitialCardMarks. For performance,
+// compiled code may elide card-marks for initializing stores
+// to a newly allocated object along the fast-path. We
+// compensate for such elided card-marks as follows:
+// (a) Generational, non-concurrent collectors, such as
+// GenCollectedHeap(ParNew,DefNew,Tenured) and
+// ParallelScavengeHeap(ParallelGC, ParallelOldGC)
+// need the card-mark if and only if the region is
+// in the old gen, and do not care if the card-mark
+// succeeds or precedes the initializing stores themselves,
+// so long as the card-mark is completed before the next
+// scavenge. For all these cases, we can do a card mark
+// at the point at which we do a slow path allocation
+// in the old gen, i.e. in this call.
+// (b) GenCollectedHeap(ConcurrentMarkSweepGeneration) requires
+// in addition that the card-mark for an old gen allocated
+// object strictly follow any associated initializing stores.
+// In these cases, the memRegion remembered below is
+// used to card-mark the entire region either just before the next
+// slow-path allocation by this thread or just before the next scavenge or
+// CMS-associated safepoint, whichever of these events happens first.
+// (The implicit assumption is that the object has been fully
+// initialized by this point, a fact that we assert when doing the
+// card-mark.)
+// (c) G1CollectedHeap(G1) uses two kinds of write barriers. When a
+// G1 concurrent marking is in progress an SATB (pre-write-)barrier
+// is used to remember the pre-value of any store. Initializing
+// stores will not need this barrier, so we need not worry about
+// compensating for the missing pre-barrier here. Turning now
+// to the post-barrier, we note that G1 needs a RS update barrier
+// which simply enqueues a (sequence of) dirty cards which may
+// optionally be refined by the concurrent update threads. Note
+// that this barrier need only be applied to a non-young write,
+// but, like in CMS, because of the presence of concurrent refinement
+// (much like CMS' precleaning), must strictly follow the oop-store.
+// Thus, using the same protocol for maintaining the intended
+// invariants turns out, serendepitously, to be the same for both
+// G1 and CMS.
+//
+// For any future collector, this code should be reexamined with
+// that specific collector in mind, and the documentation above suitably
+// extended and updated.
+void CardTableModRefBS::on_slowpath_allocation_exit(JavaThread* thread, oop new_obj) {
+ if (!ReduceInitialCardMarks) {
+ return;
+ }
+ // If a previous card-mark was deferred, flush it now.
+ flush_deferred_card_mark_barrier(thread);
+ if (new_obj->is_typeArray() || is_in_young(new_obj)) {
+ // Arrays of non-references don't need a post-barrier.
+ // The deferred_card_mark region should be empty
+ // following the flush above.
+ assert(thread->deferred_card_mark().is_empty(), "Error");
+ } else {
+ MemRegion mr((HeapWord*)new_obj, new_obj->size());
+ assert(!mr.is_empty(), "Error");
+ if (_defer_initial_card_mark) {
+ // Defer the card mark
+ thread->set_deferred_card_mark(mr);
+ } else {
+ // Do the card mark
+ write_region(mr);
+ }
+ }
+}
+
+void CardTableModRefBS::initialize_deferred_card_mark_barriers() {
+ // Used for ReduceInitialCardMarks (when COMPILER2 or JVMCI is used);
+ // otherwise remains unused.
+#if defined(COMPILER2) || INCLUDE_JVMCI
+ _defer_initial_card_mark = is_server_compilation_mode_vm() && ReduceInitialCardMarks && can_elide_tlab_store_barriers()
+ && (DeferInitialCardMark || card_mark_must_follow_store());
+#else
+ assert(_defer_initial_card_mark == false, "Who would set it?");
+#endif
+}
+
+void CardTableModRefBS::flush_deferred_card_mark_barrier(JavaThread* thread) {
+#if defined(COMPILER2) || INCLUDE_JVMCI
+ MemRegion deferred = thread->deferred_card_mark();
+ if (!deferred.is_empty()) {
+ assert(_defer_initial_card_mark, "Otherwise should be empty");
+ {
+ // Verify that the storage points to a parsable object in heap
+ DEBUG_ONLY(oop old_obj = oop(deferred.start());)
+ assert(!is_in_young(old_obj),
+ "Else should have been filtered in on_slowpath_allocation_exit()");
+ assert(oopDesc::is_oop(old_obj, true), "Not an oop");
+ assert(deferred.word_size() == (size_t)(old_obj->size()),
+ "Mismatch: multiple objects?");
+ }
+ write_region(deferred);
+ // "Clear" the deferred_card_mark field
+ thread->set_deferred_card_mark(MemRegion());
+ }
+ assert(thread->deferred_card_mark().is_empty(), "invariant");
+#else
+ assert(!_defer_initial_card_mark, "Should be false");
+ assert(thread->deferred_card_mark().is_empty(), "Should be empty");
+#endif
+}
+
+void CardTableModRefBS::flush_deferred_barriers(JavaThread* thread) {
+ // The deferred store barriers must all have been flushed to the
+ // card-table (or other remembered set structure) before GC starts
+ // processing the card-table (or other remembered set).
+ flush_deferred_card_mark_barrier(thread);
+}
--- a/src/hotspot/share/gc/shared/cardTableModRefBS.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/shared/cardTableModRefBS.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -58,6 +58,10 @@
CT_MR_BS_last_reserved = 16
};
+ // Used in support of ReduceInitialCardMarks; only consulted if COMPILER2
+ // or INCLUDE_JVMCI is being used
+ bool _defer_initial_card_mark;
+
// a word's worth (row) of clean card values
static const intptr_t clean_card_row = (intptr_t)(-1);
@@ -180,8 +184,8 @@
CardTableModRefBS(MemRegion whole_heap, const BarrierSet::FakeRtti& fake_rtti);
~CardTableModRefBS();
- protected:
- void write_region_work(MemRegion mr) {
+ public:
+ void write_region(MemRegion mr) {
dirty_MemRegion(mr);
}
@@ -314,6 +318,49 @@
void verify_not_dirty_region(MemRegion mr) PRODUCT_RETURN;
void verify_dirty_region(MemRegion mr) PRODUCT_RETURN;
+ // ReduceInitialCardMarks
+ void initialize_deferred_card_mark_barriers();
+
+ // If the CollectedHeap was asked to defer a store barrier above,
+ // this informs it to flush such a deferred store barrier to the
+ // remembered set.
+ void flush_deferred_card_mark_barrier(JavaThread* thread);
+
+ // Can a compiler initialize a new object without store barriers?
+ // This permission only extends from the creation of a new object
+ // via a TLAB up to the first subsequent safepoint. If such permission
+ // is granted for this heap type, the compiler promises to call
+ // defer_store_barrier() below on any slow path allocation of
+ // a new object for which such initializing store barriers will
+ // have been elided. G1, like CMS, allows this, but should be
+ // ready to provide a compensating write barrier as necessary
+ // if that storage came out of a non-young region. The efficiency
+ // of this implementation depends crucially on being able to
+ // answer very efficiently in constant time whether a piece of
+ // storage in the heap comes from a young region or not.
+ // See ReduceInitialCardMarks.
+ virtual bool can_elide_tlab_store_barriers() const {
+ return true;
+ }
+
+ // If a compiler is eliding store barriers for TLAB-allocated objects,
+ // we will be informed of a slow-path allocation by a call
+ // to on_slowpath_allocation_exit() below. Such a call precedes the
+ // initialization of the object itself, and no post-store-barriers will
+ // be issued. Some heap types require that the barrier strictly follows
+ // the initializing stores. (This is currently implemented by deferring the
+ // barrier until the next slow-path allocation or gc-related safepoint.)
+ // This interface answers whether a particular barrier type needs the card
+ // mark to be thus strictly sequenced after the stores.
+ virtual bool card_mark_must_follow_store() const = 0;
+
+ virtual bool is_in_young(oop obj) const = 0;
+
+ virtual void on_slowpath_allocation_exit(JavaThread* thread, oop new_obj);
+ virtual void flush_deferred_barriers(JavaThread* thread);
+
+ virtual void make_parsable(JavaThread* thread) { flush_deferred_card_mark_barrier(thread); }
+
template <DecoratorSet decorators, typename BarrierSetT = CardTableModRefBS>
class AccessBarrier: public ModRefBarrierSet::AccessBarrier<decorators, BarrierSetT> {};
};
--- a/src/hotspot/share/gc/shared/cardTableModRefBSForCTRS.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/shared/cardTableModRefBSForCTRS.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -121,3 +121,6 @@
}
}
+bool CardTableModRefBSForCTRS::is_in_young(oop obj) const {
+ return GenCollectedHeap::heap()->is_in_young(obj);
+}
--- a/src/hotspot/share/gc/shared/cardTableModRefBSForCTRS.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/shared/cardTableModRefBSForCTRS.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -43,6 +43,12 @@
void set_CTRS(CardTableRS* rs) { _rs = rs; }
+ virtual bool card_mark_must_follow_store() const {
+ return UseConcMarkSweepGC;
+ }
+
+ virtual bool is_in_young(oop obj) const;
+
private:
CardTableRS* _rs;
--- a/src/hotspot/share/gc/shared/collectedHeap.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/shared/collectedHeap.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -177,8 +177,7 @@
_total_collections(0),
_total_full_collections(0),
_gc_cause(GCCause::_no_gc),
- _gc_lastcause(GCCause::_no_gc),
- _defer_initial_card_mark(false) // strengthened by subclass in pre_initialize() below.
+ _gc_lastcause(GCCause::_no_gc)
{
const size_t max_len = size_t(arrayOopDesc::max_array_length(T_INT));
const size_t elements_per_word = HeapWordSize / sizeof(jint);
@@ -239,17 +238,6 @@
BarrierSet::set_bs(barrier_set);
}
-void CollectedHeap::pre_initialize() {
- // Used for ReduceInitialCardMarks (when COMPILER2 is used);
- // otherwise remains unused.
-#if COMPILER2_OR_JVMCI
- _defer_initial_card_mark = is_server_compilation_mode_vm() && ReduceInitialCardMarks && can_elide_tlab_store_barriers()
- && (DeferInitialCardMark || card_mark_must_follow_store());
-#else
- assert(_defer_initial_card_mark == false, "Who would set it?");
-#endif
-}
-
#ifndef PRODUCT
void CollectedHeap::check_for_bad_heap_word_value(HeapWord* addr, size_t size) {
if (CheckMemoryInitialization && ZapUnusedHeapArea) {
@@ -333,28 +321,6 @@
return obj;
}
-void CollectedHeap::flush_deferred_store_barrier(JavaThread* thread) {
- MemRegion deferred = thread->deferred_card_mark();
- if (!deferred.is_empty()) {
- assert(_defer_initial_card_mark, "Otherwise should be empty");
- {
- // Verify that the storage points to a parsable object in heap
- DEBUG_ONLY(oop old_obj = oop(deferred.start());)
- assert(is_in(old_obj), "Not in allocated heap");
- assert(!can_elide_initializing_store_barrier(old_obj),
- "Else should have been filtered in new_store_pre_barrier()");
- assert(oopDesc::is_oop(old_obj, true), "Not an oop");
- assert(deferred.word_size() == (size_t)(old_obj->size()),
- "Mismatch: multiple objects?");
- }
- BarrierSet* bs = barrier_set();
- bs->write_region(deferred);
- // "Clear" the deferred_card_mark field
- thread->set_deferred_card_mark(MemRegion());
- }
- assert(thread->deferred_card_mark().is_empty(), "invariant");
-}
-
size_t CollectedHeap::max_tlab_size() const {
// TLABs can't be bigger than we can fill with a int[Integer.MAX_VALUE].
// This restriction could be removed by enabling filling with multiple arrays.
@@ -370,72 +336,6 @@
return align_down(max_int_size, MinObjAlignment);
}
-// Helper for ReduceInitialCardMarks. For performance,
-// compiled code may elide card-marks for initializing stores
-// to a newly allocated object along the fast-path. We
-// compensate for such elided card-marks as follows:
-// (a) Generational, non-concurrent collectors, such as
-// GenCollectedHeap(ParNew,DefNew,Tenured) and
-// ParallelScavengeHeap(ParallelGC, ParallelOldGC)
-// need the card-mark if and only if the region is
-// in the old gen, and do not care if the card-mark
-// succeeds or precedes the initializing stores themselves,
-// so long as the card-mark is completed before the next
-// scavenge. For all these cases, we can do a card mark
-// at the point at which we do a slow path allocation
-// in the old gen, i.e. in this call.
-// (b) GenCollectedHeap(ConcurrentMarkSweepGeneration) requires
-// in addition that the card-mark for an old gen allocated
-// object strictly follow any associated initializing stores.
-// In these cases, the memRegion remembered below is
-// used to card-mark the entire region either just before the next
-// slow-path allocation by this thread or just before the next scavenge or
-// CMS-associated safepoint, whichever of these events happens first.
-// (The implicit assumption is that the object has been fully
-// initialized by this point, a fact that we assert when doing the
-// card-mark.)
-// (c) G1CollectedHeap(G1) uses two kinds of write barriers. When a
-// G1 concurrent marking is in progress an SATB (pre-write-)barrier
-// is used to remember the pre-value of any store. Initializing
-// stores will not need this barrier, so we need not worry about
-// compensating for the missing pre-barrier here. Turning now
-// to the post-barrier, we note that G1 needs a RS update barrier
-// which simply enqueues a (sequence of) dirty cards which may
-// optionally be refined by the concurrent update threads. Note
-// that this barrier need only be applied to a non-young write,
-// but, like in CMS, because of the presence of concurrent refinement
-// (much like CMS' precleaning), must strictly follow the oop-store.
-// Thus, using the same protocol for maintaining the intended
-// invariants turns out, serendepitously, to be the same for both
-// G1 and CMS.
-//
-// For any future collector, this code should be reexamined with
-// that specific collector in mind, and the documentation above suitably
-// extended and updated.
-oop CollectedHeap::new_store_pre_barrier(JavaThread* thread, oop new_obj) {
- // If a previous card-mark was deferred, flush it now.
- flush_deferred_store_barrier(thread);
- if (can_elide_initializing_store_barrier(new_obj) ||
- new_obj->is_typeArray()) {
- // Arrays of non-references don't need a pre-barrier.
- // The deferred_card_mark region should be empty
- // following the flush above.
- assert(thread->deferred_card_mark().is_empty(), "Error");
- } else {
- MemRegion mr((HeapWord*)new_obj, new_obj->size());
- assert(!mr.is_empty(), "Error");
- if (_defer_initial_card_mark) {
- // Defer the card mark
- thread->set_deferred_card_mark(mr);
- } else {
- // Do the card mark
- BarrierSet* bs = barrier_set();
- bs->write_region(mr);
- }
- }
- return new_obj;
-}
-
size_t CollectedHeap::filler_array_hdr_size() {
return align_object_offset(arrayOopDesc::header_size(T_INT)); // align to Long
}
@@ -538,24 +438,16 @@
" otherwise concurrent mutator activity may make heap "
" unparsable again");
const bool use_tlab = UseTLAB;
- const bool deferred = _defer_initial_card_mark;
// The main thread starts allocating via a TLAB even before it
// has added itself to the threads list at vm boot-up.
JavaThreadIteratorWithHandle jtiwh;
assert(!use_tlab || jtiwh.length() > 0,
"Attempt to fill tlabs before main thread has been added"
" to threads list is doomed to failure!");
+ BarrierSet *bs = barrier_set();
for (; JavaThread *thread = jtiwh.next(); ) {
if (use_tlab) thread->tlab().make_parsable(retire_tlabs);
-#if COMPILER2_OR_JVMCI
- // The deferred store barriers must all have been flushed to the
- // card-table (or other remembered set structure) before GC starts
- // processing the card-table (or other remembered set).
- if (deferred) flush_deferred_store_barrier(thread);
-#else
- assert(!deferred, "Should be false");
- assert(thread->deferred_card_mark().is_empty(), "Should be empty");
-#endif
+ bs->make_parsable(thread);
}
}
--- a/src/hotspot/share/gc/shared/collectedHeap.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/shared/collectedHeap.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -101,10 +101,6 @@
GCHeapLog* _gc_heap_log;
- // Used in support of ReduceInitialCardMarks; only consulted if COMPILER2
- // or INCLUDE_JVMCI is being used
- bool _defer_initial_card_mark;
-
MemRegion _reserved;
protected:
@@ -129,13 +125,6 @@
// Constructor
CollectedHeap();
- // Do common initializations that must follow instance construction,
- // for example, those needing virtual calls.
- // This code could perhaps be moved into initialize() but would
- // be slightly more awkward because we want the latter to be a
- // pure virtual.
- void pre_initialize();
-
// Create a new tlab. All TLAB allocations must go through this.
virtual HeapWord* allocate_new_tlab(size_t size);
@@ -408,45 +397,6 @@
return 0;
}
- // Can a compiler initialize a new object without store barriers?
- // This permission only extends from the creation of a new object
- // via a TLAB up to the first subsequent safepoint. If such permission
- // is granted for this heap type, the compiler promises to call
- // defer_store_barrier() below on any slow path allocation of
- // a new object for which such initializing store barriers will
- // have been elided.
- virtual bool can_elide_tlab_store_barriers() const = 0;
-
- // If a compiler is eliding store barriers for TLAB-allocated objects,
- // there is probably a corresponding slow path which can produce
- // an object allocated anywhere. The compiler's runtime support
- // promises to call this function on such a slow-path-allocated
- // object before performing initializations that have elided
- // store barriers. Returns new_obj, or maybe a safer copy thereof.
- virtual oop new_store_pre_barrier(JavaThread* thread, oop new_obj);
-
- // Answers whether an initializing store to a new object currently
- // allocated at the given address doesn't need a store
- // barrier. Returns "true" if it doesn't need an initializing
- // store barrier; answers "false" if it does.
- virtual bool can_elide_initializing_store_barrier(oop new_obj) = 0;
-
- // If a compiler is eliding store barriers for TLAB-allocated objects,
- // we will be informed of a slow-path allocation by a call
- // to new_store_pre_barrier() above. Such a call precedes the
- // initialization of the object itself, and no post-store-barriers will
- // be issued. Some heap types require that the barrier strictly follows
- // the initializing stores. (This is currently implemented by deferring the
- // barrier until the next slow-path allocation or gc-related safepoint.)
- // This interface answers whether a particular heap type needs the card
- // mark to be thus strictly sequenced after the stores.
- virtual bool card_mark_must_follow_store() const = 0;
-
- // If the CollectedHeap was asked to defer a store barrier above,
- // this informs it to flush such a deferred store barrier to the
- // remembered set.
- virtual void flush_deferred_store_barrier(JavaThread* thread);
-
// Perform a collection of the heap; intended for use in implementing
// "System.gc". This probably implies as full a collection as the
// "CollectedHeap" supports.
--- a/src/hotspot/share/gc/shared/genCollectedHeap.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/shared/genCollectedHeap.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -71,8 +71,6 @@
}
jint GenCollectedHeap::initialize() {
- CollectedHeap::pre_initialize();
-
// While there are no constraints in the GC code that HeapWordSize
// be any particular value, there are multiple other areas in the
// system which believe this to be true (e.g. oop->object_size in some
--- a/src/hotspot/share/gc/shared/genCollectedHeap.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/shared/genCollectedHeap.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -270,22 +270,6 @@
virtual size_t unsafe_max_tlab_alloc(Thread* thr) const;
virtual HeapWord* allocate_new_tlab(size_t size);
- // Can a compiler initialize a new object without store barriers?
- // This permission only extends from the creation of a new object
- // via a TLAB up to the first subsequent safepoint.
- virtual bool can_elide_tlab_store_barriers() const {
- return true;
- }
-
- // We don't need barriers for stores to objects in the
- // young gen and, a fortiori, for initializing stores to
- // objects therein. This applies to DefNew+Tenured and ParNew+CMS
- // only and may need to be re-examined in case other
- // kinds of collectors are implemented in the future.
- virtual bool can_elide_initializing_store_barrier(oop new_obj) {
- return is_in_young(new_obj);
- }
-
// The "requestor" generation is performing some garbage collection
// action for which it would be useful to have scratch space. The
// requestor promises to allocate no more than "max_alloc_words" in any
--- a/src/hotspot/share/gc/shared/modRefBarrierSet.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/shared/modRefBarrierSet.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -45,6 +45,7 @@
// Causes all refs in "mr" to be assumed to be modified.
virtual void invalidate(MemRegion mr) = 0;
+ virtual void write_region(MemRegion mr) = 0;
// The caller guarantees that "mr" contains no references. (Perhaps it's
// objects have been moved elsewhere.)
--- a/src/hotspot/share/gc/shared/modRefBarrierSet.inline.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/shared/modRefBarrierSet.inline.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -73,7 +73,7 @@
if (!HasDecorator<decorators, ARRAYCOPY_CHECKCAST>::value) {
// Optimized covariant case
bs->write_ref_array_pre(dst, (int)length,
- HasDecorator<decorators, ARRAYCOPY_DEST_NOT_INITIALIZED>::value);
+ HasDecorator<decorators, AS_DEST_NOT_INITIALIZED>::value);
Raw::oop_arraycopy(src_obj, dst_obj, src, dst, length);
bs->write_ref_array((HeapWord*)dst, length);
} else {
--- a/src/hotspot/share/gc/shared/plab.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/shared/plab.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -72,7 +72,6 @@
// Initializes the buffer to be empty, but with the given "word_sz".
// Must get initialized with "set_buf" for an allocation to succeed.
PLAB(size_t word_sz);
- virtual ~PLAB() {}
static size_t size_required_for_allocation(size_t word_size) { return word_size + AlignmentReserve; }
@@ -120,7 +119,7 @@
}
// Sets the space of the buffer to be [buf, space+word_sz()).
- virtual void set_buf(HeapWord* buf, size_t new_word_sz) {
+ void set_buf(HeapWord* buf, size_t new_word_sz) {
assert(new_word_sz > AlignmentReserve, "Too small");
_word_sz = new_word_sz;
@@ -136,11 +135,11 @@
// Flush allocation statistics into the given PLABStats supporting ergonomic
// sizing of PLAB's and retire the current buffer. To be called at the end of
// GC.
- virtual void flush_and_retire_stats(PLABStats* stats);
+ void flush_and_retire_stats(PLABStats* stats);
// Fills in the unallocated portion of the buffer with a garbage object and updates
// statistics. To be called during GC.
- virtual void retire();
+ void retire();
};
// PLAB book-keeping.
--- a/src/hotspot/share/gc/shared/taskqueue.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/shared/taskqueue.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -153,7 +153,7 @@
ParallelTaskTerminator::offer_termination(TerminatorTerminator* terminator) {
assert(_n_threads > 0, "Initialization is incorrect");
assert(_offered_termination < _n_threads, "Invariant");
- Atomic::inc((int *)&_offered_termination);
+ Atomic::inc(&_offered_termination);
uint yield_count = 0;
// Number of hard spin loops done since last yield
@@ -228,7 +228,7 @@
#endif
if (peek_in_queue_set() ||
(terminator != NULL && terminator->should_exit_termination())) {
- Atomic::dec((int *)&_offered_termination);
+ Atomic::dec(&_offered_termination);
assert(_offered_termination < _n_threads, "Invariant");
return false;
}
--- a/src/hotspot/share/gc/shared/taskqueue.inline.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/shared/taskqueue.inline.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -205,7 +205,7 @@
#if !(defined SPARC || defined IA32 || defined AMD64)
OrderAccess::fence();
#endif
- uint localBot = OrderAccess::load_acquire((volatile juint*)&_bottom);
+ uint localBot = OrderAccess::load_acquire(&_bottom);
uint n_elems = size(localBot, oldAge.top());
if (n_elems == 0) {
return false;
--- a/src/hotspot/share/gc/shared/workgroup.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/gc/shared/workgroup.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -157,7 +157,7 @@
// Wait for the coordinator to dispatch a task.
_start_semaphore->wait();
- uint num_started = (uint) Atomic::add(1, (volatile jint*)&_started);
+ uint num_started = Atomic::add(1u, &_started);
// Subtract one to get a zero-indexed worker id.
uint worker_id = num_started - 1;
@@ -168,7 +168,7 @@
void worker_done_with_task() {
// Mark that the worker is done with the task.
// The worker is not allowed to read the state variables after this line.
- uint not_finished = (uint) Atomic::add(-1, (volatile jint*)&_not_finished);
+ uint not_finished = Atomic::sub(1u, &_not_finished);
// The last worker signals to the coordinator that all work is completed.
if (not_finished == 0) {
@@ -439,7 +439,7 @@
#ifdef ASSERT
if (!res) {
assert(_claimed < _n_tasks, "Too many tasks claimed; missing clear?");
- Atomic::inc((volatile jint*) &_claimed);
+ Atomic::inc(&_claimed);
}
#endif
return res;
--- a/src/hotspot/share/jvmci/jvmciRuntime.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -116,10 +116,7 @@
oop obj = ik->allocate_instance(CHECK);
thread->set_vm_result(obj);
JRT_BLOCK_END;
-
- if (ReduceInitialCardMarks) {
- new_store_pre_barrier(thread);
- }
+ SharedRuntime::on_slowpath_allocation_exit(thread);
JRT_END
JRT_BLOCK_ENTRY(void, JVMCIRuntime::new_array(JavaThread* thread, Klass* array_klass, jint length))
@@ -151,29 +148,9 @@
}
}
JRT_BLOCK_END;
-
- if (ReduceInitialCardMarks) {
- new_store_pre_barrier(thread);
- }
+ SharedRuntime::on_slowpath_allocation_exit(thread);
JRT_END
-void JVMCIRuntime::new_store_pre_barrier(JavaThread* thread) {
- // After any safepoint, just before going back to compiled code,
- // we inform the GC that we will be doing initializing writes to
- // this object in the future without emitting card-marks, so
- // GC may take any compensating steps.
- // NOTE: Keep this code consistent with GraphKit::store_barrier.
-
- oop new_obj = thread->vm_result();
- if (new_obj == NULL) return;
-
- assert(Universe::heap()->can_elide_tlab_store_barriers(),
- "compiler must check this first");
- // GC may decide to give back a safer copy of new_obj.
- new_obj = Universe::heap()->new_store_pre_barrier(thread, new_obj);
- thread->set_vm_result(new_obj);
-}
-
JRT_ENTRY(void, JVMCIRuntime::new_multi_array(JavaThread* thread, Klass* klass, int rank, jint* dims))
assert(klass->is_klass(), "not a class");
assert(rank >= 1, "rank must be nonzero");
--- a/src/hotspot/share/jvmci/jvmciRuntime.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/jvmci/jvmciRuntime.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -154,7 +154,6 @@
static void write_barrier_pre(JavaThread* thread, oopDesc* obj);
static void write_barrier_post(JavaThread* thread, void* card);
static jboolean validate_object(JavaThread* thread, oopDesc* parent, oopDesc* child);
- static void new_store_pre_barrier(JavaThread* thread);
// used to throw exceptions from compiled JVMCI code
static void throw_and_post_jvmti_exception(JavaThread* thread, const char* exception, const char* message);
--- a/src/hotspot/share/logging/logTag.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/logging/logTag.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -60,6 +60,7 @@
LOG_TAG(cset) \
LOG_TAG(data) \
LOG_TAG(datacreation) \
+ LOG_TAG(decoder) \
LOG_TAG(defaultmethods) \
LOG_TAG(dump) \
LOG_TAG(ergo) \
--- a/src/hotspot/share/memory/allocation.inline.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/memory/allocation.inline.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -38,9 +38,9 @@
inline void inc_stat_counter(volatile julong* dest, julong add_value) {
#if defined(SPARC) || defined(X86)
// Sparc and X86 have atomic jlong (8 bytes) instructions
- julong value = Atomic::load((volatile jlong*)dest);
+ julong value = Atomic::load(dest);
value += add_value;
- Atomic::store((jlong)value, (volatile jlong*)dest);
+ Atomic::store(value, dest);
#else
// possible word-tearing during load/store
*dest += add_value;
--- a/src/hotspot/share/memory/filemap.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/memory/filemap.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -410,14 +410,11 @@
// Write the FileMapInfo information to the file.
void FileMapInfo::open_for_write() {
- _full_path = Arguments::GetSharedArchivePath();
- if (log_is_enabled(Info, cds)) {
- ResourceMark rm;
- LogMessage(cds) msg;
- stringStream info_stream;
- info_stream.print_cr("Dumping shared data to file: ");
- info_stream.print_cr(" %s", _full_path);
- msg.info("%s", info_stream.as_string());
+ _full_path = Arguments::GetSharedArchivePath();
+ LogMessage(cds) msg;
+ if (msg.is_info()) {
+ msg.info("Dumping shared data to file: ");
+ msg.info(" %s", _full_path);
}
#ifdef _WINDOWS // On Windows, need WRITE permission to remove the file.
--- a/src/hotspot/share/memory/metaspace.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/memory/metaspace.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -4372,7 +4372,7 @@
// ChunkManagerReturnTest stresses taking/returning chunks from the ChunkManager. It takes and
// returns chunks from/to the ChunkManager while keeping track of the expected ChunkManager
// content.
-class ChunkManagerReturnTestImpl {
+class ChunkManagerReturnTestImpl : public CHeapObj<mtClass> {
VirtualSpaceNode _vsn;
ChunkManager _cm;
--- a/src/hotspot/share/memory/metaspaceShared.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/memory/metaspaceShared.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -883,13 +883,11 @@
const char *sep = "--------------------+---------------------------+---------------------------+--------------------------";
const char *hdr = " ro_cnt ro_bytes % | rw_cnt rw_bytes % | all_cnt all_bytes %";
- ResourceMark rm;
LogMessage(cds) msg;
- stringStream info_stream;
- info_stream.print_cr("Detailed metadata info (excluding od/st regions; rw stats include md/mc regions):");
- info_stream.print_cr("%s", hdr);
- info_stream.print_cr("%s", sep);
+ msg.info("Detailed metadata info (excluding od/st regions; rw stats include md/mc regions):");
+ msg.info("%s", hdr);
+ msg.info("%s", sep);
for (int type = 0; type < int(_number_of_types); type ++) {
const char *name = type_name((Type)type);
int ro_count = _counts[RO][type];
@@ -903,7 +901,7 @@
double rw_perc = percent_of(rw_bytes, rw_all);
double perc = percent_of(bytes, ro_all + rw_all);
- info_stream.print_cr(fmt_stats, name,
+ msg.info(fmt_stats, name,
ro_count, ro_bytes, ro_perc,
rw_count, rw_bytes, rw_perc,
count, bytes, perc);
@@ -921,8 +919,8 @@
double all_rw_perc = percent_of(all_rw_bytes, rw_all);
double all_perc = percent_of(all_bytes, ro_all + rw_all);
- info_stream.print_cr("%s", sep);
- info_stream.print_cr(fmt_stats, "Total",
+ msg.info("%s", sep);
+ msg.info(fmt_stats, "Total",
all_ro_count, all_ro_bytes, all_ro_perc,
all_rw_count, all_rw_bytes, all_rw_perc,
all_count, all_bytes, all_perc);
@@ -930,7 +928,6 @@
assert(all_ro_bytes == ro_all, "everything should have been counted");
assert(all_rw_bytes == rw_all, "everything should have been counted");
- msg.info("%s", info_stream.as_string());
#undef fmt_stats
}
--- a/src/hotspot/share/oops/access.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/oops/access.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -155,6 +155,8 @@
// - Accesses on narrowOop* translate to encoded/decoded memory accesses without runtime checks
// - Accesses on HeapWord* translate to a runtime check choosing one of the above
// - Accesses on other types translate to raw memory accesses without runtime checks
+// * AS_DEST_NOT_INITIALIZED: This property can be important to e.g. SATB barriers by
+// marking that the previous value is uninitialized nonsense rather than a real value.
// * AS_NO_KEEPALIVE: The barrier is used only on oop references and will not keep any involved objects
// alive, regardless of the type of reference being accessed. It will however perform the memory access
// in a consistent way w.r.t. e.g. concurrent compaction, so that the right field is being accessed,
@@ -164,10 +166,12 @@
// responsibility of performing the access and what barriers to be performed to the GC. This is the default.
// Note that primitive accesses will only be resolved on the barrier set if the appropriate build-time
// decorator for enabling primitive barriers is enabled for the build.
-const DecoratorSet AS_RAW = UCONST64(1) << 11;
-const DecoratorSet AS_NO_KEEPALIVE = UCONST64(1) << 12;
-const DecoratorSet AS_NORMAL = UCONST64(1) << 13;
-const DecoratorSet AS_DECORATOR_MASK = AS_RAW | AS_NO_KEEPALIVE | AS_NORMAL;
+const DecoratorSet AS_RAW = UCONST64(1) << 11;
+const DecoratorSet AS_DEST_NOT_INITIALIZED = UCONST64(1) << 12;
+const DecoratorSet AS_NO_KEEPALIVE = UCONST64(1) << 13;
+const DecoratorSet AS_NORMAL = UCONST64(1) << 14;
+const DecoratorSet AS_DECORATOR_MASK = AS_RAW | AS_DEST_NOT_INITIALIZED |
+ AS_NO_KEEPALIVE | AS_NORMAL;
// === Reference Strength Decorators ===
// These decorators only apply to accesses on oop-like types (oop/narrowOop).
@@ -178,10 +182,10 @@
// * ON_UNKNOWN_OOP_REF: The memory access is performed on a reference of unknown strength.
// This could for example come from the unsafe API.
// * Default (no explicit reference strength specified): ON_STRONG_OOP_REF
-const DecoratorSet ON_STRONG_OOP_REF = UCONST64(1) << 14;
-const DecoratorSet ON_WEAK_OOP_REF = UCONST64(1) << 15;
-const DecoratorSet ON_PHANTOM_OOP_REF = UCONST64(1) << 16;
-const DecoratorSet ON_UNKNOWN_OOP_REF = UCONST64(1) << 17;
+const DecoratorSet ON_STRONG_OOP_REF = UCONST64(1) << 15;
+const DecoratorSet ON_WEAK_OOP_REF = UCONST64(1) << 16;
+const DecoratorSet ON_PHANTOM_OOP_REF = UCONST64(1) << 17;
+const DecoratorSet ON_UNKNOWN_OOP_REF = UCONST64(1) << 18;
const DecoratorSet ON_DECORATOR_MASK = ON_STRONG_OOP_REF | ON_WEAK_OOP_REF |
ON_PHANTOM_OOP_REF | ON_UNKNOWN_OOP_REF;
@@ -196,23 +200,21 @@
// * IN_CONCURRENT_ROOT: The access is performed in an off-heap data structure pointing into the Java heap,
// but is notably not scanned during safepoints. This is sometimes a special case for some GCs and
// implies that it is also an IN_ROOT.
-const DecoratorSet IN_HEAP = UCONST64(1) << 18;
-const DecoratorSet IN_HEAP_ARRAY = UCONST64(1) << 19;
-const DecoratorSet IN_ROOT = UCONST64(1) << 20;
-const DecoratorSet IN_CONCURRENT_ROOT = UCONST64(1) << 21;
-const DecoratorSet IN_ARCHIVE_ROOT = UCONST64(1) << 22;
+const DecoratorSet IN_HEAP = UCONST64(1) << 19;
+const DecoratorSet IN_HEAP_ARRAY = UCONST64(1) << 20;
+const DecoratorSet IN_ROOT = UCONST64(1) << 21;
+const DecoratorSet IN_CONCURRENT_ROOT = UCONST64(1) << 22;
+const DecoratorSet IN_ARCHIVE_ROOT = UCONST64(1) << 23;
const DecoratorSet IN_DECORATOR_MASK = IN_HEAP | IN_HEAP_ARRAY |
IN_ROOT | IN_CONCURRENT_ROOT |
IN_ARCHIVE_ROOT;
// == Value Decorators ==
// * OOP_NOT_NULL: This property can make certain barriers faster such as compressing oops.
-const DecoratorSet OOP_NOT_NULL = UCONST64(1) << 23;
+const DecoratorSet OOP_NOT_NULL = UCONST64(1) << 24;
const DecoratorSet OOP_DECORATOR_MASK = OOP_NOT_NULL;
// == Arraycopy Decorators ==
-// * ARRAYCOPY_DEST_NOT_INITIALIZED: This property can be important to e.g. SATB barriers by
-// marking that the previous value uninitialized nonsense rather than a real value.
// * ARRAYCOPY_CHECKCAST: This property means that the class of the objects in source
// are not guaranteed to be subclasses of the class of the destination array. This requires
// a check-cast barrier during the copying operation. If this is not set, it is assumed
@@ -222,14 +224,12 @@
// * ARRAYCOPY_ARRAYOF: The copy is in the arrayof form.
// * ARRAYCOPY_ATOMIC: The accesses have to be atomic over the size of its elements.
// * ARRAYCOPY_ALIGNED: The accesses have to be aligned on a HeapWord.
-const DecoratorSet ARRAYCOPY_DEST_NOT_INITIALIZED = UCONST64(1) << 24;
const DecoratorSet ARRAYCOPY_CHECKCAST = UCONST64(1) << 25;
const DecoratorSet ARRAYCOPY_DISJOINT = UCONST64(1) << 26;
const DecoratorSet ARRAYCOPY_ARRAYOF = UCONST64(1) << 27;
const DecoratorSet ARRAYCOPY_ATOMIC = UCONST64(1) << 28;
const DecoratorSet ARRAYCOPY_ALIGNED = UCONST64(1) << 29;
-const DecoratorSet ARRAYCOPY_DECORATOR_MASK = ARRAYCOPY_DEST_NOT_INITIALIZED |
- ARRAYCOPY_CHECKCAST | ARRAYCOPY_DISJOINT |
+const DecoratorSet ARRAYCOPY_DECORATOR_MASK = ARRAYCOPY_CHECKCAST | ARRAYCOPY_DISJOINT |
ARRAYCOPY_DISJOINT | ARRAYCOPY_ARRAYOF |
ARRAYCOPY_ATOMIC | ARRAYCOPY_ALIGNED;
@@ -343,8 +343,8 @@
template <DecoratorSet expected_mo_decorators>
static void verify_primitive_decorators() {
- const DecoratorSet primitive_decorators = (AS_DECORATOR_MASK ^ AS_NO_KEEPALIVE) | IN_HEAP |
- IN_HEAP_ARRAY;
+ const DecoratorSet primitive_decorators = (AS_DECORATOR_MASK ^ AS_NO_KEEPALIVE ^ AS_DEST_NOT_INITIALIZED) |
+ IN_HEAP | IN_HEAP_ARRAY;
verify_decorators<expected_mo_decorators | primitive_decorators>();
}
--- a/src/hotspot/share/oops/access.inline.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/oops/access.inline.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1060,6 +1060,7 @@
const DecoratorSet barrier_strength_decorators = decorators & AS_DECORATOR_MASK;
STATIC_ASSERT(barrier_strength_decorators == 0 || ( // make sure barrier strength decorators are disjoint if set
(barrier_strength_decorators ^ AS_NO_KEEPALIVE) == 0 ||
+ (barrier_strength_decorators ^ AS_DEST_NOT_INITIALIZED) == 0 ||
(barrier_strength_decorators ^ AS_RAW) == 0 ||
(barrier_strength_decorators ^ AS_NORMAL) == 0
));
--- a/src/hotspot/share/opto/callnode.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/opto/callnode.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -1441,8 +1441,10 @@
if (!allow_new_nodes) return NULL;
// Create a cast which is control dependent on the initialization to
// propagate the fact that the array length must be positive.
+ InitializeNode* init = initialization();
+ assert(init != NULL, "initialization not found");
length = new CastIINode(length, narrow_length_type);
- length->set_req(0, initialization()->proj_out_or_null(0));
+ length->set_req(0, init->proj_out_or_null(0));
}
}
--- a/src/hotspot/share/opto/graphKit.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/opto/graphKit.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -3861,7 +3861,7 @@
if (use_ReduceInitialCardMarks()
&& obj == just_allocated_object(control())) {
// We can skip marks on a freshly-allocated object in Eden.
- // Keep this code in sync with new_store_pre_barrier() in runtime.cpp.
+ // Keep this code in sync with new_deferred_store_barrier() in runtime.cpp.
// That routine informs GC to take appropriate compensating steps,
// upon a slow-path allocation, so as to make this card-mark
// elision safe.
@@ -4159,7 +4159,7 @@
* as part of the allocation in the case the allocated object is not located
* in the nursery, this would happen for humongous objects. This is similar to
* how CMS is required to handle this case, see the comments for the method
- * CollectedHeap::new_store_pre_barrier and OptoRuntime::new_store_pre_barrier.
+ * CardTableModRefBS::on_allocation_slowpath_exit and OptoRuntime::new_deferred_store_barrier.
* A deferred card mark is required for these objects and handled in the above
* mentioned methods.
*
@@ -4249,7 +4249,7 @@
if (use_ReduceInitialCardMarks() && obj == just_allocated_object(control())) {
// We can skip marks on a freshly-allocated object in Eden.
- // Keep this code in sync with new_store_pre_barrier() in runtime.cpp.
+ // Keep this code in sync with new_deferred_store_barrier() in runtime.cpp.
// That routine informs GC to take appropriate compensating steps,
// upon a slow-path allocation, so as to make this card-mark
// elision safe.
--- a/src/hotspot/share/opto/graphKit.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/opto/graphKit.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -755,8 +755,10 @@
Node* just_allocated_object(Node* current_control);
static bool use_ReduceInitialCardMarks() {
- return (ReduceInitialCardMarks
- && Universe::heap()->can_elide_tlab_store_barriers());
+ BarrierSet *bs = Universe::heap()->barrier_set();
+ return bs->is_a(BarrierSet::CardTableModRef)
+ && barrier_set_cast<CardTableModRefBS>(bs)->can_elide_tlab_store_barriers()
+ && ReduceInitialCardMarks;
}
// Sync Ideal and Graph kits.
--- a/src/hotspot/share/opto/loopnode.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/opto/loopnode.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -2347,7 +2347,7 @@
tty->print(" ");
tty->print("Loop: N%d/N%d ",_head->_idx,_tail->_idx);
if (_irreducible) tty->print(" IRREDUCIBLE");
- Node* entry = _head->as_Loop()->skip_strip_mined(-1)->in(LoopNode::EntryControl);
+ Node* entry = _head->is_Loop() ? _head->as_Loop()->skip_strip_mined(-1)->in(LoopNode::EntryControl) : _head->in(LoopNode::EntryControl);
Node* predicate = PhaseIdealLoop::find_predicate_insertion_point(entry, Deoptimization::Reason_loop_limit_check);
if (predicate != NULL ) {
tty->print(" limit_check");
@@ -2398,7 +2398,7 @@
if (Verbose) {
tty->print(" body={"); _body.dump_simple(); tty->print(" }");
}
- if (_head->as_Loop()->is_strip_mined()) {
+ if (_head->is_Loop() && _head->as_Loop()->is_strip_mined()) {
tty->print(" strip_mined");
}
tty->cr();
--- a/src/hotspot/share/opto/loopopts.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/opto/loopopts.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -693,7 +693,9 @@
Node* PhaseIdealLoop::try_move_store_before_loop(Node* n, Node *n_ctrl) {
// Store has to be first in the loop body
IdealLoopTree *n_loop = get_loop(n_ctrl);
- if (n->is_Store() && n_loop != _ltree_root && n_loop->is_loop() && n->in(0) != NULL) {
+ if (n->is_Store() && n_loop != _ltree_root &&
+ n_loop->is_loop() && n_loop->_head->is_Loop() &&
+ n->in(0) != NULL) {
Node* address = n->in(MemNode::Address);
Node* value = n->in(MemNode::ValueIn);
Node* mem = n->in(MemNode::Memory);
--- a/src/hotspot/share/opto/runtime.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/opto/runtime.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -194,23 +194,6 @@
// We failed the fast-path allocation. Now we need to do a scavenge or GC
// and try allocation again.
-void OptoRuntime::new_store_pre_barrier(JavaThread* thread) {
- // After any safepoint, just before going back to compiled code,
- // we inform the GC that we will be doing initializing writes to
- // this object in the future without emitting card-marks, so
- // GC may take any compensating steps.
- // NOTE: Keep this code consistent with GraphKit::store_barrier.
-
- oop new_obj = thread->vm_result();
- if (new_obj == NULL) return;
-
- assert(Universe::heap()->can_elide_tlab_store_barriers(),
- "compiler must check this first");
- // GC may decide to give back a safer copy of new_obj.
- new_obj = Universe::heap()->new_store_pre_barrier(thread, new_obj);
- thread->set_vm_result(new_obj);
-}
-
// object allocation
JRT_BLOCK_ENTRY(void, OptoRuntime::new_instance_C(Klass* klass, JavaThread* thread))
JRT_BLOCK;
@@ -244,10 +227,8 @@
deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION);
JRT_BLOCK_END;
- if (GraphKit::use_ReduceInitialCardMarks()) {
- // inform GC that we won't do card marks for initializing writes.
- new_store_pre_barrier(thread);
- }
+ // inform GC that we won't do card marks for initializing writes.
+ SharedRuntime::on_slowpath_allocation_exit(thread);
JRT_END
@@ -284,10 +265,8 @@
thread->set_vm_result(result);
JRT_BLOCK_END;
- if (GraphKit::use_ReduceInitialCardMarks()) {
- // inform GC that we won't do card marks for initializing writes.
- new_store_pre_barrier(thread);
- }
+ // inform GC that we won't do card marks for initializing writes.
+ SharedRuntime::on_slowpath_allocation_exit(thread);
JRT_END
// array allocation without zeroing
@@ -314,10 +293,9 @@
thread->set_vm_result(result);
JRT_BLOCK_END;
- if (GraphKit::use_ReduceInitialCardMarks()) {
- // inform GC that we won't do card marks for initializing writes.
- new_store_pre_barrier(thread);
- }
+
+ // inform GC that we won't do card marks for initializing writes.
+ SharedRuntime::on_slowpath_allocation_exit(thread);
oop result = thread->vm_result();
if ((len > 0) && (result != NULL) &&
--- a/src/hotspot/share/opto/runtime.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/opto/runtime.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -163,10 +163,6 @@
static void new_array_C(Klass* array_klass, int len, JavaThread *thread);
static void new_array_nozero_C(Klass* array_klass, int len, JavaThread *thread);
- // Post-slow-path-allocation, pre-initializing-stores step for
- // implementing ReduceInitialCardMarks
- static void new_store_pre_barrier(JavaThread* thread);
-
// Allocate storage for a multi-dimensional arrays
// Note: needs to be fixed for arbitrary number of dimensions
static void multianewarray2_C(Klass* klass, int len1, int len2, JavaThread *thread);
--- a/src/hotspot/share/prims/whitebox.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/prims/whitebox.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -60,6 +60,7 @@
#include "utilities/align.hpp"
#include "utilities/debug.hpp"
#include "utilities/exceptions.hpp"
+#include "utilities/elfFile.hpp"
#include "utilities/macros.hpp"
#if INCLUDE_CDS
#include "prims/cdsoffsets.hpp"
@@ -528,7 +529,7 @@
size_t total_memory() { return _total_memory; }
size_t total_memory_to_free() { return _total_memory_to_free; }
- bool doHeapRegion(HeapRegion* r) {
+ bool do_heap_region(HeapRegion* r) {
if (r->is_old()) {
size_t prev_live = r->marked_bytes();
size_t live = r->live_bytes();
@@ -1911,6 +1912,13 @@
os::print_os_info(tty);
WB_END
+// Elf decoder
+WB_ENTRY(void, WB_DisableElfSectionCache(JNIEnv* env))
+#if !defined(_WINDOWS) && !defined(__APPLE__)
+ ElfFile::_do_not_cache_elf_section = true;
+#endif
+WB_END
+
#define CC (char*)
@@ -2125,6 +2133,7 @@
(void*)&WB_CheckLibSpecifiesNoexecstack},
{CC"isContainerized", CC"()Z", (void*)&WB_IsContainerized },
{CC"printOsInfo", CC"()V", (void*)&WB_PrintOsInfo },
+ {CC"disableElfSectionCache", CC"()V", (void*)&WB_DisableElfSectionCache },
};
--- a/src/hotspot/share/runtime/arguments.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/runtime/arguments.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -537,6 +537,7 @@
{ "SharedReadOnlySize", JDK_Version::undefined(), JDK_Version::jdk(10), JDK_Version::undefined() },
{ "SharedMiscDataSize", JDK_Version::undefined(), JDK_Version::jdk(10), JDK_Version::undefined() },
{ "SharedMiscCodeSize", JDK_Version::undefined(), JDK_Version::jdk(10), JDK_Version::undefined() },
+ { "UseUTCFileTimestamp", JDK_Version::undefined(), JDK_Version::jdk(11), JDK_Version::jdk(12) },
#ifdef TEST_VERIFY_SPECIAL_JVM_FLAGS
{ "dep > obs", JDK_Version::jdk(9), JDK_Version::jdk(8), JDK_Version::undefined() },
--- a/src/hotspot/share/runtime/fieldDescriptor.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/runtime/fieldDescriptor.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -201,6 +201,12 @@
}
// Print a hint as to the underlying integer representation. This can be wrong for
// pointers on an LP64 machine
+#ifdef _LP64
+ if ((ft == T_OBJECT || ft == T_ARRAY) && UseCompressedOops) {
+ st->print(" (%x)", obj->int_field(offset()));
+ }
+ else // <- intended
+#endif
if (ft == T_LONG || ft == T_DOUBLE LP64_ONLY(|| !is_java_primitive(ft)) ) {
st->print(" (%x %x)", obj->int_field(offset()), obj->int_field(offset()+sizeof(jint)));
} else if (as_int < 0 || as_int > 9) {
--- a/src/hotspot/share/runtime/os.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/runtime/os.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -85,7 +85,7 @@
julong os::free_bytes = 0; // # of bytes freed
#endif
-static juint cur_malloc_words = 0; // current size for MallocMaxTestWords
+static size_t cur_malloc_words = 0; // current size for MallocMaxTestWords
void os_init_globals() {
// Called from init_globals().
@@ -629,12 +629,12 @@
//
static bool has_reached_max_malloc_test_peak(size_t alloc_size) {
if (MallocMaxTestWords > 0) {
- jint words = (jint)(alloc_size / BytesPerWord);
+ size_t words = (alloc_size / BytesPerWord);
if ((cur_malloc_words + words) > MallocMaxTestWords) {
return true;
}
- Atomic::add(words, (volatile jint *)&cur_malloc_words);
+ Atomic::add(words, &cur_malloc_words);
}
return false;
}
@@ -1826,8 +1826,7 @@
os::SuspendResume::State os::SuspendResume::switch_state(os::SuspendResume::State from,
os::SuspendResume::State to)
{
- os::SuspendResume::State result =
- (os::SuspendResume::State) Atomic::cmpxchg((jint) to, (jint *) &_state, (jint) from);
+ os::SuspendResume::State result = Atomic::cmpxchg(to, &_state, from);
if (result == from) {
// success
return to;
--- a/src/hotspot/share/runtime/os.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/runtime/os.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -27,6 +27,8 @@
#include "jvm.h"
#include "jvmtifiles/jvmti.h"
+#include "metaprogramming/isRegisteredEnum.hpp"
+#include "metaprogramming/integralConstant.hpp"
#include "runtime/extendedPC.hpp"
#include "runtime/handles.hpp"
#include "utilities/macros.hpp"
@@ -907,11 +909,11 @@
class SuspendedThreadTask {
public:
SuspendedThreadTask(Thread* thread) : _thread(thread), _done(false) {}
- virtual ~SuspendedThreadTask() {}
void run();
bool is_done() { return _done; }
virtual void do_task(const SuspendedThreadTaskContext& context) = 0;
protected:
+ ~SuspendedThreadTask() {}
private:
void internal_do_task();
Thread* _thread;
@@ -1006,6 +1008,10 @@
};
+#ifndef _WINDOWS
+template<> struct IsRegisteredEnum<os::SuspendResume::State> : public TrueType {};
+#endif // !_WINDOWS
+
// Note that "PAUSE" is almost always used with synchronization
// so arguably we should provide Atomic::SpinPause() instead
// of the global SpinPause() with C linkage.
--- a/src/hotspot/share/runtime/sharedRuntime.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/runtime/sharedRuntime.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -3169,3 +3169,16 @@
}
return activation;
}
+
+void SharedRuntime::on_slowpath_allocation_exit(JavaThread* thread) {
+ // After any safepoint, just before going back to compiled code,
+ // we inform the GC that we will be doing initializing writes to
+ // this object in the future without emitting card-marks, so
+ // GC may take any compensating steps.
+
+ oop new_obj = thread->vm_result();
+ if (new_obj == NULL) return;
+
+ BarrierSet *bs = Universe::heap()->barrier_set();
+ bs->on_slowpath_allocation_exit(thread, new_obj);
+}
--- a/src/hotspot/share/runtime/sharedRuntime.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/runtime/sharedRuntime.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -211,6 +211,10 @@
static address deoptimize_for_implicit_exception(JavaThread* thread, address pc, CompiledMethod* nm, int deopt_reason);
#endif
+ // Post-slow-path-allocation, pre-initializing-stores step for
+ // implementing e.g. ReduceInitialCardMarks
+ static void on_slowpath_allocation_exit(JavaThread* thread);
+
static void enable_stack_reserved_zone(JavaThread* thread);
static frame look_for_reserved_stack_annotated_method(JavaThread* thread, frame fr);
--- a/src/hotspot/share/runtime/stubRoutines.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/runtime/stubRoutines.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -418,7 +418,7 @@
SharedRuntime::_oop_array_copy_ctr++; // Slow-path oop array copy
#endif // !PRODUCT
assert(count != 0, "count should be non-zero");
- HeapAccess<ARRAYCOPY_DEST_NOT_INITIALIZED>::oop_arraycopy(NULL, NULL, (HeapWord*)src, (HeapWord*)dest, count);
+ HeapAccess<AS_DEST_NOT_INITIALIZED>::oop_arraycopy(NULL, NULL, (HeapWord*)src, (HeapWord*)dest, count);
JRT_END
JRT_LEAF(void, StubRoutines::arrayof_jbyte_copy(HeapWord* src, HeapWord* dest, size_t count))
@@ -462,7 +462,7 @@
SharedRuntime::_oop_array_copy_ctr++; // Slow-path oop array copy
#endif // !PRODUCT
assert(count != 0, "count should be non-zero");
- HeapAccess<ARRAYCOPY_ARRAYOF | ARRAYCOPY_DEST_NOT_INITIALIZED>::oop_arraycopy(NULL, NULL, src, dest, count);
+ HeapAccess<ARRAYCOPY_ARRAYOF | AS_DEST_NOT_INITIALIZED>::oop_arraycopy(NULL, NULL, src, dest, count);
JRT_END
address StubRoutines::select_fill_function(BasicType t, bool aligned, const char* &name) {
--- a/src/hotspot/share/runtime/thread.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/runtime/thread.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -1994,20 +1994,10 @@
JvmtiExport::cleanup_thread(this);
}
- // We must flush any deferred card marks before removing a thread from
- // the list of active threads.
- Universe::heap()->flush_deferred_store_barrier(this);
- assert(deferred_card_mark().is_empty(), "Should have been flushed");
-
-#if INCLUDE_ALL_GCS
- // We must flush the G1-related buffers before removing a thread
- // from the list of active threads. We must do this after any deferred
- // card marks have been flushed (above) so that any entries that are
- // added to the thread's dirty card queue as a result are not lost.
- if (UseG1GC) {
- flush_barrier_queues();
- }
-#endif // INCLUDE_ALL_GCS
+ // We must flush any deferred card marks and other various GC barrier
+ // related buffers (e.g. G1 SATB buffer and G1 dirty card queue buffer)
+ // before removing a thread from the list of active threads.
+ BarrierSet::barrier_set()->flush_deferred_barriers(this);
log_info(os, thread)("JavaThread %s (tid: " UINTX_FORMAT ").",
exit_type == JavaThread::normal_exit ? "exiting" : "detaching",
--- a/src/hotspot/share/runtime/thread.inline.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/runtime/thread.inline.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -30,24 +30,18 @@
#include "runtime/thread.hpp"
inline void Thread::set_suspend_flag(SuspendFlags f) {
- assert(sizeof(jint) == sizeof(_suspend_flags), "size mismatch");
uint32_t flags;
do {
flags = _suspend_flags;
}
- while (Atomic::cmpxchg((jint)(flags | f),
- (volatile jint*)&_suspend_flags,
- (jint)flags) != (jint)flags);
+ while (Atomic::cmpxchg((flags | f), &_suspend_flags, flags) != flags);
}
inline void Thread::clear_suspend_flag(SuspendFlags f) {
- assert(sizeof(jint) == sizeof(_suspend_flags), "size mismatch");
uint32_t flags;
do {
flags = _suspend_flags;
}
- while (Atomic::cmpxchg((jint)(flags & ~f),
- (volatile jint*)&_suspend_flags,
- (jint)flags) != (jint)flags);
+ while (Atomic::cmpxchg((flags & ~f), &_suspend_flags, flags) != flags);
}
inline void Thread::set_has_async_exception() {
--- a/src/hotspot/share/runtime/vmStructs.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/runtime/vmStructs.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -466,6 +466,7 @@
nonstatic_field(CardGeneration, _capacity_at_prologue, size_t) \
nonstatic_field(CardGeneration, _used_at_prologue, size_t) \
\
+ nonstatic_field(CardTableModRefBS, _defer_initial_card_mark, bool) \
nonstatic_field(CardTableModRefBS, _whole_heap, const MemRegion) \
nonstatic_field(CardTableModRefBS, _guard_index, const size_t) \
nonstatic_field(CardTableModRefBS, _last_valid_index, const size_t) \
@@ -482,7 +483,6 @@
\
nonstatic_field(CollectedHeap, _reserved, MemRegion) \
nonstatic_field(CollectedHeap, _barrier_set, BarrierSet*) \
- nonstatic_field(CollectedHeap, _defer_initial_card_mark, bool) \
nonstatic_field(CollectedHeap, _is_gc_active, bool) \
nonstatic_field(CollectedHeap, _total_collections, unsigned int) \
\
--- a/src/hotspot/share/services/mallocSiteTable.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/services/mallocSiteTable.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -151,7 +151,7 @@
~AccessLock() {
if (_lock_state == SharedLock) {
- Atomic::dec((volatile jint*)_lock);
+ Atomic::dec(_lock);
}
}
// Acquire shared lock.
@@ -159,7 +159,7 @@
inline bool sharedLock() {
jint res = Atomic::add(1, _lock);
if (res < 0) {
- Atomic::add(-1, _lock);
+ Atomic::dec(_lock);
return false;
}
_lock_state = SharedLock;
--- a/src/hotspot/share/services/mallocTracker.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/services/mallocTracker.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -66,8 +66,6 @@
assert(_size >= sz, "deallocation > allocated");
Atomic::dec(&_count);
if (sz > 0) {
- // unary minus operator applied to unsigned type, result still unsigned
- #pragma warning(suppress: 4146)
Atomic::sub(sz, &_size);
}
}
--- a/src/hotspot/share/services/threadService.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/services/threadService.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -120,7 +120,7 @@
}
void ThreadService::remove_thread(JavaThread* thread, bool daemon) {
- Atomic::dec((jint*) &_exiting_threads_count);
+ Atomic::dec(&_exiting_threads_count);
if (thread->is_hidden_from_external_view() ||
thread->is_jvmti_agent_thread()) {
@@ -131,17 +131,17 @@
if (daemon) {
_daemon_threads_count->set_value(_daemon_threads_count->get_value() - 1);
- Atomic::dec((jint*) &_exiting_daemon_threads_count);
+ Atomic::dec(&_exiting_daemon_threads_count);
}
}
void ThreadService::current_thread_exiting(JavaThread* jt) {
assert(jt == JavaThread::current(), "Called by current thread");
- Atomic::inc((jint*) &_exiting_threads_count);
+ Atomic::inc(&_exiting_threads_count);
oop threadObj = jt->threadObj();
if (threadObj != NULL && java_lang_Thread::is_daemon(threadObj)) {
- Atomic::inc((jint*) &_exiting_daemon_threads_count);
+ Atomic::inc(&_exiting_daemon_threads_count);
}
}
--- a/src/hotspot/share/utilities/copy.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/utilities/copy.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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
@@ -29,10 +29,8 @@
// Copy bytes; larger units are filled atomically if everything is aligned.
-void Copy::conjoint_memory_atomic(void* from, void* to, size_t size) {
- address src = (address) from;
- address dst = (address) to;
- uintptr_t bits = (uintptr_t) src | (uintptr_t) dst | (uintptr_t) size;
+void Copy::conjoint_memory_atomic(const void* from, void* to, size_t size) {
+ uintptr_t bits = (uintptr_t) from | (uintptr_t) to | (uintptr_t) size;
// (Note: We could improve performance by ignoring the low bits of size,
// and putting a short cleanup loop after each bulk copy loop.
@@ -43,14 +41,14 @@
// which may or may not want to include such optimizations.)
if (bits % sizeof(jlong) == 0) {
- Copy::conjoint_jlongs_atomic((jlong*) src, (jlong*) dst, size / sizeof(jlong));
+ Copy::conjoint_jlongs_atomic((const jlong*) from, (jlong*) to, size / sizeof(jlong));
} else if (bits % sizeof(jint) == 0) {
- Copy::conjoint_jints_atomic((jint*) src, (jint*) dst, size / sizeof(jint));
+ Copy::conjoint_jints_atomic((const jint*) from, (jint*) to, size / sizeof(jint));
} else if (bits % sizeof(jshort) == 0) {
- Copy::conjoint_jshorts_atomic((jshort*) src, (jshort*) dst, size / sizeof(jshort));
+ Copy::conjoint_jshorts_atomic((const jshort*) from, (jshort*) to, size / sizeof(jshort));
} else {
// Not aligned, so no need to be atomic.
- Copy::conjoint_jbytes((void*) src, (void*) dst, size);
+ Copy::conjoint_jbytes((const void*) from, (void*) to, size);
}
}
--- a/src/hotspot/share/utilities/copy.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/utilities/copy.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -31,28 +31,28 @@
// Assembly code for platforms that need it.
extern "C" {
- void _Copy_conjoint_words(HeapWord* from, HeapWord* to, size_t count);
- void _Copy_disjoint_words(HeapWord* from, HeapWord* to, size_t count);
+ void _Copy_conjoint_words(const HeapWord* from, HeapWord* to, size_t count);
+ void _Copy_disjoint_words(const HeapWord* from, HeapWord* to, size_t count);
- void _Copy_conjoint_words_atomic(HeapWord* from, HeapWord* to, size_t count);
- void _Copy_disjoint_words_atomic(HeapWord* from, HeapWord* to, size_t count);
+ void _Copy_conjoint_words_atomic(const HeapWord* from, HeapWord* to, size_t count);
+ void _Copy_disjoint_words_atomic(const HeapWord* from, HeapWord* to, size_t count);
- void _Copy_aligned_conjoint_words(HeapWord* from, HeapWord* to, size_t count);
- void _Copy_aligned_disjoint_words(HeapWord* from, HeapWord* to, size_t count);
+ void _Copy_aligned_conjoint_words(const HeapWord* from, HeapWord* to, size_t count);
+ void _Copy_aligned_disjoint_words(const HeapWord* from, HeapWord* to, size_t count);
- void _Copy_conjoint_bytes(void* from, void* to, size_t count);
+ void _Copy_conjoint_bytes(const void* from, void* to, size_t count);
- void _Copy_conjoint_bytes_atomic (void* from, void* to, size_t count);
- void _Copy_conjoint_jshorts_atomic(jshort* from, jshort* to, size_t count);
- void _Copy_conjoint_jints_atomic (jint* from, jint* to, size_t count);
- void _Copy_conjoint_jlongs_atomic (jlong* from, jlong* to, size_t count);
- void _Copy_conjoint_oops_atomic (oop* from, oop* to, size_t count);
+ void _Copy_conjoint_bytes_atomic (const void* from, void* to, size_t count);
+ void _Copy_conjoint_jshorts_atomic(const jshort* from, jshort* to, size_t count);
+ void _Copy_conjoint_jints_atomic (const jint* from, jint* to, size_t count);
+ void _Copy_conjoint_jlongs_atomic (const jlong* from, jlong* to, size_t count);
+ void _Copy_conjoint_oops_atomic (const oop* from, oop* to, size_t count);
- void _Copy_arrayof_conjoint_bytes (HeapWord* from, HeapWord* to, size_t count);
- void _Copy_arrayof_conjoint_jshorts(HeapWord* from, HeapWord* to, size_t count);
- void _Copy_arrayof_conjoint_jints (HeapWord* from, HeapWord* to, size_t count);
- void _Copy_arrayof_conjoint_jlongs (HeapWord* from, HeapWord* to, size_t count);
- void _Copy_arrayof_conjoint_oops (HeapWord* from, HeapWord* to, size_t count);
+ void _Copy_arrayof_conjoint_bytes (const HeapWord* from, HeapWord* to, size_t count);
+ void _Copy_arrayof_conjoint_jshorts(const HeapWord* from, HeapWord* to, size_t count);
+ void _Copy_arrayof_conjoint_jints (const HeapWord* from, HeapWord* to, size_t count);
+ void _Copy_arrayof_conjoint_jlongs (const HeapWord* from, HeapWord* to, size_t count);
+ void _Copy_arrayof_conjoint_oops (const HeapWord* from, HeapWord* to, size_t count);
}
class Copy : AllStatic {
@@ -87,33 +87,33 @@
// HeapWords
// Word-aligned words, conjoint, not atomic on each word
- static void conjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+ static void conjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
assert_params_ok(from, to, LogHeapWordSize);
pd_conjoint_words(from, to, count);
}
// Word-aligned words, disjoint, not atomic on each word
- static void disjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+ static void disjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
assert_params_ok(from, to, LogHeapWordSize);
assert_disjoint(from, to, count);
pd_disjoint_words(from, to, count);
}
// Word-aligned words, disjoint, atomic on each word
- static void disjoint_words_atomic(HeapWord* from, HeapWord* to, size_t count) {
+ static void disjoint_words_atomic(const HeapWord* from, HeapWord* to, size_t count) {
assert_params_ok(from, to, LogHeapWordSize);
assert_disjoint(from, to, count);
pd_disjoint_words_atomic(from, to, count);
}
// Object-aligned words, conjoint, not atomic on each word
- static void aligned_conjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+ static void aligned_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
assert_params_aligned(from, to);
pd_aligned_conjoint_words(from, to, count);
}
// Object-aligned words, disjoint, not atomic on each word
- static void aligned_disjoint_words(HeapWord* from, HeapWord* to, size_t count) {
+ static void aligned_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) {
assert_params_aligned(from, to);
assert_disjoint(from, to, count);
pd_aligned_disjoint_words(from, to, count);
@@ -122,77 +122,77 @@
// bytes, jshorts, jints, jlongs, oops
// bytes, conjoint, not atomic on each byte (not that it matters)
- static void conjoint_jbytes(void* from, void* to, size_t count) {
+ static void conjoint_jbytes(const void* from, void* to, size_t count) {
pd_conjoint_bytes(from, to, count);
}
// bytes, conjoint, atomic on each byte (not that it matters)
- static void conjoint_jbytes_atomic(void* from, void* to, size_t count) {
+ static void conjoint_jbytes_atomic(const void* from, void* to, size_t count) {
pd_conjoint_bytes(from, to, count);
}
// jshorts, conjoint, atomic on each jshort
- static void conjoint_jshorts_atomic(jshort* from, jshort* to, size_t count) {
+ static void conjoint_jshorts_atomic(const jshort* from, jshort* to, size_t count) {
assert_params_ok(from, to, LogBytesPerShort);
pd_conjoint_jshorts_atomic(from, to, count);
}
// jints, conjoint, atomic on each jint
- static void conjoint_jints_atomic(jint* from, jint* to, size_t count) {
+ static void conjoint_jints_atomic(const jint* from, jint* to, size_t count) {
assert_params_ok(from, to, LogBytesPerInt);
pd_conjoint_jints_atomic(from, to, count);
}
// jlongs, conjoint, atomic on each jlong
- static void conjoint_jlongs_atomic(jlong* from, jlong* to, size_t count) {
+ static void conjoint_jlongs_atomic(const jlong* from, jlong* to, size_t count) {
assert_params_ok(from, to, LogBytesPerLong);
pd_conjoint_jlongs_atomic(from, to, count);
}
// oops, conjoint, atomic on each oop
- static void conjoint_oops_atomic(oop* from, oop* to, size_t count) {
+ static void conjoint_oops_atomic(const oop* from, oop* to, size_t count) {
assert_params_ok(from, to, LogBytesPerHeapOop);
pd_conjoint_oops_atomic(from, to, count);
}
// overloaded for UseCompressedOops
- static void conjoint_oops_atomic(narrowOop* from, narrowOop* to, size_t count) {
+ static void conjoint_oops_atomic(const narrowOop* from, narrowOop* to, size_t count) {
assert(sizeof(narrowOop) == sizeof(jint), "this cast is wrong");
assert_params_ok(from, to, LogBytesPerInt);
- pd_conjoint_jints_atomic((jint*)from, (jint*)to, count);
+ pd_conjoint_jints_atomic((const jint*)from, (jint*)to, count);
}
// Copy a span of memory. If the span is an integral number of aligned
// longs, words, or ints, copy those units atomically.
// The largest atomic transfer unit is 8 bytes, or the largest power
// of two which divides all of from, to, and size, whichever is smaller.
- static void conjoint_memory_atomic(void* from, void* to, size_t size);
+ static void conjoint_memory_atomic(const void* from, void* to, size_t size);
// bytes, conjoint array, atomic on each byte (not that it matters)
- static void arrayof_conjoint_jbytes(HeapWord* from, HeapWord* to, size_t count) {
+ static void arrayof_conjoint_jbytes(const HeapWord* from, HeapWord* to, size_t count) {
pd_arrayof_conjoint_bytes(from, to, count);
}
// jshorts, conjoint array, atomic on each jshort
- static void arrayof_conjoint_jshorts(HeapWord* from, HeapWord* to, size_t count) {
+ static void arrayof_conjoint_jshorts(const HeapWord* from, HeapWord* to, size_t count) {
assert_params_ok(from, to, LogBytesPerShort);
pd_arrayof_conjoint_jshorts(from, to, count);
}
// jints, conjoint array, atomic on each jint
- static void arrayof_conjoint_jints(HeapWord* from, HeapWord* to, size_t count) {
+ static void arrayof_conjoint_jints(const HeapWord* from, HeapWord* to, size_t count) {
assert_params_ok(from, to, LogBytesPerInt);
pd_arrayof_conjoint_jints(from, to, count);
}
// jlongs, conjoint array, atomic on each jlong
- static void arrayof_conjoint_jlongs(HeapWord* from, HeapWord* to, size_t count) {
+ static void arrayof_conjoint_jlongs(const HeapWord* from, HeapWord* to, size_t count) {
assert_params_ok(from, to, LogBytesPerLong);
pd_arrayof_conjoint_jlongs(from, to, count);
}
// oops, conjoint array, atomic on each oop
- static void arrayof_conjoint_oops(HeapWord* from, HeapWord* to, size_t count) {
+ static void arrayof_conjoint_oops(const HeapWord* from, HeapWord* to, size_t count) {
assert_params_ok(from, to, LogBytesPerHeapOop);
pd_arrayof_conjoint_oops(from, to, count);
}
@@ -200,7 +200,7 @@
// Known overlap methods
// Copy word-aligned words from higher to lower addresses, not atomic on each word
- inline static void conjoint_words_to_lower(HeapWord* from, HeapWord* to, size_t byte_count) {
+ inline static void conjoint_words_to_lower(const HeapWord* from, HeapWord* to, size_t byte_count) {
// byte_count is in bytes to check its alignment
assert_params_ok(from, to, LogHeapWordSize);
assert_byte_count_ok(byte_count, HeapWordSize);
@@ -214,7 +214,7 @@
}
// Copy word-aligned words from lower to higher addresses, not atomic on each word
- inline static void conjoint_words_to_higher(HeapWord* from, HeapWord* to, size_t byte_count) {
+ inline static void conjoint_words_to_higher(const HeapWord* from, HeapWord* to, size_t byte_count) {
// byte_count is in bytes to check its alignment
assert_params_ok(from, to, LogHeapWordSize);
assert_byte_count_ok(byte_count, HeapWordSize);
@@ -305,7 +305,7 @@
}
private:
- static bool params_disjoint(HeapWord* from, HeapWord* to, size_t count) {
+ static bool params_disjoint(const HeapWord* from, HeapWord* to, size_t count) {
if (from < to) {
return pointer_delta(to, from) >= count;
}
@@ -314,14 +314,14 @@
// These methods raise a fatal if they detect a problem.
- static void assert_disjoint(HeapWord* from, HeapWord* to, size_t count) {
+ static void assert_disjoint(const HeapWord* from, HeapWord* to, size_t count) {
#ifdef ASSERT
if (!params_disjoint(from, to, count))
basic_fatal("source and dest overlap");
#endif
}
- static void assert_params_ok(void* from, void* to, intptr_t log_align) {
+ static void assert_params_ok(const void* from, void* to, intptr_t log_align) {
#ifdef ASSERT
if (mask_bits((uintptr_t)from, right_n_bits(log_align)) != 0)
basic_fatal("not aligned");
@@ -336,7 +336,7 @@
basic_fatal("not word aligned");
#endif
}
- static void assert_params_aligned(HeapWord* from, HeapWord* to) {
+ static void assert_params_aligned(const HeapWord* from, HeapWord* to) {
#ifdef ASSERT
if (mask_bits((uintptr_t)from, BytesPerLong-1) != 0)
basic_fatal("not long aligned");
--- a/src/hotspot/share/utilities/decoder.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/utilities/decoder.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -33,12 +33,10 @@
class AbstractDecoder : public CHeapObj<mtInternal> {
public:
- virtual ~AbstractDecoder() {}
-
// status code for decoding native C frame
enum decoder_status {
not_available = -10, // real decoder is not available
- no_error = 0, // successfully decoded frames
+ no_error = 0, // no error encountered
out_of_memory, // out of memory
file_invalid, // invalid elf file
file_not_found, // could not found symbol file (on windows), such as jvm.pdb or jvm.map
@@ -46,6 +44,12 @@
helper_init_error // SymInitialize failed (Windows only)
};
+protected:
+ decoder_status _decoder_status;
+
+public:
+ virtual ~AbstractDecoder() {}
+
// decode an pc address to corresponding function name and an offset from the beginning of
// the function
//
@@ -68,11 +72,8 @@
}
static bool is_error(decoder_status status) {
- return (status > 0);
+ return (status > no_error);
}
-
-protected:
- decoder_status _decoder_status;
};
// Do nothing decoder
@@ -96,10 +97,8 @@
virtual bool demangle(const char* symbol, char* buf, int buflen) {
return false;
}
-
};
-
class Decoder : AllStatic {
public:
static bool decode(address pc, char* buf, int buflen, int* offset, const char* modulepath = NULL, bool demangle = true);
--- a/src/hotspot/share/utilities/elfFile.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/utilities/elfFile.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -31,60 +31,150 @@
#include <limits.h>
#include <new>
+#include "logging/log.hpp"
#include "memory/allocation.inline.hpp"
+#include "memory/resourceArea.hpp"
#include "utilities/decoder.hpp"
#include "utilities/elfFile.hpp"
#include "utilities/elfFuncDescTable.hpp"
#include "utilities/elfStringTable.hpp"
#include "utilities/elfSymbolTable.hpp"
+#include "utilities/ostream.hpp"
+// For test only, disable elf section cache and force to read from file directly.
+bool ElfFile::_do_not_cache_elf_section = false;
+
+ElfSection::ElfSection(FILE* fd, const Elf_Shdr& hdr) : _section_data(NULL) {
+ _stat = load_section(fd, hdr);
+}
+
+ElfSection::~ElfSection() {
+ if (_section_data != NULL) {
+ os::free(_section_data);
+ }
+}
+
+NullDecoder::decoder_status ElfSection::load_section(FILE* const fd, const Elf_Shdr& shdr) {
+ memcpy((void*)&_section_hdr, (const void*)&shdr, sizeof(shdr));
+
+ if (ElfFile::_do_not_cache_elf_section) {
+ log_debug(decoder)("Elf section cache is disabled");
+ return NullDecoder::no_error;
+ }
+
+ _section_data = os::malloc(shdr.sh_size, mtInternal);
+ // No enough memory for caching. It is okay, we can try to read from
+ // file instead.
+ if (_section_data == NULL) return NullDecoder::no_error;
-ElfFile::ElfFile(const char* filepath) {
- assert(filepath, "null file path");
- memset(&m_elfHdr, 0, sizeof(m_elfHdr));
- m_string_tables = NULL;
- m_symbol_tables = NULL;
- m_funcDesc_table = NULL;
- m_next = NULL;
- m_status = NullDecoder::no_error;
+ MarkedFileReader mfd(fd);
+ if (mfd.has_mark() &&
+ mfd.set_position(shdr.sh_offset) &&
+ mfd.read(_section_data, shdr.sh_size)) {
+ return NullDecoder::no_error;
+ } else {
+ os::free(_section_data);
+ _section_data = NULL;
+ return NullDecoder::file_invalid;
+ }
+}
+
+bool FileReader::read(void* buf, size_t size) {
+ assert(buf != NULL, "no buffer");
+ assert(size > 0, "no space");
+ return fread(buf, size, 1, _fd) == 1;
+}
+
+int FileReader::read_buffer(void* buf, size_t size) {
+ assert(buf != NULL, "no buffer");
+ assert(size > 0, "no space");
+ return fread(buf, 1, size, _fd);
+}
+
+bool FileReader::set_position(long offset) {
+ return fseek(_fd, offset, SEEK_SET) == 0;
+}
+
+MarkedFileReader::MarkedFileReader(FILE* fd) : FileReader(fd) {
+ _marked_pos = ftell(fd);
+}
+
+MarkedFileReader::~MarkedFileReader() {
+ if (_marked_pos != -1) {
+ set_position(_marked_pos);
+ }
+}
+
+ElfFile::ElfFile(const char* filepath) :
+ _string_tables(NULL), _symbol_tables(NULL), _funcDesc_table(NULL),
+ _next(NULL), _status(NullDecoder::no_error),
+ _shdr_string_table(NULL), _file(NULL), _filepath(NULL) {
+ memset(&_elfHdr, 0, sizeof(_elfHdr));
int len = strlen(filepath) + 1;
- m_filepath = (const char*)os::malloc(len * sizeof(char), mtInternal);
- if (m_filepath != NULL) {
- strcpy((char*)m_filepath, filepath);
- m_file = fopen(filepath, "r");
- if (m_file != NULL) {
- load_tables();
- } else {
- m_status = NullDecoder::file_not_found;
- }
- } else {
- m_status = NullDecoder::out_of_memory;
+ _filepath = (char*)os::malloc(len * sizeof(char), mtInternal);
+ if (_filepath == NULL) {
+ _status = NullDecoder::out_of_memory;
+ return;
+ }
+ strcpy(_filepath, filepath);
+
+ _status = parse_elf(filepath);
+
+ // we no longer need section header string table
+ if (_shdr_string_table != NULL) {
+ delete _shdr_string_table;
+ _shdr_string_table = NULL;
}
}
ElfFile::~ElfFile() {
- if (m_string_tables != NULL) {
- delete m_string_tables;
+ if (_shdr_string_table != NULL) {
+ delete _shdr_string_table;
}
- if (m_symbol_tables != NULL) {
- delete m_symbol_tables;
+ cleanup_tables();
+
+ if (_file != NULL) {
+ fclose(_file);
+ }
+
+ if (_filepath != NULL) {
+ os::free((void*)_filepath);
}
- if (m_file != NULL) {
- fclose(m_file);
+ if (_next != NULL) {
+ delete _next;
+ }
+}
+
+void ElfFile::cleanup_tables() {
+ if (_string_tables != NULL) {
+ delete _string_tables;
+ _string_tables = NULL;
+ }
+
+ if (_symbol_tables != NULL) {
+ delete _symbol_tables;
+ _symbol_tables = NULL;
}
- if (m_filepath != NULL) {
- os::free((void*)m_filepath);
+ if (_funcDesc_table != NULL) {
+ delete _funcDesc_table;
+ _funcDesc_table = NULL;
}
+}
- if (m_next != NULL) {
- delete m_next;
+NullDecoder::decoder_status ElfFile::parse_elf(const char* filepath) {
+ assert(filepath, "null file path");
+
+ _file = fopen(filepath, "r");
+ if (_file != NULL) {
+ return load_tables();
+ } else {
+ return NullDecoder::file_not_found;
}
-};
-
+}
//Check elf header to ensure the file is valid.
bool ElfFile::is_elf_file(Elf_Ehdr& hdr) {
@@ -96,116 +186,134 @@
ELFDATANONE != hdr.e_ident[EI_DATA]);
}
-bool ElfFile::load_tables() {
- assert(m_file, "file not open");
- assert(!NullDecoder::is_error(m_status), "already in error");
+NullDecoder::decoder_status ElfFile::load_tables() {
+ assert(_file, "file not open");
+ assert(!NullDecoder::is_error(_status), "already in error");
+ FileReader freader(fd());
// read elf file header
- if (fread(&m_elfHdr, sizeof(m_elfHdr), 1, m_file) != 1) {
- m_status = NullDecoder::file_invalid;
- return false;
+ if (!freader.read(&_elfHdr, sizeof(_elfHdr))) {
+ return NullDecoder::file_invalid;
}
- if (!is_elf_file(m_elfHdr)) {
- m_status = NullDecoder::file_invalid;
- return false;
+ // Check signature
+ if (!is_elf_file(_elfHdr)) {
+ return NullDecoder::file_invalid;
}
// walk elf file's section headers, and load string tables
Elf_Shdr shdr;
- if (!fseek(m_file, m_elfHdr.e_shoff, SEEK_SET)) {
- if (NullDecoder::is_error(m_status)) return false;
+ if (!freader.set_position(_elfHdr.e_shoff)) {
+ return NullDecoder::file_invalid;
+ }
- for (int index = 0; index < m_elfHdr.e_shnum; index ++) {
- if (fread((void*)&shdr, sizeof(Elf_Shdr), 1, m_file) != 1) {
- m_status = NullDecoder::file_invalid;
- return false;
- }
- if (shdr.sh_type == SHT_STRTAB) {
- // string tables
- ElfStringTable* table = new (std::nothrow) ElfStringTable(m_file, shdr, index);
- if (table == NULL) {
- m_status = NullDecoder::out_of_memory;
- return false;
- }
- add_string_table(table);
- } else if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) {
- // symbol tables
- ElfSymbolTable* table = new (std::nothrow) ElfSymbolTable(m_file, shdr);
- if (table == NULL) {
- m_status = NullDecoder::out_of_memory;
- return false;
- }
- add_symbol_table(table);
- }
+ for (int index = 0; index < _elfHdr.e_shnum; index ++) {
+ if (!freader.read(&shdr, sizeof(shdr))) {
+ return NullDecoder::file_invalid;
}
-#if defined(PPC64) && !defined(ABI_ELFv2)
- // Now read the .opd section wich contains the PPC64 function descriptor table.
- // The .opd section is only available on PPC64 (see for example:
- // http://refspecs.linuxfoundation.org/LSB_3.1.1/LSB-Core-PPC64/LSB-Core-PPC64/specialsections.html)
- // so this code should do no harm on other platforms but because of performance reasons we only
- // execute it on PPC64 platforms.
- // Notice that we can only find the .opd section after we have successfully read in the string
- // tables in the previous loop, because we need to query the name of each section which is
- // contained in one of the string tables (i.e. the one with the index m_elfHdr.e_shstrndx).
-
- // Reset the file pointer
- if (fseek(m_file, m_elfHdr.e_shoff, SEEK_SET)) {
- m_status = NullDecoder::file_invalid;
- return false;
+ if (shdr.sh_type == SHT_STRTAB) {
+ // string tables
+ ElfStringTable* table = new (std::nothrow) ElfStringTable(fd(), shdr, index);
+ if (table == NULL) {
+ return NullDecoder::out_of_memory;
+ }
+ if (index == _elfHdr.e_shstrndx) {
+ assert(_shdr_string_table == NULL, "Only set once");
+ _shdr_string_table = table;
+ } else {
+ add_string_table(table);
+ }
+ } else if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) {
+ // symbol tables
+ ElfSymbolTable* table = new (std::nothrow) ElfSymbolTable(fd(), shdr);
+ if (table == NULL) {
+ return NullDecoder::out_of_memory;
+ }
+ add_symbol_table(table);
}
- for (int index = 0; index < m_elfHdr.e_shnum; index ++) {
- if (fread((void*)&shdr, sizeof(Elf_Shdr), 1, m_file) != 1) {
- m_status = NullDecoder::file_invalid;
- return false;
- }
- if (m_elfHdr.e_shstrndx != SHN_UNDEF && shdr.sh_type == SHT_PROGBITS) {
- ElfStringTable* string_table = get_string_table(m_elfHdr.e_shstrndx);
- if (string_table == NULL) {
- m_status = NullDecoder::file_invalid;
- return false;
- }
- char buf[8]; // '8' is enough because we only want to read ".opd"
- if (string_table->string_at(shdr.sh_name, buf, sizeof(buf)) && !strncmp(".opd", buf, 4)) {
- m_funcDesc_table = new (std::nothrow) ElfFuncDescTable(m_file, shdr, index);
- if (m_funcDesc_table == NULL) {
- m_status = NullDecoder::out_of_memory;
- return false;
- }
- break;
- }
+ }
+#if defined(PPC64) && !defined(ABI_ELFv2)
+ // Now read the .opd section wich contains the PPC64 function descriptor table.
+ // The .opd section is only available on PPC64 (see for example:
+ // http://refspecs.linuxfoundation.org/LSB_3.1.1/LSB-Core-PPC64/LSB-Core-PPC64/specialsections.html)
+ // so this code should do no harm on other platforms but because of performance reasons we only
+ // execute it on PPC64 platforms.
+ // Notice that we can only find the .opd section after we have successfully read in the string
+ // tables in the previous loop, because we need to query the name of each section which is
+ // contained in one of the string tables (i.e. the one with the index m_elfHdr.e_shstrndx).
+
+ // Reset the file pointer
+ int sect_index = section_by_name(".opd", shdr);
+
+ if (sect_index == -1) {
+ return NullDecoder::file_invalid;
+ }
+
+ _funcDesc_table = new (std::nothrow) ElfFuncDescTable(_file, shdr, sect_index);
+ if (_funcDesc_table == NULL) {
+ return NullDecoder::out_of_memory;
+ }
+#endif
+ return NullDecoder::no_error;
+}
+
+int ElfFile::section_by_name(const char* name, Elf_Shdr& hdr) {
+ assert(name != NULL, "No section name");
+ size_t len = strlen(name) + 1;
+ ResourceMark rm;
+ char* buf = NEW_RESOURCE_ARRAY(char, len);
+ if (buf == NULL) {
+ return -1;
+ }
+
+ assert(_shdr_string_table != NULL, "Section header string table should be loaded");
+ ElfStringTable* const table = _shdr_string_table;
+ MarkedFileReader mfd(fd());
+ if (!mfd.has_mark() || !mfd.set_position(_elfHdr.e_shoff)) return -1;
+
+ int sect_index = -1;
+ for (int index = 0; index < _elfHdr.e_shnum; index ++) {
+ if (!mfd.read((void*)&hdr, sizeof(hdr))) {
+ break;
+ }
+ if (table->string_at(hdr.sh_name, buf, len)) {
+ if (strncmp(buf, name, len) == 0) {
+ sect_index = index;
+ break;
}
}
-#endif
-
}
- return true;
+ return sect_index;
}
bool ElfFile::decode(address addr, char* buf, int buflen, int* offset) {
// something already went wrong, just give up
- if (NullDecoder::is_error(m_status)) {
+ if (NullDecoder::is_error(_status)) {
return false;
}
- ElfSymbolTable* symbol_table = m_symbol_tables;
+
int string_table_index;
int pos_in_string_table;
int off = INT_MAX;
bool found_symbol = false;
+ ElfSymbolTable* symbol_table = _symbol_tables;
+
while (symbol_table != NULL) {
- if (symbol_table->lookup(addr, &string_table_index, &pos_in_string_table, &off, m_funcDesc_table)) {
+ if (symbol_table->lookup(addr, &string_table_index, &pos_in_string_table, &off, _funcDesc_table)) {
found_symbol = true;
break;
}
- symbol_table = symbol_table->m_next;
+ symbol_table = symbol_table->next();
}
- if (!found_symbol) return false;
+ if (!found_symbol) {
+ return false;
+ }
ElfStringTable* string_table = get_string_table(string_table_index);
if (string_table == NULL) {
- m_status = NullDecoder::file_invalid;
+ _status = NullDecoder::file_invalid;
return false;
}
if (offset) *offset = off;
@@ -213,74 +321,31 @@
return string_table->string_at(pos_in_string_table, buf, buflen);
}
-
void ElfFile::add_symbol_table(ElfSymbolTable* table) {
- if (m_symbol_tables == NULL) {
- m_symbol_tables = table;
+ if (_symbol_tables == NULL) {
+ _symbol_tables = table;
} else {
- table->m_next = m_symbol_tables;
- m_symbol_tables = table;
+ table->set_next(_symbol_tables);
+ _symbol_tables = table;
}
}
void ElfFile::add_string_table(ElfStringTable* table) {
- if (m_string_tables == NULL) {
- m_string_tables = table;
+ if (_string_tables == NULL) {
+ _string_tables = table;
} else {
- table->m_next = m_string_tables;
- m_string_tables = table;
+ table->set_next(_string_tables);
+ _string_tables = table;
}
}
ElfStringTable* ElfFile::get_string_table(int index) {
- ElfStringTable* p = m_string_tables;
+ ElfStringTable* p = _string_tables;
while (p != NULL) {
if (p->index() == index) return p;
- p = p->m_next;
+ p = p->next();
}
return NULL;
}
-#ifdef LINUX
-bool ElfFile::specifies_noexecstack(const char* filepath) {
- // Returns true if the elf file is marked NOT to require an executable stack,
- // or if the file could not be opened.
- // Returns false if the elf file requires an executable stack, the stack flag
- // is not set at all, or if the file can not be read.
- if (filepath == NULL) return true;
-
- FILE* file = fopen(filepath, "r");
- if (file == NULL) return true;
-
- // AARCH64 defaults to noexecstack. All others default to execstack.
-#ifdef AARCH64
- bool result = true;
-#else
- bool result = false;
-#endif
-
- // Read file header
- Elf_Ehdr head;
- if (fread(&head, sizeof(Elf_Ehdr), 1, file) == 1 &&
- is_elf_file(head) &&
- fseek(file, head.e_phoff, SEEK_SET) == 0) {
-
- // Read program header table
- Elf_Phdr phdr;
- for (int index = 0; index < head.e_phnum; index ++) {
- if (fread((void*)&phdr, sizeof(Elf_Phdr), 1, file) != 1) {
- result = false;
- break;
- }
- if (phdr.p_type == PT_GNU_STACK) {
- result = (phdr.p_flags == (PF_R | PF_W));
- break;
- }
- }
- }
- fclose(file);
- return result;
-}
-#endif // LINUX
-
#endif // !_WINDOWS && !__APPLE__
--- a/src/hotspot/share/utilities/elfFile.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/utilities/elfFile.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -57,7 +57,6 @@
typedef Elf32_Off Elf_Off;
typedef Elf32_Addr Elf_Addr;
-
typedef Elf32_Ehdr Elf_Ehdr;
typedef Elf32_Shdr Elf_Shdr;
typedef Elf32_Phdr Elf_Phdr;
@@ -72,46 +71,126 @@
#include "memory/allocation.hpp"
#include "utilities/decoder.hpp"
-
class ElfStringTable;
class ElfSymbolTable;
class ElfFuncDescTable;
+// ELF section, may or may not have cached data
+class ElfSection VALUE_OBJ_CLASS_SPEC {
+private:
+ Elf_Shdr _section_hdr;
+ void* _section_data;
+ NullDecoder::decoder_status _stat;
+public:
+ ElfSection(FILE* fd, const Elf_Shdr& hdr);
+ ~ElfSection();
-// On Solaris/Linux platforms, libjvm.so does contain all private symbols.
+ NullDecoder::decoder_status status() const { return _stat; }
+
+ const Elf_Shdr* section_header() const { return &_section_hdr; }
+ const void* section_data() const { return (const void*)_section_data; }
+private:
+ // load this section.
+ // it return no_error, when it fails to cache the section data due to lack of memory
+ NullDecoder::decoder_status load_section(FILE* const file, const Elf_Shdr& hdr);
+};
+
+class FileReader : public StackObj {
+protected:
+ FILE* const _fd;
+public:
+ FileReader(FILE* const fd) : _fd(fd) {};
+ bool read(void* buf, size_t size);
+ int read_buffer(void* buf, size_t size);
+ bool set_position(long offset);
+};
+
+// Mark current position, so we can get back to it after
+// reads.
+class MarkedFileReader : public FileReader {
+private:
+ long _marked_pos;
+public:
+ MarkedFileReader(FILE* const fd);
+ ~MarkedFileReader();
+
+ bool has_mark() const { return _marked_pos >= 0; }
+};
+
// ElfFile is basically an elf file parser, which can lookup the symbol
// that is the nearest to the given address.
// Beware, this code is called from vm error reporting code, when vm is already
// in "error" state, so there are scenarios, lookup will fail. We want this
// part of code to be very defensive, and bait out if anything went wrong.
-
class ElfFile: public CHeapObj<mtInternal> {
friend class ElfDecoder;
- public:
+
+private:
+ // link ElfFiles
+ ElfFile* _next;
+
+ // Elf file
+ char* _filepath;
+ FILE* _file;
+
+ // Elf header
+ Elf_Ehdr _elfHdr;
+
+ // symbol tables
+ ElfSymbolTable* _symbol_tables;
+
+ // regular string tables
+ ElfStringTable* _string_tables;
+
+ // section header string table, used for finding section name
+ ElfStringTable* _shdr_string_table;
+
+ // function descriptors table
+ ElfFuncDescTable* _funcDesc_table;
+
+ NullDecoder::decoder_status _status;
+
+public:
ElfFile(const char* filepath);
~ElfFile();
bool decode(address addr, char* buf, int buflen, int* offset);
- const char* filepath() {
- return m_filepath;
+
+ const char* filepath() const {
+ return _filepath;
+ }
+
+ bool same_elf_file(const char* filepath) const {
+ assert(filepath != NULL, "null file path");
+ return (_filepath != NULL && !strcmp(filepath, _filepath));
}
- bool same_elf_file(const char* filepath) {
- assert(filepath, "null file path");
- assert(m_filepath, "already out of memory");
- return (m_filepath && !strcmp(filepath, m_filepath));
+ NullDecoder::decoder_status get_status() const {
+ return _status;
}
- NullDecoder::decoder_status get_status() {
- return m_status;
- }
-
- private:
+ // Returns true if the elf file is marked NOT to require an executable stack,
+ // or if the file could not be opened.
+ // Returns false if the elf file requires an executable stack, the stack flag
+ // is not set at all, or if the file can not be read.
+ // On systems other than linux it always returns false.
+ static bool specifies_noexecstack(const char* filepath) NOT_LINUX({ return false; });
+private:
// sanity check, if the file is a real elf file
static bool is_elf_file(Elf_Ehdr&);
- // load string tables from the elf file
- bool load_tables();
+ // parse this elf file
+ NullDecoder::decoder_status parse_elf(const char* filename);
+
+ // load string, symbol and function descriptor tables from the elf file
+ NullDecoder::decoder_status load_tables();
+
+ ElfFile* next() const { return _next; }
+ void set_next(ElfFile* file) { _next = file; }
+
+ // find a section by name, return section index
+ // if there is no such section, return -1
+ int section_by_name(const char* name, Elf_Shdr& hdr);
// string tables are stored in a linked list
void add_string_table(ElfStringTable* table);
@@ -122,39 +201,15 @@
// return a string table at specified section index
ElfStringTable* get_string_table(int index);
-protected:
- ElfFile* next() const { return m_next; }
- void set_next(ElfFile* file) { m_next = file; }
- public:
- // Returns true if the elf file is marked NOT to require an executable stack,
- // or if the file could not be opened.
- // Returns false if the elf file requires an executable stack, the stack flag
- // is not set at all, or if the file can not be read.
- // On systems other than linux it always returns false.
- static bool specifies_noexecstack(const char* filepath) NOT_LINUX({ return false; });
-
- protected:
- ElfFile* m_next;
+ FILE* const fd() const { return _file; }
- private:
- // file
- const char* m_filepath;
- FILE* m_file;
-
- // Elf header
- Elf_Ehdr m_elfHdr;
+ // Cleanup string, symbol and function descriptor tables
+ void cleanup_tables();
- // symbol tables
- ElfSymbolTable* m_symbol_tables;
-
- // string tables
- ElfStringTable* m_string_tables;
-
- // function descriptors table
- ElfFuncDescTable* m_funcDesc_table;
-
- NullDecoder::decoder_status m_status;
+public:
+ // For whitebox test
+ static bool _do_not_cache_elf_section;
};
#endif // !_WINDOWS && !__APPLE__
--- a/src/hotspot/share/utilities/elfFuncDescTable.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/utilities/elfFuncDescTable.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2013 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -30,7 +30,8 @@
#include "memory/allocation.inline.hpp"
#include "utilities/elfFuncDescTable.hpp"
-ElfFuncDescTable::ElfFuncDescTable(FILE* file, Elf_Shdr shdr, int index) {
+ElfFuncDescTable::ElfFuncDescTable(FILE* file, Elf_Shdr shdr, int index) :
+ _file(file), _index(index), _section(file, shdr) {
assert(file, "null file handle");
// The actual function address (i.e. function entry point) is always the
// first value in the function descriptor (on IA64 and PPC64 they look as follows):
@@ -39,62 +40,33 @@
// Unfortunately 'shdr.sh_entsize' doesn't always seem to contain this size (it's zero on PPC64) so we can't assert
// assert(IA64_ONLY(2) PPC64_ONLY(3) * sizeof(address) == shdr.sh_entsize, "Size mismatch for '.opd' section entries");
- m_funcDescs = NULL;
- m_file = file;
- m_index = index;
- m_status = NullDecoder::no_error;
-
- // try to load the function descriptor table
- long cur_offset = ftell(file);
- if (cur_offset != -1) {
- // call malloc so we can back up if memory allocation fails.
- m_funcDescs = (address*)os::malloc(shdr.sh_size, mtInternal);
- if (m_funcDescs) {
- if (fseek(file, shdr.sh_offset, SEEK_SET) ||
- fread((void*)m_funcDescs, shdr.sh_size, 1, file) != 1 ||
- fseek(file, cur_offset, SEEK_SET)) {
- m_status = NullDecoder::file_invalid;
- os::free(m_funcDescs);
- m_funcDescs = NULL;
- }
- }
- if (!NullDecoder::is_error(m_status)) {
- memcpy(&m_shdr, &shdr, sizeof(Elf_Shdr));
- }
- } else {
- m_status = NullDecoder::file_invalid;
- }
+ _status = _section.status();
}
ElfFuncDescTable::~ElfFuncDescTable() {
- if (m_funcDescs != NULL) {
- os::free(m_funcDescs);
- }
}
address ElfFuncDescTable::lookup(Elf_Word index) {
- if (NullDecoder::is_error(m_status)) {
+ if (NullDecoder::is_error(_status)) {
return NULL;
}
- if (m_funcDescs != NULL) {
- if (m_shdr.sh_size > 0 && m_shdr.sh_addr <= index && index <= m_shdr.sh_addr + m_shdr.sh_size) {
- // Notice that 'index' is a byte-offset into the function descriptor table.
- return m_funcDescs[(index - m_shdr.sh_addr) / sizeof(address)];
- }
+ address* func_descs = cached_func_descs();
+ const Elf_Shdr* shdr = _section.section_header();
+ if (!(shdr->sh_size > 0 && shdr->sh_addr <= index && index <= shdr->sh_addr + shdr->sh_size)) {
+ // don't put the whole decoder in error mode if we just tried a wrong index
return NULL;
+ }
+
+ if (func_descs != NULL) {
+ return func_descs[(index - shdr->sh_addr) / sizeof(address)];
} else {
- long cur_pos;
+ MarkedFileReader mfd(_file);
address addr;
- if (!(m_shdr.sh_size > 0 && m_shdr.sh_addr <= index && index <= m_shdr.sh_addr + m_shdr.sh_size)) {
- // don't put the whole decoder in error mode if we just tried a wrong index
- return NULL;
- }
- if ((cur_pos = ftell(m_file)) == -1 ||
- fseek(m_file, m_shdr.sh_offset + index - m_shdr.sh_addr, SEEK_SET) ||
- fread(&addr, sizeof(addr), 1, m_file) != 1 ||
- fseek(m_file, cur_pos, SEEK_SET)) {
- m_status = NullDecoder::file_invalid;
+ if (!mfd.has_mark() ||
+ !mfd.set_position(shdr->sh_offset + index - shdr->sh_addr) ||
+ !mfd.read((void*)&addr, sizeof(addr))) {
+ _status = NullDecoder::file_invalid;
return NULL;
}
return addr;
--- a/src/hotspot/share/utilities/elfFuncDescTable.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/utilities/elfFuncDescTable.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2013 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -116,32 +116,31 @@
class ElfFuncDescTable: public CHeapObj<mtInternal> {
friend class ElfFile;
- public:
+private:
+ // holds the complete function descriptor section if
+ // we can allocate enough memory
+ ElfSection _section;
+
+ // file contains string table
+ FILE* const _file;
+
+ // The section index of this function descriptor (i.e. '.opd') section in the ELF file
+ const int _index;
+
+ NullDecoder::decoder_status _status;
+public:
ElfFuncDescTable(FILE* file, Elf_Shdr shdr, int index);
~ElfFuncDescTable();
// return the function address for the function descriptor at 'index' or NULL on error
address lookup(Elf_Word index);
- int get_index() { return m_index; };
-
- NullDecoder::decoder_status get_status() { return m_status; };
-
- protected:
- // holds the complete function descriptor section if
- // we can allocate enough memory
- address* m_funcDescs;
+ int get_index() const { return _index; };
- // file contains string table
- FILE* m_file;
+ NullDecoder::decoder_status get_status() const { return _status; };
- // section header
- Elf_Shdr m_shdr;
-
- // The section index of this function descriptor (i.e. '.opd') section in the ELF file
- int m_index;
-
- NullDecoder::decoder_status m_status;
+private:
+ address* cached_func_descs() const { return (address*)_section.section_data(); }
};
#endif // !_WINDOWS && !__APPLE__
--- a/src/hotspot/share/utilities/elfStringTable.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/utilities/elfStringTable.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -33,58 +33,44 @@
// We will try to load whole string table into memory if we can.
// Otherwise, fallback to more expensive file operation.
-ElfStringTable::ElfStringTable(FILE* file, Elf_Shdr shdr, int index) {
- assert(file, "null file handle");
- m_table = NULL;
- m_index = index;
- m_next = NULL;
- m_file = file;
- m_status = NullDecoder::no_error;
-
- // try to load the string table
- long cur_offset = ftell(file);
- m_table = (char*)os::malloc(sizeof(char) * shdr.sh_size, mtInternal);
- if (m_table != NULL) {
- // if there is an error, mark the error
- if (fseek(file, shdr.sh_offset, SEEK_SET) ||
- fread((void*)m_table, shdr.sh_size, 1, file) != 1 ||
- fseek(file, cur_offset, SEEK_SET)) {
- m_status = NullDecoder::file_invalid;
- os::free((void*)m_table);
- m_table = NULL;
- }
- } else {
- memcpy(&m_shdr, &shdr, sizeof(Elf_Shdr));
- }
+ElfStringTable::ElfStringTable(FILE* const file, Elf_Shdr& shdr, int index) :
+ _section(file, shdr), _index(index), _fd(file), _next(NULL) {
+ _status = _section.status();
}
ElfStringTable::~ElfStringTable() {
- if (m_table != NULL) {
- os::free((void*)m_table);
- }
-
- if (m_next != NULL) {
- delete m_next;
+ if (_next != NULL) {
+ delete _next;
}
}
-bool ElfStringTable::string_at(int pos, char* buf, int buflen) {
- if (NullDecoder::is_error(m_status)) {
+bool ElfStringTable::string_at(size_t pos, char* buf, int buflen) {
+ if (NullDecoder::is_error(get_status())) {
+ return false;
+ }
+
+ assert(buflen > 0, "no buffer");
+ if (pos >= _section.section_header()->sh_size) {
return false;
}
- if (m_table != NULL) {
- jio_snprintf(buf, buflen, "%s", (const char*)(m_table + pos));
+
+ const char* data = (const char*)_section.section_data();
+ if (data != NULL) {
+ jio_snprintf(buf, buflen, "%s", data + pos);
return true;
- } else {
- long cur_pos = ftell(m_file);
- if (cur_pos == -1 ||
- fseek(m_file, m_shdr.sh_offset + pos, SEEK_SET) ||
- fread(buf, 1, buflen, m_file) <= 0 ||
- fseek(m_file, cur_pos, SEEK_SET)) {
- m_status = NullDecoder::file_invalid;
+ } else { // no cache data, read from file instead
+ const Elf_Shdr* const shdr = _section.section_header();
+ MarkedFileReader mfd(_fd);
+ if (mfd.has_mark() &&
+ mfd.set_position(shdr->sh_offset + pos) &&
+ mfd.read((void*)buf, size_t(buflen))) {
+ buf[buflen - 1] = '\0';
+ return true;
+ } else {
+ // put it in error state to avoid retry
+ _status = NullDecoder::file_invalid;
return false;
}
- return true;
}
}
--- a/src/hotspot/share/utilities/elfStringTable.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/utilities/elfStringTable.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -37,37 +37,36 @@
// one blob. Otherwise, it will load string from file when requested.
class ElfStringTable: CHeapObj<mtInternal> {
friend class ElfFile;
- public:
- ElfStringTable(FILE* file, Elf_Shdr shdr, int index);
+private:
+ ElfStringTable* _next;
+ int _index; // section index
+ ElfSection _section;
+ FILE* const _fd;
+ NullDecoder::decoder_status _status;
+
+public:
+ ElfStringTable(FILE* const file, Elf_Shdr& shdr, int index);
~ElfStringTable();
// section index
- int index() { return m_index; };
+ int index() const { return _index; };
// get string at specified offset
- bool string_at(int offset, char* buf, int buflen);
+ bool string_at(size_t offset, char* buf, int buflen);
// get status code
- NullDecoder::decoder_status get_status() { return m_status; };
-
- protected:
- ElfStringTable* m_next;
-
- // section index
- int m_index;
+ NullDecoder::decoder_status get_status() const {
+ return _status;
+ }
- // holds complete string table if can
- // allocate enough memory
- const char* m_table;
+private:
+ void set_next(ElfStringTable* next) {
+ _next = next;
+ }
- // file contains string table
- FILE* m_file;
-
- // section header
- Elf_Shdr m_shdr;
-
- // error code
- NullDecoder::decoder_status m_status;
+ ElfStringTable* next() const {
+ return _next;
+ }
};
#endif // !_WINDOWS && !__APPLE__
--- a/src/hotspot/share/utilities/elfSymbolTable.cpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/utilities/elfSymbolTable.cpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -30,48 +30,26 @@
#include "utilities/elfFuncDescTable.hpp"
#include "utilities/elfSymbolTable.hpp"
-ElfSymbolTable::ElfSymbolTable(FILE* file, Elf_Shdr shdr) {
- assert(file, "null file handle");
- m_symbols = NULL;
- m_next = NULL;
- m_file = file;
- m_status = NullDecoder::no_error;
+ElfSymbolTable::ElfSymbolTable(FILE* const file, Elf_Shdr& shdr) :
+ _section(file, shdr), _fd(file), _next(NULL) {
+ assert(file != NULL, "null file handle");
+ _status = _section.status();
- // try to load the string table
- long cur_offset = ftell(file);
- if (cur_offset != -1) {
- // call malloc so we can back up if memory allocation fails.
- m_symbols = (Elf_Sym*)os::malloc(shdr.sh_size, mtInternal);
- if (m_symbols) {
- if (fseek(file, shdr.sh_offset, SEEK_SET) ||
- fread((void*)m_symbols, shdr.sh_size, 1, file) != 1 ||
- fseek(file, cur_offset, SEEK_SET)) {
- m_status = NullDecoder::file_invalid;
- os::free(m_symbols);
- m_symbols = NULL;
- }
- }
- if (!NullDecoder::is_error(m_status)) {
- memcpy(&m_shdr, &shdr, sizeof(Elf_Shdr));
- }
- } else {
- m_status = NullDecoder::file_invalid;
+ if (_section.section_header()->sh_size % sizeof(Elf_Sym) != 0) {
+ _status = NullDecoder::file_invalid;
}
}
ElfSymbolTable::~ElfSymbolTable() {
- if (m_symbols != NULL) {
- os::free(m_symbols);
- }
-
- if (m_next != NULL) {
- delete m_next;
+ if (_next != NULL) {
+ delete _next;
}
}
bool ElfSymbolTable::compare(const Elf_Sym* sym, address addr, int* stringtableIndex, int* posIndex, int* offset, ElfFuncDescTable* funcDescTable) {
if (STT_FUNC == ELF_ST_TYPE(sym->st_info)) {
Elf_Word st_size = sym->st_size;
+ const Elf_Shdr* shdr = _section.section_header();
address sym_addr;
if (funcDescTable != NULL && funcDescTable->get_index() == sym->st_shndx) {
// We need to go another step trough the function descriptor table (currently PPC64 only)
@@ -82,7 +60,7 @@
if (sym_addr <= addr && (Elf_Word)(addr - sym_addr) < st_size) {
*offset = (int)(addr - sym_addr);
*posIndex = sym->st_name;
- *stringtableIndex = m_shdr.sh_link;
+ *stringtableIndex = shdr->sh_link;
return true;
}
}
@@ -94,39 +72,39 @@
assert(posIndex, "null string table offset pointer");
assert(offset, "null offset pointer");
- if (NullDecoder::is_error(m_status)) {
+ if (NullDecoder::is_error(get_status())) {
return false;
}
size_t sym_size = sizeof(Elf_Sym);
- assert((m_shdr.sh_size % sym_size) == 0, "check size");
- int count = m_shdr.sh_size / sym_size;
- if (m_symbols != NULL) {
+ int count = _section.section_header()->sh_size / sym_size;
+ Elf_Sym* symbols = (Elf_Sym*)_section.section_data();
+
+ if (symbols != NULL) {
for (int index = 0; index < count; index ++) {
- if (compare(&m_symbols[index], addr, stringtableIndex, posIndex, offset, funcDescTable)) {
+ if (compare(&symbols[index], addr, stringtableIndex, posIndex, offset, funcDescTable)) {
return true;
}
}
} else {
- long cur_pos;
- if ((cur_pos = ftell(m_file)) == -1 ||
- fseek(m_file, m_shdr.sh_offset, SEEK_SET)) {
- m_status = NullDecoder::file_invalid;
+ MarkedFileReader mfd(_fd);
+
+ if (!mfd.has_mark() || !mfd.set_position(_section.section_header()->sh_offset)) {
+ _status = NullDecoder::file_invalid;
return false;
}
Elf_Sym sym;
for (int index = 0; index < count; index ++) {
- if (fread(&sym, sym_size, 1, m_file) == 1) {
- if (compare(&sym, addr, stringtableIndex, posIndex, offset, funcDescTable)) {
- return true;
- }
- } else {
- m_status = NullDecoder::file_invalid;
+ if (!mfd.read((void*)&sym, sizeof(sym))) {
+ _status = NullDecoder::file_invalid;
return false;
}
+
+ if (compare(&sym, addr, stringtableIndex, posIndex, offset, funcDescTable)) {
+ return true;
+ }
}
- fseek(m_file, cur_pos, SEEK_SET);
}
return false;
}
--- a/src/hotspot/share/utilities/elfSymbolTable.hpp Thu Feb 15 00:25:01 2018 -0800
+++ b/src/hotspot/share/utilities/elfSymbolTable.hpp Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -40,29 +40,27 @@
*/
class ElfSymbolTable: public CHeapObj<mtInternal> {
friend class ElfFile;
- public:
- ElfSymbolTable(FILE* file, Elf_Shdr shdr);
+private:
+ ElfSymbolTable* _next;
+
+ // file contains string table
+ FILE* const _fd;
+
+ // corresponding section
+ ElfSection _section;
+
+ NullDecoder::decoder_status _status;
+public:
+ ElfSymbolTable(FILE* const file, Elf_Shdr& shdr);
~ElfSymbolTable();
// search the symbol that is nearest to the specified address.
bool lookup(address addr, int* stringtableIndex, int* posIndex, int* offset, ElfFuncDescTable* funcDescTable);
- NullDecoder::decoder_status get_status() { return m_status; };
-
- protected:
- ElfSymbolTable* m_next;
-
- // holds a complete symbol table section if
- // can allocate enough memory
- Elf_Sym* m_symbols;
-
- // file contains string table
- FILE* m_file;
-
- // section header
- Elf_Shdr m_shdr;
-
- NullDecoder::decoder_status m_status;
+ NullDecoder::decoder_status get_status() const { return _status; };
+private:
+ ElfSymbolTable* next() const { return _next; }
+ void set_next(ElfSymbolTable* next) { _next = next; }
bool compare(const Elf_Sym* sym, address addr, int* stringtableIndex, int* posIndex, int* offset, ElfFuncDescTable* funcDescTable);
};
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ArrayKlass.java Thu Feb 15 00:25:01 2018 -0800
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ArrayKlass.java Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -57,6 +57,7 @@
super(addr);
}
+ public boolean isArrayKlass() { return true; }
private static CIntField dimension;
private static MetadataField higherDimension;
private static MetadataField lowerDimension;
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPool.java Thu Feb 15 00:25:01 2018 -0800
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPool.java Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -339,24 +339,28 @@
}
// returns null, if not resolved.
- public InstanceKlass getFieldOrMethodKlassRefAt(int which) {
+ public Klass getFieldOrMethodKlassRefAt(int which) {
int refIndex = getFieldOrMethodAt(which);
int klassIndex = extractLowShortFromInt(refIndex);
- return (InstanceKlass) getKlassAt(klassIndex);
+ return getKlassAt(klassIndex);
}
// returns null, if not resolved.
public Method getMethodRefAt(int which) {
- InstanceKlass klass = getFieldOrMethodKlassRefAt(which);
+ Klass klass = getFieldOrMethodKlassRefAt(which);
if (klass == null) return null;
Symbol name = getNameRefAt(which);
Symbol sig = getSignatureRefAt(which);
- return klass.findMethod(name, sig);
+ // Consider the super class for arrays. (java.lang.Object)
+ if (klass.isArrayKlass()) {
+ klass = klass.getJavaSuper();
+ }
+ return ((InstanceKlass)klass).findMethod(name, sig);
}
// returns null, if not resolved.
public Field getFieldRefAt(int which) {
- InstanceKlass klass = getFieldOrMethodKlassRefAt(which);
+ InstanceKlass klass = (InstanceKlass)getFieldOrMethodKlassRefAt(which);
if (klass == null) return null;
Symbol name = getNameRefAt(which);
Symbol sig = getSignatureRefAt(which);
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Klass.java Thu Feb 15 00:25:01 2018 -0800
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Klass.java Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -86,6 +86,7 @@
}
public boolean isKlass() { return true; }
+ public boolean isArrayKlass() { return false; }
// Fields
private static AddressField javaMirror;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/loopopts/StoreMovedBeforeInfiniteLoop.java Thu Feb 15 16:16:17 2018 +0100
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2018, Red Hat, Inc. 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 8197563
+ * @summary assert(is_Loop()) crash in PhaseIdealLoop::try_move_store_before_loop()
+ *
+ * @run main/othervm -Xcomp -XX:-TieredCompilation -XX:CompileOnly=StoreMovedBeforeInfiniteLoop::test StoreMovedBeforeInfiniteLoop
+ *
+ */
+
+public class StoreMovedBeforeInfiniteLoop {
+ public static void main(String[] args) {
+ field = -1;
+ test(new Object());
+ }
+
+ static int field;
+
+ static int constant() {
+ return 65;
+ }
+
+ private static int test(Object o) {
+ do {
+ if (field <= 0) {
+ return -109;
+ }
+ do {
+ field = 4;
+ } while (constant() >= 0);
+ } while (o == null);
+ return -109;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/ElfDecoder/TestElfDirectRead.java Thu Feb 15 16:16:17 2018 +0100
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8193373
+ * @summary Test reading ELF info direct from underlaying file
+ * @requires (os.family == "linux")
+ * @modules java.base/jdk.internal.misc
+ * @library /test/lib
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail TestElfDirectRead
+ */
+
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.JDKToolFinder;
+import sun.hotspot.WhiteBox;
+
+public class TestElfDirectRead {
+ public static void main(String args[]) throws Exception {
+ WhiteBox wb = WhiteBox.getWhiteBox();
+ wb.disableElfSectionCache();
+ ProcessBuilder pb = new ProcessBuilder();
+ OutputAnalyzer output;
+ // Grab my own PID
+ String pid = Long.toString(ProcessTools.getProcessId());
+
+ pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "detail"});
+ output = new OutputAnalyzer(pb.start());
+ // This is a pre-populated stack frame, should always exist if can decode
+ output.shouldContain("MallocSiteTable::new_entry");
+ }
+}
+
--- a/test/hotspot/jtreg/runtime/appcds/VerifierTest.java Thu Feb 15 00:25:01 2018 -0800
+++ b/test/hotspot/jtreg/runtime/appcds/VerifierTest.java Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -279,7 +279,7 @@
MethodVisitor mv;
AnnotationVisitor av0;
- cw.visit(V1_6, ACC_SUPER, "UnverifiableBase", null, "java/lang/Object", null);
+ cw.visit(V1_8, ACC_SUPER, "UnverifiableBase", null, "java/lang/Object", null);
{
fv = cw.visitField(ACC_FINAL + ACC_STATIC, "x", "LVerifierTest;", null, null);
fv.visitEnd();
@@ -296,8 +296,7 @@
{
mv = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null);
mv.visitCode();
- //WAS mv.visitTypeInsn(NEW, "VerifierTest");
- mv.visitTypeInsn(NEW, "java/lang/Object");
+ mv.visitTypeInsn(NEW, "VerifierTest0");
mv.visitInsn(DUP);
mv.visitMethodInsn(INVOKESPECIAL, "VerifierTest0", "<init>", "()V", false);
mv.visitFieldInsn(PUTSTATIC, "UnverifiableBase", "x", "LVerifierTest;");
@@ -305,6 +304,7 @@
mv.visitMaxs(2, 0);
mv.visitEnd();
}
+ addBadMethod(cw);
cw.visitEnd();
return cw.toByteArray();
@@ -317,7 +317,7 @@
MethodVisitor mv;
AnnotationVisitor av0;
- cw.visit(V1_6, ACC_ABSTRACT + ACC_INTERFACE, "UnverifiableIntf", null, "java/lang/Object", null);
+ cw.visit(V1_8, ACC_ABSTRACT + ACC_INTERFACE, "UnverifiableIntf", null, "java/lang/Object", null);
{
fv = cw.visitField(ACC_PUBLIC + ACC_FINAL + ACC_STATIC, "x", "LVerifierTest0;", null, null);
@@ -326,8 +326,7 @@
{
mv = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null);
mv.visitCode();
- //WAS mv.visitTypeInsn(NEW, "VerifierTest");
- mv.visitTypeInsn(NEW, "java/lang/Object");
+ mv.visitTypeInsn(NEW, "VerifierTest0");
mv.visitInsn(DUP);
mv.visitMethodInsn(INVOKESPECIAL, "VerifierTest0", "<init>", "()V", false);
mv.visitFieldInsn(PUTSTATIC, "UnverifiableIntf", "x", "LVerifierTest0;");
@@ -335,9 +334,18 @@
mv.visitMaxs(2, 0);
mv.visitEnd();
}
+ addBadMethod(cw);
cw.visitEnd();
return cw.toByteArray();
}
+ // Add a bad method to make the class fail verification.
+ static void addBadMethod(ClassWriter cw) throws Exception {
+ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "bad", "()V", null, null);
+ mv.visitCode();
+ mv.visitInsn(ARETURN); // java.lang.VerifyError: Operand stack underflow
+ mv.visitMaxs(2, 2);
+ mv.visitEnd();
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/condy/BadBSMUseTest.java Thu Feb 15 16:16:17 2018 +0100
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8186211
+ * @summary CONSTANT_Dynamic_info structure's tries to use a BSM index whose signature is for an invokedynamic and vice versa.
+ * @requires os.arch != "sparcv9"
+ * @modules java.base/jdk.internal.misc
+ * @library /test/lib
+ * @compile CondyUsesIndyBSM.jcod
+ * @compile IndyUsesCondyBSM.jcod
+ * @run main/othervm -Xverify:all BadBSMUseTest
+ */
+
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.compiler.InMemoryJavaCompiler;
+
+// BootstrapMethodError expected in each test case below.
+public class BadBSMUseTest {
+ public static void main(String args[]) throws Throwable {
+ // 1. Test a CONSTANT_Dynamic_info's bootstrap_method_attr_index points
+ // at a BSM meant for a CONSTANT_InvokeDynamic_info
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("CondyUsesIndyBSM");
+ OutputAnalyzer oa = new OutputAnalyzer(pb.start());
+ oa.shouldContain("In Indybsm target CallSite method foo");
+ oa.shouldContain("BootstrapMethodError: bootstrap method initialization exception");
+ oa.shouldHaveExitValue(1);
+
+ // 2. Test a CONSTANT_InvokeDynamic_info's bootstrap_method_attr_index points
+ // at a BSM meant for a CONSTANT_Dynamic_info
+ pb = ProcessTools.createJavaProcessBuilder("IndyUsesCondyBSM");
+ oa = new OutputAnalyzer(pb.start());
+ oa.shouldContain("In Condybsm");
+ oa.shouldContain("BootstrapMethodError: bootstrap method initialization exception");
+ oa.shouldHaveExitValue(1);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/condy/CondyBadBSMArrayTest.java Thu Feb 15 16:16:17 2018 +0100
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8186211
+ * @summary CONSTANT_Dynamic_info structure present with various bad BSM index, BSM array attribute checks.
+ * @requires os.arch != "sparcv9"
+ * @compile CondyBadBSMIndex.jcod
+ * @compile CondyEmptyBSMArray1.jcod
+ * @compile CondyNoBSMArray.jcod
+ * @run main/othervm -Xverify:all CondyBadBSMArrayTest
+ */
+
+// Test that a CONSTANT_Dynamic_info structure present with the following issues:
+// 1. The CONSTANT_Dynamic_info structure's bootstrap_method_attr_index value is
+// an index outside of the array size.
+// 2. An empty BootstrapMethods Attribute array
+// 3. No BootstrapMethods Attribute array present.
+public class CondyBadBSMArrayTest {
+ public static void main(String args[]) throws Throwable {
+ // 1. The CONSTANT_Dynamic_info structure's bootstrap_method_attr_index is outside the array size
+ try {
+ Class newClass = Class.forName("CondyBadBSMIndex");
+ throw new RuntimeException("Expected ClassFormatError exception not thrown");
+ } catch (java.lang.ClassFormatError e) {
+ if (!e.getMessage().contains("Short length on BootstrapMethods in class file")) {
+ throw new RuntimeException("ClassFormatError thrown, incorrect message");
+ }
+ System.out.println("Test CondyBadBSMIndex passed: " + e.getMessage());
+ } catch (Throwable e) {
+ throw new RuntimeException("Expected ClassFormatError exception not thrown");
+ }
+
+ // 2. An empty BootstrapMethods Attribute array - contains zero elements
+ try {
+ Class newClass = Class.forName("CondyEmptyBSMArray1");
+ throw new RuntimeException("Expected ClassFormatError exception not thrown");
+ } catch (java.lang.ClassFormatError e) {
+ if (!e.getMessage().contains("Short length on BootstrapMethods in class file")) {
+ throw new RuntimeException("ClassFormatError thrown, incorrect message");
+ }
+ System.out.println("Test CondyEmptyBSMArray1 passed: " + e.getMessage());
+ } catch (Throwable e) {
+ throw new RuntimeException("Expected ClassFormatError exception not thrown");
+ }
+
+ // 3. No BootstrapMethods Attribute array present`
+ try {
+ Class newClass = Class.forName("CondyNoBSMArray");
+ throw new RuntimeException("Expected ClassFormatError exception not thrown");
+ } catch (java.lang.ClassFormatError e) {
+ if (!e.getMessage().contains("Missing BootstrapMethods attribute in class file")) {
+ throw new RuntimeException("ClassFormatError thrown, incorrect message");
+ }
+ System.out.println("Test CondyNoBSMArray passed: " + e.getMessage());
+ } catch (Throwable e) {
+ throw new RuntimeException("Expected ClassFormatError exception not thrown");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/condy/CondyBadBSMIndex.jcod Thu Feb 15 16:16:17 2018 +0100
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This test contains a CONSTANT_Dynamic_info whose bootstrap_method_attr_index is bogus.
+ * ClassFormatError expected.
+ */
+
+/*
+class CondyBadBSMIndex {
+ CondyBadBSMIndex() { }
+ public static Object m() {
+ // ldc Dynamic where the CONSTANT_Dynamic_info bootstrap_method_attr_index points at slot #5
+ // in the bootstrap_methods array, however, the bootstrap_methods array is composed of only 1 slot.
+ // Outcome -> java.lang.ClassFormatError: Short length on BootstrapMethods in class file CondyBadBSMIndex
+ return of ldc's Object;
+ public static void main(String[] args) { return; }
+}
+*/
+
+class CondyBadBSMIndex {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Utf8 "java/lang/Object"; // #1
+ class #1; // #2
+ Utf8 "<init>"; // #3
+ Utf8 "()V"; // #4
+ NameAndType #3 #4; // #5
+ Method #2 #5; // #6
+ Utf8 "Code"; // #7
+ Utf8 "CondyBadBSMIndex"; // #8
+ class #8; // #9
+ Utf8 "bsm"; // #10
+ Utf8 "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/Object;"; // #11
+ NameAndType #10 #11; // #12
+ Method #9 #12; // #13
+ MethodHandle 6b #13; // #14
+ Utf8 "name"; // #15
+ Utf8 "Ljava/lang/Object;"; // #16
+ NameAndType #15 #16; // #17
+ Dynamic 5s #17; // #18
+ Utf8 "m"; // #19
+ Utf8 "()Ljava/lang/Object;"; // #20
+ Utf8 "main"; // #21
+ Utf8 "([Ljava/lang/String;)V"; // #22
+ Utf8 "BootstrapMethods"; // #23
+ Utf8 "CondyBadBSMIndex"; // #24
+ class #24; // #25
+ } // Constant Pool
+
+ 0x0000; // access
+ #25;// this_cpx
+ #2;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0001; // access
+ #3; // name_cpx
+ #4; // sig_cpx
+ [] { // Attributes
+ Attr(#7) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70006B1;
+ }
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #19; // name_cpx
+ #20; // sig_cpx
+ [] { // Attributes
+ Attr(#7) { // Code
+ 1; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0x1212B0;
+ }
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #21; // name_cpx
+ #22; // sig_cpx
+ [] { // Attributes
+ Attr(#7) { // Code
+ 0; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0xB1;
+ }
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#23) { // BootstrapMethods
+ [] { // bootstrap_methods
+ { // bootstrap_method
+ #14; // bootstrap_method_ref
+ [] { // bootstrap_arguments
+ } // bootstrap_arguments
+ } // bootstrap_method
+ }
+ } // end BootstrapMethods
+ } // Attributes
+} // end class CondyBadBSMIndex
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/condy/CondyBadLDC.jasm Thu Feb 15 16:16:17 2018 +0100
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This test contains a incorrect ldc instruction of a condy whose loadable
+ * constant is a double. VerifyError expected.
+ */
+
+class CondyBadLDC
+ version 55:0
+{
+
+
+public Method "<init>":"()V"
+ stack 1 locals 1
+{
+ aload_0;
+ invokespecial Method java/lang/Object."<init>":"()V";
+ return;
+}
+
+public static Method intConversion:"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;I)Ljava/lang/Object;"
+ throws java/lang/Throwable
+ stack 4 locals 6
+{
+ aload_1;
+ astore 4;
+ iconst_m1;
+ istore 5;
+ aload 4;
+ invokevirtual Method java/lang/String.hashCode:"()I";
+ lookupswitch{ //11
+ -2001159796: L238;
+ -1538095928: L272;
+ -891985903: L255;
+ 66: L108;
+ 67: L124;
+ 68: L140;
+ 70: L156;
+ 73: L172;
+ 74: L188;
+ 83: L204;
+ 90: L221;
+ default: L286 };
+ L108: stack_frame_type append;
+ locals_map class java/lang/String, int;
+ aload 4;
+ ldc String "B";
+ invokevirtual Method java/lang/String.equals:"(Ljava/lang/Object;)Z";
+ ifeq L286;
+ iconst_0;
+ istore 5;
+ goto L286;
+ L124: stack_frame_type same;
+ aload 4;
+ ldc String "C";
+ invokevirtual Method java/lang/String.equals:"(Ljava/lang/Object;)Z";
+ ifeq L286;
+ iconst_1;
+ istore 5;
+ goto L286;
+ L140: stack_frame_type same;
+ aload 4;
+ ldc String "D";
+ invokevirtual Method java/lang/String.equals:"(Ljava/lang/Object;)Z";
+ ifeq L286;
+ iconst_2;
+ istore 5;
+ goto L286;
+ L156: stack_frame_type same;
+ aload 4;
+ ldc String "F";
+ invokevirtual Method java/lang/String.equals:"(Ljava/lang/Object;)Z";
+ ifeq L286;
+ iconst_3;
+ istore 5;
+ goto L286;
+ L172: stack_frame_type same;
+ aload 4;
+ ldc String "I";
+ invokevirtual Method java/lang/String.equals:"(Ljava/lang/Object;)Z";
+ ifeq L286;
+ iconst_4;
+ istore 5;
+ goto L286;
+ L188: stack_frame_type same;
+ aload 4;
+ ldc String "J";
+ invokevirtual Method java/lang/String.equals:"(Ljava/lang/Object;)Z";
+ ifeq L286;
+ iconst_5;
+ istore 5;
+ goto L286;
+ L204: stack_frame_type same;
+ aload 4;
+ ldc String "S";
+ invokevirtual Method java/lang/String.equals:"(Ljava/lang/Object;)Z";
+ ifeq L286;
+ bipush 6;
+ istore 5;
+ goto L286;
+ L221: stack_frame_type same;
+ aload 4;
+ ldc String "Z";
+ invokevirtual Method java/lang/String.equals:"(Ljava/lang/Object;)Z";
+ ifeq L286;
+ bipush 7;
+ istore 5;
+ goto L286;
+ L238: stack_frame_type same;
+ aload 4;
+ ldc String "nullRef";
+ invokevirtual Method java/lang/String.equals:"(Ljava/lang/Object;)Z";
+ ifeq L286;
+ bipush 8;
+ istore 5;
+ goto L286;
+ L255: stack_frame_type same;
+ aload 4;
+ ldc String "string";
+ invokevirtual Method java/lang/String.equals:"(Ljava/lang/Object;)Z";
+ ifeq L286;
+ bipush 9;
+ istore 5;
+ goto L286;
+ L272: stack_frame_type same;
+ aload 4;
+ ldc String "stringArray";
+ invokevirtual Method java/lang/String.equals:"(Ljava/lang/Object;)Z";
+ ifeq L286;
+ bipush 10;
+ istore 5;
+ L286: stack_frame_type same;
+ iload 5;
+ tableswitch{ //0 to 10
+ 0: L348;
+ 1: L354;
+ 2: L360;
+ 3: L366;
+ 4: L372;
+ 5: L377;
+ 6: L383;
+ 7: L389;
+ 8: L402;
+ 9: L404;
+ 10: L407;
+ default: L422 };
+ L348: stack_frame_type same;
+ iload_3;
+ i2b;
+ invokestatic Method java/lang/Byte.valueOf:"(B)Ljava/lang/Byte;";
+ areturn;
+ L354: stack_frame_type same;
+ iload_3;
+ i2c;
+ invokestatic Method java/lang/Character.valueOf:"(C)Ljava/lang/Character;";
+ areturn;
+ L360: stack_frame_type same;
+ iload_3;
+ i2d;
+ invokestatic Method java/lang/Double.valueOf:"(D)Ljava/lang/Double;";
+ areturn;
+ L366: stack_frame_type same;
+ iload_3;
+ i2f;
+ invokestatic Method java/lang/Float.valueOf:"(F)Ljava/lang/Float;";
+ areturn;
+ L372: stack_frame_type same;
+ iload_3;
+ invokestatic Method java/lang/Integer.valueOf:"(I)Ljava/lang/Integer;";
+ areturn;
+ L377: stack_frame_type same;
+ iload_3;
+ i2l;
+ invokestatic Method java/lang/Long.valueOf:"(J)Ljava/lang/Long;";
+ areturn;
+ L383: stack_frame_type same;
+ iload_3;
+ i2s;
+ invokestatic Method java/lang/Short.valueOf:"(S)Ljava/lang/Short;";
+ areturn;
+ L389: stack_frame_type same;
+ iload_3;
+ ifle L397;
+ iconst_1;
+ goto L398;
+ L397: stack_frame_type same;
+ iconst_0;
+ L398: stack_frame_type stack1;
+ stack_map int;
+ invokestatic Method java/lang/Boolean.valueOf:"(Z)Ljava/lang/Boolean;";
+ areturn;
+ L402: stack_frame_type same;
+ aconst_null;
+ areturn;
+ L404: stack_frame_type same;
+ ldc String "string";
+ areturn;
+ L407: stack_frame_type same;
+ iconst_2;
+ anewarray class java/lang/String;
+ dup;
+ iconst_0;
+ ldc String "string";
+ aastore;
+ dup;
+ iconst_1;
+ ldc String "string";
+ aastore;
+ areturn;
+ L422: stack_frame_type same;
+ new class java/lang/BootstrapMethodError;
+ dup;
+ ldc String "Failure to generate a dynamic constant";
+ invokespecial Method java/lang/BootstrapMethodError."<init>":"(Ljava/lang/String;)V";
+ athrow;
+}
+
+public static Method D:"()D"
+ stack 2 locals 0
+{
+ // ldc of a double will yield a VerifyError, should be an ldc2_w instruction
+ ldc Dynamic REF_invokeStatic:CondyBadLDC.intConversion:"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;I)Ljava/lang/Object;":D:"D" int 2147483647;
+ dreturn;
+}
+
+public static Method main:"([Ljava/lang/String;)V"
+ stack 2 locals 1
+{
+ invokestatic Method D:"()D";
+ return;
+}
+
+} // end Class CondyBadLDC
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/condy/CondyBadLDC2_W.jasm Thu Feb 15 16:16:17 2018 +0100
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This test contains a ldc2_w instruction of a condy which returns a loadable float
+ * constant. VerifyError expected.
+ */
+class CondyBadLDC2_W
+ version 55:0
+{
+
+public Method "<init>":"()V"
+ stack 1 locals 1
+{
+ aload_0;
+ invokespecial Method java/lang/Object."<init>":"()V";
+ return;
+}
+
+public static Method intConversion:"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;I)Ljava/lang/Object;"
+ throws java/lang/Throwable
+ stack 4 locals 6
+{
+ aload_1;
+ astore 4;
+ iconst_m1;
+ istore 5;
+ aload 4;
+ invokevirtual Method java/lang/String.hashCode:"()I";
+ lookupswitch{ //11
+ -2001159796: L238;
+ -1538095928: L272;
+ -891985903: L255;
+ 66: L108;
+ 67: L124;
+ 68: L140;
+ 70: L156;
+ 73: L172;
+ 74: L188;
+ 83: L204;
+ 90: L221;
+ default: L286 };
+ L108: stack_frame_type append;
+ locals_map class java/lang/String, int;
+ aload 4;
+ ldc String "B";
+ invokevirtual Method java/lang/String.equals:"(Ljava/lang/Object;)Z";
+ ifeq L286;
+ iconst_0;
+ istore 5;
+ goto L286;
+ L124: stack_frame_type same;
+ aload 4;
+ ldc String "C";
+ invokevirtual Method java/lang/String.equals:"(Ljava/lang/Object;)Z";
+ ifeq L286;
+ iconst_1;
+ istore 5;
+ goto L286;
+ L140: stack_frame_type same;
+ aload 4;
+ ldc String "D";
+ invokevirtual Method java/lang/String.equals:"(Ljava/lang/Object;)Z";
+ ifeq L286;
+ iconst_2;
+ istore 5;
+ goto L286;
+ L156: stack_frame_type same;
+ aload 4;
+ ldc String "F";
+ invokevirtual Method java/lang/String.equals:"(Ljava/lang/Object;)Z";
+ ifeq L286;
+ iconst_3;
+ istore 5;
+ goto L286;
+ L172: stack_frame_type same;
+ aload 4;
+ ldc String "I";
+ invokevirtual Method java/lang/String.equals:"(Ljava/lang/Object;)Z";
+ ifeq L286;
+ iconst_4;
+ istore 5;
+ goto L286;
+ L188: stack_frame_type same;
+ aload 4;
+ ldc String "J";
+ invokevirtual Method java/lang/String.equals:"(Ljava/lang/Object;)Z";
+ ifeq L286;
+ iconst_5;
+ istore 5;
+ goto L286;
+ L204: stack_frame_type same;
+ aload 4;
+ ldc String "S";
+ invokevirtual Method java/lang/String.equals:"(Ljava/lang/Object;)Z";
+ ifeq L286;
+ bipush 6;
+ istore 5;
+ goto L286;
+ L221: stack_frame_type same;
+ aload 4;
+ ldc String "Z";
+ invokevirtual Method java/lang/String.equals:"(Ljava/lang/Object;)Z";
+ ifeq L286;
+ bipush 7;
+ istore 5;
+ goto L286;
+ L238: stack_frame_type same;
+ aload 4;
+ ldc String "nullRef";
+ invokevirtual Method java/lang/String.equals:"(Ljava/lang/Object;)Z";
+ ifeq L286;
+ bipush 8;
+ istore 5;
+ goto L286;
+ L255: stack_frame_type same;
+ aload 4;
+ ldc String "string";
+ invokevirtual Method java/lang/String.equals:"(Ljava/lang/Object;)Z";
+ ifeq L286;
+ bipush 9;
+ istore 5;
+ goto L286;
+ L272: stack_frame_type same;
+ aload 4;
+ ldc String "stringArray";
+ invokevirtual Method java/lang/String.equals:"(Ljava/lang/Object;)Z";
+ ifeq L286;
+ bipush 10;
+ istore 5;
+ L286: stack_frame_type same;
+ iload 5;
+ tableswitch{ //0 to 10
+ 0: L348;
+ 1: L354;
+ 2: L360;
+ 3: L366;
+ 4: L372;
+ 5: L377;
+ 6: L383;
+ 7: L389;
+ 8: L402;
+ 9: L404;
+ 10: L407;
+ default: L422 };
+ L348: stack_frame_type same;
+ iload_3;
+ i2b;
+ invokestatic Method java/lang/Byte.valueOf:"(B)Ljava/lang/Byte;";
+ areturn;
+ L354: stack_frame_type same;
+ iload_3;
+ i2c;
+ invokestatic Method java/lang/Character.valueOf:"(C)Ljava/lang/Character;";
+ areturn;
+ L360: stack_frame_type same;
+ iload_3;
+ i2d;
+ invokestatic Method java/lang/Double.valueOf:"(D)Ljava/lang/Double;";
+ areturn;
+ L366: stack_frame_type same;
+ iload_3;
+ i2f;
+ invokestatic Method java/lang/Float.valueOf:"(F)Ljava/lang/Float;";
+ areturn;
+ L372: stack_frame_type same;
+ iload_3;
+ invokestatic Method java/lang/Integer.valueOf:"(I)Ljava/lang/Integer;";
+ areturn;
+ L377: stack_frame_type same;
+ iload_3;
+ i2l;
+ invokestatic Method java/lang/Long.valueOf:"(J)Ljava/lang/Long;";
+ areturn;
+ L383: stack_frame_type same;
+ iload_3;
+ i2s;
+ invokestatic Method java/lang/Short.valueOf:"(S)Ljava/lang/Short;";
+ areturn;
+ L389: stack_frame_type same;
+ iload_3;
+ ifle L397;
+ iconst_1;
+ goto L398;
+ L397: stack_frame_type same;
+ iconst_0;
+ L398: stack_frame_type stack1;
+ stack_map int;
+ invokestatic Method java/lang/Boolean.valueOf:"(Z)Ljava/lang/Boolean;";
+ areturn;
+ L402: stack_frame_type same;
+ aconst_null;
+ areturn;
+ L404: stack_frame_type same;
+ ldc String "string";
+ areturn;
+ L407: stack_frame_type same;
+ iconst_2;
+ anewarray class java/lang/String;
+ dup;
+ iconst_0;
+ ldc String "string";
+ aastore;
+ dup;
+ iconst_1;
+ ldc String "string";
+ aastore;
+ areturn;
+ L422: stack_frame_type same;
+ new class java/lang/BootstrapMethodError;
+ dup;
+ ldc String "Failure to generate a dynamic constant";
+ invokespecial Method java/lang/BootstrapMethodError."<init>":"(Ljava/lang/String;)V";
+ athrow;
+}
+
+public static Method F:"()F"
+ stack 1 locals 0
+{
+ // VerifyError, ldc2_w of a float, should be ldc
+ ldc2_w Dynamic REF_invokeStatic:CondyBadLDC2_W.intConversion:"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;I)Ljava/lang/Object;":F:"F" int 2147483647;
+ freturn;
+}
+
+public static Method main:"([Ljava/lang/String;)V"
+ stack 1 locals 1
+{
+ invokestatic Method F:"()F";
+ return;
+}
+
+} // end Class CondyBadLDC2_W
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/condy/CondyBadNameType.jcod Thu Feb 15 16:16:17 2018 +0100
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This test contains a CONSTANT_Dynamic_info structure whose name_and_type_index
+ * does not point at a CONSTANT_NameAndType_info structure. ClassFormatError expected.
+ */
+
+/*
+class CondyBadNameType {
+ CondyBadNameType() { }
+ public static Object m() {
+ // ldc Dynamic where the CONSTANT_Dynamic_info name_and_type_index erroneously points
+ // at a Utf8 instead of the expected CONSTANT_NameAndType.
+ // Outcome -> java.lang.ClassFormatError: Invalid constant pool index 16 in class file CondyBadNameType
+ return of ldc's Object;
+ public static void main(String[] args) { return; }
+}
+*/
+
+class CondyBadNameType {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Utf8 "java/lang/Object"; // #1
+ class #1; // #2
+ Utf8 "<init>"; // #3
+ Utf8 "()V"; // #4
+ NameAndType #3 #4; // #5
+ Method #2 #5; // #6
+ Utf8 "Code"; // #7
+ Utf8 "CondyBadNameType"; // #8
+ class #8; // #9
+ Utf8 "bsm"; // #10
+ Utf8 "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/Object;"; // #11
+ NameAndType #10 #11; // #12
+ Method #9 #12; // #13
+ MethodHandle 6b #13; // #14
+ Utf8 "name"; // #15
+ Utf8 "Ljava/lang/Object;"; // #16
+ NameAndType #15 #16; // #17
+ Dynamic 0s #16; // #18
+ Utf8 "m"; // #19
+ Utf8 "()Ljava/lang/Object;"; // #20
+ Utf8 "main"; // #21
+ Utf8 "([Ljava/lang/String;)V"; // #22
+ Utf8 "BootstrapMethods"; // #23
+ Utf8 "CondyBadNameType"; // #24
+ class #24; // #25
+ } // Constant Pool
+
+ 0x0000; // access
+ #25;// this_cpx
+ #2;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0001; // access
+ #3; // name_cpx
+ #4; // sig_cpx
+ [] { // Attributes
+ Attr(#7) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70006B1;
+ }
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #19; // name_cpx
+ #20; // sig_cpx
+ [] { // Attributes
+ Attr(#7) { // Code
+ 1; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0x1212B0;
+ }
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #21; // name_cpx
+ #22; // sig_cpx
+ [] { // Attributes
+ Attr(#7) { // Code
+ 0; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0xB1;
+ }
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#23) { // BootstrapMethods
+ [] { // bootstrap_methods
+ { // bootstrap_method
+ #14; // bootstrap_method_ref
+ [] { // bootstrap_arguments
+ } // bootstrap_arguments
+ } // bootstrap_method
+ }
+ } // end BootstrapMethods
+ } // Attributes
+} // end class CondyBadNameType
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/condy/CondyBadNameTypeTest.java Thu Feb 15 16:16:17 2018 +0100
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8186211
+ * @summary CONSTANT_Dynamic_info structure's name_and_type_index item does not point at CONSANT_NameAndType_info
+ * @requires os.arch != "sparcv9"
+ * @compile CondyBadNameType.jcod
+ * @run main/othervm -Xverify:all CondyBadNameTypeTest
+ */
+
+// Test a CONSTANT_Dynamic_info structure's name_and_type_index points at a
+// constant pool NameAndType_info structure.
+public class CondyBadNameTypeTest {
+ public static void main(String args[]) throws Throwable {
+ try {
+ Class newClass = Class.forName("CondyBadNameType");
+ throw new RuntimeException("Expected ClassFormatError exception not thrown");
+ } catch (java.lang.ClassFormatError e) {
+ if (!e.getMessage().contains("Invalid constant pool index")) {
+ throw new RuntimeException("ClassFormatError thrown, incorrect message");
+ }
+ System.out.println("Test CondyBadNameTypeTest passed: " + e.getMessage());
+ } catch (Throwable e) {
+ throw new RuntimeException("Expected ClassFormatError exception not thrown");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/condy/CondyCFVCheck.jcod Thu Feb 15 16:16:17 2018 +0100
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This test contains a CONSTANT_Dynamic_info structure in a version 54 class file.
+ */
+
+/*
+class CondyCFVCheck {
+ CondyCondyCFVCheck() {}
+ public static Object m() {
+ // ldc Dynamic
+ // Outcome -> java.lang.ClassFormatError: Class file version does not support constant tag 17 in class file CondyCFVCheck
+ return of ldc's Object;
+ public static void main(String[] args) { return; }
+}
+*/
+
+class CondyCFVCheck {
+ 0xCAFEBABE;
+ 0; // minor version
+ 54; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Utf8 "java/lang/Object"; // #1
+ class #1; // #2
+ Utf8 "<init>"; // #3
+ Utf8 "()V"; // #4
+ NameAndType #3 #4; // #5
+ Method #2 #5; // #6
+ Utf8 "Code"; // #7
+ Utf8 "CondyCFVCheck"; // #8
+ class #8; // #9
+ Utf8 "bsm"; // #10
+ Utf8 "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/Object;"; // #11
+ NameAndType #10 #11; // #12
+ Method #9 #12; // #13
+ MethodHandle 6b #13; // #14
+ Utf8 "name"; // #15
+ Utf8 "Ljava/lang/Object;"; // #16
+ NameAndType #15 #16; // #17
+ Dynamic 0s #17; // #18
+ Utf8 "m"; // #19
+ Utf8 "()Ljava/lang/Object;"; // #20
+ Utf8 "main"; // #21
+ Utf8 "([Ljava/lang/String;)V"; // #22
+ Utf8 "BootstrapMethods"; // #23
+ Utf8 "CondyCFVCheck"; // #24
+ class #24; // #25
+ } // Constant Pool
+
+ 0x0000; // access
+ #25;// this_cpx
+ #2;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0001; // access
+ #3; // name_cpx
+ #4; // sig_cpx
+ [] { // Attributes
+ Attr(#7) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70006B1;
+ }
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #19; // name_cpx
+ #20; // sig_cpx
+ [] { // Attributes
+ Attr(#7) { // Code
+ 1; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0x1212B0;
+ }
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #21; // name_cpx
+ #22; // sig_cpx
+ [] { // Attributes
+ Attr(#7) { // Code
+ 0; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0xB1;
+ }
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#23) { // BootstrapMethods
+ [] { // bootstrap_methods
+ { // bootstrap_method
+ #14; // bootstrap_method_ref
+ [] { // bootstrap_arguments
+ } // bootstrap_arguments
+ } // bootstrap_method
+ }
+ } // end BootstrapMethods
+ } // Attributes
+} // end class CondyCFVCheck
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/condy/CondyCFVCheckTest.java Thu Feb 15 16:16:17 2018 +0100
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8186211
+ * @summary CONSTANT_Dynamic_info structure present within an unsupported class file version.
+ * @requires os.arch != "sparcv9"
+ * @compile CondyCFVCheck.jcod
+ * @run main/othervm -Xverify:all CondyCFVCheckTest
+ */
+
+// Test a CONSTANT_Dynamic_info structure present within an unsupported class file version
+// yields a ClassFormatError.
+public class CondyCFVCheckTest {
+ public static void main(String args[]) throws Throwable {
+ try {
+ Class newClass = Class.forName("CondyCFVCheck");
+ throw new RuntimeException("Expected ClassFormatError exception not thrown");
+ } catch (java.lang.ClassFormatError e) {
+ if (!e.getMessage().contains("Class file version does not support constant tag 17 in class file")) {
+ throw new RuntimeException("ClassFormatError thrown, incorrect message");
+ }
+ System.out.println("Test CondyCFVCheckTest passed: " + e.getMessage());
+ } catch (Throwable e) {
+ throw new RuntimeException("Expected ClassFormatError exception not thrown");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/condy/CondyEmptyBSMArray1.jcod Thu Feb 15 16:16:17 2018 +0100
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This test contains a CONSTANT_Dynamic_info structure, but the BootstrapMethods Attribute
+ * contains bootstrap_methods array with 0 elements. ClassFormatError expected.
+ */
+
+/*
+class CondyEmptyBSMArray1 {
+ CondyEmptyBSMArray1() {}
+ public static Object m() {
+ // ldc Dynamic where the CONSTANT_Dynamic_info bootstrap_method_attr_index points to slot #0
+ // in the bootstrap_methods array, however the BootstrapMethods array is empty.
+ // Outcome -> java.lang.ClassFormatError: Short length on BootstrapMethods in class file CondyEmptyBSMArray1
+ return of ldc's Object;
+ public static void main(String[] args) { return; }
+}
+*/
+
+class CondyEmptyBSMArray1 {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Utf8 "java/lang/Object"; // #1
+ class #1; // #2
+ Utf8 "<init>"; // #3
+ Utf8 "()V"; // #4
+ NameAndType #3 #4; // #5
+ Method #2 #5; // #6
+ Utf8 "Code"; // #7
+ Utf8 "CondyEmptyBSMArray1"; // #8
+ class #8; // #9
+ Utf8 "bsm"; // #10
+ Utf8 "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/Object;"; // #11
+ NameAndType #10 #11; // #12
+ Method #9 #12; // #13
+ MethodHandle 6b #13; // #14
+ Utf8 "name"; // #15
+ Utf8 "Ljava/lang/Object;"; // #16
+ NameAndType #15 #16; // #17
+ Dynamic 0s #17; // #18
+ Utf8 "m"; // #19
+ Utf8 "()Ljava/lang/Object;"; // #20
+ Utf8 "main"; // #21
+ Utf8 "([Ljava/lang/String;)V"; // #22
+ Utf8 "BootstrapMethods"; // #23
+ Utf8 "CondyEmptyBSMArray1"; // #24
+ class #24; // #25
+ } // Constant Pool
+
+ 0x0000; // access
+ #25;// this_cpx
+ #2;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0001; // access
+ #3; // name_cpx
+ #4; // sig_cpx
+ [] { // Attributes
+ Attr(#7) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70006B1;
+ }
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #19; // name_cpx
+ #20; // sig_cpx
+ [] { // Attributes
+ Attr(#7) { // Code
+ 1; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0x1212B0;
+ }
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #21; // name_cpx
+ #22; // sig_cpx
+ [] { // Attributes
+ Attr(#7) { // Code
+ 0; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0xB1;
+ }
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#23) { // BootstrapMethods
+ [0] { // bootstrap_methods
+ }
+ } // end BootstrapMethods
+ } // Attributes
+} // end class CondyEmptyBSMArray1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/condy/CondyLDCTest.java Thu Feb 15 16:16:17 2018 +0100
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8186211
+ * @summary Tests various ldc, ldc_w, ldc2_w instructions of CONSTANT_Dynamic.
+ * @requires os.arch != "sparcv9"
+ * @modules java.base/jdk.internal.misc
+ * @library /test/lib
+ * @compile CondyUseLDC_W.jasm
+ * @compile CondyBadLDC2_W.jasm
+ * @compile CondyBadLDC.jasm
+ * @run main/othervm -Xverify:all CondyLDCTest
+ */
+
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.compiler.InMemoryJavaCompiler;
+
+public class CondyLDCTest {
+ public static void main(String args[]) throws Throwable {
+ // 1. Test a ldc_w instruction can be used with condy's which generate
+ // loadable constants of the following types: byte, char, short, float, integer, boolean.
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("CondyUseLDC_W");
+ OutputAnalyzer oa = new OutputAnalyzer(pb.start());
+ oa.shouldNotContain("VerifyError");
+ oa.shouldHaveExitValue(0);
+
+ // 2. Test ldc2_w of a condy which returns a dynamically generated
+ // float constant, generates a VerifyError.
+ pb = ProcessTools.createJavaProcessBuilder("CondyBadLDC2_W");
+ oa = new OutputAnalyzer(pb.start());
+ oa.shouldContain("java.lang.VerifyError: Illegal type at constant pool entry");
+ oa.shouldContain("CondyBadLDC2_W.F()F @0: ldc2_w");
+ oa.shouldHaveExitValue(1);
+
+ // 3. Test a ldc of a condy which returns a dynamically generated
+ // double constant, generates a VerifyError.
+ pb = ProcessTools.createJavaProcessBuilder("CondyBadLDC");
+ oa = new OutputAnalyzer(pb.start());
+ oa.shouldContain("java.lang.VerifyError: Illegal type at constant pool entry");
+ oa.shouldContain("CondyBadLDC.D()D @0: ldc");
+ oa.shouldHaveExitValue(1);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/condy/CondyNewInvokeSpecial.jasm Thu Feb 15 16:16:17 2018 +0100
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+super public class CondyNewInvokeSpecial
+ version 55:0
+{
+
+public Method "<init>":"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;)V"
+ stack 3 locals 4
+{
+ aload_0;
+ invokespecial Method java/lang/Object."<init>":"()V";
+ getstatic Field java/lang/System.out:"Ljava/io/PrintStream;";
+ ldc String "In CondyNewInvokeSpecial <init> method";
+ invokevirtual Method java/io/PrintStream.println:"(Ljava/lang/String;)V";
+ return;
+}
+
+public static Method main:"([Ljava/lang/String;)V"
+ stack 3 locals 1
+{
+ new class CondyNewInvokeSpecial;
+ dup;
+ ldc Dynamic REF_newInvokeSpecial:CondyNewInvokeSpecial."<init>":"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;)V":CondyNewInvokeSpecial:"Ljava/lang/Object;";
+ return;
+}
+
+} // end Class CondyNewInvokeSpecial
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/condy/CondyNewInvokeSpecialTest.java Thu Feb 15 16:16:17 2018 +0100
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8186211
+ * @summary Test CONSTANT_Dynamic where the BSM is invoked via a REF_newInvokeSpecial.
+ * @requires os.arch != "sparcv9"
+ * @modules java.base/jdk.internal.misc
+ * @library /test/lib
+ * @compile CondyNewInvokeSpecial.jasm
+ * @run main/othervm -Xverify:all CondyNewInvokeSpecialTest
+ */
+
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.compiler.InMemoryJavaCompiler;
+
+public class CondyNewInvokeSpecialTest {
+ public static void main(String args[]) throws Throwable {
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("CondyNewInvokeSpecial");
+ OutputAnalyzer oa = new OutputAnalyzer(pb.start());
+ oa.shouldContain("In CondyNewInvokeSpecial <init> method");
+ oa.shouldHaveExitValue(0);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/condy/CondyNoBSMArray.jcod Thu Feb 15 16:16:17 2018 +0100
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This test contains a CONSTANT_Dynamic_info structure but the class file contains
+ * no BootstrapMethods Attribute array. ClassFormatError expected.
+ */
+
+/*
+class CondyNoBSMArray {
+ CondyNoBSMArray() {}
+ public static Object m() {
+ // ldc Dynamic where the CONSTANT_Dynamic_info bootstrap_method_attr_index points to slot #0
+ // in the bootstrap_methods array, however the BootstrapMethods array is non-existent.
+ // Outcome -> java.lang.ClassFormatError: Missing BootstrapMethods attribute in class file CondyNoBSMArray
+ return of ldc's Object;
+ public static void main(String[] args) { return; }
+}
+*/
+
+class CondyNoBSMArray {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Utf8 "java/lang/Object"; // #1
+ class #1; // #2
+ Utf8 "<init>"; // #3
+ Utf8 "()V"; // #4
+ NameAndType #3 #4; // #5
+ Method #2 #5; // #6
+ Utf8 "Code"; // #7
+ Utf8 "CondyNoBSMArray"; // #8
+ class #8; // #9
+ Utf8 "bsm"; // #10
+ Utf8 "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/Object;"; // #11
+ NameAndType #10 #11; // #12
+ Method #9 #12; // #13
+ MethodHandle 6b #13; // #14
+ Utf8 "name"; // #15
+ Utf8 "Ljava/lang/Object;"; // #16
+ NameAndType #15 #16; // #17
+ Dynamic 0s #17; // #18
+ Utf8 "m"; // #19
+ Utf8 "()Ljava/lang/Object;"; // #20
+ Utf8 "main"; // #21
+ Utf8 "([Ljava/lang/String;)V"; // #22
+ Utf8 "BootstrapMethods"; // #23
+ Utf8 "CondyNoBSMArray"; // #24
+ class #24; // #25
+ } // Constant Pool
+
+ 0x0000; // access
+ #25;// this_cpx
+ #2;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0001; // access
+ #3; // name_cpx
+ #4; // sig_cpx
+ [] { // Attributes
+ Attr(#7) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70006B1;
+ }
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #19; // name_cpx
+ #20; // sig_cpx
+ [] { // Attributes
+ Attr(#7) { // Code
+ 1; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0x1212B0;
+ }
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #21; // name_cpx
+ #22; // sig_cpx
+ [] { // Attributes
+ Attr(#7) { // Code
+ 0; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0xB1;
+ }
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ } // Attributes
+} // end class CondyNoBSMArray
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/condy/CondyUseLDC_W.jasm Thu Feb 15 16:16:17 2018 +0100
@@ -0,0 +1,307 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This test contains ldc_w instructions of condy's who generate dynamic constants
+ * of the following types: byte, char, short, int, float, boolean.
+ */
+class CondyUseLDC_W
+ version 55:0
+{
+
+public Method "<init>":"()V"
+ stack 1 locals 1
+{
+ aload_0;
+ invokespecial Method java/lang/Object."<init>":"()V";
+ return;
+}
+
+public static Method intConversion:"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;I)Ljava/lang/Object;"
+ throws java/lang/Throwable
+ stack 4 locals 6
+{
+ aload_1;
+ astore 4;
+ iconst_m1;
+ istore 5;
+ aload 4;
+ invokevirtual Method java/lang/String.hashCode:"()I";
+ lookupswitch{ //11
+ -2001159796: L238;
+ -1538095928: L272;
+ -891985903: L255;
+ 66: L108;
+ 67: L124;
+ 68: L140;
+ 70: L156;
+ 73: L172;
+ 74: L188;
+ 83: L204;
+ 90: L221;
+ default: L286 };
+ L108: stack_frame_type append;
+ locals_map class java/lang/String, int;
+ aload 4;
+ ldc String "B";
+ invokevirtual Method java/lang/String.equals:"(Ljava/lang/Object;)Z";
+ ifeq L286;
+ iconst_0;
+ istore 5;
+ goto L286;
+ L124: stack_frame_type same;
+ aload 4;
+ ldc String "C";
+ invokevirtual Method java/lang/String.equals:"(Ljava/lang/Object;)Z";
+ ifeq L286;
+ iconst_1;
+ istore 5;
+ goto L286;
+ L140: stack_frame_type same;
+ aload 4;
+ ldc String "D";
+ invokevirtual Method java/lang/String.equals:"(Ljava/lang/Object;)Z";
+ ifeq L286;
+ iconst_2;
+ istore 5;
+ goto L286;
+ L156: stack_frame_type same;
+ aload 4;
+ ldc String "F";
+ invokevirtual Method java/lang/String.equals:"(Ljava/lang/Object;)Z";
+ ifeq L286;
+ iconst_3;
+ istore 5;
+ goto L286;
+ L172: stack_frame_type same;
+ aload 4;
+ ldc String "I";
+ invokevirtual Method java/lang/String.equals:"(Ljava/lang/Object;)Z";
+ ifeq L286;
+ iconst_4;
+ istore 5;
+ goto L286;
+ L188: stack_frame_type same;
+ aload 4;
+ ldc String "J";
+ invokevirtual Method java/lang/String.equals:"(Ljava/lang/Object;)Z";
+ ifeq L286;
+ iconst_5;
+ istore 5;
+ goto L286;
+ L204: stack_frame_type same;
+ aload 4;
+ ldc String "S";
+ invokevirtual Method java/lang/String.equals:"(Ljava/lang/Object;)Z";
+ ifeq L286;
+ bipush 6;
+ istore 5;
+ goto L286;
+ L221: stack_frame_type same;
+ aload 4;
+ ldc String "Z";
+ invokevirtual Method java/lang/String.equals:"(Ljava/lang/Object;)Z";
+ ifeq L286;
+ bipush 7;
+ istore 5;
+ goto L286;
+ L238: stack_frame_type same;
+ aload 4;
+ ldc String "nullRef";
+ invokevirtual Method java/lang/String.equals:"(Ljava/lang/Object;)Z";
+ ifeq L286;
+ bipush 8;
+ istore 5;
+ goto L286;
+ L255: stack_frame_type same;
+ aload 4;
+ ldc String "string";
+ invokevirtual Method java/lang/String.equals:"(Ljava/lang/Object;)Z";
+ ifeq L286;
+ bipush 9;
+ istore 5;
+ goto L286;
+ L272: stack_frame_type same;
+ aload 4;
+ ldc String "stringArray";
+ invokevirtual Method java/lang/String.equals:"(Ljava/lang/Object;)Z";
+ ifeq L286;
+ bipush 10;
+ istore 5;
+ L286: stack_frame_type same;
+ iload 5;
+ tableswitch{ //0 to 10
+ 0: L348;
+ 1: L354;
+ 2: L360;
+ 3: L366;
+ 4: L372;
+ 5: L377;
+ 6: L383;
+ 7: L389;
+ 8: L402;
+ 9: L404;
+ 10: L407;
+ default: L422 };
+ L348: stack_frame_type same;
+ iload_3;
+ i2b;
+ invokestatic Method java/lang/Byte.valueOf:"(B)Ljava/lang/Byte;";
+ areturn;
+ L354: stack_frame_type same;
+ iload_3;
+ i2c;
+ invokestatic Method java/lang/Character.valueOf:"(C)Ljava/lang/Character;";
+ areturn;
+ L360: stack_frame_type same;
+ iload_3;
+ i2d;
+ invokestatic Method java/lang/Double.valueOf:"(D)Ljava/lang/Double;";
+ areturn;
+ L366: stack_frame_type same;
+ iload_3;
+ i2f;
+ invokestatic Method java/lang/Float.valueOf:"(F)Ljava/lang/Float;";
+ areturn;
+ L372: stack_frame_type same;
+ iload_3;
+ invokestatic Method java/lang/Integer.valueOf:"(I)Ljava/lang/Integer;";
+ areturn;
+ L377: stack_frame_type same;
+ iload_3;
+ i2l;
+ invokestatic Method java/lang/Long.valueOf:"(J)Ljava/lang/Long;";
+ areturn;
+ L383: stack_frame_type same;
+ iload_3;
+ i2s;
+ invokestatic Method java/lang/Short.valueOf:"(S)Ljava/lang/Short;";
+ areturn;
+ L389: stack_frame_type same;
+ iload_3;
+ ifle L397;
+ iconst_1;
+ goto L398;
+ L397: stack_frame_type same;
+ iconst_0;
+ L398: stack_frame_type stack1;
+ stack_map int;
+ invokestatic Method java/lang/Boolean.valueOf:"(Z)Ljava/lang/Boolean;";
+ areturn;
+ L402: stack_frame_type same;
+ aconst_null;
+ areturn;
+ L404: stack_frame_type same;
+ ldc String "string";
+ areturn;
+ L407: stack_frame_type same;
+ iconst_2;
+ anewarray class java/lang/String;
+ dup;
+ iconst_0;
+ ldc String "string";
+ aastore;
+ dup;
+ iconst_1;
+ ldc String "string";
+ aastore;
+ areturn;
+ L422: stack_frame_type same;
+ new class java/lang/BootstrapMethodError;
+ dup;
+ ldc String "Failure to generate a dynamic constant";
+ invokespecial Method java/lang/BootstrapMethodError."<init>":"(Ljava/lang/String;)V";
+ athrow;
+}
+
+public static Method B:"()B"
+ stack 1 locals 0
+{
+ ldc_w Dynamic REF_invokeStatic:CondyUseLDC_W.intConversion:"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;I)Ljava/lang/Object;":B:"B" int 127;
+ ireturn;
+}
+
+public static Method C:"()C"
+ stack 1 locals 0
+{
+ ldc_w Dynamic REF_invokeStatic:CondyUseLDC_W.intConversion:"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;I)Ljava/lang/Object;":C:"C" int 65535;
+ ireturn;
+}
+
+public static Method F:"()F"
+ stack 1 locals 0
+{
+ ldc_w Dynamic REF_invokeStatic:CondyUseLDC_W.intConversion:"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;I)Ljava/lang/Object;":F:"F" int 2147483647;
+ freturn;
+}
+
+public static Method F_AsType:"()F"
+ stack 1 locals 0
+{
+ ldc_w Dynamic REF_invokeStatic:CondyUseLDC_W.intConversion:"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;I)Ljava/lang/Object;":I:"F" int 2147483647;
+ freturn;
+}
+
+public static Method I:"()I"
+ stack 1 locals 0
+{
+ ldc_w Dynamic REF_invokeStatic:CondyUseLDC_W.intConversion:"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;I)Ljava/lang/Object;":I:"I" int 2147483647;
+ ireturn;
+}
+
+public static Method S:"()S"
+ stack 1 locals 0
+{
+ ldc_w Dynamic REF_invokeStatic:CondyUseLDC_W.intConversion:"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;I)Ljava/lang/Object;":S:"S" int 32767;
+ ireturn;
+}
+
+public static Method Z_F:"()Z"
+ stack 1 locals 0
+{
+ ldc_w Dynamic REF_invokeStatic:CondyUseLDC_W.intConversion:"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;I)Ljava/lang/Object;":Z:"Z" int 0;
+ ireturn;
+}
+
+public static Method Z_T:"()Z"
+ stack 1 locals 0
+{
+ ldc_w Dynamic REF_invokeStatic:CondyUseLDC_W.intConversion:"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;I)Ljava/lang/Object;":Z:"Z" int 1;
+ ireturn;
+}
+
+public static Method main:"([Ljava/lang/String;)V"
+ stack 8 locals 1
+{
+ invokestatic Method B:"()B";
+ invokestatic Method C:"()C";
+ invokestatic Method S:"()S";
+ invokestatic Method F:"()F";
+ invokestatic Method F_AsType:"()F";
+ invokestatic Method Z_F:"()Z";
+ invokestatic Method Z_T:"()Z";
+ invokestatic Method I:"()I";
+ return;
+}
+
+} // end Class CondyUseLDC_W
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/condy/CondyUsesIndyBSM.jcod Thu Feb 15 16:16:17 2018 +0100
@@ -0,0 +1,332 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This test contains a CONSTANT_Dynamic_info structure whose bootstrap_method_attr_index
+ * points to a BSM for an invokedynamic. Both the condy & indy point at element 0 in the
+ * bootstrap methods array. BootstrapMethodError expected.
+ */
+
+/*
+class CondyUsesIndyBSM {
+ CondyUsesIndyBSM() { }
+ public static Object Condybsm(java.lang.invoke.MethodHandles$Lookup, java.lang.String, java.lang.Class) {
+ System.out.println("In Condybsm");
+ return String(0);
+ }
+ public static int foo() {
+ System.out.println("In Indybsm target CallSite method foo");
+ return 100;
+ }
+ public static MethodHandle MH_foo() {
+ // Constructs a MethodHandle for foo
+ Lookup lookup = MethodHandles.lookup();
+ MethodType mt = MethodType.methodType(int.class);
+ return lookup.findStatic(CondyUsesIndyBSM.class, "foo", mt);
+ }
+ public static CallSite Indybsm(java.lang.invoke.MethodHandles$Lookup, java.lang.String, java.lang.invoke.MethodType) {
+ return new CallSite(CondyUsesIndyBSM.MH_foo());
+ }
+ public static Object m() {
+ // invokedynamic where the BSM = slot #0 in the BootstrapMethods array is CondyUsesIndyBSM.Indybsm() -> succeeds
+ // ldc_w dynamic where the BSM = slot #0 in the BootstrapMethods array is CondyUsesIndyBSM.Indybsm() -> receives a BootstrapMethodError
+ return of ldc's Object;
+ }
+ public static void main(String[] args) {
+ CondyUsesIndyBSM.m();
+ return;
+ }
+
+BootstrapMethods:
+ 0: #70 REF_invokeStatic CondyUsesIndyBSM.Indybsm:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
+ Method arguments:
+ 1: #75 REF_invokeStatic CondyUsesIndyBSM.Condybsm:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/Object;
+ Method arguments:
+}
+*/
+
+class CondyUsesIndyBSM {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Utf8 "java/lang/Object"; // #1
+ class #1; // #2
+ Utf8 "<init>"; // #3
+ Utf8 "()V"; // #4
+ NameAndType #3 #4; // #5
+ Method #2 #5; // #6
+ Utf8 "Code"; // #7
+ Utf8 "java/lang/System"; // #8
+ class #8; // #9
+ Utf8 "out"; // #10
+ Utf8 "Ljava/io/PrintStream;"; // #11
+ NameAndType #10 #11; // #12
+ Field #9 #12; // #13
+ Utf8 "In Condybsm"; // #14
+ String #14; // #15
+ Utf8 "java/io/PrintStream"; // #16
+ class #16; // #17
+ Utf8 "println"; // #18
+ Utf8 "(Ljava/lang/String;)V"; // #19
+ NameAndType #18 #19; // #20
+ Method #17 #20; // #21
+ Utf8 "0"; // #22
+ String #22; // #23
+ Utf8 "Condybsm"; // #24
+ Utf8 "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/Object;"; // #25
+ Utf8 "In Indybsm target CallSite method foo"; // #26
+ String #26; // #27
+ Utf8 "foo"; // #28
+ Utf8 "()I"; // #29
+ Utf8 "java/lang/invoke/MethodHandles"; // #30
+ class #30; // #31
+ Utf8 "lookup"; // #32
+ Utf8 "()Ljava/lang/invoke/MethodHandles$Lookup;"; // #33
+ NameAndType #32 #33; // #34
+ Method #31 #34; // #35
+ Utf8 "CondyUsesIndyBSM"; // #36
+ class #36; // #37
+ String #28; // #38
+ Utf8 "java/lang/Integer"; // #39
+ class #39; // #40
+ Utf8 "TYPE"; // #41
+ Utf8 "Ljava/lang/Class;"; // #42
+ NameAndType #41 #42; // #43
+ Field #40 #43; // #44
+ Utf8 "java/lang/invoke/MethodType"; // #45
+ class #45; // #46
+ Utf8 "methodType"; // #47
+ Utf8 "(Ljava/lang/Class;)Ljava/lang/invoke/MethodType;"; // #48
+ NameAndType #47 #48; // #49
+ Method #46 #49; // #50
+ Utf8 "java/lang/invoke/MethodHandles$Lookup"; // #51
+ class #51; // #52
+ Utf8 "findStatic"; // #53
+ Utf8 "(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;"; // #54
+ NameAndType #53 #54; // #55
+ Method #52 #55; // #56
+ Utf8 "MH_foo"; // #57
+ Utf8 "()Ljava/lang/invoke/MethodHandle;"; // #58
+ Utf8 "java/lang/invoke/ConstantCallSite"; // #59
+ class #59; // #60
+ NameAndType #57 #58; // #61
+ Method #37 #61; // #62
+ Utf8 "(Ljava/lang/invoke/MethodHandle;)V"; // #63
+ NameAndType #3 #63; // #64
+ Method #60 #64; // #65
+ Utf8 "Indybsm"; // #66
+ Utf8 "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"; // #67
+ NameAndType #66 #67; // #68
+ Method #37 #68; // #69
+ MethodHandle 6b #69; // #70
+ NameAndType #28 #29; // #71
+ InvokeDynamic 0s #71; // #72
+ NameAndType #24 #25; // #73
+ Method #37 #73; // #74
+ MethodHandle 6b #74; // #75
+ Utf8 "name"; // #76
+ Utf8 "Ljava/lang/Object;"; // #77
+ NameAndType #76 #77; // #78
+ Dynamic 0s #78; // #79
+ Utf8 "m"; // #80
+ Utf8 "()Ljava/lang/Object;"; // #81
+ NameAndType #80 #81; // #82
+ Method #37 #82; // #83
+ Utf8 "main"; // #84
+ Utf8 "([Ljava/lang/String;)V"; // #85
+ Utf8 "BootstrapMethods"; // #86
+ Utf8 "CondyUsesIndyBSM"; // #87
+ class #87; // #88
+ } // Constant Pool
+
+ 0x0000; // access
+ #88;// this_cpx
+ #2;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0001; // access
+ #3; // name_cpx
+ #4; // sig_cpx
+ [] { // Attributes
+ Attr(#7) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70006B1;
+ }
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #24; // name_cpx
+ #25; // sig_cpx
+ [] { // Attributes
+ Attr(#7) { // Code
+ 2; // max_stack
+ 3; // max_locals
+ Bytes[]{
+ 0xB2000D120FB60015;
+ 0x1217B0;
+ }
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #28; // name_cpx
+ #29; // sig_cpx
+ [] { // Attributes
+ Attr(#7) { // Code
+ 2; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0xB2000D121BB60015;
+ 0x1064AC;
+ }
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #57; // name_cpx
+ #58; // sig_cpx
+ [] { // Attributes
+ Attr(#7) { // Code
+ 4; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0xB8002312251226B2;
+ 0x002CB80032B60038;
+ 0xB0;
+ }
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #66; // name_cpx
+ #67; // sig_cpx
+ [] { // Attributes
+ Attr(#7) { // Code
+ 3; // max_stack
+ 3; // max_locals
+ Bytes[]{
+ 0xBB003C59B8003EB7;
+ 0x0041B0;
+ }
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #80; // name_cpx
+ #81; // sig_cpx
+ [] { // Attributes
+ Attr(#7) { // Code
+ 2; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0xBA0048000013004F;
+ 0xB0;
+ }
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #84; // name_cpx
+ #85; // sig_cpx
+ [] { // Attributes
+ Attr(#7) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0xB80053B1;
+ }
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#86) { // BootstrapMethods
+ [] { // bootstrap_methods
+ { // bootstrap_method
+ #70; // bootstrap_method_ref
+ [] { // bootstrap_arguments
+ } // bootstrap_arguments
+ } // bootstrap_method
+ ;
+ { // bootstrap_method
+ #75; // bootstrap_method_ref
+ [] { // bootstrap_arguments
+ } // bootstrap_arguments
+ } // bootstrap_method
+ }
+ } // end BootstrapMethods
+ } // Attributes
+} // end class CondyUsesIndyBSM
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/condy/IndyUsesCondyBSM.jcod Thu Feb 15 16:16:17 2018 +0100
@@ -0,0 +1,335 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This test contains a CONSTANT_InvokeDynamic_info structure whose bootstrap_method_attr_index
+ * points to a BSM for an CONSTANT_Dynamic. Both the condy & indy point at element 0 in the
+ * bootstrap methods array. BootstrapMethodError expected.
+ */
+
+/*
+class IndyUsesCondyBSM {
+ IndyUsesCondyBSM() { }
+ public static Object Condybsm(java.lang.invoke.MethodHandles$Lookup, java.lang.String, java.lang.Class) {
+ System.out.println("In Condybsm");
+ return String(0);
+ }
+ public static int foo() {
+ System.out.println("In Indybsm target CallSite method foo");
+ return 100;
+ }
+ public static MethodHandle MH_foo() {
+ // Constructs a MethodHandle for foo
+ Lookup lookup = MethodHandles.lookup();
+ MethodType mt = MethodType.methodType(int.class);
+ return lookup.findStatic(IndyUsesCondyBSM.class, "foo", mt);
+ }
+ public static CallSite Indybsm(java.lang.invoke.MethodHandles$Lookup, java.lang.String, java.lang.invoke.MethodType) {
+ return new CallSite(IndyUsesCondyBSM.MH_foo());
+ }
+ public static int m() {
+ // ldc_w dynamic where the BSM = slot #0 in the BootstrapMethods array is IndyUsesCondyBSM.Condybsm() -> succeeds
+ // invokedynamic where the BSM = slot #0 in the BootstrapMethods array is IndyUsesCondyBSM.Condybsm() -> receives a BootstrapMethodError
+ return Callsite.foo();
+ }
+ public static void main(String[] args) {
+ IndyUsesCondyBSM.m();
+ return;
+ }
+
+BootstrapMethods:
+ 0: #65 REF_invokeStatic IndyUsesCondyBSM.Condybsm:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/Object;
+ Method arguments:
+ 1: #74 REF_invokeStatic IndyUsesCondyBSM.Indybsm:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
+ Method arguments:
+}
+*/
+
+class IndyUsesCondyBSM {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [88] { // Constant Pool
+ ; // first element is empty
+ String #48; // #1 at 0x0A
+ String #49; // #2 at 0x0D
+ String #56; // #3 at 0x10
+ String #58; // #4 at 0x13
+ class #51; // #5 at 0x16
+ Method #62 #20; // #6 at 0x19
+ InvokeDynamic 0s #53; // #7 at 0x1E
+ Method #5 #71; // #8 at 0x23
+ Method #26 #47; // #9 at 0x28
+ Field #21 #86; // #10 at 0x2D
+ Method #28 #75; // #11 at 0x32
+ Field #61 #82; // #12 at 0x37
+ Method #18 #36; // #13 at 0x3C
+ Method #29 #46; // #14 at 0x41
+ Method #57 #87; // #15 at 0x46
+ Method #5 #73; // #16 at 0x4B
+ Dynamic 0s #23; // #17 at 0x50
+ class #80; // #18 at 0x55
+ Utf8 "java/io/PrintStream"; // #19 at 0x58
+ NameAndType #81 #59; // #20 at 0x6E
+ class #85; // #21 at 0x73
+ Utf8 "java/lang/invoke/MethodType"; // #22 at 0x76
+ NameAndType #31 #77; // #23 at 0x94
+ Utf8 "m"; // #24 at 0x99
+ Utf8 "java/lang/invoke/MethodHandles$Lookup"; // #25 at 0x9D
+ class #19; // #26 at 0xC5
+ Utf8 "SourceFile"; // #27 at 0xC8
+ class #22; // #28 at 0xD5
+ class #25; // #29 at 0xD8
+ Utf8 "IndyUsesCondyBSM.jasm"; // #30 at 0xDB
+ Utf8 "name"; // #31 at 0xF3
+ Utf8 "Indybsm"; // #32 at 0xFA
+ Utf8 "findStatic"; // #33 at 0x0104
+ Utf8 "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/Object;"; // #34 at 0x0111
+ Utf8 "()Ljava/lang/invoke/MethodHandles$Lookup;"; // #35 at 0x0172
+ NameAndType #81 #66; // #36 at 0x019E
+ Utf8 "MH_foo"; // #37 at 0x01A3
+ Method #5 #84; // #38 at 0x01AC
+ Utf8 "Code"; // #39 at 0x01B1
+ Utf8 "lookup"; // #40 at 0x01B8
+ Utf8 "([Ljava/lang/String;)V"; // #41 at 0x01C1
+ Utf8 "out"; // #42 at 0x01DA
+ Utf8 "BootstrapMethods"; // #43 at 0x01E0
+ Utf8 "(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;"; // #44 at 0x01F3
+ Utf8 "Ljava/lang/Class;"; // #45 at 0x0257
+ NameAndType #33 #44; // #46 at 0x026B
+ NameAndType #52 #63; // #47 at 0x0270
+ Utf8 "0"; // #48 at 0x0275
+ Utf8 "In Condybsm"; // #49 at 0x0279
+ Utf8 "java/lang/invoke/MethodHandles"; // #50 at 0x0287
+ Utf8 "IndyUsesCondyBSM"; // #51 at 0x02A8
+ Utf8 "println"; // #52 at 0x02BB
+ NameAndType #58 #67; // #53 at 0x02C5
+ Utf8 "java/lang/Object"; // #54 at 0x02CA
+ Utf8 "java/lang/System"; // #55 at 0x02DD
+ Utf8 "In Indybsm target CallSite method foo"; // #56 at 0x02F0
+ class #50; // #57 at 0x0318
+ Utf8 "foo"; // #58 at 0x031B
+ Utf8 "()V"; // #59 at 0x0321
+ Utf8 "()Ljava/lang/invoke/MethodHandle;"; // #60 at 0x0327
+ class #55; // #61 at 0x034B
+ class #54; // #62 at 0x034E
+ Utf8 "(Ljava/lang/String;)V"; // #63 at 0x0351
+ Utf8 "main"; // #64 at 0x0369
+ MethodHandle 6b #79; // #65 at 0x0370
+ Utf8 "(Ljava/lang/invoke/MethodHandle;)V"; // #66 at 0x0374
+ Utf8 "()I"; // #67 at 0x0399
+ Utf8 "(Ljava/lang/Class;)Ljava/lang/invoke/MethodType;"; // #68 at 0x039F
+ Utf8 "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"; // #69 at 0x03D2
+ Utf8 "Condybsm"; // #70 at 0x0448
+ NameAndType #37 #60; // #71 at 0x0453
+ NameAndType #70 #34; // #72 at 0x0458
+ NameAndType #24 #67; // #73 at 0x045D
+ MethodHandle 6b #38; // #74 at 0x0462
+ NameAndType #78 #68; // #75 at 0x0466
+ Utf8 "Ljava/io/PrintStream;"; // #76 at 0x046B
+ Utf8 "Ljava/lang/Object;"; // #77 at 0x0483
+ Utf8 "methodType"; // #78 at 0x0498
+ Method #5 #72; // #79 at 0x04A5
+ Utf8 "java/lang/invoke/ConstantCallSite"; // #80 at 0x04AA
+ Utf8 "<init>"; // #81 at 0x04CE
+ NameAndType #42 #76; // #82 at 0x04D7
+ Utf8 "TYPE"; // #83 at 0x04DC
+ NameAndType #32 #69; // #84 at 0x04E3
+ Utf8 "java/lang/Integer"; // #85 at 0x04E8
+ NameAndType #83 #45; // #86 at 0x04FC
+ NameAndType #40 #35; // #87 at 0x0501
+ } // Constant Pool
+
+ 0x0000; // access [ ]
+ #5;// this_cpx
+ #62;// super_cpx
+
+ [0] { // Interfaces
+ } // Interfaces
+
+ [0] { // fields
+ } // fields
+
+ [7] { // methods
+ { // Member at 0x0512
+ 0x0001; // access
+ #81; // name_cpx
+ #59; // sig_cpx
+ [1] { // Attributes
+ Attr(#39, 17) { // Code at 0x051A
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[5]{
+ 0x2AB70006B1;
+ }
+ [0] { // Traps
+ } // end Traps
+ [0] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member at 0x0531
+ 0x0009; // access
+ #70; // name_cpx
+ #34; // sig_cpx
+ [1] { // Attributes
+ Attr(#39, 23) { // Code at 0x0539
+ 2; // max_stack
+ 3; // max_locals
+ Bytes[11]{
+ 0xB2000C1202B60009;
+ 0x1201B0;
+ }
+ [0] { // Traps
+ } // end Traps
+ [0] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member at 0x0556
+ 0x0009; // access
+ #58; // name_cpx
+ #67; // sig_cpx
+ [1] { // Attributes
+ Attr(#39, 23) { // Code at 0x055E
+ 2; // max_stack
+ 0; // max_locals
+ Bytes[11]{
+ 0xB2000C1203B60009;
+ 0x1064AC;
+ }
+ [0] { // Traps
+ } // end Traps
+ [0] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member at 0x057B
+ 0x0009; // access
+ #37; // name_cpx
+ #60; // sig_cpx
+ [1] { // Attributes
+ Attr(#39, 29) { // Code at 0x0583
+ 4; // max_stack
+ 0; // max_locals
+ Bytes[17]{
+ 0xB8000F12051204B2;
+ 0x000AB8000BB6000E;
+ 0xB0;
+ }
+ [0] { // Traps
+ } // end Traps
+ [0] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member at 0x05A6
+ 0x0009; // access
+ #32; // name_cpx
+ #69; // sig_cpx
+ [1] { // Attributes
+ Attr(#39, 23) { // Code at 0x05AE
+ 3; // max_stack
+ 3; // max_locals
+ Bytes[11]{
+ 0xBB001259B80008B7;
+ 0x000DB0;
+ }
+ [0] { // Traps
+ } // end Traps
+ [0] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member at 0x05CB
+ 0x0009; // access
+ #24; // name_cpx
+ #67; // sig_cpx
+ [1] { // Attributes
+ Attr(#39, 21) { // Code at 0x05D3
+ 2; // max_stack
+ 0; // max_locals
+ Bytes[9]{
+ 0x130011BA00070000;
+ 0xAC;
+ }
+ [0] { // Traps
+ } // end Traps
+ [0] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member at 0x05EE
+ 0x0009; // access
+ #64; // name_cpx
+ #41; // sig_cpx
+ [1] { // Attributes
+ Attr(#39, 16) { // Code at 0x05F6
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[4]{
+ 0xB80010B1;
+ }
+ [0] { // Traps
+ } // end Traps
+ [0] { // Attributes
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [2] { // Attributes
+ Attr(#27, 2) { // SourceFile at 0x060E
+ #30;
+ } // end SourceFile
+ ;
+ Attr(#43, 10) { // BootstrapMethods at 0x0616
+ [2] { // bootstrap_methods
+ { // bootstrap_method
+ #65; // bootstrap_method_ref
+ [0] { // bootstrap_arguments
+ } // bootstrap_arguments
+ } // bootstrap_method
+ ;
+ { // bootstrap_method
+ #74; // bootstrap_method_ref
+ [0] { // bootstrap_arguments
+ } // bootstrap_arguments
+ } // bootstrap_method
+ }
+ } // end BootstrapMethods
+ } // Attributes
+} // end class IndyUsesCondyBSM
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/containers/docker/Dockerfile-BasicTest-s390x Thu Feb 15 16:16:17 2018 +0100
@@ -0,0 +1,7 @@
+FROM s390x/ubuntu
+
+COPY /jdk /jdk
+
+ENV JAVA_HOME=/jdk
+
+CMD ["/bin/bash"]
--- a/test/hotspot/jtreg/runtime/containers/docker/TestCPUSets.java Thu Feb 15 00:25:01 2018 -0800
+++ b/test/hotspot/jtreg/runtime/containers/docker/TestCPUSets.java Thu Feb 15 16:16:17 2018 +0100
@@ -26,6 +26,7 @@
* @test
* @summary Test JVM's awareness of cpu sets (cpus and mems)
* @requires docker.support
+ * @requires (os.arch != "s390x")
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
--- a/test/hotspot/jtreg/serviceability/sa/ClhsdbLauncher.java Thu Feb 15 00:25:01 2018 -0800
+++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbLauncher.java Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -41,7 +41,7 @@
private Process toolProcess;
- public void ClhsdbLauncher() {
+ public ClhsdbLauncher() {
toolProcess = null;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbPrintAll.java Thu Feb 15 16:16:17 2018 +0100
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import jdk.test.lib.apps.LingeredApp;
+
+/*
+ * @test
+ * @bug 8175384
+ * @summary Test clhsdb 'printall' command
+ * @library /test/lib
+ * @run main/othervm/timeout=2400 -Xmx1g ClhsdbPrintAll
+ */
+
+public class ClhsdbPrintAll {
+
+ public static void main(String[] args) throws Exception {
+ System.out.println("Starting ClhsdbPrintAll test");
+
+ LingeredAppWithEnum theApp = null;
+ try {
+ ClhsdbLauncher test = new ClhsdbLauncher();
+
+ theApp = new LingeredAppWithEnum();
+ LingeredApp.startApp(null, theApp);
+ System.out.println("Started LingeredAppWithEnum with pid " + theApp.getPid());
+
+ List<String> cmds = List.of("printall");
+
+ Map<String, List<String>> expStrMap = new HashMap<>();
+ Map<String, List<String>> unExpStrMap = new HashMap<>();
+ expStrMap.put("printall", List.of(
+ "aload_0",
+ "Constant Pool of",
+ "public static void main(java.lang.String[])",
+ "Bytecode",
+ "[enum] class Song [signature Ljava/lang/Enum<LSong;>;]",
+ "Method java.lang.Object clone()",
+ "public static Song[] values()",
+ "invokevirtual",
+ "checkcast",
+ "Field Song HAVANA",
+ "Exception Table",
+ "invokedynamic"));
+ unExpStrMap.put("printall", List.of(
+ "cannot be cast to"));
+ test.run(theApp.getPid(), cmds, expStrMap, unExpStrMap);
+ } catch (Exception ex) {
+ throw new RuntimeException("Test ERROR " + ex, ex);
+ } finally {
+ LingeredApp.stopApp(theApp);
+ }
+ System.out.println("Test PASSED");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/sa/LingeredAppWithEnum.java Thu Feb 15 16:16:17 2018 +0100
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import jdk.test.lib.apps.LingeredApp;
+
+enum Song {
+ HALL_OF_FAME,
+ HAVANA
+};
+
+public class LingeredAppWithEnum extends LingeredApp {
+
+ public static void main(String args[]) {
+ for (Song s : Song.values()) {
+ System.out.println ("song " + s);
+ }
+ LingeredApp.main(args);
+ }
+ }
--- a/test/jdk/ProblemList.txt Thu Feb 15 00:25:01 2018 -0800
+++ b/test/jdk/ProblemList.txt Thu Feb 15 16:16:17 2018 +0100
@@ -282,6 +282,9 @@
java/lang/String/nativeEncoding/StringPlatformChars.java 8182569 windows-all,solaris-all
+java/lang/invoke/condy/CondyRepeatFailedResolution.java 8197944 windows-all
+java/lang/invoke/condy/CondyReturnPrimitiveTest.java 8197944 windows-all
+
############################################################################
# jdk_instrument
@@ -482,6 +485,8 @@
com/sun/jdi/sde/SourceDebugExtensionTest.java 8158066 windows-all
+com/sun/jdi/NashornPopFrameTest.java 8187143 generic-all
+
############################################################################
# jdk_time
--- a/test/jdk/com/sun/jdi/AllLineLocations.java Thu Feb 15 00:25:01 2018 -0800
+++ b/test/jdk/com/sun/jdi/AllLineLocations.java Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -27,7 +27,7 @@
* @summary Test ReferenceType.allLineLocations
* @author Gordon Hirsch
*
- * @run build JDIScaffold VMConnection
+ * @run build TestScaffold VMConnection
* @run compile -g RefTypes.java
* @run build AllLineLocations
*
@@ -39,26 +39,22 @@
import java.util.List;
-public class AllLineLocations extends JDIScaffold {
- final String[] args;
+public class AllLineLocations extends TestScaffold {
public static void main(String args[]) throws Exception {
new AllLineLocations(args).startTests();
}
AllLineLocations(String args[]) {
- super();
- this.args = args;
+ super(args);
}
protected void runTests() throws Exception {
- connect(args);
- waitForVMStart();
/*
* Get to a point where the classes are loaded.
*/
- BreakpointEvent bp = resumeTo("RefTypes", "loadClasses", "()V");
+ BreakpointEvent bp = startTo("RefTypes", "loadClasses", "()V");
stepOut(bp.thread());
/*
@@ -220,6 +216,6 @@
System.out.println("AbstractAndNative: passed");
// Allow application to complete
- resumeToVMDeath();
+ resumeToVMDisconnect();
}
}
--- a/test/jdk/com/sun/jdi/ClassesByName.java Thu Feb 15 00:25:01 2018 -0800
+++ b/test/jdk/com/sun/jdi/ClassesByName.java Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -28,7 +28,7 @@
* loaded class list can be found with classesByName..
* @author Robert Field
*
- * @run build JDIScaffold VMConnection
+ * @run build TestScaffold VMConnection
* @run compile -g HelloWorld.java
* @run build ClassesByName
*
@@ -41,21 +41,18 @@
import java.util.List;
import java.util.Iterator;
-public class ClassesByName extends JDIScaffold {
- final String[] args;
+public class ClassesByName extends TestScaffold {
public static void main(String args[]) throws Exception {
new ClassesByName(args).startTests();
}
ClassesByName(String args[]) throws Exception {
- super();
- this.args = args;
+ super(args);
}
protected void runTests() throws Exception {
- connect(args);
- waitForVMStart();
+ startUp("ClassesByName");
List all = vm().allClasses();
for (Iterator it = all.iterator(); it.hasNext(); ) {
@@ -71,6 +68,6 @@
}
// Allow application to complete
- resumeToVMDeath();
+ resumeToVMDisconnect();
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/com/sun/jdi/NashornPopFrameTest.java Thu Feb 15 16:16:17 2018 +0100
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2001, 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.
+ */
+
+/**
+ * @test
+ * @bug 8187143
+ * @summary JDI crash in ~BufferBlob::MethodHandles adapters
+ *
+ * @run build TestScaffold VMConnection TargetListener TargetAdapter
+ * @run compile -g NashornPopFrameTest.java
+ * @run driver NashornPopFrameTest
+ */
+import com.sun.jdi.*;
+import com.sun.jdi.event.*;
+import com.sun.jdi.request.*;
+
+import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
+import javax.script.*;
+
+import java.io.PrintStream;
+
+
+// The debuggee, creates and uses a Nashorn engine to evaluate a simple script.
+
+// The debugger tries to set a breakpoint in Nashorn internal DEBUGGER method.
+// When the breakpoint is reached, it looks for stack frame whose method's
+// declaring type name starts with jdk.nashorn.internal.scripts.Script$.
+// (nashorn dynamically generated classes)
+// It then pops stack frames using the ThreadReference.popFrames() call, up to
+// and including the above stackframe.
+// The execution of the debuggee application is resumed after the needed
+// frames have been popped.
+
+class ScriptDebuggee {
+ public final static int BKPT_LINE = 74;
+ static ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine();
+ static public String failReason = null;
+
+ static void doit() throws Exception {
+ System.out.println("Debugee: started!");
+ String script =
+ "function f() {\r\n" +
+ " debugger;\r\n" +
+ " debugger;\r\n" +
+ "}\r\n" +
+ "f();";
+ try {
+ engine.eval(script);
+ } catch (Exception ex) {
+ failReason = "ScriptDebuggee failed: Exception in engine.eval(): "
+ + ex.toString();
+ ex.printStackTrace();
+ }
+ System.out.println("Debugee: finished!"); // BKPT_LINE
+ }
+
+ public static void main(String[] args) throws Exception {
+ doit();
+ }
+}
+
+/********** test program **********/
+
+public class NashornPopFrameTest extends TestScaffold {
+ static PrintStream out = System.out;
+ static boolean breakpointReached = false;
+ String debuggeeFailReason = null;
+ ClassType targetClass;
+ ThreadReference mainThread;
+ BreakpointRequest bkptRequest;
+
+ NashornPopFrameTest(String args[]) {
+ super(args);
+ }
+
+ public static void main(String[] args) throws Exception {
+ NashornPopFrameTest nashornPopFrameTest = new NashornPopFrameTest(args);
+ nashornPopFrameTest.startTests();
+ }
+
+ /********** test core **********/
+
+ protected void runTests() throws Exception {
+ /*
+ * Get to the top of main() to determine targetClass and mainThread
+ */
+ BreakpointEvent bpe = startToMain("ScriptDebuggee");
+ targetClass = (ClassType)bpe.location().declaringType();
+ out.println("Agent: runTests: after startToMain()");
+
+ mainThread = bpe.thread();
+ EventRequestManager erm = vm().eventRequestManager();
+
+ Location loc = findLocation(targetClass, ScriptDebuggee.BKPT_LINE);
+
+ try {
+ addListener(this);
+ } catch (Exception ex){
+ ex.printStackTrace();
+ failure("Failed: Could not add listener");
+ throw new Exception("NashornPopFrameTest: failed with Exception in AddListener");
+ }
+
+ pauseAtDebugger(vm());
+ bkptRequest = erm.createBreakpointRequest(loc);
+ bkptRequest.enable();
+
+ vm().resume();
+
+ try {
+ listen(vm());
+ } catch (Exception exp) {
+ exp.printStackTrace();
+ failure("Failed: Caught Exception while Listening");
+ throw new Exception("NashornPopFrameTest: failed with Exception in listen()");
+ }
+
+ // Debugger continues to run until it receives a VMdisconnect event either because
+ // the Debuggee crashed / got exception / finished successfully.
+ while (!vmDisconnected) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException ee) {
+ }
+ }
+
+ removeListener(this);
+
+ if (breakpointReached) {
+ if (debuggeeFailReason != null) {
+ failure(debuggeeFailReason);
+ }
+ } else {
+ failure("Expected breakpoint in ScriptDebuggee:" +
+ ScriptDebuggee.BKPT_LINE + " was not reached");
+ }
+ if (testFailed) {
+ throw new Exception("NashornPopFrameTest: failed");
+ }
+ out.println("NashornPopFrameTest: passed");
+ }
+
+ private static void pauseAtDebugger(VirtualMachine vm) throws AbsentInformationException {
+ for (ReferenceType t : vm.allClasses()) pauseAtDebugger(t);
+ }
+
+ // Set a breakpoint in Nashorn internal DEBUGGER method.
+ private static void pauseAtDebugger(ReferenceType t) throws AbsentInformationException {
+ if (!t.name().endsWith(".ScriptRuntime")) {
+ return;
+ }
+ for (Location l : t.allLineLocations()) {
+ if (!l.method().name().equals("DEBUGGER")) continue;
+ BreakpointRequest bkptReq = t.virtualMachine().eventRequestManager().createBreakpointRequest(l);
+ out.println("Setting breakpoint for " + l);
+ bkptReq.enable();
+ break;
+ }
+ }
+
+ private static void listen(VirtualMachine vm) throws Exception {
+ EventQueue eventQueue = vm.eventQueue();
+ EventSet es = eventQueue.remove();
+ if (es != null) {
+ handle(es);
+ }
+ }
+
+ // Handle event when breakpoint is reached
+ private static void handle(EventSet eventSet) throws Exception {
+ out.println("Agent handle(): started");
+ for (Event event : eventSet) {
+ if (event instanceof BreakpointEvent) {
+ findFrameAndPop(event);
+ }
+ }
+ eventSet.resume();
+ out.println("Agent handle(): finished");
+ }
+
+ private static void findFrameAndPop(Event event) throws Exception {
+ ThreadReference thread = ((BreakpointEvent) event).thread();
+ out.println("Agent: handling Breakpoint " + " at " +
+ ((BreakpointEvent) event).location() +
+ " in thread: " + thread);
+ StackFrame sf = findScriptFrame(thread);
+ if (sf != null) {
+ out.println("Thread Pop Frame on StackFrame = " + sf);
+ thread.popFrames(sf);
+ }
+ }
+
+ // Find stack frame whose method's declaring type name starts with
+ // jdk.nashorn.internal.scripts.Script$ and return that frame
+ private static StackFrame findScriptFrame(ThreadReference t) throws IncompatibleThreadStateException {
+ for (int i = 0; i < t.frameCount(); i++) {
+ StackFrame sf = t.frame(i);
+ String typeName = sf.location().method().declaringType().name();
+ if (typeName.startsWith("jdk.nashorn.internal.scripts.Script$")) {
+ out.println("Agent: in findScriptFrame: TypeName = " + typeName);
+ return sf;
+ }
+ }
+ throw new RuntimeException("no script frame");
+ }
+
+ static int bkptCount = 0;
+
+ /********** event handlers **********/
+
+ public void breakpointReached(BreakpointEvent event) {
+ ThreadReference thread = ((BreakpointEvent) event).thread();
+ String locStr = "" + ((BreakpointEvent) event).location();
+ out.println("Agent: BreakpointEvent #" + (bkptCount++) +
+ " at " + locStr + " in thread: " + thread);
+ if (locStr.equals("ScriptDebuggee:" + ScriptDebuggee.BKPT_LINE)) {
+ breakpointReached = true;
+ Field failReasonField = targetClass.fieldByName("failReason");
+ Value failReasonVal = targetClass.getValue(failReasonField);
+ if (failReasonVal != null) {
+ debuggeeFailReason = ((StringReference)failReasonVal).value();
+ }
+ bkptRequest.disable();
+ }
+ }
+
+ public void eventSetComplete(EventSet set) {
+ set.resume();
+ }
+
+ public void vmDisconnected(VMDisconnectEvent event) {
+ println("Agent: Got VMDisconnectEvent");
+ }
+
+}
--- a/test/jdk/java/lang/invoke/condy/CondyRepeatFailedResolution.java Thu Feb 15 00:25:01 2018 -0800
+++ b/test/jdk/java/lang/invoke/condy/CondyRepeatFailedResolution.java Thu Feb 15 16:16:17 2018 +0100
@@ -25,7 +25,7 @@
* @test
* @bug 8186211
* @summary Test basic invocation of multiple ldc's of the same dynamic constant that fail resolution
- * @requires os.arch == "x86_64"
+ * @requires os.arch != "sparcv9"
* @library /lib/testlibrary/bytecode /java/lang/invoke/common
* @build jdk.experimental.bytecode.BasicClassBuilder
* @run testng CondyRepeatFailedResolution
--- a/test/jdk/java/lang/invoke/condy/CondyReturnPrimitiveTest.java Thu Feb 15 00:25:01 2018 -0800
+++ b/test/jdk/java/lang/invoke/condy/CondyReturnPrimitiveTest.java Thu Feb 15 16:16:17 2018 +0100
@@ -25,7 +25,7 @@
* @test
* @bug 8186046
* @summary Test for condy BSMs returning primitive values or null
- * @requires os.arch == "x86_64"
+ * @requires os.arch != "sparcv9"
* @library /lib/testlibrary/bytecode
* @build jdk.experimental.bytecode.BasicClassBuilder
* @run testng CondyReturnPrimitiveTest
--- a/test/jdk/java/lang/invoke/condy/CondyWrongType.java Thu Feb 15 00:25:01 2018 -0800
+++ b/test/jdk/java/lang/invoke/condy/CondyWrongType.java Thu Feb 15 16:16:17 2018 +0100
@@ -25,7 +25,7 @@
* @test
* @bug 8186046
* @summary Test bootstrap methods returning the wrong type
- * @requires os.arch == "x86_64"
+ * @requires os.arch != "sparcv9"
* @library /lib/testlibrary/bytecode /java/lang/invoke/common
* @build jdk.experimental.bytecode.BasicClassBuilder test.java.lang.invoke.lib.InstructionHelper
* @run testng CondyWrongType
--- a/test/jtreg-ext/requires/VMProps.java Thu Feb 15 00:25:01 2018 -0800
+++ b/test/jtreg-ext/requires/VMProps.java Thu Feb 15 16:16:17 2018 +0100
@@ -352,9 +352,9 @@
* @return true if docker is supported in a given environment
*/
protected String dockerSupport() {
- // currently docker testing is only supported for Linux-x64 and Linux-ppc64le
+ // currently docker testing is only supported for Linux-x64, Linux-s390x and Linux-ppc64le
String arch = System.getProperty("os.arch");
- if (! (Platform.isLinux() && (Platform.isX64() || arch.equals("ppc64le")))) {
+ if (! (Platform.isLinux() && (Platform.isX64() || Platform.isS390x() || arch.equals("ppc64le")))) {
return "false";
}
--- a/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java Thu Feb 15 00:25:01 2018 -0800
+++ b/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java Thu Feb 15 16:16:17 2018 +0100
@@ -161,7 +161,7 @@
Files.copy(dockerfile, buildDir.resolve("Dockerfile"));
// Build the docker
- execute("docker", "build", buildDir.toString(), "--no-cache", "--tag", imageName)
+ execute("docker", "build", "--no-cache", "--tag", imageName, buildDir.toString())
.shouldHaveExitValue(0)
.shouldContain("Successfully built");
}
--- a/test/lib/sun/hotspot/WhiteBox.java Thu Feb 15 00:25:01 2018 -0800
+++ b/test/lib/sun/hotspot/WhiteBox.java Thu Feb 15 16:16:17 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -541,4 +541,6 @@
public native boolean isContainerized();
public native void printOsInfo();
+ // Decoder
+ public native void disableElfSectionCache();
}