This commit is contained in:
Jesper Wilhelmsson 2018-01-13 02:56:22 +01:00
commit fc1b01b9a2
89 changed files with 1880 additions and 1482 deletions

View File

@ -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
@ -869,7 +869,6 @@ JDWP "Java(tm) Debug Wire Protocol"
"section in "
"<cite>The Java&trade; Virtual Machine Specification</cite>. "
"Since JDWP version 1.5."
"<p>
(Out
(referenceType refType "The reference type ID.")
)
@ -2723,7 +2722,6 @@ JDWP "Java(tm) Debug Wire Protocol"
"<P>"
"The events that are grouped in a composite event are restricted in the "
"following ways: "
"<P>"
"<UL>"
"<LI>Only with other thread start events for the same thread:"
" <UL>"

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2013, 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
@ -30,8 +30,8 @@ import java.io.*;
class AbstractCommandNode extends AbstractNamedNode {
void document(PrintWriter writer) {
writer.println("<h5><a name=\"" + context.whereC + "\">" + name +
" Command</a> (" + nameNode.value() + ")</h5>");
writer.println("<h5 id=\"" + context.whereC + "\">" + name +
" Command (" + nameNode.value() + ")</h5>");
writer.println(comment());
writer.println("<dl>");
for (Node node : components) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2013, 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
@ -62,8 +62,8 @@ abstract class AbstractNamedNode extends Node {
}
void document(PrintWriter writer) {
writer.println("<h4><a name=" + name + ">" + name +
" Command Set</a></h4>");
writer.println("<h4 id=\"" + name + "\">" + name +
" Command Set</h4>");
for (Node node : components) {
node.document(writer);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2013, 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
@ -43,11 +43,11 @@ abstract class AbstractTypeListNode extends AbstractNamedNode {
if (components.isEmpty()) {
writer.println("<dd>(None)");
} else {
writer.println("<dd><table border=1 cellpadding=3 cellspacing=0 width=\"90%\" summary=\"\"><tr>");
writer.println("<dd><table><tr>");
for (int i = maxStructIndent; i > 0; --i) {
writer.print("<th width=\"4%\">");
writer.print("<th style=\"width: 4%\">");
}
writer.println("<th width=\"15%\"><th width=\"65%\">");
writer.println("<th style=\"width: 15%\"><th style=\"width: 65%\">");
writer.println("");
for (Node node : components) {
node.document(writer);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2013, 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
@ -38,8 +38,8 @@ class CommandSetNode extends AbstractNamedNode {
}
void document(PrintWriter writer) {
writer.println("<h4><a name=\"" + context.whereC + "\">" + name +
" Command Set</a> (" +
writer.println("<h4 id=\"" + context.whereC + "\">" + name +
" Command Set (" +
nameNode.value() + ")</h4>");
writer.println(comment());
for (Node node : components) {
@ -51,11 +51,13 @@ class CommandSetNode extends AbstractNamedNode {
writer.print("<li><a href=\"#" + context.whereC + "\">");
writer.println(name() + "</a> Command Set (" +
nameNode.value() + ")");
writer.println("<ul>");
for (Node node : components) {
node.documentIndex(writer);
if (components.size() > 0) {
writer.println("<ul>");
for (Node node : components) {
node.documentIndex(writer);
}
writer.println("</ul>");
}
writer.println("</ul>");
}
void genJavaClassSpecifics(PrintWriter writer, int depth) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2013, 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
@ -54,15 +54,15 @@ class ConstantSetNode extends AbstractNamedNode {
}
void document(PrintWriter writer) {
writer.println("<h4><a name=\"" + context.whereC + "\">" + name +
" Constants</a></h4>");
writer.println("<h4 id=\"" + context.whereC + "\">" + name +
" Constants</h4>");
writer.println(comment());
writer.println("<dd><table border=1 cellpadding=3 cellspacing=0 width=\"90%\" summary=\"\"><tr>");
writer.println("<th width=\"20%\"><th width=\"5%\"><th width=\"65%\">");
writer.println("<table><tr>");
writer.println("<th style=\"width: 20%\"><th style=\"width: 5%\"><th style=\"width: 65%\">");
ConstantNode n;
for (Node node : components) {
n = (ConstantNode)node;
writer.println("<a NAME=\"" + name + "_" + n.name + "\"></a>");
writer.println("<span id=\"" + name + "_" + n.name + "\"></span>");
n.document(writer);
}
writer.println("</table>");

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2013, 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
@ -43,7 +43,7 @@ class ErrorSetNode extends AbstractSimpleNode {
if (components.isEmpty()) {
writer.println("<dd>(None)");
} else {
writer.println("<dd><table border=1 cellpadding=3 cellspacing=0 width=\"90%\" summary=\"\">");
writer.println("<dd><table>");
for (Node node : components) {
node.document(writer);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2013, 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
@ -41,11 +41,22 @@ class RootNode extends AbstractNamedNode {
void document(PrintWriter writer) {
writer.println("<!DOCTYPE html>");
writer.println("<html><head><title>" + comment() + "</title></head>");
writer.println("<body bgcolor=\"white\">");
writer.println("<html lang=\"en\">");
writer.println("<head>");
writer.println("<meta charset=\"utf-8\"/>");
writer.println("<title>" + comment() + "</title>");
writer.println("<style>");
writer.println("body {background-color:white;}");
writer.println("table {border: 1px solid grey; border-spacing:0px; border-collapse: separate; width: 90%;}");
writer.println("td, th {padding: 3px; border: 1px solid black;}");
writer.println("</style>");
writer.println("</head>");
writer.println("<body>");
writer.println("<ul>");
for (Node node : components) {
node.documentIndex(writer);
}
writer.println("</ul>");
for (Node node : components) {
node.document(writer);
}

View File

@ -44,6 +44,7 @@ $(eval $(call IncludeCustomExtension, test/JtregNativeHotspot.gmk))
# Add more directories here when needed.
BUILD_HOTSPOT_JTREG_NATIVE_SRC += \
$(TOPDIR)/test/hotspot/jtreg/gc/g1/TestJNIWeakG1 \
$(TOPDIR)/test/hotspot/jtreg/gc/stress/TestJNIBlockFullGC \
$(TOPDIR)/test/hotspot/jtreg/gc/stress/gclocker \
$(TOPDIR)/test/hotspot/jtreg/gc/cslocker \
$(TOPDIR)/test/hotspot/jtreg/native_sanity \

View File

@ -2295,23 +2295,32 @@ public:
rf(Vn, 5), rf(Rd, 0);
}
#define INSN(NAME, opc, opc2) \
#define INSN(NAME, opc, opc2, isSHR) \
void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, int shift){ \
starti; \
/* The encodings for the immh:immb fields (bits 22:16) are \
* 0001 xxx 8B/16B, shift = xxx \
* 001x xxx 4H/8H, shift = xxxx \
* 01xx xxx 2S/4S, shift = xxxxx \
* 1xxx xxx 1D/2D, shift = xxxxxx (1D is RESERVED) \
/* The encodings for the immh:immb fields (bits 22:16) in *SHR are \
* 0001 xxx 8B/16B, shift = 16 - UInt(immh:immb) \
* 001x xxx 4H/8H, shift = 32 - UInt(immh:immb) \
* 01xx xxx 2S/4S, shift = 64 - UInt(immh:immb) \
* 1xxx xxx 1D/2D, shift = 128 - UInt(immh:immb) \
* (1D is RESERVED) \
* for SHL shift is calculated as: \
* 0001 xxx 8B/16B, shift = UInt(immh:immb) - 8 \
* 001x xxx 4H/8H, shift = UInt(immh:immb) - 16 \
* 01xx xxx 2S/4S, shift = UInt(immh:immb) - 32 \
* 1xxx xxx 1D/2D, shift = UInt(immh:immb) - 64 \
* (1D is RESERVED) \
*/ \
assert((1 << ((T>>1)+3)) > shift, "Invalid Shift value"); \
int cVal = (1 << (((T >> 1) + 3) + (isSHR ? 1 : 0))); \
int encodedShift = isSHR ? cVal - shift : cVal + shift; \
f(0, 31), f(T & 1, 30), f(opc, 29), f(0b011110, 28, 23), \
f((1 << ((T>>1)+3))|shift, 22, 16); f(opc2, 15, 10), rf(Vn, 5), rf(Vd, 0); \
f(encodedShift, 22, 16); f(opc2, 15, 10), rf(Vn, 5), rf(Vd, 0); \
}
INSN(shl, 0, 0b010101);
INSN(sshr, 0, 0b000001);
INSN(ushr, 1, 0b000001);
INSN(shl, 0, 0b010101, /* isSHR = */ false);
INSN(sshr, 0, 0b000001, /* isSHR = */ true);
INSN(ushr, 1, 0b000001, /* isSHR = */ true);
#undef INSN

View File

@ -4335,7 +4335,6 @@ void TemplateTable::_new() {
Label done;
Label initialize_header;
Label initialize_object; // including clearing the fields
Label allocate_shared;
const bool allow_shared_alloc =
Universe::heap()->supports_inline_contig_alloc();
@ -4380,13 +4379,19 @@ void TemplateTable::_new() {
// Klass::_lh_instance_slow_path_bit is really a bit mask, not bit number
__ tbnz(Rsize, exact_log2(Klass::_lh_instance_slow_path_bit), slow_case);
// Allocate the instance:
// If TLAB is enabled:
// Try to allocate in the TLAB.
// If fails, go to the slow path.
// Else If inline contiguous allocations are enabled:
// Try to allocate in eden.
// If fails due to heap end, go to slow path.
//
// Allocate the instance
// 1) Try to allocate in the TLAB
// 2) if fail and the object is large allocate in the shared Eden
// 3) if the above fails (or is not applicable), go to a slow case
// (creates a new TLAB, etc.)
// If TLAB is enabled OR inline contiguous is enabled:
// Initialize the allocation.
// Exit.
//
// Go to slow path.
if (UseTLAB) {
const Register Rtlab_top = R1_tmp;
const Register Rtlab_end = R2_tmp;
@ -4396,7 +4401,7 @@ void TemplateTable::_new() {
__ ldr(Rtlab_end, Address(Rthread, in_bytes(JavaThread::tlab_end_offset())));
__ add(Rtlab_top, Robj, Rsize);
__ cmp(Rtlab_top, Rtlab_end);
__ b(allow_shared_alloc ? allocate_shared : slow_case, hi);
__ b(slow_case, hi);
__ str(Rtlab_top, Address(Rthread, JavaThread::tlab_top_offset()));
if (ZeroTLAB) {
// the fields have been already cleared
@ -4405,45 +4410,43 @@ void TemplateTable::_new() {
// initialize both the header and fields
__ b(initialize_object);
}
}
} else {
// Allocation in the shared Eden, if allowed.
if (allow_shared_alloc) {
const Register Rheap_top_addr = R2_tmp;
const Register Rheap_top = R5_tmp;
const Register Rheap_end = Rtemp;
assert_different_registers(Robj, Rklass, Rsize, Rheap_top_addr, Rheap_top, Rheap_end, LR);
// Allocation in the shared Eden, if allowed.
if (allow_shared_alloc) {
__ bind(allocate_shared);
// heap_end now (re)loaded in the loop since also used as a scratch register in the CAS
__ ldr_literal(Rheap_top_addr, Lheap_top_addr);
const Register Rheap_top_addr = R2_tmp;
const Register Rheap_top = R5_tmp;
const Register Rheap_end = Rtemp;
assert_different_registers(Robj, Rklass, Rsize, Rheap_top_addr, Rheap_top, Rheap_end, LR);
// heap_end now (re)loaded in the loop since also used as a scratch register in the CAS
__ ldr_literal(Rheap_top_addr, Lheap_top_addr);
Label retry;
__ bind(retry);
Label retry;
__ bind(retry);
#ifdef AARCH64
__ ldxr(Robj, Rheap_top_addr);
__ ldxr(Robj, Rheap_top_addr);
#else
__ ldr(Robj, Address(Rheap_top_addr));
__ ldr(Robj, Address(Rheap_top_addr));
#endif // AARCH64
__ ldr(Rheap_end, Address(Rheap_top_addr, (intptr_t)Universe::heap()->end_addr()-(intptr_t)Universe::heap()->top_addr()));
__ add(Rheap_top, Robj, Rsize);
__ cmp(Rheap_top, Rheap_end);
__ b(slow_case, hi);
__ ldr(Rheap_end, Address(Rheap_top_addr, (intptr_t)Universe::heap()->end_addr()-(intptr_t)Universe::heap()->top_addr()));
__ add(Rheap_top, Robj, Rsize);
__ cmp(Rheap_top, Rheap_end);
__ b(slow_case, hi);
// Update heap top atomically.
// If someone beats us on the allocation, try again, otherwise continue.
// Update heap top atomically.
// If someone beats us on the allocation, try again, otherwise continue.
#ifdef AARCH64
__ stxr(Rtemp2, Rheap_top, Rheap_top_addr);
__ cbnz_w(Rtemp2, retry);
__ stxr(Rtemp2, Rheap_top, Rheap_top_addr);
__ cbnz_w(Rtemp2, retry);
#else
__ atomic_cas_bool(Robj, Rheap_top, Rheap_top_addr, 0, Rheap_end/*scratched*/);
__ b(retry, ne);
__ atomic_cas_bool(Robj, Rheap_top, Rheap_top_addr, 0, Rheap_end/*scratched*/);
__ b(retry, ne);
#endif // AARCH64
__ incr_allocated_bytes(Rsize, Rtemp);
__ incr_allocated_bytes(Rsize, Rtemp);
}
}
if (UseTLAB || allow_shared_alloc) {

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2015 SAP SE. All rights reserved.
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2018 SAP SE. 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
@ -34,8 +34,8 @@
#include "runtime/basicLock.hpp"
#include "runtime/biasedLocking.hpp"
#include "runtime/os.hpp"
#include "runtime/stubRoutines.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/stubRoutines.hpp"
#include "utilities/align.hpp"

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2015 SAP SE. All rights reserved.
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2018 SAP SE. 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,36 +33,36 @@
// (see c1_globals.hpp)
#ifndef TIERED
define_pd_global(bool, BackgroundCompilation, true );
define_pd_global(bool, CICompileOSR, true );
define_pd_global(bool, InlineIntrinsics, true );
define_pd_global(bool, PreferInterpreterNativeStubs, false);
define_pd_global(bool, ProfileTraps, false);
define_pd_global(bool, UseOnStackReplacement, true );
define_pd_global(bool, TieredCompilation, false);
define_pd_global(intx, CompileThreshold, 1000 );
define_pd_global(bool, BackgroundCompilation, true);
define_pd_global(bool, CICompileOSR, true);
define_pd_global(bool, InlineIntrinsics, true);
define_pd_global(bool, PreferInterpreterNativeStubs, false);
define_pd_global(bool, ProfileTraps, false);
define_pd_global(bool, UseOnStackReplacement, true);
define_pd_global(bool, TieredCompilation, false);
define_pd_global(intx, CompileThreshold, 1000);
define_pd_global(intx, OnStackReplacePercentage, 1400 );
define_pd_global(bool, UseTLAB, true );
define_pd_global(bool, ProfileInterpreter, false);
define_pd_global(intx, FreqInlineSize, 325 );
define_pd_global(bool, ResizeTLAB, true );
define_pd_global(intx, ReservedCodeCacheSize, 32*M );
define_pd_global(intx, CodeCacheExpansionSize, 32*K );
define_pd_global(uintx,CodeCacheMinBlockLength, 1);
define_pd_global(uintx,MetaspaceSize, 12*M );
define_pd_global(bool, NeverActAsServerClassMachine, true );
define_pd_global(intx, NewSizeThreadIncrease, 16*K );
define_pd_global(uint64_t,MaxRAM, 1ULL*G);
define_pd_global(intx, InitialCodeCacheSize, 160*K);
define_pd_global(intx, OnStackReplacePercentage, 1400);
define_pd_global(bool, UseTLAB, true);
define_pd_global(bool, ProfileInterpreter, false);
define_pd_global(intx, FreqInlineSize, 325 );
define_pd_global(bool, ResizeTLAB, true);
define_pd_global(uintx, ReservedCodeCacheSize, 32*M);
define_pd_global(uintx, CodeCacheExpansionSize, 32*K);
define_pd_global(uintx, CodeCacheMinBlockLength, 1);
define_pd_global(size_t, MetaspaceSize, 12*M);
define_pd_global(bool, NeverActAsServerClassMachine, true);
define_pd_global(size_t, NewSizeThreadIncrease, 16*K);
define_pd_global(uint64_t, MaxRAM, 1ULL*G);
define_pd_global(uintx, InitialCodeCacheSize, 160*K);
#endif // !TIERED
define_pd_global(bool, UseTypeProfile, false);
define_pd_global(bool, RoundFPResults, false);
define_pd_global(bool, UseTypeProfile, false);
define_pd_global(bool, RoundFPResults, false);
define_pd_global(bool, LIRFillDelaySlots, false);
define_pd_global(bool, OptimizeSinglePrecision, false);
define_pd_global(bool, CSEArrayLength, true );
define_pd_global(bool, TwoOperandLIRForm, false);
define_pd_global(bool, LIRFillDelaySlots, false);
define_pd_global(bool, OptimizeSinglePrecision, false);
define_pd_global(bool, CSEArrayLength, true);
define_pd_global(bool, TwoOperandLIRForm, false);
#endif // CPU_PPC_VM_C1_GLOBALS_PPC_HPP

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2016 SAP SE. All rights reserved.
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2018 SAP SE. 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
@ -39,7 +39,7 @@ define_pd_global(bool, PreferInterpreterNativeStubs, false);
define_pd_global(bool, ProfileTraps, true);
define_pd_global(bool, UseOnStackReplacement, true);
define_pd_global(bool, ProfileInterpreter, true);
define_pd_global(bool, TieredCompilation, true);
define_pd_global(bool, TieredCompilation, trueInTiered);
define_pd_global(intx, CompileThreshold, 10000);
define_pd_global(intx, OnStackReplacePercentage, 140);
@ -78,27 +78,27 @@ define_pd_global(bool, SuperWordLoopUnrollAnalysis, false);
// x.f = 0
// loc = x.f
// NullCheck loc
define_pd_global(bool, OptoScheduling, false);
define_pd_global(bool, IdealizeClearArrayNode, true);
define_pd_global(bool, OptoScheduling, false);
define_pd_global(bool, IdealizeClearArrayNode, true);
define_pd_global(intx, InitialCodeCacheSize, 2048*K); // Integral multiple of CodeCacheExpansionSize
define_pd_global(intx, ReservedCodeCacheSize, 256*M);
define_pd_global(intx, NonProfiledCodeHeapSize, 125*M);
define_pd_global(intx, ProfiledCodeHeapSize, 126*M);
define_pd_global(intx, NonNMethodCodeHeapSize, 5*M );
define_pd_global(intx, CodeCacheExpansionSize, 64*K);
define_pd_global(uintx, InitialCodeCacheSize, 2048*K); // Integral multiple of CodeCacheExpansionSize
define_pd_global(uintx, ReservedCodeCacheSize, 256*M);
define_pd_global(uintx, NonProfiledCodeHeapSize, 125*M);
define_pd_global(uintx, ProfiledCodeHeapSize, 126*M);
define_pd_global(uintx, NonNMethodCodeHeapSize, 5*M );
define_pd_global(uintx, CodeCacheExpansionSize, 64*K);
// Ergonomics related flags
define_pd_global(uint64_t, MaxRAM, 4ULL*G);
define_pd_global(uintx, CodeCacheMinBlockLength, 4);
define_pd_global(uintx, CodeCacheMinimumUseSpace, 400*K);
define_pd_global(uint64_t, MaxRAM, 128ULL*G);
define_pd_global(uintx, CodeCacheMinBlockLength, 4);
define_pd_global(uintx, CodeCacheMinimumUseSpace, 400*K);
define_pd_global(bool, TrapBasedRangeChecks, true);
define_pd_global(bool, TrapBasedRangeChecks, true);
// Heap related flags
define_pd_global(size_t, MetaspaceSize, ScaleForWordSize(16*M));
define_pd_global(size_t, MetaspaceSize, ScaleForWordSize(16*M));
// Ergonomics related flags
define_pd_global(bool, NeverActAsServerClassMachine, false);
define_pd_global(bool, NeverActAsServerClassMachine, false);
#endif // CPU_PPC_VM_C2_GLOBALS_PPC_HPP

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2015 SAP SE. All rights reserved.
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2018 SAP SE. 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,11 +29,11 @@
#include "runtime/globals.hpp"
#include "utilities/debug.hpp"
// processor dependent initialization for ppc
// Processor dependent initialization of C2 compiler for ppc.
void Compile::pd_compiler2_init() {
// Power7 and later
// Power7 and later.
if (PowerArchitecturePPC64 > 6) {
if (FLAG_IS_DEFAULT(UsePopCountInstruction)) {
FLAG_SET_ERGO(bool, UsePopCountInstruction, true);

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2017 SAP SE. All rights reserved.
* Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2018 SAP SE. 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,14 +86,14 @@ define_pd_global(intx, InitArrayShortSize, 9*BytesPerLong);
define_pd_global(bool, ThreadLocalHandshakes, true);
// Platform dependent flag handling: flags only defined on this platform.
#define ARCH_FLAGS(develop, \
product, \
diagnostic, \
#define ARCH_FLAGS(develop, \
product, \
diagnostic, \
experimental, \
notproduct, \
range, \
constraint, \
writeable) \
notproduct, \
range, \
constraint, \
writeable) \
\
product(uintx, PowerArchitecturePPC64, 0, \
"CPU Version: x for PowerX. Currently recognizes Power5 to " \

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2013 SAP SE. All rights reserved.
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2018 SAP SE. 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,7 +24,6 @@
*/
#include "precompiled.hpp"
#include "assembler_ppc.inline.hpp"
#include "runtime/icache.hpp"
// Use inline assembler to implement icache flush.
@ -32,7 +31,7 @@ int ICache::ppc64_flush_icache(address start, int lines, int magic) {
address end = start + (unsigned int)lines*ICache::line_size;
assert(start <= end, "flush_icache parms");
// store modified cache lines from data cache
// Store modified cache lines from data cache.
for (address a = start; a < end; a += ICache::line_size) {
__asm__ __volatile__(
"dcbst 0, %0 \n"
@ -48,7 +47,7 @@ int ICache::ppc64_flush_icache(address start, int lines, int magic) {
:
: "memory");
// invalidate respective cache lines in instruction cache
// Invalidate respective cache lines in instruction cache.
for (address a = start; a < end; a += ICache::line_size) {
__asm__ __volatile__(
"icbi 0, %0 \n"
@ -57,7 +56,7 @@ int ICache::ppc64_flush_icache(address start, int lines, int magic) {
: "memory");
}
// discard fetched instructions
// Discard fetched instructions.
__asm__ __volatile__(
"isync \n"
:
@ -71,6 +70,8 @@ void ICacheStubGenerator::generate_icache_flush(ICache::flush_icache_stub_t* flu
*flush_icache_stub = (ICache::flush_icache_stub_t)ICache::ppc64_flush_icache;
// First call to flush itself
// First call to flush itself.
// Pointless since we call C, but it is expected to get
// executed during VM_Version::determine_features().
ICache::invalidate_range((address)(*flush_icache_stub), 0);
}

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2017 SAP SE. All rights reserved.
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2018 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -32,6 +32,10 @@
#include "runtime/safepointMechanism.hpp"
#include "runtime/sharedRuntime.hpp"
// Implementation of InterpreterMacroAssembler.
// This file specializes the assembler with interpreter-specific macros.
#ifdef PRODUCT
#define BLOCK_COMMENT(str) // nothing
#else

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2013 SAP SE. All rights reserved.
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2018 SAP SE. 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,7 +24,7 @@
*/
#include "precompiled.hpp"
#include "assembler_ppc.inline.hpp"
#include "asm/assembler.inline.hpp"
#include "memory/resourceArea.hpp"
#include "prims/jniFastGetField.hpp"
#include "prims/jvm_misc.hpp"

View File

@ -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.
* Copyright (c) 2012, 2017, SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -2883,10 +2883,6 @@ void MacroAssembler::compiler_fast_lock_object(ConditionRegister flag, Register
//assert(ObjectMonitor::recursions_size_in_bytes() == 8, "unexpected size");
asm_assert_mem8_is_zero(ObjectMonitor::recursions_offset_in_bytes(), temp,
"monitor->_recursions should be 0", -1);
// Invariant 2: OwnerIsThread shouldn't be 0.
//assert(ObjectMonitor::OwnerIsThread_size_in_bytes() == 4, "unexpected size");
//asm_assert_mem4_isnot_zero(ObjectMonitor::OwnerIsThread_offset_in_bytes(), temp,
// "monitor->OwnerIsThread shouldn't be 0", -1);
# endif
#if INCLUDE_RTM_OPT

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2015 SAP SE. All rights reserved.
* Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2018 SAP SE. 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,6 @@
#ifndef CPU_PPC_VM_NATIVEINST_PPC_HPP
#define CPU_PPC_VM_NATIVEINST_PPC_HPP
#include "asm/assembler.hpp"
#include "asm/macroAssembler.hpp"
#include "memory/allocation.hpp"
#include "runtime/icache.hpp"

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2015 SAP SE. All rights reserved.
* Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2018 SAP SE. 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,6 @@
#include "precompiled.hpp"
#ifdef COMPILER2
#include "asm/assembler.inline.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "classfile/systemDictionary.hpp"
#include "code/vmreg.hpp"

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2017 SAP SE. All rights reserved.
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2018 SAP SE. 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
@ -1912,8 +1912,8 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
// - *_slot_offset Indicates offset from SP in number of stack slots.
// - *_offset Indicates offset from SP in bytes.
int stack_slots = c_calling_convention(out_sig_bt, out_regs, out_regs2, total_c_args) // 1+2)
+ SharedRuntime::out_preserve_stack_slots(); // See c_calling_convention.
int stack_slots = c_calling_convention(out_sig_bt, out_regs, out_regs2, total_c_args) + // 1+2)
SharedRuntime::out_preserve_stack_slots(); // See c_calling_convention.
// Now the space for the inbound oop handle area.
int total_save_slots = num_java_iarg_registers * VMRegImpl::slots_per_word;
@ -2044,7 +2044,8 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
OopMap *oop_map = new OopMap(stack_slots * 2, 0 /* arg_slots*/);
if (is_critical_native) {
check_needs_gc_for_critical_native(masm, stack_slots, total_in_args, oop_handle_slot_offset, oop_maps, in_regs, in_sig_bt, r_temp_1);
check_needs_gc_for_critical_native(masm, stack_slots, total_in_args, oop_handle_slot_offset,
oop_maps, in_regs, in_sig_bt, r_temp_1);
}
// Move arguments from register/stack to register/stack.

View File

@ -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.
* Copyright (c) 2012, 2017, SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -40,6 +40,10 @@
#include "runtime/thread.inline.hpp"
#include "utilities/align.hpp"
// Declaration and definition of StubGenerator (no .hpp file).
// For a more detailed description of the stub routine structure
// see the comment in stubRoutines.hpp.
#define __ _masm->
#ifdef PRODUCT

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2017, SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -23,6 +23,7 @@
*
*/
#include "precompiled.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "runtime/stubRoutines.hpp"

View File

@ -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.
* Copyright (c) 2015, 2017, SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -582,25 +582,6 @@ address TemplateInterpreterGenerator::generate_ArrayIndexOutOfBounds_handler(con
return entry;
}
#if 0
// Call special ClassCastException constructor taking object to cast
// and target class as arguments.
address TemplateInterpreterGenerator::generate_ClassCastException_verbose_handler() {
address entry = __ pc();
// Expression stack must be empty before entering the VM if an
// exception happened.
__ empty_expression_stack();
// Thread will be loaded to R3_ARG1.
// Target class oop is in register R5_ARG3 by convention!
__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_ClassCastException_verbose), R17_tos, R5_ARG3);
// Above call must not return here since exception pending.
DEBUG_ONLY(__ should_not_reach_here();)
return entry;
}
#endif
address TemplateInterpreterGenerator::generate_ClassCastException_handler() {
address entry = __ pc();
// Expression stack must be empty before entering the VM if an
@ -1896,7 +1877,6 @@ address TemplateInterpreterGenerator::generate_CRC32_update_entry() {
return NULL;
}
/**
* Method entry for static native methods:
* int java.util.zip.CRC32.updateBytes( int crc, byte[] b, int off, int len)

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016 SAP SE. All rights reserved.
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2018 SAP SE. 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
@ -42,11 +42,6 @@ class Bytes: AllStatic {
//
// In short, it makes no sense on z/Architecture to piecemeal get or put unaligned data.
// Only swap on little endian machines => suffix `_le'.
static inline u2 swap_u2_le(u2 x) { return x; }
static inline u4 swap_u4_le(u4 x) { return x; }
static inline u8 swap_u8_le(u8 x) { return x; }
static inline u2 get_native_u2(address p) { return *(u2*)p; }
static inline u4 get_native_u4(address p) { return *(u4*)p; }
static inline u8 get_native_u8(address p) { return *(u8*)p; }
@ -55,7 +50,8 @@ class Bytes: AllStatic {
static inline void put_native_u4(address p, u4 x) { *(u4*)p = x; }
static inline void put_native_u8(address p, u8 x) { *(u8*)p = x; }
#include "bytes_linux_s390.inline.hpp"
// The following header contains the implementations of swap_u2, swap_u4, and swap_u8.
#include OS_CPU_HEADER_INLINE(bytes)
// Efficient reading and writing of unaligned unsigned data in Java byte ordering (i.e. big-endian ordering)
static inline u2 get_Java_u2(address p) { return get_native_u2(p); }

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016 SAP SE. All rights reserved.
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2018 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -48,7 +48,7 @@ define_pd_global(bool, UseTLAB, true);
define_pd_global(bool, ProfileInterpreter, false);
define_pd_global(intx, FreqInlineSize, 325);
define_pd_global(bool, ResizeTLAB, true);
define_pd_global(intx, ReservedCodeCacheSize, 32*M);
define_pd_global(uintx, ReservedCodeCacheSize, 32*M);
define_pd_global(uintx, NonProfiledCodeHeapSize, 13*M);
define_pd_global(uintx, ProfiledCodeHeapSize, 14*M);
define_pd_global(uintx, NonNMethodCodeHeapSize, 5*M);

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016 SAP SE. All rights reserved.
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2018 SAP SE. 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,7 +58,7 @@ define_pd_global(intx, LoopUnrollLimit, 60);
define_pd_global(intx, LoopPercentProfileLimit, 10);
define_pd_global(intx, MinJumpTableSize, 18);
// Peephole and CISC spilling both break the graph, and so makes the
// Peephole and CISC spilling both break the graph, and so make the
// scheduler sick.
define_pd_global(bool, OptoPeephole, false);
define_pd_global(bool, UseCISCSpill, true);

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2016, 2017 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017 SAP SE. All rights reserved.
* Copyright (c) 2016, 2018 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -87,7 +87,14 @@ define_pd_global(intx, InitArrayShortSize, 1*BytesPerLong);
define_pd_global(bool, ThreadLocalHandshakes, true);
#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint, writeable) \
#define ARCH_FLAGS(develop, \
product, \
diagnostic, \
experimental, \
notproduct, \
range, \
constraint, \
writeable) \
\
/* Reoptimize code-sequences of calls at runtime, e.g. replace an */ \
/* indirect call by a direct call. */ \

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2017 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -1723,7 +1723,7 @@ void os::signal_notify(int sig) {
local_sem_post();
}
static int check_pending_signals(bool wait) {
static int check_pending_signals() {
Atomic::store(0, &sigint_count);
for (;;) {
for (int i = 0; i < NSIG + 1; i++) {
@ -1732,9 +1732,6 @@ static int check_pending_signals(bool wait) {
return i;
}
}
if (!wait) {
return -1;
}
JavaThread *thread = JavaThread::current();
ThreadBlockInVM tbivm(thread);
@ -1763,12 +1760,8 @@ static int check_pending_signals(bool wait) {
}
}
int os::signal_lookup() {
return check_pending_signals(false);
}
int os::signal_wait() {
return check_pending_signals(true);
return check_pending_signals();
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2017, 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
@ -52,13 +52,13 @@
#include "runtime/orderAccess.inline.hpp"
#include "runtime/osThread.hpp"
#include "runtime/perfMemory.hpp"
#include "runtime/semaphore.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/statSampler.hpp"
#include "runtime/stubRoutines.hpp"
#include "runtime/thread.inline.hpp"
#include "runtime/threadCritical.hpp"
#include "runtime/timer.hpp"
#include "semaphore_bsd.hpp"
#include "services/attachListener.hpp"
#include "services/memTracker.hpp"
#include "services/runtimeService.hpp"
@ -91,7 +91,6 @@
# include <time.h>
# include <pwd.h>
# include <poll.h>
# include <semaphore.h>
# include <fcntl.h>
# include <string.h>
# include <sys/param.h>
@ -1829,135 +1828,28 @@ int os::sigexitnum_pd() {
// a counter for each possible signal value
static volatile jint pending_signals[NSIG+1] = { 0 };
// Bsd(POSIX) specific hand shaking semaphore.
#ifdef __APPLE__
typedef semaphore_t os_semaphore_t;
#define SEM_INIT(sem, value) semaphore_create(mach_task_self(), &sem, SYNC_POLICY_FIFO, value)
#define SEM_WAIT(sem) semaphore_wait(sem)
#define SEM_POST(sem) semaphore_signal(sem)
#define SEM_DESTROY(sem) semaphore_destroy(mach_task_self(), sem)
#else
typedef sem_t os_semaphore_t;
#define SEM_INIT(sem, value) sem_init(&sem, 0, value)
#define SEM_WAIT(sem) sem_wait(&sem)
#define SEM_POST(sem) sem_post(&sem)
#define SEM_DESTROY(sem) sem_destroy(&sem)
#endif
#ifdef __APPLE__
// OS X doesn't support unamed POSIX semaphores, so the implementation in os_posix.cpp can't be used.
static const char* sem_init_strerror(kern_return_t value) {
switch (value) {
case KERN_INVALID_ARGUMENT: return "Invalid argument";
case KERN_RESOURCE_SHORTAGE: return "Resource shortage";
default: return "Unknown";
}
}
OSXSemaphore::OSXSemaphore(uint value) {
kern_return_t ret = SEM_INIT(_semaphore, value);
guarantee(ret == KERN_SUCCESS, "Failed to create semaphore: %s", sem_init_strerror(ret));
}
OSXSemaphore::~OSXSemaphore() {
SEM_DESTROY(_semaphore);
}
void OSXSemaphore::signal(uint count) {
for (uint i = 0; i < count; i++) {
kern_return_t ret = SEM_POST(_semaphore);
assert(ret == KERN_SUCCESS, "Failed to signal semaphore");
}
}
void OSXSemaphore::wait() {
kern_return_t ret;
while ((ret = SEM_WAIT(_semaphore)) == KERN_ABORTED) {
// Semaphore was interrupted. Retry.
}
assert(ret == KERN_SUCCESS, "Failed to wait on semaphore");
}
jlong OSXSemaphore::currenttime() {
struct timeval tv;
gettimeofday(&tv, NULL);
return (tv.tv_sec * NANOSECS_PER_SEC) + (tv.tv_usec * 1000);
}
bool OSXSemaphore::trywait() {
return timedwait(0, 0);
}
bool OSXSemaphore::timedwait(unsigned int sec, int nsec) {
kern_return_t kr = KERN_ABORTED;
mach_timespec_t waitspec;
waitspec.tv_sec = sec;
waitspec.tv_nsec = nsec;
jlong starttime = currenttime();
kr = semaphore_timedwait(_semaphore, waitspec);
while (kr == KERN_ABORTED) {
jlong totalwait = (sec * NANOSECS_PER_SEC) + nsec;
jlong current = currenttime();
jlong passedtime = current - starttime;
if (passedtime >= totalwait) {
waitspec.tv_sec = 0;
waitspec.tv_nsec = 0;
} else {
jlong waittime = totalwait - (current - starttime);
waitspec.tv_sec = waittime / NANOSECS_PER_SEC;
waitspec.tv_nsec = waittime % NANOSECS_PER_SEC;
}
kr = semaphore_timedwait(_semaphore, waitspec);
}
return kr == KERN_SUCCESS;
}
#else
// Use POSIX implementation of semaphores.
struct timespec PosixSemaphore::create_timespec(unsigned int sec, int nsec) {
struct timespec ts;
unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec);
return ts;
}
#endif // __APPLE__
static os_semaphore_t sig_sem;
#ifdef __APPLE__
static OSXSemaphore sr_semaphore;
#else
static PosixSemaphore sr_semaphore;
#endif
static Semaphore* sig_sem = NULL;
void os::signal_init_pd() {
// Initialize signal structures
::memset((void*)pending_signals, 0, sizeof(pending_signals));
// Initialize signal semaphore
::SEM_INIT(sig_sem, 0);
sig_sem = new Semaphore();
}
void os::signal_notify(int sig) {
Atomic::inc(&pending_signals[sig]);
::SEM_POST(sig_sem);
if (sig_sem != NULL) {
Atomic::inc(&pending_signals[sig]);
sig_sem->signal();
} else {
// Signal thread is not created with ReduceSignalUsage and signal_init_pd
// initialization isn't called.
assert(ReduceSignalUsage, "signal semaphore should be created");
}
}
static int check_pending_signals(bool wait) {
static int check_pending_signals() {
Atomic::store(0, &sigint_count);
for (;;) {
for (int i = 0; i < NSIG + 1; i++) {
@ -1966,9 +1858,6 @@ static int check_pending_signals(bool wait) {
return i;
}
}
if (!wait) {
return -1;
}
JavaThread *thread = JavaThread::current();
ThreadBlockInVM tbivm(thread);
@ -1976,7 +1865,7 @@ static int check_pending_signals(bool wait) {
do {
thread->set_suspend_equivalent();
// cleared by handle_special_suspend_equivalent_condition() or java_suspend_self()
::SEM_WAIT(sig_sem);
sig_sem->wait();
// were we externally suspended while we were waiting?
threadIsSuspended = thread->handle_special_suspend_equivalent_condition();
@ -1985,7 +1874,7 @@ static int check_pending_signals(bool wait) {
// another thread suspended us. We don't want to continue running
// while suspended because that would surprise the thread that
// suspended us.
::SEM_POST(sig_sem);
sig_sem->signal();
thread->java_suspend_self();
}
@ -1993,12 +1882,8 @@ static int check_pending_signals(bool wait) {
}
}
int os::signal_lookup() {
return check_pending_signals(false);
}
int os::signal_wait() {
return check_pending_signals(true);
return check_pending_signals();
}
////////////////////////////////////////////////////////////////////////////////
@ -2663,6 +2548,12 @@ static void suspend_save_context(OSThread *osthread, siginfo_t* siginfo, ucontex
//
// Currently only ever called on the VMThread or JavaThread
//
#ifdef __APPLE__
static OSXSemaphore sr_semaphore;
#else
static PosixSemaphore sr_semaphore;
#endif
static void SR_handler(int sig, siginfo_t* siginfo, ucontext_t* context) {
// Save and restore errno to avoid confusing native code with EINTR
// after sigsuspend.

View File

@ -0,0 +1,107 @@
/*
* 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.
*
*/
#include "precompiled/precompiled.hpp"
#include "semaphore_bsd.hpp"
#include "utilities/debug.hpp"
#include <semaphore.h>
#ifdef __APPLE__
// OS X doesn't support unamed POSIX semaphores, so the implementation in os_posix.cpp can't be used.
static const char* sem_init_strerror(kern_return_t value) {
switch (value) {
case KERN_INVALID_ARGUMENT: return "Invalid argument";
case KERN_RESOURCE_SHORTAGE: return "Resource shortage";
default: return "Unknown";
}
}
OSXSemaphore::OSXSemaphore(uint value) {
kern_return_t ret = semaphore_create(mach_task_self(), &_semaphore, SYNC_POLICY_FIFO, value);
guarantee(ret == KERN_SUCCESS, "Failed to create semaphore: %s", sem_init_strerror(ret));
}
OSXSemaphore::~OSXSemaphore() {
semaphore_destroy(mach_task_self(), _semaphore);
}
void OSXSemaphore::signal(uint count) {
for (uint i = 0; i < count; i++) {
kern_return_t ret = semaphore_signal(_semaphore);
assert(ret == KERN_SUCCESS, "Failed to signal semaphore");
}
}
void OSXSemaphore::wait() {
kern_return_t ret;
while ((ret = semaphore_wait(_semaphore)) == KERN_ABORTED) {
// Semaphore was interrupted. Retry.
}
assert(ret == KERN_SUCCESS, "Failed to wait on semaphore");
}
int64_t OSXSemaphore::currenttime() {
struct timeval tv;
gettimeofday(&tv, NULL);
return (tv.tv_sec * NANOSECS_PER_SEC) + (tv.tv_usec * 1000);
}
bool OSXSemaphore::trywait() {
return timedwait(0, 0);
}
bool OSXSemaphore::timedwait(unsigned int sec, int nsec) {
kern_return_t kr = KERN_ABORTED;
mach_timespec_t waitspec;
waitspec.tv_sec = sec;
waitspec.tv_nsec = nsec;
int64_t starttime = currenttime();
kr = semaphore_timedwait(_semaphore, waitspec);
while (kr == KERN_ABORTED) {
int64_t totalwait = (sec * NANOSECS_PER_SEC) + nsec;
int64_t current = currenttime();
int64_t passedtime = current - starttime;
if (passedtime >= totalwait) {
waitspec.tv_sec = 0;
waitspec.tv_nsec = 0;
} else {
int64_t waittime = totalwait - (current - starttime);
waitspec.tv_sec = waittime / NANOSECS_PER_SEC;
waitspec.tv_nsec = waittime % NANOSECS_PER_SEC;
}
kr = semaphore_timedwait(_semaphore, waitspec);
}
return kr == KERN_SUCCESS;
}
#endif // __APPLE__

View File

@ -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
@ -53,7 +53,7 @@ class OSXSemaphore : public CHeapObj<mtInternal>{
bool timedwait(unsigned int sec, int nsec);
private:
static jlong currenttime();
static int64_t currenttime();
};
typedef OSXSemaphore SemaphoreImpl;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2017, 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
@ -95,7 +95,6 @@
# include <sys/wait.h>
# include <pwd.h>
# include <poll.h>
# include <semaphore.h>
# include <fcntl.h>
# include <string.h>
# include <syscall.h>
@ -2479,11 +2478,11 @@ void* os::user_handler() {
return CAST_FROM_FN_PTR(void*, UserHandler);
}
struct timespec PosixSemaphore::create_timespec(unsigned int sec, int nsec) {
static struct timespec create_semaphore_timespec(unsigned int sec, int nsec) {
struct timespec ts;
// Semaphore's are always associated with CLOCK_REALTIME
os::Linux::clock_gettime(CLOCK_REALTIME, &ts);
// see unpackTime for discussion on overflow checking
// see os_posix.cpp for discussion on overflow checking
if (sec >= MAX_SECS) {
ts.tv_sec += MAX_SECS;
ts.tv_nsec = 0;
@ -2535,7 +2534,7 @@ int os::sigexitnum_pd() {
static volatile jint pending_signals[NSIG+1] = { 0 };
// Linux(POSIX) specific hand shaking semaphore.
static sem_t sig_sem;
static Semaphore* sig_sem = NULL;
static PosixSemaphore sr_semaphore;
void os::signal_init_pd() {
@ -2543,15 +2542,21 @@ void os::signal_init_pd() {
::memset((void*)pending_signals, 0, sizeof(pending_signals));
// Initialize signal semaphore
::sem_init(&sig_sem, 0, 0);
sig_sem = new Semaphore();
}
void os::signal_notify(int sig) {
Atomic::inc(&pending_signals[sig]);
::sem_post(&sig_sem);
if (sig_sem != NULL) {
Atomic::inc(&pending_signals[sig]);
sig_sem->signal();
} else {
// Signal thread is not created with ReduceSignalUsage and signal_init_pd
// initialization isn't called.
assert(ReduceSignalUsage, "signal semaphore should be created");
}
}
static int check_pending_signals(bool wait) {
static int check_pending_signals() {
Atomic::store(0, &sigint_count);
for (;;) {
for (int i = 0; i < NSIG + 1; i++) {
@ -2560,9 +2565,6 @@ static int check_pending_signals(bool wait) {
return i;
}
}
if (!wait) {
return -1;
}
JavaThread *thread = JavaThread::current();
ThreadBlockInVM tbivm(thread);
@ -2570,7 +2572,7 @@ static int check_pending_signals(bool wait) {
do {
thread->set_suspend_equivalent();
// cleared by handle_special_suspend_equivalent_condition() or java_suspend_self()
::sem_wait(&sig_sem);
sig_sem->wait();
// were we externally suspended while we were waiting?
threadIsSuspended = thread->handle_special_suspend_equivalent_condition();
@ -2579,7 +2581,7 @@ static int check_pending_signals(bool wait) {
// another thread suspended us. We don't want to continue running
// while suspended because that would surprise the thread that
// suspended us.
::sem_post(&sig_sem);
sig_sem->signal();
thread->java_suspend_self();
}
@ -2587,12 +2589,8 @@ static int check_pending_signals(bool wait) {
}
}
int os::signal_lookup() {
return check_pending_signals(false);
}
int os::signal_wait() {
return check_pending_signals(true);
return check_pending_signals();
}
////////////////////////////////////////////////////////////////////////////////
@ -4317,7 +4315,7 @@ static bool do_suspend(OSThread* osthread) {
// managed to send the signal and switch to SUSPEND_REQUEST, now wait for SUSPENDED
while (true) {
if (sr_semaphore.timedwait(0, 2 * NANOSECS_PER_MILLISEC)) {
if (sr_semaphore.timedwait(create_semaphore_timespec(0, 2 * NANOSECS_PER_MILLISEC))) {
break;
} else {
// timeout
@ -4351,7 +4349,7 @@ static void do_resume(OSThread* osthread) {
while (true) {
if (sr_notify(osthread) == 0) {
if (sr_semaphore.timedwait(0, 2 * NANOSECS_PER_MILLISEC)) {
if (sr_semaphore.timedwait(create_semaphore_timespec(0, 2 * NANOSECS_PER_MILLISEC))) {
if (osthread->sr.is_running()) {
return;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2017, 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
@ -31,14 +31,8 @@
#include "utilities/macros.hpp"
#include "utilities/vmError.hpp"
#ifndef __APPLE__
// POSIX unamed semaphores are not supported on OS X.
#include "semaphore_posix.hpp"
#endif
#include <dlfcn.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <sys/mman.h>
#include <sys/resource.h>
@ -1499,67 +1493,6 @@ void os::ThreadCrashProtection::check_crash_protection(int sig,
}
}
// POSIX unamed semaphores are not supported on OS X.
#ifndef __APPLE__
PosixSemaphore::PosixSemaphore(uint value) {
int ret = sem_init(&_semaphore, 0, value);
guarantee_with_errno(ret == 0, "Failed to initialize semaphore");
}
PosixSemaphore::~PosixSemaphore() {
sem_destroy(&_semaphore);
}
void PosixSemaphore::signal(uint count) {
for (uint i = 0; i < count; i++) {
int ret = sem_post(&_semaphore);
assert_with_errno(ret == 0, "sem_post failed");
}
}
void PosixSemaphore::wait() {
int ret;
do {
ret = sem_wait(&_semaphore);
} while (ret != 0 && errno == EINTR);
assert_with_errno(ret == 0, "sem_wait failed");
}
bool PosixSemaphore::trywait() {
int ret;
do {
ret = sem_trywait(&_semaphore);
} while (ret != 0 && errno == EINTR);
assert_with_errno(ret == 0 || errno == EAGAIN, "trywait failed");
return ret == 0;
}
bool PosixSemaphore::timedwait(struct timespec ts) {
while (true) {
int result = sem_timedwait(&_semaphore, &ts);
if (result == 0) {
return true;
} else if (errno == EINTR) {
continue;
} else if (errno == ETIMEDOUT) {
return false;
} else {
assert_with_errno(false, "timedwait failed");
return false;
}
}
}
#endif // __APPLE__
// Shared pthread_mutex/cond based PlatformEvent implementation.
// Not currently usable by Solaris.

View File

@ -0,0 +1,98 @@
/*
* 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.
*
*/
#include "precompiled/precompiled.hpp"
#ifndef __APPLE__
#include "runtime/os.hpp"
// POSIX unamed semaphores are not supported on OS X.
#include "semaphore_posix.hpp"
#include <semaphore.h>
#define check_with_errno(check_type, cond, msg) \
do { \
int err = errno; \
check_type(cond, "%s; error='%s' (errno=%s)", msg, os::strerror(err), \
os::errno_name(err)); \
} while (false)
#define assert_with_errno(cond, msg) check_with_errno(assert, cond, msg)
#define guarantee_with_errno(cond, msg) check_with_errno(guarantee, cond, msg)
PosixSemaphore::PosixSemaphore(uint value) {
int ret = sem_init(&_semaphore, 0, value);
guarantee_with_errno(ret == 0, "Failed to initialize semaphore");
}
PosixSemaphore::~PosixSemaphore() {
sem_destroy(&_semaphore);
}
void PosixSemaphore::signal(uint count) {
for (uint i = 0; i < count; i++) {
int ret = sem_post(&_semaphore);
assert_with_errno(ret == 0, "sem_post failed");
}
}
void PosixSemaphore::wait() {
int ret;
do {
ret = sem_wait(&_semaphore);
} while (ret != 0 && errno == EINTR);
assert_with_errno(ret == 0, "sem_wait failed");
}
bool PosixSemaphore::trywait() {
int ret;
do {
ret = sem_trywait(&_semaphore);
} while (ret != 0 && errno == EINTR);
assert_with_errno(ret == 0 || errno == EAGAIN, "trywait failed");
return ret == 0;
}
bool PosixSemaphore::timedwait(struct timespec ts) {
while (true) {
int result = sem_timedwait(&_semaphore, &ts);
if (result == 0) {
return true;
} else if (errno == EINTR) {
continue;
} else if (errno == ETIMEDOUT) {
return false;
} else {
assert_with_errno(false, "timedwait failed");
return false;
}
}
}
#endif // __APPLE__

View File

@ -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
@ -45,15 +45,7 @@ class PosixSemaphore : public CHeapObj<mtInternal> {
void wait();
bool trywait();
bool timedwait(unsigned int sec, int nsec) {
return timedwait(create_timespec(sec, nsec));
}
private:
bool timedwait(struct timespec ts);
// OS specific implementation to create a timespec suitable for semaphores.
struct timespec create_timespec(unsigned int set, int nsec);
};
typedef PosixSemaphore SemaphoreImpl;

View File

@ -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
@ -2062,7 +2062,7 @@ void* os::user_handler() {
return CAST_FROM_FN_PTR(void*, UserHandler);
}
struct timespec PosixSemaphore::create_timespec(unsigned int sec, int nsec) {
static struct timespec create_semaphore_timespec(unsigned int sec, int nsec) {
struct timespec ts;
unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec);
@ -2100,7 +2100,7 @@ static int Sigexit = 0;
static jint *pending_signals = NULL;
static int *preinstalled_sigs = NULL;
static struct sigaction *chainedsigactions = NULL;
static sema_t sig_sem;
static Semaphore* sig_sem = NULL;
typedef int (*version_getting_t)();
version_getting_t os::Solaris::get_libjsig_version = NULL;
@ -2115,6 +2115,7 @@ void os::Solaris::init_signal_mem() {
Sigexit = Maxsignum+1;
assert(Maxsignum >0, "Unable to obtain max signal number");
// Initialize signal structures
// pending_signals has one int per signal
// The additional signal is for SIGEXIT - exit signal to signal_thread
pending_signals = (jint *)os::malloc(sizeof(jint) * (Sigexit+1), mtInternal);
@ -2132,21 +2133,22 @@ void os::Solaris::init_signal_mem() {
}
void os::signal_init_pd() {
int ret;
ret = ::sema_init(&sig_sem, 0, NULL, NULL);
assert(ret == 0, "sema_init() failed");
// Initialize signal semaphore
sig_sem = new Semaphore();
}
void os::signal_notify(int signal_number) {
int ret;
Atomic::inc(&pending_signals[signal_number]);
ret = ::sema_post(&sig_sem);
assert(ret == 0, "sema_post() failed");
void os::signal_notify(int sig) {
if (sig_sem != NULL) {
Atomic::inc(&pending_signals[sig]);
sig_sem->signal();
} else {
// Signal thread is not created with ReduceSignalUsage and signal_init_pd
// initialization isn't called.
assert(ReduceSignalUsage, "signal semaphore should be created");
}
}
static int check_pending_signals(bool wait_for_signal) {
static int check_pending_signals() {
int ret;
while (true) {
for (int i = 0; i < Sigexit + 1; i++) {
@ -2155,19 +2157,13 @@ static int check_pending_signals(bool wait_for_signal) {
return i;
}
}
if (!wait_for_signal) {
return -1;
}
JavaThread *thread = JavaThread::current();
ThreadBlockInVM tbivm(thread);
bool threadIsSuspended;
do {
thread->set_suspend_equivalent();
// cleared by handle_special_suspend_equivalent_condition() or java_suspend_self()
while ((ret = ::sema_wait(&sig_sem)) == EINTR)
;
assert(ret == 0, "sema_wait() failed");
sig_sem->wait();
// were we externally suspended while we were waiting?
threadIsSuspended = thread->handle_special_suspend_equivalent_condition();
@ -2176,8 +2172,7 @@ static int check_pending_signals(bool wait_for_signal) {
// another thread suspended us. We don't want to continue running
// while suspended because that would surprise the thread that
// suspended us.
ret = ::sema_post(&sig_sem);
assert(ret == 0, "sema_post() failed");
sig_sem->signal();
thread->java_suspend_self();
}
@ -2185,12 +2180,8 @@ static int check_pending_signals(bool wait_for_signal) {
}
}
int os::signal_lookup() {
return check_pending_signals(false);
}
int os::signal_wait() {
return check_pending_signals(true);
return check_pending_signals();
}
////////////////////////////////////////////////////////////////////////////////
@ -3599,7 +3590,7 @@ static bool do_suspend(OSThread* osthread) {
// managed to send the signal and switch to SUSPEND_REQUEST, now wait for SUSPENDED
while (true) {
if (sr_semaphore.timedwait(0, 2000 * NANOSECS_PER_MILLISEC)) {
if (sr_semaphore.timedwait(create_semaphore_timespec(0, 2000 * NANOSECS_PER_MILLISEC))) {
break;
} else {
// timeout
@ -3633,7 +3624,7 @@ static void do_resume(OSThread* osthread) {
while (true) {
if (sr_notify(osthread) == 0) {
if (sr_semaphore.timedwait(0, 2 * NANOSECS_PER_MILLISEC)) {
if (sr_semaphore.timedwait(create_semaphore_timespec(0, 2 * NANOSECS_PER_MILLISEC))) {
if (osthread->sr.is_running()) {
return;
}

View File

@ -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
@ -62,7 +62,6 @@
#include "runtime/threadCritical.hpp"
#include "runtime/timer.hpp"
#include "runtime/vm_version.hpp"
#include "semaphore_windows.hpp"
#include "services/attachListener.hpp"
#include "services/memTracker.hpp"
#include "services/runtimeService.hpp"
@ -1845,36 +1844,6 @@ int os::get_last_error() {
return (int)error;
}
WindowsSemaphore::WindowsSemaphore(uint value) {
_semaphore = ::CreateSemaphore(NULL, value, LONG_MAX, NULL);
guarantee(_semaphore != NULL, "CreateSemaphore failed with error code: %lu", GetLastError());
}
WindowsSemaphore::~WindowsSemaphore() {
::CloseHandle(_semaphore);
}
void WindowsSemaphore::signal(uint count) {
if (count > 0) {
BOOL ret = ::ReleaseSemaphore(_semaphore, count, NULL);
assert(ret != 0, "ReleaseSemaphore failed with error code: %lu", GetLastError());
}
}
void WindowsSemaphore::wait() {
DWORD ret = ::WaitForSingleObject(_semaphore, INFINITE);
assert(ret != WAIT_FAILED, "WaitForSingleObject failed with error code: %lu", GetLastError());
assert(ret == WAIT_OBJECT_0, "WaitForSingleObject failed with return value: %lu", ret);
}
bool WindowsSemaphore::trywait() {
DWORD ret = ::WaitForSingleObject(_semaphore, 0);
assert(ret != WAIT_FAILED, "WaitForSingleObject failed with error code: %lu", GetLastError());
return ret == WAIT_OBJECT_0;
}
// sun.misc.Signal
// NOTE that this is a workaround for an apparent kernel bug where if
// a signal handler for SIGBREAK is installed then that signal handler
@ -1966,13 +1935,14 @@ int os::sigexitnum_pd() {
// a counter for each possible signal value, including signal_thread exit signal
static volatile jint pending_signals[NSIG+1] = { 0 };
static HANDLE sig_sem = NULL;
static Semaphore* sig_sem = NULL;
void os::signal_init_pd() {
// Initialize signal structures
memset((void*)pending_signals, 0, sizeof(pending_signals));
sig_sem = ::CreateSemaphore(NULL, 0, NSIG+1, NULL);
// Initialize signal semaphore
sig_sem = new Semaphore();
// Programs embedding the VM do not want it to attempt to receive
// events like CTRL_LOGOFF_EVENT, which are used to implement the
@ -1994,17 +1964,18 @@ void os::signal_init_pd() {
}
}
void os::signal_notify(int signal_number) {
BOOL ret;
void os::signal_notify(int sig) {
if (sig_sem != NULL) {
Atomic::inc(&pending_signals[signal_number]);
ret = ::ReleaseSemaphore(sig_sem, 1, NULL);
assert(ret != 0, "ReleaseSemaphore() failed");
Atomic::inc(&pending_signals[sig]);
sig_sem->signal();
} else {
// Signal thread is not created with ReduceSignalUsage and signal_init_pd
// initialization isn't called.
assert(ReduceSignalUsage, "signal semaphore should be created");
}
}
static int check_pending_signals(bool wait_for_signal) {
DWORD ret;
static int check_pending_signals() {
while (true) {
for (int i = 0; i < NSIG + 1; i++) {
jint n = pending_signals[i];
@ -2012,10 +1983,6 @@ static int check_pending_signals(bool wait_for_signal) {
return i;
}
}
if (!wait_for_signal) {
return -1;
}
JavaThread *thread = JavaThread::current();
ThreadBlockInVM tbivm(thread);
@ -2024,8 +1991,7 @@ static int check_pending_signals(bool wait_for_signal) {
do {
thread->set_suspend_equivalent();
// cleared by handle_special_suspend_equivalent_condition() or java_suspend_self()
ret = ::WaitForSingleObject(sig_sem, INFINITE);
assert(ret == WAIT_OBJECT_0, "WaitForSingleObject() failed");
sig_sem->wait();
// were we externally suspended while we were waiting?
threadIsSuspended = thread->handle_special_suspend_equivalent_condition();
@ -2034,8 +2000,7 @@ static int check_pending_signals(bool wait_for_signal) {
// another thread suspended us. We don't want to continue running
// while suspended because that would surprise the thread that
// suspended us.
ret = ::ReleaseSemaphore(sig_sem, 1, NULL);
assert(ret != 0, "ReleaseSemaphore() failed");
sig_sem->signal();
thread->java_suspend_self();
}
@ -2043,12 +2008,8 @@ static int check_pending_signals(bool wait_for_signal) {
}
}
int os::signal_lookup() {
return check_pending_signals(false);
}
int os::signal_wait() {
return check_pending_signals(true);
return check_pending_signals();
}
// Implicit OS exception handling
@ -4394,13 +4355,49 @@ FILE* os::open(int fd, const char* mode) {
// Is a (classpath) directory empty?
bool os::dir_is_empty(const char* path) {
WIN32_FIND_DATA fd;
HANDLE f = FindFirstFile(path, &fd);
if (f == INVALID_HANDLE_VALUE) {
return true;
char* search_path = (char*)os::malloc(strlen(path) + 3, mtInternal);
if (search_path == NULL) {
errno = ENOMEM;
return false;
}
FindClose(f);
return false;
strcpy(search_path, path);
// Append "*", or possibly "\\*", to path
if (path[1] == ':' &&
(path[2] == '\0' ||
(path[2] == '\\' && path[3] == '\0'))) {
// No '\\' needed for cases like "Z:" or "Z:\"
strcat(search_path, "*");
}
else {
strcat(search_path, "\\*");
}
errno_t err = ERROR_SUCCESS;
wchar_t* wpath = create_unc_path(search_path, err);
if (err != ERROR_SUCCESS) {
if (wpath != NULL) {
destroy_unc_path(wpath);
}
os::free(search_path);
errno = err;
return false;
}
WIN32_FIND_DATAW fd;
HANDLE f = ::FindFirstFileW(wpath, &fd);
destroy_unc_path(wpath);
bool is_empty = true;
if (f != INVALID_HANDLE_VALUE) {
while (is_empty && ::FindNextFileW(f, &fd)) {
// An empty directory contains only the current directory file
// and the previous directory file.
if ((wcscmp(fd.cFileName, L".") != 0) &&
(wcscmp(fd.cFileName, L"..") != 0)) {
is_empty = false;
}
}
FindClose(f);
}
os::free(search_path);
return is_empty;
}
// create binary file, rewriting existing file if required

View File

@ -0,0 +1,60 @@
/*
* 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.
*
*/
#include "precompiled.hpp"
#include "semaphore_windows.hpp"
#include "utilities/debug.hpp"
#include <windows.h>
#include <errno.h>
WindowsSemaphore::WindowsSemaphore(uint value) {
_semaphore = ::CreateSemaphore(NULL, value, LONG_MAX, NULL);
guarantee(_semaphore != NULL, "CreateSemaphore failed with error code: %lu", GetLastError());
}
WindowsSemaphore::~WindowsSemaphore() {
::CloseHandle(_semaphore);
}
void WindowsSemaphore::signal(uint count) {
if (count > 0) {
BOOL ret = ::ReleaseSemaphore(_semaphore, count, NULL);
assert(ret != 0, "ReleaseSemaphore failed with error code: %lu", GetLastError());
}
}
void WindowsSemaphore::wait() {
DWORD ret = ::WaitForSingleObject(_semaphore, INFINITE);
assert(ret != WAIT_FAILED, "WaitForSingleObject failed with error code: %lu", GetLastError());
assert(ret == WAIT_OBJECT_0, "WaitForSingleObject failed with return value: %lu", ret);
}
bool WindowsSemaphore::trywait() {
DWORD ret = ::WaitForSingleObject(_semaphore, 0);
assert(ret != WAIT_FAILED, "WaitForSingleObject failed with error code: %lu", GetLastError());
return ret == WAIT_OBJECT_0;
}

View File

@ -34,35 +34,12 @@
#include "oops/oop.inline.hpp"
#include "oops/fieldStreams.hpp"
#include "runtime/fieldDescriptor.hpp"
#if INCLUDE_ALL_GCS
# include "gc/g1/g1SATBCardTableModRefBS.hpp"
#endif
// ciInstanceKlass
//
// This class represents a Klass* in the HotSpot virtual machine
// whose Klass part in an InstanceKlass.
// ------------------------------------------------------------------
// ensure_metadata_alive
//
// Ensure that the metadata wrapped by the ciMetadata is kept alive by GC.
// This is primarily useful for metadata which is considered as weak roots
// by the GC but need to be strong roots if reachable from a current compilation.
// InstanceKlass are created for both weak and strong metadata. Ensuring this metadata
// alive covers the cases where there are weak roots without performance cost.
//
static void ensure_metadata_alive(oop metadata_holder) {
#if INCLUDE_ALL_GCS
if (!UseG1GC) {
return;
}
if (metadata_holder != NULL) {
G1SATBCardTableModRefBS::enqueue(metadata_holder);
}
#endif
}
// ------------------------------------------------------------------
// ciInstanceKlass::ciInstanceKlass
@ -88,8 +65,12 @@ ciInstanceKlass::ciInstanceKlass(Klass* k) :
_has_injected_fields = -1;
_implementor = NULL; // we will fill these lazily
oop holder = ik->klass_holder();
ensure_metadata_alive(holder);
// Ensure that the metadata wrapped by the ciMetadata is kept alive by GC.
// This is primarily useful for metadata which is considered as weak roots
// by the GC but need to be strong roots if reachable from a current compilation.
// InstanceKlass are created for both weak and strong metadata. Ensuring this metadata
// alive covers the cases where there are weak roots without performance cost.
oop holder = ik->klass_holder_phantom();
if (ik->is_anonymous()) {
// Though ciInstanceKlass records class loader oop, it's not enough to keep
// VM anonymous classes alive (loader == NULL). Klass holder should be used instead.

View File

@ -63,6 +63,7 @@
#include "memory/metaspaceShared.hpp"
#include "memory/oopFactory.hpp"
#include "memory/resourceArea.hpp"
#include "oops/access.inline.hpp"
#include "oops/objArrayOop.inline.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/atomic.hpp"
@ -75,9 +76,6 @@
#include "utilities/growableArray.hpp"
#include "utilities/macros.hpp"
#include "utilities/ostream.hpp"
#if INCLUDE_ALL_GCS
#include "gc/g1/g1SATBCardTableModRefBS.hpp"
#endif // INCLUDE_ALL_GCS
#if INCLUDE_TRACE
#include "trace/tracing.hpp"
#endif
@ -759,18 +757,9 @@ void ClassLoaderData::remove_handle(OopHandle h) {
oop* ptr = h.ptr_raw();
if (ptr != NULL) {
assert(_handles.contains(ptr), "Got unexpected handle " PTR_FORMAT, p2i(ptr));
#if INCLUDE_ALL_GCS
// This barrier is used by G1 to remember the old oop values, so
// that we don't forget any objects that were live at the snapshot at
// the beginning.
if (UseG1GC) {
oop obj = *ptr;
if (obj != NULL) {
G1SATBCardTableModRefBS::enqueue(obj);
}
}
#endif
*ptr = NULL;
// This root is not walked in safepoints, and hence requires an appropriate
// decorator that e.g. maintains the SATB invariant in SATB collectors.
RootAccess<IN_CONCURRENT_ROOT>::oop_store(ptr, oop(NULL));
}
}

View File

@ -217,6 +217,7 @@ class ClassLoaderData : public CHeapObj<mtClass> {
friend class ClassLoaderDataGraphKlassIteratorAtomic;
friend class ClassLoaderDataGraphKlassIteratorStatic;
friend class ClassLoaderDataGraphMetaspaceIterator;
friend class InstanceKlass;
friend class MetaDataFactory;
friend class Method;

View File

@ -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,6 +33,8 @@
#include "code/dependencyContext.hpp"
#include "code/pcDesc.hpp"
#include "interpreter/interpreter.hpp"
#include "logging/log.hpp"
#include "logging/logStream.hpp"
#include "memory/oopFactory.hpp"
#include "memory/resourceArea.hpp"
#include "memory/universe.inline.hpp"
@ -104,52 +106,59 @@ InjectedField* JavaClasses::get_injected(Symbol* class_name, int* field_count) {
}
static bool find_field(InstanceKlass* ik,
Symbol* name_symbol, Symbol* signature_symbol,
fieldDescriptor* fd,
bool is_static = false, bool allow_super = false) {
if (allow_super || is_static) {
return ik->find_field(name_symbol, signature_symbol, is_static, fd) != NULL;
} else {
return ik->find_local_field(name_symbol, signature_symbol, fd);
}
}
// Helpful routine for computing field offsets at run time rather than hardcoding them
static void
compute_offset(int &dest_offset,
Klass* klass, Symbol* name_symbol, Symbol* signature_symbol,
bool is_static = false, bool allow_super = false) {
// Finds local fields only, including static fields. Static field offsets are from the
// beginning of the mirror.
static void compute_offset(int &dest_offset,
InstanceKlass* ik, Symbol* name_symbol, Symbol* signature_symbol,
bool is_static = false) {
fieldDescriptor fd;
InstanceKlass* ik = InstanceKlass::cast(klass);
if (!find_field(ik, name_symbol, signature_symbol, &fd, is_static, allow_super)) {
if (ik == NULL) {
ResourceMark rm;
tty->print_cr("Invalid layout of %s at %s", ik->external_name(), name_symbol->as_C_string());
log_error(class)("Mismatch JDK version for field: %s type: %s", name_symbol->as_C_string(), signature_symbol->as_C_string());
vm_exit_during_initialization("Invalid layout of preloaded class");
}
if (!ik->find_local_field(name_symbol, signature_symbol, &fd) || fd.is_static() != is_static) {
ResourceMark rm;
log_error(class)("Invalid layout of %s field: %s type: %s", ik->external_name(),
name_symbol->as_C_string(), signature_symbol->as_C_string());
#ifndef PRODUCT
ik->print();
tty->print_cr("all fields:");
for (AllFieldStream fs(ik); !fs.done(); fs.next()) {
tty->print_cr(" name: %s, sig: %s, flags: %08x", fs.name()->as_C_string(), fs.signature()->as_C_string(), fs.access_flags().as_int());
}
// Prints all fields and offsets
Log(class) lt;
LogStream ls(lt.error());
ik->print_on(&ls);
#endif //PRODUCT
vm_exit_during_initialization("Invalid layout of preloaded class: use -Xlog:class+load=info to see the origin of the problem class");
}
dest_offset = fd.offset();
}
// Overloading to pass name as a string.
static void compute_offset(int& dest_offset, InstanceKlass* ik,
const char* name_string, Symbol* signature_symbol,
bool is_static = false) {
TempNewSymbol name = SymbolTable::probe(name_string, (int)strlen(name_string));
if (name == NULL) {
ResourceMark rm;
log_error(class)("Name %s should be in the SymbolTable since its class is loaded", name_string);
vm_exit_during_initialization("Invalid layout of preloaded class", ik->external_name());
}
compute_offset(dest_offset, ik, name, signature_symbol, is_static);
}
// Same as above but for "optional" offsets that might not be present in certain JDK versions
// Old versions should be cleaned out since Hotspot only supports the current JDK, and this
// function should be removed.
static void
compute_optional_offset(int& dest_offset,
Klass* klass, Symbol* name_symbol, Symbol* signature_symbol,
bool allow_super = false) {
InstanceKlass* ik, Symbol* name_symbol, Symbol* signature_symbol) {
fieldDescriptor fd;
InstanceKlass* ik = InstanceKlass::cast(klass);
if (find_field(ik, name_symbol, signature_symbol, &fd, allow_super)) {
if (ik->find_local_field(name_symbol, signature_symbol, &fd)) {
dest_offset = fd.offset();
}
}
int java_lang_String::value_offset = 0;
int java_lang_String::hash_offset = 0;
int java_lang_String::coder_offset = 0;
@ -163,10 +172,10 @@ bool java_lang_String::is_instance(oop obj) {
void java_lang_String::compute_offsets() {
assert(!initialized, "offsets should be initialized only once");
Klass* k = SystemDictionary::String_klass();
InstanceKlass* k = SystemDictionary::String_klass();
compute_offset(value_offset, k, vmSymbols::value_name(), vmSymbols::byte_array_signature());
compute_offset(hash_offset, k, vmSymbols::hash_name(), vmSymbols::int_signature());
compute_offset(coder_offset, k, vmSymbols::coder_name(), vmSymbols::byte_signature());
compute_offset(hash_offset, k, "hash", vmSymbols::int_signature());
compute_offset(coder_offset, k, "coder", vmSymbols::byte_signature());
initialized = true;
}
@ -619,12 +628,12 @@ char* java_lang_String::as_utf8_string(oop java_string, int start, int len, char
bool java_lang_String::equals(oop java_string, jchar* chars, int len) {
assert(java_string->klass() == SystemDictionary::String_klass(),
"must be java_string");
typeArrayOop value = java_lang_String::value(java_string);
int length = java_lang_String::length(java_string);
typeArrayOop value = java_lang_String::value_no_keepalive(java_string);
int length = java_lang_String::length(java_string);
if (length != len) {
return false;
}
bool is_latin1 = java_lang_String::is_latin1(java_string);
bool is_latin1 = java_lang_String::is_latin1(java_string);
if (!is_latin1) {
for (int i = 0; i < len; i++) {
if (value->char_at(i) != chars[i]) {
@ -646,12 +655,12 @@ bool java_lang_String::equals(oop str1, oop str2) {
"must be java String");
assert(str2->klass() == SystemDictionary::String_klass(),
"must be java String");
typeArrayOop value1 = java_lang_String::value(str1);
int length1 = java_lang_String::length(str1);
bool is_latin1 = java_lang_String::is_latin1(str1);
typeArrayOop value2 = java_lang_String::value(str2);
int length2 = java_lang_String::length(str2);
bool is_latin2 = java_lang_String::is_latin1(str2);
typeArrayOop value1 = java_lang_String::value_no_keepalive(str1);
int length1 = java_lang_String::length(value1);
bool is_latin1 = java_lang_String::is_latin1(str1);
typeArrayOop value2 = java_lang_String::value_no_keepalive(str2);
int length2 = java_lang_String::length(value2);
bool is_latin2 = java_lang_String::is_latin1(str2);
if ((length1 != length2) || (is_latin1 != is_latin2)) {
// Strings of different size or with different
@ -659,7 +668,7 @@ bool java_lang_String::equals(oop str1, oop str2) {
return false;
}
int blength1 = value1->length();
for (int i = 0; i < value1->length(); i++) {
for (int i = 0; i < blength1; i++) {
if (value1->byte_at(i) != value2->byte_at(i)) {
return false;
}
@ -669,7 +678,7 @@ bool java_lang_String::equals(oop str1, oop str2) {
void java_lang_String::print(oop java_string, outputStream* st) {
assert(java_string->klass() == SystemDictionary::String_klass(), "must be java_string");
typeArrayOop value = java_lang_String::value(java_string);
typeArrayOop value = java_lang_String::value_no_keepalive(java_string);
if (value == NULL) {
// This can happen if, e.g., printing a String
@ -1161,25 +1170,11 @@ void java_lang_Class::compute_offsets() {
assert(!offsets_computed, "offsets should be initialized only once");
offsets_computed = true;
Klass* k = SystemDictionary::Class_klass();
// The classRedefinedCount field is only present starting in 1.5,
// so don't go fatal.
compute_optional_offset(classRedefinedCount_offset,
k, vmSymbols::classRedefinedCount_name(), vmSymbols::int_signature());
// Needs to be optional because the old build runs Queens during bootstrapping
// and jdk8-9 doesn't have coordinated pushes yet.
compute_optional_offset(_class_loader_offset,
k, vmSymbols::classLoader_name(),
vmSymbols::classloader_signature());
compute_offset(_component_mirror_offset,
k, vmSymbols::componentType_name(),
vmSymbols::class_signature());
compute_offset(_module_offset,
k, vmSymbols::module_name(),
vmSymbols::module_signature());
InstanceKlass* k = SystemDictionary::Class_klass();
compute_offset(classRedefinedCount_offset, k, "classRedefinedCount", vmSymbols::int_signature());
compute_offset(_class_loader_offset, k, "classLoader", vmSymbols::classloader_signature());
compute_offset(_component_mirror_offset, k, "componentType", vmSymbols::class_signature());
compute_offset(_module_offset, k, "module", vmSymbols::module_signature());
// Init lock is a C union with component_mirror. Only instanceKlass mirrors have
// init_lock and only ArrayKlass mirrors have component_mirror. Since both are oops
@ -1234,24 +1229,22 @@ int java_lang_Thread::_park_event_offset = 0 ;
void java_lang_Thread::compute_offsets() {
assert(_group_offset == 0, "offsets should be initialized only once");
Klass* k = SystemDictionary::Thread_klass();
InstanceKlass* k = SystemDictionary::Thread_klass();
compute_offset(_name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
compute_offset(_group_offset, k, vmSymbols::group_name(), vmSymbols::threadgroup_signature());
compute_offset(_contextClassLoader_offset, k, vmSymbols::contextClassLoader_name(), vmSymbols::classloader_signature());
compute_offset(_inheritedAccessControlContext_offset, k, vmSymbols::inheritedAccessControlContext_name(), vmSymbols::accesscontrolcontext_signature());
compute_offset(_contextClassLoader_offset, k, vmSymbols::contextClassLoader_name(),
vmSymbols::classloader_signature());
compute_offset(_inheritedAccessControlContext_offset, k, vmSymbols::inheritedAccessControlContext_name(),
vmSymbols::accesscontrolcontext_signature());
compute_offset(_priority_offset, k, vmSymbols::priority_name(), vmSymbols::int_signature());
compute_offset(_daemon_offset, k, vmSymbols::daemon_name(), vmSymbols::bool_signature());
compute_offset(_eetop_offset, k, vmSymbols::eetop_name(), vmSymbols::long_signature());
compute_offset(_stillborn_offset, k, vmSymbols::stillborn_name(), vmSymbols::bool_signature());
// The stackSize field is only present starting in 1.4, so don't go fatal.
compute_optional_offset(_stackSize_offset, k, vmSymbols::stackSize_name(), vmSymbols::long_signature());
// The tid and thread_status fields are only present starting in 1.5, so don't go fatal.
compute_optional_offset(_tid_offset, k, vmSymbols::thread_id_name(), vmSymbols::long_signature());
compute_optional_offset(_thread_status_offset, k, vmSymbols::thread_status_name(), vmSymbols::int_signature());
// The parkBlocker field is only present starting in 1.6, so don't go fatal.
compute_optional_offset(_park_blocker_offset, k, vmSymbols::park_blocker_name(), vmSymbols::object_signature());
compute_optional_offset(_park_event_offset, k, vmSymbols::park_event_name(),
vmSymbols::long_signature());
compute_offset(_eetop_offset, k, "eetop", vmSymbols::long_signature());
compute_offset(_stillborn_offset, k, "stillborn", vmSymbols::bool_signature());
compute_offset(_stackSize_offset, k, "stackSize", vmSymbols::long_signature());
compute_offset(_tid_offset, k, "tid", vmSymbols::long_signature());
compute_offset(_thread_status_offset, k, "threadStatus", vmSymbols::int_signature());
compute_offset(_park_blocker_offset, k, "parkBlocker", vmSymbols::object_signature());
compute_offset(_park_event_offset, k, "nativeParkEventPointer", vmSymbols::long_signature());
}
@ -1486,7 +1479,7 @@ bool java_lang_ThreadGroup::is_daemon(oop java_thread_group) {
void java_lang_ThreadGroup::compute_offsets() {
assert(_parent_offset == 0, "offsets should be initialized only once");
Klass* k = SystemDictionary::ThreadGroup_klass();
InstanceKlass* k = SystemDictionary::ThreadGroup_klass();
compute_offset(_parent_offset, k, vmSymbols::parent_name(), vmSymbols::threadgroup_signature());
compute_offset(_name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
@ -1501,8 +1494,13 @@ void java_lang_ThreadGroup::compute_offsets() {
void java_lang_Throwable::compute_offsets() {
Klass* k = SystemDictionary::Throwable_klass();
compute_offset(depth_offset, k, vmSymbols::depth_name(), vmSymbols::int_signature());
InstanceKlass* k = SystemDictionary::Throwable_klass();
compute_offset(backtrace_offset, k, "backtrace", vmSymbols::object_signature());
compute_offset(detailMessage_offset, k, "detailMessage", vmSymbols::string_signature());
compute_offset(stackTrace_offset, k, "stackTrace", vmSymbols::java_lang_StackTraceElement_array());
compute_offset(depth_offset, k, "depth", vmSymbols::int_signature());
compute_offset(static_unassigned_stacktrace_offset, k, "UNASSIGNED_STACK", vmSymbols::java_lang_StackTraceElement_array(),
/*is_static*/true);
}
oop java_lang_Throwable::unassigned_stacktrace() {
@ -2270,23 +2268,23 @@ void java_lang_StackFrameInfo::to_stack_trace_element(Handle stackFrame, Handle
}
void java_lang_StackFrameInfo::compute_offsets() {
Klass* k = SystemDictionary::StackFrameInfo_klass();
compute_offset(_memberName_offset, k, vmSymbols::memberName_name(), vmSymbols::object_signature());
compute_offset(_bci_offset, k, vmSymbols::bci_name(), vmSymbols::short_signature());
InstanceKlass* k = SystemDictionary::StackFrameInfo_klass();
compute_offset(_memberName_offset, k, "memberName", vmSymbols::object_signature());
compute_offset(_bci_offset, k, "bci", vmSymbols::short_signature());
STACKFRAMEINFO_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
}
void java_lang_LiveStackFrameInfo::compute_offsets() {
Klass* k = SystemDictionary::LiveStackFrameInfo_klass();
compute_offset(_monitors_offset, k, vmSymbols::monitors_name(), vmSymbols::object_array_signature());
compute_offset(_locals_offset, k, vmSymbols::locals_name(), vmSymbols::object_array_signature());
compute_offset(_operands_offset, k, vmSymbols::operands_name(), vmSymbols::object_array_signature());
compute_offset(_mode_offset, k, vmSymbols::mode_name(), vmSymbols::int_signature());
InstanceKlass* k = SystemDictionary::LiveStackFrameInfo_klass();
compute_offset(_monitors_offset, k, "monitors", vmSymbols::object_array_signature());
compute_offset(_locals_offset, k, "locals", vmSymbols::object_array_signature());
compute_offset(_operands_offset, k, "operands", vmSymbols::object_array_signature());
compute_offset(_mode_offset, k, "mode", vmSymbols::int_signature());
}
void java_lang_reflect_AccessibleObject::compute_offsets() {
Klass* k = SystemDictionary::reflect_AccessibleObject_klass();
compute_offset(override_offset, k, vmSymbols::override_name(), vmSymbols::bool_signature());
InstanceKlass* k = SystemDictionary::reflect_AccessibleObject_klass();
compute_offset(override_offset, k, "override", vmSymbols::bool_signature());
}
jboolean java_lang_reflect_AccessibleObject::override(oop reflect) {
@ -2300,7 +2298,7 @@ void java_lang_reflect_AccessibleObject::set_override(oop reflect, jboolean valu
}
void java_lang_reflect_Method::compute_offsets() {
Klass* k = SystemDictionary::reflect_Method_klass();
InstanceKlass* k = SystemDictionary::reflect_Method_klass();
compute_offset(clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature());
compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
compute_offset(returnType_offset, k, vmSymbols::returnType_name(), vmSymbols::class_signature());
@ -2481,7 +2479,7 @@ void java_lang_reflect_Method::set_type_annotations(oop method, oop value) {
}
void java_lang_reflect_Constructor::compute_offsets() {
Klass* k = SystemDictionary::reflect_Constructor_klass();
InstanceKlass* k = SystemDictionary::reflect_Constructor_klass();
compute_offset(clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature());
compute_offset(parameterTypes_offset, k, vmSymbols::parameterTypes_name(), vmSymbols::class_array_signature());
compute_offset(exceptionTypes_offset, k, vmSymbols::exceptionTypes_name(), vmSymbols::class_array_signature());
@ -2623,7 +2621,7 @@ void java_lang_reflect_Constructor::set_type_annotations(oop constructor, oop va
}
void java_lang_reflect_Field::compute_offsets() {
Klass* k = SystemDictionary::reflect_Field_klass();
InstanceKlass* k = SystemDictionary::reflect_Field_klass();
compute_offset(clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature());
compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
compute_offset(type_offset, k, vmSymbols::type_name(), vmSymbols::class_signature());
@ -2747,22 +2745,17 @@ void java_lang_reflect_Field::set_type_annotations(oop field, oop value) {
}
void reflect_ConstantPool::compute_offsets() {
Klass* k = SystemDictionary::reflect_ConstantPool_klass();
// This null test can be removed post beta
if (k != NULL) {
// The field is called ConstantPool* in the sun.reflect.ConstantPool class.
compute_offset(_oop_offset, k, vmSymbols::ConstantPool_name(), vmSymbols::object_signature());
}
InstanceKlass* k = SystemDictionary::reflect_ConstantPool_klass();
// The field is called ConstantPool* in the sun.reflect.ConstantPool class.
compute_offset(_oop_offset, k, "constantPoolOop", vmSymbols::object_signature());
}
void java_lang_reflect_Parameter::compute_offsets() {
Klass* k = SystemDictionary::reflect_Parameter_klass();
if(NULL != k) {
compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
compute_offset(modifiers_offset, k, vmSymbols::modifiers_name(), vmSymbols::int_signature());
compute_offset(index_offset, k, vmSymbols::index_name(), vmSymbols::int_signature());
compute_offset(executable_offset, k, vmSymbols::executable_name(), vmSymbols::executable_signature());
}
InstanceKlass* k = SystemDictionary::reflect_Parameter_klass();
compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
compute_offset(modifiers_offset, k, vmSymbols::modifiers_name(), vmSymbols::int_signature());
compute_offset(index_offset, k, vmSymbols::index_name(), vmSymbols::int_signature());
compute_offset(executable_offset, k, vmSymbols::executable_name(), vmSymbols::executable_signature());
}
Handle java_lang_reflect_Parameter::create(TRAPS) {
@ -2836,12 +2829,10 @@ Handle java_lang_Module::create(Handle loader, Handle module_name, TRAPS) {
}
void java_lang_Module::compute_offsets() {
Klass* k = SystemDictionary::Module_klass();
if(NULL != k) {
compute_offset(loader_offset, k, vmSymbols::loader_name(), vmSymbols::classloader_signature());
compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
MODULE_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
}
InstanceKlass* k = SystemDictionary::Module_klass();
compute_offset(loader_offset, k, vmSymbols::loader_name(), vmSymbols::classloader_signature());
compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
MODULE_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
}
@ -2921,12 +2912,8 @@ ConstantPool* reflect_ConstantPool::get_cp(oop reflect) {
}
void reflect_UnsafeStaticFieldAccessorImpl::compute_offsets() {
Klass* k = SystemDictionary::reflect_UnsafeStaticFieldAccessorImpl_klass();
// This null test can be removed post beta
if (k != NULL) {
compute_offset(_base_offset, k,
vmSymbols::base_name(), vmSymbols::object_signature());
}
InstanceKlass* k = SystemDictionary::reflect_UnsafeStaticFieldAccessorImpl_klass();
compute_offset(_base_offset, k, "base", vmSymbols::object_signature());
}
oop java_lang_boxing_object::initialize_and_allocate(BasicType type, TRAPS) {
@ -3084,6 +3071,13 @@ bool java_lang_ref_Reference::is_referent_field(oop obj, ptrdiff_t offset) {
}
// Support for java_lang_ref_SoftReference
//
void java_lang_ref_SoftReference::compute_offsets() {
InstanceKlass* k = SystemDictionary::SoftReference_klass();
compute_offset(timestamp_offset, k, "timestamp", vmSymbols::long_signature());
compute_offset(static_clock_offset, k, "clock", vmSymbols::long_signature(), true);
}
jlong java_lang_ref_SoftReference::timestamp(oop ref) {
return ref->long_field(timestamp_offset);
@ -3113,10 +3107,8 @@ oop java_lang_invoke_DirectMethodHandle::member(oop dmh) {
}
void java_lang_invoke_DirectMethodHandle::compute_offsets() {
Klass* k = SystemDictionary::DirectMethodHandle_klass();
if (k != NULL) {
compute_offset(_member_offset, k, vmSymbols::member_name(), vmSymbols::java_lang_invoke_MemberName_signature());
}
InstanceKlass* k = SystemDictionary::DirectMethodHandle_klass();
compute_offset(_member_offset, k, "member", vmSymbols::java_lang_invoke_MemberName_signature());
}
// Support for java_lang_invoke_MethodHandle
@ -3137,16 +3129,13 @@ int java_lang_invoke_ResolvedMethodName::_vmholder_offset;
int java_lang_invoke_LambdaForm::_vmentry_offset;
void java_lang_invoke_MethodHandle::compute_offsets() {
Klass* k = SystemDictionary::MethodHandle_klass();
if (k != NULL) {
compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::java_lang_invoke_MethodType_signature());
compute_offset(_form_offset, k, vmSymbols::form_name(), vmSymbols::java_lang_invoke_LambdaForm_signature());
}
InstanceKlass* k = SystemDictionary::MethodHandle_klass();
compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::java_lang_invoke_MethodType_signature());
compute_offset(_form_offset, k, "form", vmSymbols::java_lang_invoke_LambdaForm_signature());
}
void java_lang_invoke_MemberName::compute_offsets() {
Klass* k = SystemDictionary::MemberName_klass();
assert (k != NULL, "jdk mismatch");
InstanceKlass* k = SystemDictionary::MemberName_klass();
compute_offset(_clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature());
compute_offset(_name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::object_signature());
@ -3156,15 +3145,15 @@ void java_lang_invoke_MemberName::compute_offsets() {
}
void java_lang_invoke_ResolvedMethodName::compute_offsets() {
Klass* k = SystemDictionary::ResolvedMethodName_klass();
InstanceKlass* k = SystemDictionary::ResolvedMethodName_klass();
assert(k != NULL, "jdk mismatch");
RESOLVEDMETHOD_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
}
void java_lang_invoke_LambdaForm::compute_offsets() {
Klass* k = SystemDictionary::LambdaForm_klass();
InstanceKlass* k = SystemDictionary::LambdaForm_klass();
assert (k != NULL, "jdk mismatch");
compute_offset(_vmentry_offset, k, vmSymbols::vmentry_name(), vmSymbols::java_lang_invoke_MemberName_signature());
compute_offset(_vmentry_offset, k, "vmentry", vmSymbols::java_lang_invoke_MemberName_signature());
}
bool java_lang_invoke_LambdaForm::is_instance(oop obj) {
@ -3305,11 +3294,9 @@ int java_lang_invoke_MethodType::_rtype_offset;
int java_lang_invoke_MethodType::_ptypes_offset;
void java_lang_invoke_MethodType::compute_offsets() {
Klass* k = SystemDictionary::MethodType_klass();
if (k != NULL) {
compute_offset(_rtype_offset, k, vmSymbols::rtype_name(), vmSymbols::class_signature());
compute_offset(_ptypes_offset, k, vmSymbols::ptypes_name(), vmSymbols::class_array_signature());
}
InstanceKlass* k = SystemDictionary::MethodType_klass();
compute_offset(_rtype_offset, k, "rtype", vmSymbols::class_signature());
compute_offset(_ptypes_offset, k, "ptypes", vmSymbols::class_array_signature());
}
void java_lang_invoke_MethodType::print_signature(oop mt, outputStream* st) {
@ -3392,12 +3379,10 @@ int java_lang_invoke_CallSite::_target_offset;
int java_lang_invoke_CallSite::_context_offset;
void java_lang_invoke_CallSite::compute_offsets() {
Klass* k = SystemDictionary::CallSite_klass();
if (k != NULL) {
compute_offset(_target_offset, k, vmSymbols::target_name(), vmSymbols::java_lang_invoke_MethodHandle_signature());
compute_offset(_context_offset, k, vmSymbols::context_name(),
vmSymbols::java_lang_invoke_MethodHandleNatives_CallSiteContext_signature());
}
InstanceKlass* k = SystemDictionary::CallSite_klass();
compute_offset(_target_offset, k, "target", vmSymbols::java_lang_invoke_MethodHandle_signature());
compute_offset(_context_offset, k, "context",
vmSymbols::java_lang_invoke_MethodHandleNatives_CallSiteContext_signature());
}
oop java_lang_invoke_CallSite::context(oop call_site) {
@ -3412,10 +3397,8 @@ oop java_lang_invoke_CallSite::context(oop call_site) {
int java_lang_invoke_MethodHandleNatives_CallSiteContext::_vmdependencies_offset;
void java_lang_invoke_MethodHandleNatives_CallSiteContext::compute_offsets() {
Klass* k = SystemDictionary::Context_klass();
if (k != NULL) {
CALLSITECONTEXT_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
}
InstanceKlass* k = SystemDictionary::Context_klass();
CALLSITECONTEXT_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
}
DependencyContext java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(oop call_site) {
@ -3434,28 +3417,12 @@ int java_security_AccessControlContext::_isAuthorized_offset = -1;
void java_security_AccessControlContext::compute_offsets() {
assert(_isPrivileged_offset == 0, "offsets should be initialized only once");
fieldDescriptor fd;
InstanceKlass* ik = SystemDictionary::AccessControlContext_klass();
InstanceKlass* k = SystemDictionary::AccessControlContext_klass();
if (!ik->find_local_field(vmSymbols::context_name(), vmSymbols::protectiondomain_signature(), &fd)) {
fatal("Invalid layout of java.security.AccessControlContext");
}
_context_offset = fd.offset();
if (!ik->find_local_field(vmSymbols::privilegedContext_name(), vmSymbols::accesscontrolcontext_signature(), &fd)) {
fatal("Invalid layout of java.security.AccessControlContext");
}
_privilegedContext_offset = fd.offset();
if (!ik->find_local_field(vmSymbols::isPrivileged_name(), vmSymbols::bool_signature(), &fd)) {
fatal("Invalid layout of java.security.AccessControlContext");
}
_isPrivileged_offset = fd.offset();
// The offset may not be present for bootstrapping with older JDK.
if (ik->find_local_field(vmSymbols::isAuthorized_name(), vmSymbols::bool_signature(), &fd)) {
_isAuthorized_offset = fd.offset();
}
compute_offset(_context_offset, k, "context", vmSymbols::protectiondomain_signature());
compute_offset(_privilegedContext_offset, k, "privilegedContext", vmSymbols::accesscontrolcontext_signature());
compute_offset(_isPrivileged_offset, k, "isPrivileged", vmSymbols::bool_signature());
compute_offset(_isAuthorized_offset, k, "isAuthorized", vmSymbols::bool_signature());
}
@ -3504,16 +3471,17 @@ void java_lang_ClassLoader::compute_offsets() {
assert(!offsets_computed, "offsets should be initialized only once");
offsets_computed = true;
// The field indicating parallelCapable (parallelLockMap) is only present starting in 7,
Klass* k1 = SystemDictionary::ClassLoader_klass();
compute_optional_offset(parallelCapable_offset,
k1, vmSymbols::parallelCapable_name(), vmSymbols::concurrenthashmap_signature());
InstanceKlass* k1 = SystemDictionary::ClassLoader_klass();
compute_offset(parallelCapable_offset,
k1, "parallelLockMap", vmSymbols::concurrenthashmap_signature());
compute_offset(name_offset,
k1, vmSymbols::name_name(), vmSymbols::string_signature());
compute_offset(unnamedModule_offset,
k1, vmSymbols::unnamedModule_name(), vmSymbols::module_signature());
k1, "unnamedModule", vmSymbols::module_signature());
compute_offset(parent_offset, k1, "parent", vmSymbols::classloader_signature());
CLASSLOADER_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
}
@ -3600,19 +3568,18 @@ oop java_lang_ClassLoader::unnamedModule(oop loader) {
}
// Support for java_lang_System
int java_lang_System::in_offset_in_bytes() {
return (InstanceMirrorKlass::offset_of_static_fields() + static_in_offset);
//
void java_lang_System::compute_offsets() {
InstanceKlass* k = SystemDictionary::System_klass();
compute_offset(static_in_offset, k, "in", vmSymbols::input_stream_signature(), true);
compute_offset(static_out_offset, k, "out", vmSymbols::print_stream_signature(), true);
compute_offset(static_err_offset, k, "err", vmSymbols::print_stream_signature(), true);
compute_offset(static_security_offset, k, "security", vmSymbols::security_manager_signature(), true);
}
int java_lang_System::out_offset_in_bytes() {
return (InstanceMirrorKlass::offset_of_static_fields() + static_out_offset);
}
int java_lang_System::err_offset_in_bytes() {
return (InstanceMirrorKlass::offset_of_static_fields() + static_err_offset);
}
int java_lang_System::in_offset_in_bytes() { return static_in_offset; }
int java_lang_System::out_offset_in_bytes() { return static_out_offset; }
int java_lang_System::err_offset_in_bytes() { return static_err_offset; }
bool java_lang_System::has_security_manager() {
@ -3682,7 +3649,6 @@ int java_lang_ref_Reference::referent_offset;
int java_lang_ref_Reference::queue_offset;
int java_lang_ref_Reference::next_offset;
int java_lang_ref_Reference::discovered_offset;
int java_lang_ref_Reference::number_of_fake_oop_fields;
int java_lang_ref_SoftReference::timestamp_offset;
int java_lang_ref_SoftReference::static_clock_offset;
int java_lang_ClassLoader::parent_offset;
@ -3717,6 +3683,17 @@ int reflect_UnsafeStaticFieldAccessorImpl::_base_offset;
// Support for java_lang_StackTraceElement
void java_lang_StackTraceElement::compute_offsets() {
InstanceKlass* k = SystemDictionary::StackTraceElement_klass();
compute_offset(declaringClassObject_offset, k, "declaringClassObject", vmSymbols::class_signature());
compute_offset(classLoaderName_offset, k, "classLoaderName", vmSymbols::string_signature());
compute_offset(moduleName_offset, k, "moduleName", vmSymbols::string_signature());
compute_offset(moduleVersion_offset, k, "moduleVersion", vmSymbols::string_signature());
compute_offset(declaringClass_offset, k, "declaringClass", vmSymbols::string_signature());
compute_offset(methodName_offset, k, "methodName", vmSymbols::string_signature());
compute_offset(fileName_offset, k, "fileName", vmSymbols::string_signature());
compute_offset(lineNumber_offset, k, "lineNumber", vmSymbols::int_signature());
}
void java_lang_StackTraceElement::set_fileName(oop element, oop value) {
element->obj_field_put(fileName_offset, value);
@ -3776,6 +3753,16 @@ void java_lang_LiveStackFrameInfo::set_mode(oop element, int value) {
// Support for java Assertions - java_lang_AssertionStatusDirectives.
void java_lang_AssertionStatusDirectives::compute_offsets() {
InstanceKlass* k = SystemDictionary::AssertionStatusDirectives_klass();
compute_offset(classes_offset, k, "classes", vmSymbols::string_array_signature());
compute_offset(classEnabled_offset, k, "classEnabled", vmSymbols::bool_array_signature());
compute_offset(packages_offset, k, "packages", vmSymbols::string_array_signature());
compute_offset(packageEnabled_offset, k, "packageEnabled", vmSymbols::bool_array_signature());
compute_offset(deflt_offset, k, "deflt", vmSymbols::bool_signature());
}
void java_lang_AssertionStatusDirectives::set_classes(oop o, oop val) {
o->obj_field_put(classes_offset, val);
}
@ -3804,18 +3791,18 @@ int java_nio_Buffer::limit_offset() {
void java_nio_Buffer::compute_offsets() {
Klass* k = SystemDictionary::nio_Buffer_klass();
InstanceKlass* k = SystemDictionary::nio_Buffer_klass();
assert(k != NULL, "must be loaded in 1.4+");
compute_offset(_limit_offset, k, vmSymbols::limit_name(), vmSymbols::int_signature());
compute_offset(_limit_offset, k, "limit", vmSymbols::int_signature());
}
void java_util_concurrent_locks_AbstractOwnableSynchronizer::initialize(TRAPS) {
if (_owner_offset != 0) return;
SystemDictionary::load_abstract_ownable_synchronizer_klass(CHECK);
Klass* k = SystemDictionary::abstract_ownable_synchronizer_klass();
InstanceKlass* k = SystemDictionary::abstract_ownable_synchronizer_klass();
compute_offset(_owner_offset, k,
vmSymbols::exclusive_owner_thread_name(), vmSymbols::thread_signature());
"exclusiveOwnerThread", vmSymbols::thread_signature());
}
oop java_util_concurrent_locks_AbstractOwnableSynchronizer::get_owner_threadObj(oop obj) {
@ -3823,71 +3810,37 @@ oop java_util_concurrent_locks_AbstractOwnableSynchronizer::get_owner_threadObj(
return obj->obj_field(_owner_offset);
}
static int member_offset(int hardcoded_offset) {
return (hardcoded_offset * heapOopSize) + instanceOopDesc::base_offset_in_bytes();
}
// Compute hard-coded offsets
// Invoked before SystemDictionary::initialize, so pre-loaded classes
// are not available to determine the offset_of_static_fields.
void JavaClasses::compute_hard_coded_offsets() {
const int x = heapOopSize;
const int header = instanceOopDesc::base_offset_in_bytes();
// Throwable Class
java_lang_Throwable::backtrace_offset = java_lang_Throwable::hc_backtrace_offset * x + header;
java_lang_Throwable::detailMessage_offset = java_lang_Throwable::hc_detailMessage_offset * x + header;
java_lang_Throwable::stackTrace_offset = java_lang_Throwable::hc_stackTrace_offset * x + header;
java_lang_Throwable::static_unassigned_stacktrace_offset = java_lang_Throwable::hc_static_unassigned_stacktrace_offset * x;
// java_lang_boxing_object
java_lang_boxing_object::value_offset = java_lang_boxing_object::hc_value_offset + header;
java_lang_boxing_object::long_value_offset = align_up((java_lang_boxing_object::hc_value_offset + header), BytesPerLong);
// java_lang_ref_Reference:
java_lang_ref_Reference::referent_offset = java_lang_ref_Reference::hc_referent_offset * x + header;
java_lang_ref_Reference::queue_offset = java_lang_ref_Reference::hc_queue_offset * x + header;
java_lang_ref_Reference::next_offset = java_lang_ref_Reference::hc_next_offset * x + header;
java_lang_ref_Reference::discovered_offset = java_lang_ref_Reference::hc_discovered_offset * x + header;
// Artificial fields for java_lang_ref_Reference
// The first field is for the discovered field added in 1.4
java_lang_ref_Reference::number_of_fake_oop_fields = 1;
// java_lang_ref_SoftReference Class
java_lang_ref_SoftReference::timestamp_offset = align_up((java_lang_ref_SoftReference::hc_timestamp_offset * x + header), BytesPerLong);
// Don't multiply static fields because they are always in wordSize units
java_lang_ref_SoftReference::static_clock_offset = java_lang_ref_SoftReference::hc_static_clock_offset * x;
// java_lang_ClassLoader
java_lang_ClassLoader::parent_offset = java_lang_ClassLoader::hc_parent_offset * x + header;
// java_lang_System
java_lang_System::static_in_offset = java_lang_System::hc_static_in_offset * x;
java_lang_System::static_out_offset = java_lang_System::hc_static_out_offset * x;
java_lang_System::static_err_offset = java_lang_System::hc_static_err_offset * x;
java_lang_System::static_security_offset = java_lang_System::hc_static_security_offset * x;
// java_lang_StackTraceElement
java_lang_StackTraceElement::declaringClassObject_offset = java_lang_StackTraceElement::hc_declaringClassObject_offset * x + header;
java_lang_StackTraceElement::classLoaderName_offset = java_lang_StackTraceElement::hc_classLoaderName_offset * x + header;
java_lang_StackTraceElement::moduleName_offset = java_lang_StackTraceElement::hc_moduleName_offset * x + header;
java_lang_StackTraceElement::moduleVersion_offset = java_lang_StackTraceElement::hc_moduleVersion_offset * x + header;
java_lang_StackTraceElement::declaringClass_offset = java_lang_StackTraceElement::hc_declaringClass_offset * x + header;
java_lang_StackTraceElement::methodName_offset = java_lang_StackTraceElement::hc_methodName_offset * x + header;
java_lang_StackTraceElement::fileName_offset = java_lang_StackTraceElement::hc_fileName_offset * x + header;
java_lang_StackTraceElement::lineNumber_offset = java_lang_StackTraceElement::hc_lineNumber_offset * x + header;
java_lang_AssertionStatusDirectives::classes_offset = java_lang_AssertionStatusDirectives::hc_classes_offset * x + header;
java_lang_AssertionStatusDirectives::classEnabled_offset = java_lang_AssertionStatusDirectives::hc_classEnabled_offset * x + header;
java_lang_AssertionStatusDirectives::packages_offset = java_lang_AssertionStatusDirectives::hc_packages_offset * x + header;
java_lang_AssertionStatusDirectives::packageEnabled_offset = java_lang_AssertionStatusDirectives::hc_packageEnabled_offset * x + header;
java_lang_AssertionStatusDirectives::deflt_offset = java_lang_AssertionStatusDirectives::hc_deflt_offset * x + header;
java_lang_boxing_object::value_offset = member_offset(java_lang_boxing_object::hc_value_offset);
java_lang_boxing_object::long_value_offset = align_up(member_offset(java_lang_boxing_object::hc_value_offset), BytesPerLong);
// java_lang_ref_Reference
java_lang_ref_Reference::referent_offset = member_offset(java_lang_ref_Reference::hc_referent_offset);
java_lang_ref_Reference::queue_offset = member_offset(java_lang_ref_Reference::hc_queue_offset);
java_lang_ref_Reference::next_offset = member_offset(java_lang_ref_Reference::hc_next_offset);
java_lang_ref_Reference::discovered_offset = member_offset(java_lang_ref_Reference::hc_discovered_offset);
}
// Compute non-hard-coded field offsets of all the classes in this file
void JavaClasses::compute_offsets() {
// java_lang_Class::compute_offsets was called earlier in bootstrap
java_lang_System::compute_offsets();
java_lang_ClassLoader::compute_offsets();
java_lang_Throwable::compute_offsets();
java_lang_Thread::compute_offsets();
java_lang_ThreadGroup::compute_offsets();
java_lang_AssertionStatusDirectives::compute_offsets();
java_lang_ref_SoftReference::compute_offsets();
java_lang_invoke_MethodHandle::compute_offsets();
java_lang_invoke_DirectMethodHandle::compute_offsets();
java_lang_invoke_MemberName::compute_offsets();
@ -3910,6 +3863,7 @@ void JavaClasses::compute_offsets() {
reflect_UnsafeStaticFieldAccessorImpl::compute_offsets();
java_lang_reflect_Parameter::compute_offsets();
java_lang_Module::compute_offsets();
java_lang_StackTraceElement::compute_offsets();
java_lang_StackFrameInfo::compute_offsets();
java_lang_LiveStackFrameInfo::compute_offsets();
@ -3947,62 +3901,6 @@ bool JavaClasses::check_offset(const char *klass_name, int hardcoded_offset, con
}
}
bool JavaClasses::check_static_offset(const char *klass_name, int hardcoded_offset, const char *field_name, const char* field_sig) {
EXCEPTION_MARK;
fieldDescriptor fd;
TempNewSymbol klass_sym = SymbolTable::new_symbol(klass_name, CATCH);
Klass* k = SystemDictionary::resolve_or_fail(klass_sym, true, CATCH);
InstanceKlass* ik = InstanceKlass::cast(k);
TempNewSymbol f_name = SymbolTable::new_symbol(field_name, CATCH);
TempNewSymbol f_sig = SymbolTable::new_symbol(field_sig, CATCH);
if (!ik->find_local_field(f_name, f_sig, &fd)) {
tty->print_cr("Static field %s.%s not found", klass_name, field_name);
return false;
}
if (!fd.is_static()) {
tty->print_cr("Static field %s.%s appears to be nonstatic", klass_name, field_name);
return false;
}
if (fd.offset() == hardcoded_offset + InstanceMirrorKlass::offset_of_static_fields()) {
return true;
} else {
tty->print_cr("Offset of static field %s.%s is hardcoded as %d but should really be %d.", klass_name, field_name, hardcoded_offset, fd.offset() - InstanceMirrorKlass::offset_of_static_fields());
return false;
}
}
bool JavaClasses::check_constant(const char *klass_name, int hardcoded_constant, const char *field_name, const char* field_sig) {
EXCEPTION_MARK;
fieldDescriptor fd;
TempNewSymbol klass_sym = SymbolTable::new_symbol(klass_name, CATCH);
Klass* k = SystemDictionary::resolve_or_fail(klass_sym, true, CATCH);
InstanceKlass* ik = InstanceKlass::cast(k);
TempNewSymbol f_name = SymbolTable::new_symbol(field_name, CATCH);
TempNewSymbol f_sig = SymbolTable::new_symbol(field_sig, CATCH);
if (!ik->find_local_field(f_name, f_sig, &fd)) {
tty->print_cr("Static field %s.%s not found", klass_name, field_name);
return false;
}
if (!fd.is_static() || !fd.has_initial_value()) {
tty->print_cr("Static field %s.%s appears to be non-constant", klass_name, field_name);
return false;
}
if (!fd.initial_value_tag().is_int()) {
tty->print_cr("Static field %s.%s is not an int", klass_name, field_name);
return false;
}
jint field_value = fd.int_initial_value();
if (field_value == hardcoded_constant) {
return true;
} else {
tty->print_cr("Constant value of static field %s.%s is hardcoded as %d but should really be %d.", klass_name, field_name, hardcoded_constant, field_value);
return false;
}
}
// Check the hard-coded field offsets of all the classes in this file
void JavaClasses::check_offsets() {
@ -4014,31 +3912,6 @@ void JavaClasses::check_offsets() {
#define CHECK_LONG_OFFSET(klass_name, cpp_klass_name, field_name, field_sig) \
valid &= check_offset(klass_name, cpp_klass_name :: long_ ## field_name ## _offset, #field_name, field_sig)
#define CHECK_STATIC_OFFSET(klass_name, cpp_klass_name, field_name, field_sig) \
valid &= check_static_offset(klass_name, cpp_klass_name :: static_ ## field_name ## _offset, #field_name, field_sig)
#define CHECK_CONSTANT(klass_name, cpp_klass_name, field_name, field_sig) \
valid &= check_constant(klass_name, cpp_klass_name :: field_name, #field_name, field_sig)
// java.lang.String
CHECK_OFFSET("java/lang/String", java_lang_String, value, "[B");
CHECK_OFFSET("java/lang/String", java_lang_String, hash, "I");
CHECK_OFFSET("java/lang/String", java_lang_String, coder, "B");
// java.lang.Class
// Fake fields
// CHECK_OFFSET("java/lang/Class", java_lang_Class, klass); // %%% this needs to be checked
// CHECK_OFFSET("java/lang/Class", java_lang_Class, array_klass); // %%% this needs to be checked
// java.lang.Throwable
CHECK_OFFSET("java/lang/Throwable", java_lang_Throwable, backtrace, "Ljava/lang/Object;");
CHECK_OFFSET("java/lang/Throwable", java_lang_Throwable, detailMessage, "Ljava/lang/String;");
CHECK_OFFSET("java/lang/Throwable", java_lang_Throwable, stackTrace, "[Ljava/lang/StackTraceElement;");
CHECK_OFFSET("java/lang/Throwable", java_lang_Throwable, depth, "I");
// Boxed primitive objects (java_lang_boxing_object)
CHECK_OFFSET("java/lang/Boolean", java_lang_boxing_object, value, "Z");
@ -4050,28 +3923,6 @@ void JavaClasses::check_offsets() {
CHECK_OFFSET("java/lang/Integer", java_lang_boxing_object, value, "I");
CHECK_LONG_OFFSET("java/lang/Long", java_lang_boxing_object, value, "J");
// java.lang.ClassLoader
CHECK_OFFSET("java/lang/ClassLoader", java_lang_ClassLoader, parent, "Ljava/lang/ClassLoader;");
// java.lang.System
CHECK_STATIC_OFFSET("java/lang/System", java_lang_System, in, "Ljava/io/InputStream;");
CHECK_STATIC_OFFSET("java/lang/System", java_lang_System, out, "Ljava/io/PrintStream;");
CHECK_STATIC_OFFSET("java/lang/System", java_lang_System, err, "Ljava/io/PrintStream;");
CHECK_STATIC_OFFSET("java/lang/System", java_lang_System, security, "Ljava/lang/SecurityManager;");
// java.lang.StackTraceElement
CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, declaringClassObject, "Ljava/lang/Class;");
CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, classLoaderName, "Ljava/lang/String;");
CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, moduleName, "Ljava/lang/String;");
CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, moduleVersion, "Ljava/lang/String;");
CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, declaringClass, "Ljava/lang/String;");
CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, methodName, "Ljava/lang/String;");
CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, fileName, "Ljava/lang/String;");
CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, lineNumber, "I");
// java.lang.ref.Reference
CHECK_OFFSET("java/lang/ref/Reference", java_lang_ref_Reference, referent, "Ljava/lang/Object;");
@ -4080,28 +3931,6 @@ void JavaClasses::check_offsets() {
// Fake field
//CHECK_OFFSET("java/lang/ref/Reference", java_lang_ref_Reference, discovered, "Ljava/lang/ref/Reference;");
// java.lang.ref.SoftReference
CHECK_OFFSET("java/lang/ref/SoftReference", java_lang_ref_SoftReference, timestamp, "J");
CHECK_STATIC_OFFSET("java/lang/ref/SoftReference", java_lang_ref_SoftReference, clock, "J");
// java.lang.AssertionStatusDirectives
//
// The CheckAssertionStatusDirectives boolean can be removed from here and
// globals.hpp after the AssertionStatusDirectives class has been integrated
// into merlin "for some time." Without it, the vm will fail with early
// merlin builds.
if (CheckAssertionStatusDirectives) {
const char* nm = "java/lang/AssertionStatusDirectives";
const char* sig = "[Ljava/lang/String;";
CHECK_OFFSET(nm, java_lang_AssertionStatusDirectives, classes, sig);
CHECK_OFFSET(nm, java_lang_AssertionStatusDirectives, classEnabled, "[Z");
CHECK_OFFSET(nm, java_lang_AssertionStatusDirectives, packages, sig);
CHECK_OFFSET(nm, java_lang_AssertionStatusDirectives, packageEnabled, "[Z");
CHECK_OFFSET(nm, java_lang_AssertionStatusDirectives, deflt, "Z");
}
if (!valid) vm_exit_during_initialization("Hard-coded field offset verification failed");
}

View File

@ -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
@ -102,6 +102,7 @@ class java_lang_String : AllStatic {
// Accessors
static inline typeArrayOop value(oop java_string);
static inline typeArrayOop value_no_keepalive(oop java_string);
static inline unsigned int hash(oop java_string);
static inline bool is_latin1(oop java_string);
static inline int length(oop java_string);
@ -444,9 +445,6 @@ class java_lang_Throwable: AllStatic {
hc_cause_offset = 2, // New since 1.4
hc_stackTrace_offset = 3 // New since 1.4
};
enum {
hc_static_unassigned_stacktrace_offset = 0 // New since 1.7
};
// Trace constants
enum {
trace_methods_offset = 0,
@ -878,7 +876,6 @@ class java_lang_ref_Reference: AllStatic {
static int queue_offset;
static int next_offset;
static int discovered_offset;
static int number_of_fake_oop_fields;
// Accessors
static inline oop referent(oop ref);
@ -902,14 +899,6 @@ class java_lang_ref_Reference: AllStatic {
class java_lang_ref_SoftReference: public java_lang_ref_Reference {
public:
enum {
// The timestamp is a long field and may need to be adjusted for alignment.
hc_timestamp_offset = hc_discovered_offset + 1
};
enum {
hc_static_clock_offset = 0
};
static int timestamp_offset;
static int static_clock_offset;
@ -919,6 +908,8 @@ class java_lang_ref_SoftReference: public java_lang_ref_Reference {
// Accessors for statics
static jlong clock();
static void set_clock(jlong value);
static void compute_offsets();
};
// Interface to java.lang.invoke.MethodHandle objects
@ -1228,10 +1219,6 @@ class java_security_AccessControlContext: AllStatic {
class java_lang_ClassLoader : AllStatic {
private:
// The fake offsets are added by the class loader when java.lang.Class is loaded
enum {
hc_parent_offset = 0
};
static int _loader_data_offset;
static bool offsets_computed;
static int parent_offset;
@ -1279,13 +1266,6 @@ class java_lang_ClassLoader : AllStatic {
class java_lang_System : AllStatic {
private:
enum {
hc_static_in_offset = 0,
hc_static_out_offset = 1,
hc_static_err_offset = 2,
hc_static_security_offset = 3
};
static int static_in_offset;
static int static_out_offset;
static int static_err_offset;
@ -1298,6 +1278,8 @@ class java_lang_System : AllStatic {
static bool has_security_manager();
static void compute_offsets();
// Debugging
friend class JavaClasses;
};
@ -1307,17 +1289,6 @@ class java_lang_System : AllStatic {
class java_lang_StackTraceElement: AllStatic {
private:
enum {
hc_declaringClassObject_offset = 0,
hc_classLoaderName_offset = 1,
hc_moduleName_offset = 2,
hc_moduleVersion_offset = 3,
hc_declaringClass_offset = 4,
hc_methodName_offset = 5,
hc_fileName_offset = 6,
hc_lineNumber_offset = 7
};
static int declaringClassObject_offset;
static int classLoaderName_offset;
static int moduleName_offset;
@ -1344,6 +1315,8 @@ class java_lang_StackTraceElement: AllStatic {
static void fill_in(Handle element, InstanceKlass* holder, const methodHandle& method,
int version, int bci, Symbol* name, TRAPS);
static void compute_offsets();
// Debugging
friend class JavaClasses;
};
@ -1416,14 +1389,6 @@ class java_lang_LiveStackFrameInfo: AllStatic {
class java_lang_AssertionStatusDirectives: AllStatic {
private:
enum {
hc_classes_offset,
hc_classEnabled_offset,
hc_packages_offset,
hc_packageEnabled_offset,
hc_deflt_offset
};
static int classes_offset;
static int classEnabled_offset;
static int packages_offset;
@ -1437,6 +1402,9 @@ class java_lang_AssertionStatusDirectives: AllStatic {
static void set_packages(oop obj, oop val);
static void set_packageEnabled(oop obj, oop val);
static void set_deflt(oop obj, bool val);
static void compute_offsets();
// Debugging
friend class JavaClasses;
};
@ -1508,9 +1476,6 @@ class JavaClasses : AllStatic {
static InjectedField _injected_fields[];
static bool check_offset(const char *klass_name, int offset, const char *field_name, const char* field_sig) PRODUCT_RETURN0;
static bool check_static_offset(const char *klass_name, int hardcoded_offset, const char *field_name, const char* field_sig) PRODUCT_RETURN0;
static bool check_constant(const char *klass_name, int constant, const char *field_name, const char* field_sig) PRODUCT_RETURN0;
public:
enum InjectedFieldID {
ALL_INJECTED_FIELDS(DECLARE_INJECTED_FIELD_ENUM)

View File

@ -26,6 +26,7 @@
#define SHARE_VM_CLASSFILE_JAVACLASSES_INLINE_HPP
#include "classfile/javaClasses.hpp"
#include "oops/access.inline.hpp"
#include "oops/oop.inline.hpp"
#include "oops/oopsHierarchy.hpp"
@ -53,6 +54,11 @@ typeArrayOop java_lang_String::value(oop java_string) {
assert(is_instance(java_string), "must be java_string");
return (typeArrayOop) java_string->obj_field(value_offset);
}
typeArrayOop java_lang_String::value_no_keepalive(oop java_string) {
assert(initialized && (value_offset > 0), "Must be initialized");
assert(is_instance(java_string), "must be java_string");
return (typeArrayOop) java_string->obj_field_access<AS_NO_KEEPALIVE>(value_offset);
}
unsigned int java_lang_String::hash(oop java_string) {
assert(initialized && (hash_offset > 0), "Must be initialized");
assert(is_instance(java_string), "must be java_string");
@ -68,11 +74,11 @@ bool java_lang_String::is_latin1(oop java_string) {
int java_lang_String::length(oop java_string) {
assert(initialized, "Must be initialized");
assert(is_instance(java_string), "must be java_string");
typeArrayOop value_array = ((typeArrayOop)java_string->obj_field(value_offset));
if (value_array == NULL) {
typeArrayOop value = java_lang_String::value_no_keepalive(java_string);
if (value == NULL) {
return 0;
}
int arr_length = value_array->length();
int arr_length = value->length();
if (!is_latin1(java_string)) {
assert((arr_length & 1) == 0, "should be even for UTF16 string");
arr_length >>= 1; // convert number of bytes to number of elements

View File

@ -35,6 +35,7 @@
#include "memory/filemap.hpp"
#include "memory/metaspaceShared.hpp"
#include "memory/resourceArea.hpp"
#include "oops/access.inline.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/atomic.hpp"
#include "runtime/mutexLocker.hpp"
@ -43,7 +44,6 @@
#include "utilities/macros.hpp"
#if INCLUDE_ALL_GCS
#include "gc/g1/g1CollectedHeap.hpp"
#include "gc/g1/g1SATBCardTableModRefBS.hpp"
#include "gc/g1/g1StringDedup.hpp"
#endif
@ -124,6 +124,22 @@ unsigned int StringTable::hash_string(oop string) {
}
}
oop StringTable::string_object(HashtableEntry<oop, mtSymbol>* entry) {
return RootAccess<ON_PHANTOM_OOP_REF>::oop_load(entry->literal_addr());
}
oop StringTable::string_object_no_keepalive(HashtableEntry<oop, mtSymbol>* entry) {
// The AS_NO_KEEPALIVE peeks at the oop without keeping it alive.
// This is *very dangerous* in general but is okay in this specific
// case. The subsequent oop_load keeps the oop alive if it it matched
// the jchar* string.
return RootAccess<ON_PHANTOM_OOP_REF | AS_NO_KEEPALIVE>::oop_load(entry->literal_addr());
}
void StringTable::set_string_object(HashtableEntry<oop, mtSymbol>* entry, oop string) {
RootAccess<ON_PHANTOM_OOP_REF>::oop_store(entry->literal_addr(), string);
}
oop StringTable::lookup_shared(jchar* name, int len, unsigned int hash) {
assert(hash == java_lang_String::hash_code(name, len),
"hash must be computed using java_lang_String::hash_code");
@ -131,13 +147,16 @@ oop StringTable::lookup_shared(jchar* name, int len, unsigned int hash) {
}
oop StringTable::lookup_in_main_table(int index, jchar* name,
int len, unsigned int hash) {
int len, unsigned int hash) {
int count = 0;
for (HashtableEntry<oop, mtSymbol>* l = bucket(index); l != NULL; l = l->next()) {
count++;
if (l->hash() == hash) {
if (java_lang_String::equals(l->literal(), name, len)) {
return l->literal();
if (java_lang_String::equals(string_object_no_keepalive(l), name, len)) {
// We must perform a new load with string_object() that keeps the string
// alive as we must expose the oop as strongly reachable when exiting
// this context, in case the oop gets published.
return string_object(l);
}
}
}
@ -192,18 +211,6 @@ oop StringTable::lookup(Symbol* symbol) {
return lookup(chars, length);
}
// Tell the GC that this string was looked up in the StringTable.
static void ensure_string_alive(oop string) {
// A lookup in the StringTable could return an object that was previously
// considered dead. The SATB part of G1 needs to get notified about this
// potential resurrection, otherwise the marking might not find the object.
#if INCLUDE_ALL_GCS
if (UseG1GC && string != NULL) {
G1SATBCardTableModRefBS::enqueue(string);
}
#endif
}
oop StringTable::lookup(jchar* name, int len) {
// shared table always uses java_lang_String::hash_code
unsigned int hash = java_lang_String::hash_code(name, len);
@ -217,8 +224,6 @@ oop StringTable::lookup(jchar* name, int len) {
int index = the_table()->hash_to_index(hash);
string = the_table()->lookup_in_main_table(index, name, len, hash);
ensure_string_alive(string);
return string;
}
@ -238,9 +243,6 @@ oop StringTable::intern(Handle string_or_null, jchar* name,
// Found
if (found_string != NULL) {
if (found_string != string_or_null()) {
ensure_string_alive(found_string);
}
return found_string;
}
@ -276,10 +278,6 @@ oop StringTable::intern(Handle string_or_null, jchar* name,
hashValue, CHECK_NULL);
}
if (added_or_found != string()) {
ensure_string_alive(added_or_found);
}
return added_or_found;
}
@ -388,9 +386,9 @@ void StringTable::buckets_unlink_or_oops_do(BoolObjectClosure* is_alive, OopClos
while (entry != NULL) {
assert(!entry->is_shared(), "CDS not used for the StringTable");
if (is_alive->do_object_b(entry->literal())) {
if (is_alive->do_object_b(string_object_no_keepalive(entry))) {
if (f != NULL) {
f->do_oop((oop*)entry->literal_addr());
f->do_oop(entry->literal_addr());
}
p = entry->next_addr();
} else {
@ -429,7 +427,7 @@ void StringTable::verify() {
for (int i = 0; i < the_table()->table_size(); ++i) {
HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i);
for ( ; p != NULL; p = p->next()) {
oop s = p->literal();
oop s = string_object_no_keepalive(p);
guarantee(s != NULL, "interned string is NULL");
unsigned int h = hash_string(s);
guarantee(p->hash() == h, "broken hash in string table entry");
@ -448,10 +446,10 @@ void StringTable::dump(outputStream* st, bool verbose) {
for (int i = 0; i < the_table()->table_size(); ++i) {
HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i);
for ( ; p != NULL; p = p->next()) {
oop s = p->literal();
typeArrayOop value = java_lang_String::value(s);
int length = java_lang_String::length(s);
bool is_latin1 = java_lang_String::is_latin1(s);
oop s = string_object_no_keepalive(p);
typeArrayOop value = java_lang_String::value_no_keepalive(s);
int length = java_lang_String::length(s);
bool is_latin1 = java_lang_String::is_latin1(s);
if (length <= 0) {
st->print("%d: ", length);
@ -484,8 +482,8 @@ StringTable::VerifyRetTypes StringTable::compare_entries(
HashtableEntry<oop, mtSymbol>* e_ptr2) {
// These entries are sanity checked by verify_and_compare_entries()
// before this function is called.
oop str1 = e_ptr1->literal();
oop str2 = e_ptr2->literal();
oop str1 = string_object_no_keepalive(e_ptr1);
oop str2 = string_object_no_keepalive(e_ptr2);
if (str1 == str2) {
tty->print_cr("ERROR: identical oop values (0x" PTR_FORMAT ") "
@ -505,12 +503,12 @@ StringTable::VerifyRetTypes StringTable::compare_entries(
}
StringTable::VerifyRetTypes StringTable::verify_entry(int bkt, int e_cnt,
HashtableEntry<oop, mtSymbol>* e_ptr,
StringTable::VerifyMesgModes mesg_mode) {
HashtableEntry<oop, mtSymbol>* e_ptr,
StringTable::VerifyMesgModes mesg_mode) {
VerifyRetTypes ret = _verify_pass; // be optimistic
oop str = e_ptr->literal();
oop str = string_object_no_keepalive(e_ptr);
if (str == NULL) {
if (mesg_mode == _verify_with_mesgs) {
tty->print_cr("ERROR: NULL oop value in entry @ bucket[%d][%d]", bkt,
@ -684,7 +682,7 @@ oop StringTable::create_archived_string(oop s, Thread* THREAD) {
assert(DumpSharedSpaces, "this function is only used with -Xshare:dump");
oop new_s = NULL;
typeArrayOop v = java_lang_String::value(s);
typeArrayOop v = java_lang_String::value_no_keepalive(s);
typeArrayOop new_v = (typeArrayOop)MetaspaceShared::archive_heap_object(v, THREAD);
if (new_v == NULL) {
return NULL;
@ -708,7 +706,7 @@ bool StringTable::copy_shared_string(GrowableArray<MemRegion> *string_space,
for (int i = 0; i < the_table()->table_size(); ++i) {
HashtableEntry<oop, mtSymbol>* bucket = the_table()->bucket(i);
for ( ; bucket != NULL; bucket = bucket->next()) {
oop s = bucket->literal();
oop s = string_object_no_keepalive(bucket);
unsigned int hash = java_lang_String::hash_code(s);
if (hash == 0) {
continue;
@ -721,7 +719,7 @@ bool StringTable::copy_shared_string(GrowableArray<MemRegion> *string_space,
}
// set the archived string in bucket
bucket->set_literal(new_s);
set_string_object(bucket, new_s);
// add to the compact table
writer->add(hash, new_s);
@ -763,4 +761,3 @@ void StringTable::shared_oops_do(OopClosure* f) {
_shared_table.oops_do(f);
}
#endif //INCLUDE_CDS_JAVA_HEAP

View File

@ -76,6 +76,13 @@ private:
static unsigned int hash_string(oop string);
static unsigned int alt_hash_string(const jchar* s, int len);
// Accessors for the string roots in the hashtable entries.
// Use string_object_no_keepalive() only when the value is not returned
// outside of a scope where a thread transition is possible.
static oop string_object(HashtableEntry<oop, mtSymbol>* entry);
static oop string_object_no_keepalive(HashtableEntry<oop, mtSymbol>* entry);
static void set_string_object(HashtableEntry<oop, mtSymbol>* entry, oop string);
StringTable() : RehashableHashtable<oop, mtSymbol>((int)StringTableSize,
sizeof (HashtableEntry<oop, mtSymbol>)) {}

View File

@ -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
@ -173,6 +173,7 @@ class GCTimer;
do_klass(VolatileCallSite_klass, java_lang_invoke_VolatileCallSite, Pre ) \
/* Note: MethodHandle must be first, and VolatileCallSite last in group */ \
\
do_klass(AssertionStatusDirectives_klass, java_lang_AssertionStatusDirectives, Pre ) \
do_klass(StringBuffer_klass, java_lang_StringBuffer, Pre ) \
do_klass(StringBuilder_klass, java_lang_StringBuilder, Pre ) \
do_klass(internal_Unsafe_klass, jdk_internal_misc_Unsafe, Pre ) \

View File

@ -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
@ -251,7 +251,6 @@
template(compiledLambdaForm_name, "<compiledLambdaForm>") /*fake name*/ \
template(star_name, "*") /*not really a name*/ \
template(invoke_name, "invoke") \
template(override_name, "override") \
template(parameterTypes_name, "parameterTypes") \
template(returnType_name, "returnType") \
template(signature_name, "signature") \
@ -265,7 +264,6 @@
template(parameter_annotations_name, "parameterAnnotations") \
template(annotation_default_name, "annotationDefault") \
template(reflect_ConstantPool, "jdk/internal/reflect/ConstantPool") \
template(ConstantPool_name, "constantPoolOop") \
template(reflect_UnsafeStaticFieldAccessorImpl, "jdk/internal/reflect/UnsafeStaticFieldAccessorImpl")\
template(base_name, "base") \
/* Type Annotations (JDK 8 and above) */ \
@ -341,8 +339,6 @@
template(stillborn_name, "stillborn") \
template(group_name, "group") \
template(daemon_name, "daemon") \
template(eetop_name, "eetop") \
template(thread_status_name, "threadStatus") \
template(run_method_name, "run") \
template(exit_method_name, "exit") \
template(add_method_name, "add") \
@ -376,34 +372,21 @@
template(fillInStackTrace_name, "fillInStackTrace") \
template(getCause_name, "getCause") \
template(initCause_name, "initCause") \
template(depth_name, "depth") \
template(setProperty_name, "setProperty") \
template(getProperty_name, "getProperty") \
template(context_name, "context") \
template(privilegedContext_name, "privilegedContext") \
template(contextClassLoader_name, "contextClassLoader") \
template(inheritedAccessControlContext_name, "inheritedAccessControlContext") \
template(isPrivileged_name, "isPrivileged") \
template(isAuthorized_name, "isAuthorized") \
template(getClassContext_name, "getClassContext") \
template(wait_name, "wait") \
template(checkPackageAccess_name, "checkPackageAccess") \
template(stackSize_name, "stackSize") \
template(thread_id_name, "tid") \
template(newInstance0_name, "newInstance0") \
template(limit_name, "limit") \
template(member_name, "member") \
template(forName_name, "forName") \
template(forName0_name, "forName0") \
template(isJavaIdentifierStart_name, "isJavaIdentifierStart") \
template(isJavaIdentifierPart_name, "isJavaIdentifierPart") \
template(exclusive_owner_thread_name, "exclusiveOwnerThread") \
template(park_blocker_name, "parkBlocker") \
template(park_event_name, "nativeParkEventPointer") \
template(cache_field_name, "cache") \
template(value_name, "value") \
template(hash_name, "hash") \
template(coder_name, "coder") \
template(compact_strings_name, "COMPACT_STRINGS") \
template(numberOfLeadingZeros_name, "numberOfLeadingZeros") \
template(numberOfTrailingZeros_name, "numberOfTrailingZeros") \
@ -420,27 +403,17 @@
template(method_name, "method") \
template(vmindex_name, "vmindex") \
template(vmcount_name, "vmcount") \
template(vmentry_name, "vmentry") \
template(flags_name, "flags") \
template(rtype_name, "rtype") \
template(ptypes_name, "ptypes") \
template(form_name, "form") \
template(basicType_name, "basicType") \
template(append_name, "append") \
template(klass_name, "klass") \
template(array_klass_name, "array_klass") \
template(memberName_name, "memberName") \
template(mid_name, "mid") \
template(cpref_name, "cpref") \
template(version_name, "version") \
template(bci_name, "bci") \
template(methodName_name, "methodName") \
template(fileName_name, "fileName") \
template(lineNumber_name, "lineNumber") \
template(monitors_name, "monitors") \
template(locals_name, "locals") \
template(operands_name, "operands") \
template(mode_name, "mode") \
template(oop_size_name, "oop_size") \
template(static_oop_field_count_name, "static_oop_field_count") \
template(protection_domain_name, "protection_domain") \
@ -448,9 +421,11 @@
template(loader_data_name, "loader_data") \
template(vmdependencies_name, "vmdependencies") \
template(loader_name, "loader") \
template(module_name, "module") \
template(getModule_name, "getModule") \
template(input_stream_void_signature, "(Ljava/io/InputStream;)V") \
template(input_stream_signature, "Ljava/io/InputStream;") \
template(print_stream_signature, "Ljava/io/PrintStream;") \
template(security_manager_signature, "Ljava/lang/SecurityManager;") \
template(definePackage_name, "definePackage") \
template(definePackage_signature, "(Ljava/lang/String;Ljava/lang/Module;)Ljava/lang/Package;") \
template(defineOrCheckPackage_name, "defineOrCheckPackage") \
@ -499,6 +474,7 @@
template(short_signature, "S") \
template(bool_signature, "Z") \
template(void_signature, "V") \
template(bool_array_signature, "[Z") \
template(byte_array_signature, "[B") \
template(char_array_signature, "[C") \
template(int_array_signature, "[I") \
@ -553,6 +529,7 @@
template(object_array_signature, "[Ljava/lang/Object;") \
template(class_signature, "Ljava/lang/Class;") \
template(string_signature, "Ljava/lang/String;") \
template(string_array_signature, "[Ljava/lang/String;") \
template(reference_signature, "Ljava/lang/ref/Reference;") \
template(sun_misc_Cleaner_signature, "Lsun/misc/Cleaner;") \
template(executable_signature, "Ljava/lang/reflect/Executable;") \
@ -579,12 +556,6 @@
/* used by ClassFormatError when class name is not known yet */ \
template(unknown_class_name, "<Unknown>") \
\
/* used to identify class loaders handling parallel class loading */ \
template(parallelCapable_name, "parallelLockMap") \
\
/* used to return a class loader's unnamed module */ \
template(unnamedModule_name, "unnamedModule") \
\
/* JVM monitoring and management support */ \
template(java_lang_StackTraceElement_array, "[Ljava/lang/StackTraceElement;") \
template(java_lang_management_ThreadState, "java/lang/management/ThreadState") \

View File

@ -445,9 +445,7 @@ HeapWord* G1CollectedHeap::allocate_new_tlab(size_t word_size) {
assert_heap_not_locked_and_not_at_safepoint();
assert(!is_humongous(word_size), "we do not allow humongous TLABs");
uint dummy_gc_count_before;
uint dummy_gclocker_retry_count = 0;
return attempt_allocation(word_size, &dummy_gc_count_before, &dummy_gclocker_retry_count);
return attempt_allocation(word_size);
}
HeapWord*
@ -455,62 +453,16 @@ G1CollectedHeap::mem_allocate(size_t word_size,
bool* gc_overhead_limit_was_exceeded) {
assert_heap_not_locked_and_not_at_safepoint();
// Loop until the allocation is satisfied, or unsatisfied after GC.
for (uint try_count = 1, gclocker_retry_count = 0; /* we'll return */; try_count += 1) {
uint gc_count_before;
HeapWord* result = NULL;
if (!is_humongous(word_size)) {
result = attempt_allocation(word_size, &gc_count_before, &gclocker_retry_count);
} else {
result = attempt_allocation_humongous(word_size, &gc_count_before, &gclocker_retry_count);
}
if (result != NULL) {
return result;
}
// Create the garbage collection operation...
VM_G1CollectForAllocation op(gc_count_before, word_size);
op.set_allocation_context(AllocationContext::current());
// ...and get the VM thread to execute it.
VMThread::execute(&op);
if (op.prologue_succeeded() && op.pause_succeeded()) {
// If the operation was successful we'll return the result even
// if it is NULL. If the allocation attempt failed immediately
// after a Full GC, it's unlikely we'll be able to allocate now.
HeapWord* result = op.result();
if (result != NULL && !is_humongous(word_size)) {
// Allocations that take place on VM operations do not do any
// card dirtying and we have to do it here. We only have to do
// this for non-humongous allocations, though.
dirty_young_block(result, word_size);
}
return result;
} else {
if (gclocker_retry_count > GCLockerRetryAllocationCount) {
return NULL;
}
assert(op.result() == NULL,
"the result should be NULL if the VM op did not succeed");
}
// Give a warning if we seem to be looping forever.
if ((QueuedAllocationWarningCount > 0) &&
(try_count % QueuedAllocationWarningCount == 0)) {
log_warning(gc)("G1CollectedHeap::mem_allocate retries %d times", try_count);
}
if (is_humongous(word_size)) {
return attempt_allocation_humongous(word_size);
}
ShouldNotReachHere();
return NULL;
return attempt_allocation(word_size);
}
HeapWord* G1CollectedHeap::attempt_allocation_slow(size_t word_size,
AllocationContext_t context,
uint* gc_count_before_ret,
uint* gclocker_retry_count_ret) {
AllocationContext_t context) {
ResourceMark rm; // For retrieving the thread names in log messages.
// Make sure you read the note in attempt_allocation_humongous().
assert_heap_not_locked_and_not_at_safepoint();
@ -525,7 +477,7 @@ HeapWord* G1CollectedHeap::attempt_allocation_slow(size_t word_size,
// fails to perform the allocation. b) is the only case when we'll
// return NULL.
HeapWord* result = NULL;
for (int try_count = 1; /* we'll return */; try_count += 1) {
for (uint try_count = 1, gclocker_retry_count = 0; /* we'll return */; try_count += 1) {
bool should_try_gc;
uint gc_count_before;
@ -536,30 +488,23 @@ HeapWord* G1CollectedHeap::attempt_allocation_slow(size_t word_size,
return result;
}
if (GCLocker::is_active_and_needs_gc()) {
if (g1_policy()->can_expand_young_list()) {
// No need for an ergo verbose message here,
// can_expand_young_list() does this when it returns true.
result = _allocator->attempt_allocation_force(word_size, context);
if (result != NULL) {
return result;
}
}
should_try_gc = false;
} else {
// The GCLocker may not be active but the GCLocker initiated
// GC may not yet have been performed (GCLocker::needs_gc()
// returns true). In this case we do not try this GC and
// wait until the GCLocker initiated GC is performed, and
// then retry the allocation.
if (GCLocker::needs_gc()) {
should_try_gc = false;
} else {
// Read the GC count while still holding the Heap_lock.
gc_count_before = total_collections();
should_try_gc = true;
// If the GCLocker is active and we are bound for a GC, try expanding young gen.
// This is different to when only GCLocker::needs_gc() is set: try to avoid
// waiting because the GCLocker is active to not wait too long.
if (GCLocker::is_active_and_needs_gc() && g1_policy()->can_expand_young_list()) {
// No need for an ergo message here, can_expand_young_list() does this when
// it returns true.
result = _allocator->attempt_allocation_force(word_size, context);
if (result != NULL) {
return result;
}
}
// Only try a GC if the GCLocker does not signal the need for a GC. Wait until
// the GCLocker initiated GC has been performed and then retry. This includes
// the case when the GC Locker is not active but has not been performed.
should_try_gc = !GCLocker::needs_gc();
// Read the GC count while still holding the Heap_lock.
gc_count_before = total_collections();
}
if (should_try_gc) {
@ -568,28 +513,33 @@ HeapWord* G1CollectedHeap::attempt_allocation_slow(size_t word_size,
GCCause::_g1_inc_collection_pause);
if (result != NULL) {
assert(succeeded, "only way to get back a non-NULL result");
log_trace(gc, alloc)("%s: Successfully scheduled collection returning " PTR_FORMAT,
Thread::current()->name(), p2i(result));
return result;
}
if (succeeded) {
// If we get here we successfully scheduled a collection which
// failed to allocate. No point in trying to allocate
// further. We'll just return NULL.
MutexLockerEx x(Heap_lock);
*gc_count_before_ret = total_collections();
// We successfully scheduled a collection which failed to allocate. No
// point in trying to allocate further. We'll just return NULL.
log_trace(gc, alloc)("%s: Successfully scheduled collection failing to allocate "
SIZE_FORMAT " words", Thread::current()->name(), word_size);
return NULL;
}
log_trace(gc, alloc)("%s: Unsuccessfully scheduled collection allocating " SIZE_FORMAT " words",
Thread::current()->name(), word_size);
} else {
if (*gclocker_retry_count_ret > GCLockerRetryAllocationCount) {
MutexLockerEx x(Heap_lock);
*gc_count_before_ret = total_collections();
// Failed to schedule a collection.
if (gclocker_retry_count > GCLockerRetryAllocationCount) {
log_warning(gc, alloc)("%s: Retried waiting for GCLocker too often allocating "
SIZE_FORMAT " words", Thread::current()->name(), word_size);
return NULL;
}
log_trace(gc, alloc)("%s: Stall until clear", Thread::current()->name());
// The GCLocker is either active or the GCLocker initiated
// GC has not yet been performed. Stall until it is and
// then retry the allocation.
GCLocker::stall_until_clear();
(*gclocker_retry_count_ret) += 1;
gclocker_retry_count += 1;
}
// We can reach here if we were unsuccessful in scheduling a
@ -600,6 +550,7 @@ HeapWord* G1CollectedHeap::attempt_allocation_slow(size_t word_size,
// first attempt (without holding the Heap_lock) here and the
// follow-on attempt will be at the start of the next loop
// iteration (after taking the Heap_lock).
result = _allocator->attempt_allocation(word_size, context);
if (result != NULL) {
return result;
@ -608,8 +559,8 @@ HeapWord* G1CollectedHeap::attempt_allocation_slow(size_t word_size,
// Give a warning if we seem to be looping forever.
if ((QueuedAllocationWarningCount > 0) &&
(try_count % QueuedAllocationWarningCount == 0)) {
log_warning(gc)("G1CollectedHeap::attempt_allocation_slow() "
"retries %d times", try_count);
log_warning(gc, alloc)("%s: Retried allocation %u times for " SIZE_FORMAT " words",
Thread::current()->name(), try_count, word_size);
}
}
@ -830,9 +781,7 @@ void G1CollectedHeap::fill_archive_regions(MemRegion* ranges, size_t count) {
}
}
inline HeapWord* G1CollectedHeap::attempt_allocation(size_t word_size,
uint* gc_count_before_ret,
uint* gclocker_retry_count_ret) {
inline HeapWord* G1CollectedHeap::attempt_allocation(size_t word_size) {
assert_heap_not_locked_and_not_at_safepoint();
assert(!is_humongous(word_size), "attempt_allocation() should not "
"be called for humongous allocation requests");
@ -841,10 +790,7 @@ inline HeapWord* G1CollectedHeap::attempt_allocation(size_t word_size,
HeapWord* result = _allocator->attempt_allocation(word_size, context);
if (result == NULL) {
result = attempt_allocation_slow(word_size,
context,
gc_count_before_ret,
gclocker_retry_count_ret);
result = attempt_allocation_slow(word_size, context);
}
assert_heap_not_locked();
if (result != NULL) {
@ -925,9 +871,9 @@ void G1CollectedHeap::dealloc_archive_regions(MemRegion* ranges, size_t count) {
decrease_used(size_used);
}
HeapWord* G1CollectedHeap::attempt_allocation_humongous(size_t word_size,
uint* gc_count_before_ret,
uint* gclocker_retry_count_ret) {
HeapWord* G1CollectedHeap::attempt_allocation_humongous(size_t word_size) {
ResourceMark rm; // For retrieving the thread names in log messages.
// The structure of this method has a lot of similarities to
// attempt_allocation_slow(). The reason these two were not merged
// into a single one is that such a method would require several "if
@ -958,10 +904,11 @@ HeapWord* G1CollectedHeap::attempt_allocation_humongous(size_t word_size,
// fails to perform the allocation. b) is the only case when we'll
// return NULL.
HeapWord* result = NULL;
for (int try_count = 1; /* we'll return */; try_count += 1) {
for (uint try_count = 1, gclocker_retry_count = 0; /* we'll return */; try_count += 1) {
bool should_try_gc;
uint gc_count_before;
{
MutexLockerEx x(Heap_lock);
@ -975,69 +922,63 @@ HeapWord* G1CollectedHeap::attempt_allocation_humongous(size_t word_size,
return result;
}
if (GCLocker::is_active_and_needs_gc()) {
should_try_gc = false;
} else {
// The GCLocker may not be active but the GCLocker initiated
// GC may not yet have been performed (GCLocker::needs_gc()
// returns true). In this case we do not try this GC and
// wait until the GCLocker initiated GC is performed, and
// then retry the allocation.
if (GCLocker::needs_gc()) {
should_try_gc = false;
} else {
// Read the GC count while still holding the Heap_lock.
gc_count_before = total_collections();
should_try_gc = true;
}
}
// Only try a GC if the GCLocker does not signal the need for a GC. Wait until
// the GCLocker initiated GC has been performed and then retry. This includes
// the case when the GC Locker is not active but has not been performed.
should_try_gc = !GCLocker::needs_gc();
// Read the GC count while still holding the Heap_lock.
gc_count_before = total_collections();
}
if (should_try_gc) {
// If we failed to allocate the humongous object, we should try to
// do a collection pause (if we're allowed) in case it reclaims
// enough space for the allocation to succeed after the pause.
bool succeeded;
result = do_collection_pause(word_size, gc_count_before, &succeeded,
GCCause::_g1_humongous_allocation);
if (result != NULL) {
assert(succeeded, "only way to get back a non-NULL result");
log_trace(gc, alloc)("%s: Successfully scheduled collection returning " PTR_FORMAT,
Thread::current()->name(), p2i(result));
return result;
}
if (succeeded) {
// If we get here we successfully scheduled a collection which
// failed to allocate. No point in trying to allocate
// further. We'll just return NULL.
MutexLockerEx x(Heap_lock);
*gc_count_before_ret = total_collections();
// We successfully scheduled a collection which failed to allocate. No
// point in trying to allocate further. We'll just return NULL.
log_trace(gc, alloc)("%s: Successfully scheduled collection failing to allocate "
SIZE_FORMAT " words", Thread::current()->name(), word_size);
return NULL;
}
log_trace(gc, alloc)("%s: Unsuccessfully scheduled collection allocating " SIZE_FORMAT "",
Thread::current()->name(), word_size);
} else {
if (*gclocker_retry_count_ret > GCLockerRetryAllocationCount) {
MutexLockerEx x(Heap_lock);
*gc_count_before_ret = total_collections();
// Failed to schedule a collection.
if (gclocker_retry_count > GCLockerRetryAllocationCount) {
log_warning(gc, alloc)("%s: Retried waiting for GCLocker too often allocating "
SIZE_FORMAT " words", Thread::current()->name(), word_size);
return NULL;
}
log_trace(gc, alloc)("%s: Stall until clear", Thread::current()->name());
// The GCLocker is either active or the GCLocker initiated
// GC has not yet been performed. Stall until it is and
// then retry the allocation.
GCLocker::stall_until_clear();
(*gclocker_retry_count_ret) += 1;
gclocker_retry_count += 1;
}
// We can reach here if we were unsuccessful in scheduling a
// collection (because another thread beat us to it) or if we were
// stalled due to the GC locker. In either can we should retry the
// allocation attempt in case another thread successfully
// performed a collection and reclaimed enough space. Give a
// warning if we seem to be looping forever.
// performed a collection and reclaimed enough space.
// Humongous object allocation always needs a lock, so we wait for the retry
// in the next iteration of the loop, unlike for the regular iteration case.
// Give a warning if we seem to be looping forever.
if ((QueuedAllocationWarningCount > 0) &&
(try_count % QueuedAllocationWarningCount == 0)) {
log_warning(gc)("G1CollectedHeap::attempt_allocation_humongous() "
"retries %d times", try_count);
log_warning(gc, alloc)("%s: Retried allocation %u times for " SIZE_FORMAT " words",
Thread::current()->name(), try_count, word_size);
}
}
@ -1339,7 +1280,6 @@ HeapWord* G1CollectedHeap::satisfy_failed_allocation_helper(size_t word_size,
context,
expect_null_mutator_alloc_region);
if (result != NULL) {
assert(*gc_succeeded, "sanity");
return result;
}
@ -1349,7 +1289,6 @@ HeapWord* G1CollectedHeap::satisfy_failed_allocation_helper(size_t word_size,
// do something smarter than full collection to satisfy a failed alloc.)
result = expand_and_allocate(word_size, context);
if (result != NULL) {
assert(*gc_succeeded, "sanity");
return result;
}
@ -1401,7 +1340,6 @@ HeapWord* G1CollectedHeap::satisfy_failed_allocation(size_t word_size,
succeeded);
if (result != NULL) {
assert(*succeeded, "sanity");
return result;
}
@ -1412,7 +1350,6 @@ HeapWord* G1CollectedHeap::satisfy_failed_allocation(size_t word_size,
// space available is large enough for the allocation, then a more
// complete compaction phase than we've tried so far might be
// appropriate.
assert(*succeeded, "sanity");
return NULL;
}
@ -2147,7 +2084,7 @@ void G1CollectedHeap::increment_old_marking_cycles_completed(bool concurrent) {
// This notify_all() will ensure that a thread that called
// System.gc() with (with ExplicitGCInvokesConcurrent set or not)
// and it's waiting for a full GC to finish will be woken up. It is
// waiting in VM_G1IncCollectionPause::doit_epilogue().
// waiting in VM_G1CollectForAllocation::doit_epilogue().
FullGCCount_lock->notify_all();
}
@ -2175,13 +2112,12 @@ void G1CollectedHeap::collect(GCCause::Cause cause) {
// Schedule an initial-mark evacuation pause that will start a
// concurrent cycle. We're setting word_size to 0 which means that
// we are not requesting a post-GC allocation.
VM_G1IncCollectionPause op(gc_count_before,
0, /* word_size */
true, /* should_initiate_conc_mark */
g1_policy()->max_pause_time_ms(),
cause);
op.set_allocation_context(AllocationContext::current());
VM_G1CollectForAllocation op(0, /* word_size */
gc_count_before,
cause,
true, /* should_initiate_conc_mark */
g1_policy()->max_pause_time_ms(),
AllocationContext::current());
VMThread::execute(&op);
if (!op.pause_succeeded()) {
if (old_marking_count_before == _old_marking_cycles_started) {
@ -2204,11 +2140,12 @@ void G1CollectedHeap::collect(GCCause::Cause cause) {
// Schedule a standard evacuation pause. We're setting word_size
// to 0 which means that we are not requesting a post-GC allocation.
VM_G1IncCollectionPause op(gc_count_before,
0, /* word_size */
false, /* should_initiate_conc_mark */
g1_policy()->max_pause_time_ms(),
cause);
VM_G1CollectForAllocation op(0, /* word_size */
gc_count_before,
cause,
false, /* should_initiate_conc_mark */
g1_policy()->max_pause_time_ms(),
AllocationContext::current());
VMThread::execute(&op);
} else {
// Schedule a Full GC.
@ -2619,13 +2556,12 @@ HeapWord* G1CollectedHeap::do_collection_pause(size_t word_size,
bool* succeeded,
GCCause::Cause gc_cause) {
assert_heap_not_locked_and_not_at_safepoint();
VM_G1IncCollectionPause op(gc_count_before,
word_size,
false, /* should_initiate_conc_mark */
g1_policy()->max_pause_time_ms(),
gc_cause);
op.set_allocation_context(AllocationContext::current());
VM_G1CollectForAllocation op(word_size,
gc_count_before,
gc_cause,
false, /* should_initiate_conc_mark */
g1_policy()->max_pause_time_ms(),
AllocationContext::current());
VMThread::execute(&op);
HeapWord* result = op.result();

View File

@ -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
@ -125,7 +125,6 @@ class G1CollectedHeap : public CollectedHeap {
friend class VM_CollectForMetadataAllocation;
friend class VM_G1CollectForAllocation;
friend class VM_G1CollectFull;
friend class VM_G1IncCollectionPause;
friend class VMStructs;
friend class MutatorAllocRegion;
friend class G1FullCollector;
@ -454,35 +453,20 @@ protected:
virtual HeapWord* mem_allocate(size_t word_size,
bool* gc_overhead_limit_was_exceeded);
// The following three methods take a gc_count_before_ret
// parameter which is used to return the GC count if the method
// returns NULL. Given that we are required to read the GC count
// while holding the Heap_lock, and these paths will take the
// Heap_lock at some point, it's easier to get them to read the GC
// count while holding the Heap_lock before they return NULL instead
// of the caller (namely: mem_allocate()) having to also take the
// Heap_lock just to read the GC count.
// First-level mutator allocation attempt: try to allocate out of
// the mutator alloc region without taking the Heap_lock. This
// should only be used for non-humongous allocations.
inline HeapWord* attempt_allocation(size_t word_size,
uint* gc_count_before_ret,
uint* gclocker_retry_count_ret);
inline HeapWord* attempt_allocation(size_t word_size);
// Second-level mutator allocation attempt: take the Heap_lock and
// retry the allocation attempt, potentially scheduling a GC
// pause. This should only be used for non-humongous allocations.
HeapWord* attempt_allocation_slow(size_t word_size,
AllocationContext_t context,
uint* gc_count_before_ret,
uint* gclocker_retry_count_ret);
AllocationContext_t context);
// Takes the Heap_lock and attempts a humongous allocation. It can
// potentially schedule a GC pause.
HeapWord* attempt_allocation_humongous(size_t word_size,
uint* gc_count_before_ret,
uint* gclocker_retry_count_ret);
HeapWord* attempt_allocation_humongous(size_t word_size);
// Allocation attempt that should be called during safepoints (e.g.,
// at the end of a successful GC). expect_null_mutator_alloc_region
@ -1078,6 +1062,11 @@ public:
return _hrm.available() == 0;
}
// Returns whether there are any regions left in the heap for allocation.
bool has_regions_left_for_allocation() const {
return !is_maximal_no_gc() || num_free_regions() != 0;
}
// The current number of regions in the heap.
uint num_regions() const { return _hrm.length(); }

View File

@ -33,6 +33,7 @@
#include "gc/g1/heapRegion.inline.hpp"
#include "gc/g1/heapRegionRemSet.hpp"
#include "memory/iterator.inline.hpp"
#include "oops/access.inline.hpp"
#include "runtime/prefetch.inline.hpp"
template <class T>
@ -87,13 +88,13 @@ inline void G1ScanEvacuatedObjClosure::do_oop_nv(T* p) {
template <class T>
inline void G1CMOopClosure::do_oop_nv(T* p) {
oop obj = oopDesc::load_decode_heap_oop(p);
oop obj = RawAccess<MO_VOLATILE>::oop_load(p);
_task->deal_with_reference(obj);
}
template <class T>
inline void G1RootRegionScanClosure::do_oop_nv(T* p) {
T heap_oop = oopDesc::load_heap_oop(p);
T heap_oop = RawAccess<MO_VOLATILE>::oop_load(p);
if (oopDesc::is_null(heap_oop)) {
return;
}
@ -124,7 +125,7 @@ inline static void check_obj_during_refinement(T* p, oop const obj) {
template <class T>
inline void G1ConcurrentRefineOopClosure::do_oop_nv(T* p) {
T o = oopDesc::load_heap_oop(p);
T o = RawAccess<MO_VOLATILE>::oop_load(p);
if (oopDesc::is_null(o)) {
return;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -27,7 +27,6 @@
#include "gc/shared/accessBarrierSupport.inline.hpp"
#include "gc/g1/g1SATBCardTableModRefBS.hpp"
#include "oops/oop.inline.hpp"
template <DecoratorSet decorators, typename T>
inline void G1SATBCardTableModRefBS::write_ref_field_pre(T* field) {

View File

@ -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
@ -33,34 +33,21 @@
#include "gc/shared/isGCActiveMark.hpp"
#include "runtime/interfaceSupport.hpp"
VM_G1CollectForAllocation::VM_G1CollectForAllocation(uint gc_count_before,
size_t word_size)
: VM_G1OperationWithAllocRequest(gc_count_before, word_size,
GCCause::_allocation_failure) {
guarantee(word_size != 0, "An allocation should always be requested with this operation.");
}
void VM_G1CollectForAllocation::doit() {
G1CollectedHeap* g1h = G1CollectedHeap::heap();
GCCauseSetter x(g1h, _gc_cause);
_result = g1h->satisfy_failed_allocation(_word_size, allocation_context(), &_pause_succeeded);
assert(_result == NULL || _pause_succeeded,
"if we get back a result, the pause should have succeeded");
}
void VM_G1CollectFull::doit() {
G1CollectedHeap* g1h = G1CollectedHeap::heap();
GCCauseSetter x(g1h, _gc_cause);
g1h->do_full_collection(false /* clear_all_soft_refs */);
}
VM_G1IncCollectionPause::VM_G1IncCollectionPause(uint gc_count_before,
size_t word_size,
bool should_initiate_conc_mark,
double target_pause_time_ms,
GCCause::Cause gc_cause)
: VM_G1OperationWithAllocRequest(gc_count_before, word_size, gc_cause),
VM_G1CollectForAllocation::VM_G1CollectForAllocation(size_t word_size,
uint gc_count_before,
GCCause::Cause gc_cause,
bool should_initiate_conc_mark,
double target_pause_time_ms,
AllocationContext_t allocation_context)
: VM_CollectForAllocation(word_size, gc_count_before, gc_cause),
_pause_succeeded(false),
_allocation_context(allocation_context),
_should_initiate_conc_mark(should_initiate_conc_mark),
_target_pause_time_ms(target_pause_time_ms),
_should_retry_gc(false),
@ -71,8 +58,8 @@ VM_G1IncCollectionPause::VM_G1IncCollectionPause(uint gc_count_before,
_gc_cause = gc_cause;
}
bool VM_G1IncCollectionPause::doit_prologue() {
bool res = VM_G1OperationWithAllocRequest::doit_prologue();
bool VM_G1CollectForAllocation::doit_prologue() {
bool res = VM_CollectForAllocation::doit_prologue();
if (!res) {
if (_should_initiate_conc_mark) {
// The prologue can fail for a couple of reasons. The first is that another GC
@ -87,7 +74,7 @@ bool VM_G1IncCollectionPause::doit_prologue() {
return res;
}
void VM_G1IncCollectionPause::doit() {
void VM_G1CollectForAllocation::doit() {
G1CollectedHeap* g1h = G1CollectedHeap::heap();
assert(!_should_initiate_conc_mark || g1h->should_do_concurrent_full_gc(_gc_cause),
"only a GC locker, a System.gc(), stats update, whitebox, or a hum allocation induced GC should start a cycle");
@ -95,7 +82,7 @@ void VM_G1IncCollectionPause::doit() {
if (_word_size > 0) {
// An allocation has been requested. So, try to do that first.
_result = g1h->attempt_allocation_at_safepoint(_word_size,
allocation_context(),
_allocation_context,
false /* expect_null_cur_alloc_region */);
if (_result != NULL) {
// If we can successfully allocate before we actually do the
@ -144,27 +131,34 @@ void VM_G1IncCollectionPause::doit() {
}
}
_pause_succeeded =
g1h->do_collection_pause_at_safepoint(_target_pause_time_ms);
if (_pause_succeeded && _word_size > 0) {
// An allocation had been requested.
_result = g1h->attempt_allocation_at_safepoint(_word_size,
allocation_context(),
true /* expect_null_cur_alloc_region */);
// Try a partial collection of some kind.
_pause_succeeded = g1h->do_collection_pause_at_safepoint(_target_pause_time_ms);
if (_pause_succeeded) {
if (_word_size > 0) {
// An allocation had been requested. Do it, eventually trying a stronger
// kind of GC.
_result = g1h->satisfy_failed_allocation(_word_size, _allocation_context, &_pause_succeeded);
} else if (!g1h->has_regions_left_for_allocation()) {
// There has been a request to perform a GC to free some space. We have no
// information on how much memory has been asked for. In case there are
// absolutely no regions left to allocate into, do a maximally compacting full GC.
log_info(gc, ergo)("Attempting maximally compacting collection");
_pause_succeeded = g1h->do_full_collection(false, /* explicit gc */
true /* clear_all_soft_refs */);
}
guarantee(_pause_succeeded, "Elevated collections during the safepoint must always succeed.");
} else {
assert(_result == NULL, "invariant");
if (!_pause_succeeded) {
// Another possible reason reason for the pause to not be successful
// is that, again, the GC locker is active (and has become active
// since the prologue was executed). In this case we should retry
// the pause after waiting for the GC locker to become inactive.
_should_retry_gc = true;
}
// The only reason for the pause to not be successful is that, the GC locker is
// active (or has become active since the prologue was executed). In this case
// we should retry the pause after waiting for the GC locker to become inactive.
_should_retry_gc = true;
}
}
void VM_G1IncCollectionPause::doit_epilogue() {
VM_G1OperationWithAllocRequest::doit_epilogue();
void VM_G1CollectForAllocation::doit_epilogue() {
VM_CollectForAllocation::doit_epilogue();
// If the pause was initiated by a System.gc() and
// +ExplicitGCInvokesConcurrent, we have to wait here for the cycle

View File

@ -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
@ -32,26 +32,8 @@
// VM_operations for the G1 collector.
// VM_GC_Operation:
// - VM_CGC_Operation
// - VM_G1CollectForAllocation
// - VM_G1CollectFull
// - VM_G1OperationWithAllocRequest
// - VM_G1CollectForAllocation
// - VM_G1IncCollectionPause
class VM_G1OperationWithAllocRequest : public VM_CollectForAllocation {
protected:
bool _pause_succeeded;
AllocationContext_t _allocation_context;
public:
VM_G1OperationWithAllocRequest(uint gc_count_before,
size_t word_size,
GCCause::Cause gc_cause)
: VM_CollectForAllocation(word_size, gc_count_before, gc_cause),
_pause_succeeded(false) {}
bool pause_succeeded() { return _pause_succeeded; }
void set_allocation_context(AllocationContext_t context) { _allocation_context = context; }
AllocationContext_t allocation_context() { return _allocation_context; }
};
class VM_G1CollectFull: public VM_GC_Operation {
public:
@ -62,41 +44,35 @@ public:
virtual VMOp_Type type() const { return VMOp_G1CollectFull; }
virtual void doit();
virtual const char* name() const {
return "full garbage-first collection";
return "G1 Full collection";
}
};
class VM_G1CollectForAllocation: public VM_G1OperationWithAllocRequest {
public:
VM_G1CollectForAllocation(uint gc_count_before,
size_t word_size);
virtual VMOp_Type type() const { return VMOp_G1CollectForAllocation; }
virtual void doit();
virtual const char* name() const {
return "garbage-first collection to satisfy allocation";
}
};
class VM_G1IncCollectionPause: public VM_G1OperationWithAllocRequest {
class VM_G1CollectForAllocation: public VM_CollectForAllocation {
private:
bool _pause_succeeded;
AllocationContext_t _allocation_context;
bool _should_initiate_conc_mark;
bool _should_retry_gc;
double _target_pause_time_ms;
uint _old_marking_cycles_completed_before;
public:
VM_G1IncCollectionPause(uint gc_count_before,
size_t word_size,
bool should_initiate_conc_mark,
double target_pause_time_ms,
GCCause::Cause gc_cause);
virtual VMOp_Type type() const { return VMOp_G1IncCollectionPause; }
VM_G1CollectForAllocation(size_t word_size,
uint gc_count_before,
GCCause::Cause gc_cause,
bool should_initiate_conc_mark,
double target_pause_time_ms,
AllocationContext_t allocation_context);
virtual VMOp_Type type() const { return VMOp_G1CollectForAllocation; }
virtual bool doit_prologue();
virtual void doit();
virtual void doit_epilogue();
virtual const char* name() const {
return "garbage-first incremental collection pause";
return "G1 collect for allocation";
}
bool should_retry_gc() const { return _should_retry_gc; }
bool pause_succeeded() { return _pause_succeeded; }
};
// Concurrent GC stop-the-world operations such as remark and cleanup;

View File

@ -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
@ -147,9 +147,8 @@ public:
// 3) Provide specializations for BarrierSet::GetName and BarrierSet::GetType.
template <DecoratorSet decorators, typename BarrierSetT>
class AccessBarrier: protected RawAccessBarrier<decorators> {
protected:
private:
typedef RawAccessBarrier<decorators> Raw;
typedef typename BarrierSetT::template AccessBarrier<decorators> CRTPAccessBarrier;
public:
// Primitive heap accesses. These accessors get resolved when

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 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
@ -351,7 +351,7 @@ class name : AllStatic {
static type name() { \
assert(klassName::klass() != NULL && klassName::klass()->is_linked(), "Class not yet linked: " #klassName); \
InstanceKlass* ik = klassName::klass(); \
address addr = ik->static_field_addr(_##name##_offset - InstanceMirrorKlass::offset_of_static_fields()); \
address addr = ik->static_field_addr(_##name##_offset); \
oop result = HeapAccess<>::oop_load((HeapWord*)addr); \
return type(result); \
} \
@ -359,7 +359,7 @@ class name : AllStatic {
assert(klassName::klass() != NULL && klassName::klass()->is_linked(), "Class not yet linked: " #klassName); \
assert(klassName::klass() != NULL, "Class not yet loaded: " #klassName); \
InstanceKlass* ik = klassName::klass(); \
address addr = ik->static_field_addr(_##name##_offset - InstanceMirrorKlass::offset_of_static_fields()); \
address addr = ik->static_field_addr(_##name##_offset); \
HeapAccess<>::oop_store((HeapWord*)addr, x); \
}
#define STATIC_PRIMITIVE_FIELD(klassName, name, jtypename) \
@ -367,13 +367,13 @@ class name : AllStatic {
static jtypename name() { \
assert(klassName::klass() != NULL && klassName::klass()->is_linked(), "Class not yet linked: " #klassName); \
InstanceKlass* ik = klassName::klass(); \
address addr = ik->static_field_addr(_##name##_offset - InstanceMirrorKlass::offset_of_static_fields()); \
address addr = ik->static_field_addr(_##name##_offset); \
return HeapAccess<>::load((jtypename*)addr); \
} \
static void set_##name(jtypename x) { \
assert(klassName::klass() != NULL && klassName::klass()->is_linked(), "Class not yet linked: " #klassName); \
InstanceKlass* ik = klassName::klass(); \
address addr = ik->static_field_addr(_##name##_offset - InstanceMirrorKlass::offset_of_static_fields()); \
address addr = ik->static_field_addr(_##name##_offset); \
HeapAccess<>::store((jtypename*)addr, x); \
}

View File

@ -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
@ -342,7 +342,7 @@ class Access: public AllStatic {
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 | MO_DECORATOR_MASK;
IN_HEAP_ARRAY;
verify_decorators<expected_mo_decorators | primitive_decorators>();
}
@ -350,7 +350,7 @@ class Access: public AllStatic {
static void verify_oop_decorators() {
const DecoratorSet oop_decorators = AS_DECORATOR_MASK | IN_DECORATOR_MASK |
(ON_DECORATOR_MASK ^ ON_UNKNOWN_OOP_REF) | // no unknown oop refs outside of the heap
OOP_DECORATOR_MASK | MO_DECORATOR_MASK;
OOP_DECORATOR_MASK;
verify_decorators<expected_mo_decorators | oop_decorators>();
}
@ -358,8 +358,7 @@ class Access: public AllStatic {
static void verify_heap_oop_decorators() {
const DecoratorSet heap_oop_decorators = AS_DECORATOR_MASK | ON_DECORATOR_MASK |
OOP_DECORATOR_MASK | (IN_DECORATOR_MASK ^
(IN_ROOT ^ IN_CONCURRENT_ROOT)) | // no root accesses in the heap
MO_DECORATOR_MASK;
(IN_ROOT | IN_CONCURRENT_ROOT)); // no root accesses in the heap
verify_decorators<expected_mo_decorators | heap_oop_decorators>();
}

View File

@ -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
@ -491,11 +491,12 @@ namespace AccessInternal {
// not possible.
struct PreRuntimeDispatch: AllStatic {
template<DecoratorSet decorators>
static bool can_hardwire_raw() {
return !HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value || // primitive access
!HasDecorator<decorators, INTERNAL_CONVERT_COMPRESSED_OOP>::value || // don't care about compressed oops (oop* address)
HasDecorator<decorators, INTERNAL_RT_USE_COMPRESSED_OOPS>::value; // we can infer we use compressed oops (narrowOop* address)
}
struct CanHardwireRaw: public IntegralConstant<
bool,
!HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value || // primitive access
!HasDecorator<decorators, INTERNAL_CONVERT_COMPRESSED_OOP>::value || // don't care about compressed oops (oop* address)
HasDecorator<decorators, INTERNAL_RT_USE_COMPRESSED_OOPS>::value> // we can infer we use compressed oops (narrowOop* address)
{};
static const DecoratorSet convert_compressed_oops = INTERNAL_RT_USE_COMPRESSED_OOPS | INTERNAL_CONVERT_COMPRESSED_OOP;
@ -507,16 +508,21 @@ namespace AccessInternal {
template <DecoratorSet decorators, typename T>
inline static typename EnableIf<
HasDecorator<decorators, AS_RAW>::value>::type
HasDecorator<decorators, AS_RAW>::value && CanHardwireRaw<decorators>::value>::type
store(void* addr, T value) {
typedef RawAccessBarrier<decorators & RAW_DECORATOR_MASK> Raw;
if (can_hardwire_raw<decorators>()) {
if (HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value) {
Raw::oop_store(addr, value);
} else {
Raw::store(addr, value);
}
} else if (UseCompressedOops) {
if (HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value) {
Raw::oop_store(addr, value);
} else {
Raw::store(addr, value);
}
}
template <DecoratorSet decorators, typename T>
inline static typename EnableIf<
HasDecorator<decorators, AS_RAW>::value && !CanHardwireRaw<decorators>::value>::type
store(void* addr, T value) {
if (UseCompressedOops) {
const DecoratorSet expanded_decorators = decorators | convert_compressed_oops;
PreRuntimeDispatch::store<expanded_decorators>(addr, value);
} else {
@ -558,16 +564,21 @@ namespace AccessInternal {
template <DecoratorSet decorators, typename T>
inline static typename EnableIf<
HasDecorator<decorators, AS_RAW>::value, T>::type
HasDecorator<decorators, AS_RAW>::value && CanHardwireRaw<decorators>::value, T>::type
load(void* addr) {
typedef RawAccessBarrier<decorators & RAW_DECORATOR_MASK> Raw;
if (can_hardwire_raw<decorators>()) {
if (HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value) {
return Raw::template oop_load<T>(addr);
} else {
return Raw::template load<T>(addr);
}
} else if (UseCompressedOops) {
if (HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value) {
return Raw::template oop_load<T>(addr);
} else {
return Raw::template load<T>(addr);
}
}
template <DecoratorSet decorators, typename T>
inline static typename EnableIf<
HasDecorator<decorators, AS_RAW>::value && !CanHardwireRaw<decorators>::value, T>::type
load(void* addr) {
if (UseCompressedOops) {
const DecoratorSet expanded_decorators = decorators | convert_compressed_oops;
return PreRuntimeDispatch::load<expanded_decorators, T>(addr);
} else {
@ -609,16 +620,21 @@ namespace AccessInternal {
template <DecoratorSet decorators, typename T>
inline static typename EnableIf<
HasDecorator<decorators, AS_RAW>::value, T>::type
HasDecorator<decorators, AS_RAW>::value && CanHardwireRaw<decorators>::value, T>::type
atomic_cmpxchg(T new_value, void* addr, T compare_value) {
typedef RawAccessBarrier<decorators & RAW_DECORATOR_MASK> Raw;
if (can_hardwire_raw<decorators>()) {
if (HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value) {
return Raw::oop_atomic_cmpxchg(new_value, addr, compare_value);
} else {
return Raw::atomic_cmpxchg(new_value, addr, compare_value);
}
} else if (UseCompressedOops) {
if (HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value) {
return Raw::oop_atomic_cmpxchg(new_value, addr, compare_value);
} else {
return Raw::atomic_cmpxchg(new_value, addr, compare_value);
}
}
template <DecoratorSet decorators, typename T>
inline static typename EnableIf<
HasDecorator<decorators, AS_RAW>::value && !CanHardwireRaw<decorators>::value, T>::type
atomic_cmpxchg(T new_value, void* addr, T compare_value) {
if (UseCompressedOops) {
const DecoratorSet expanded_decorators = decorators | convert_compressed_oops;
return PreRuntimeDispatch::atomic_cmpxchg<expanded_decorators>(new_value, addr, compare_value);
} else {
@ -661,16 +677,21 @@ namespace AccessInternal {
template <DecoratorSet decorators, typename T>
inline static typename EnableIf<
HasDecorator<decorators, AS_RAW>::value, T>::type
HasDecorator<decorators, AS_RAW>::value && CanHardwireRaw<decorators>::value, T>::type
atomic_xchg(T new_value, void* addr) {
typedef RawAccessBarrier<decorators & RAW_DECORATOR_MASK> Raw;
if (can_hardwire_raw<decorators>()) {
if (HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value) {
return Raw::oop_atomic_xchg(new_value, addr);
} else {
return Raw::atomic_xchg(new_value, addr);
}
} else if (UseCompressedOops) {
if (HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value) {
return Raw::oop_atomic_xchg(new_value, addr);
} else {
return Raw::atomic_xchg(new_value, addr);
}
}
template <DecoratorSet decorators, typename T>
inline static typename EnableIf<
HasDecorator<decorators, AS_RAW>::value && !CanHardwireRaw<decorators>::value, T>::type
atomic_xchg(T new_value, void* addr) {
if (UseCompressedOops) {
const DecoratorSet expanded_decorators = decorators | convert_compressed_oops;
return PreRuntimeDispatch::atomic_xchg<expanded_decorators>(new_value, addr);
} else {
@ -797,6 +818,13 @@ namespace AccessInternal {
PreRuntimeDispatch::store<expanded_decorators>(addr, value);
}
template <DecoratorSet decorators>
inline void store_reduce_types(narrowOop* addr, narrowOop value) {
const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP |
INTERNAL_RT_USE_COMPRESSED_OOPS;
PreRuntimeDispatch::store<expanded_decorators>(addr, value);
}
template <DecoratorSet decorators>
inline void store_reduce_types(HeapWord* addr, oop value) {
const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP;
@ -816,7 +844,16 @@ namespace AccessInternal {
}
template <DecoratorSet decorators>
inline oop atomic_cmpxchg_reduce_types(oop new_value, HeapWord* addr, oop compare_value) {
inline narrowOop atomic_cmpxchg_reduce_types(narrowOop new_value, narrowOop* addr, narrowOop compare_value) {
const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP |
INTERNAL_RT_USE_COMPRESSED_OOPS;
return PreRuntimeDispatch::atomic_cmpxchg<expanded_decorators>(new_value, addr, compare_value);
}
template <DecoratorSet decorators>
inline oop atomic_cmpxchg_reduce_types(oop new_value,
HeapWord* addr,
oop compare_value) {
const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP;
return PreRuntimeDispatch::atomic_cmpxchg<expanded_decorators>(new_value, addr, compare_value);
}
@ -834,6 +871,13 @@ namespace AccessInternal {
return PreRuntimeDispatch::atomic_xchg<expanded_decorators>(new_value, addr);
}
template <DecoratorSet decorators>
inline narrowOop atomic_xchg_reduce_types(narrowOop new_value, narrowOop* addr) {
const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP |
INTERNAL_RT_USE_COMPRESSED_OOPS;
return PreRuntimeDispatch::atomic_xchg<expanded_decorators>(new_value, addr);
}
template <DecoratorSet decorators>
inline oop atomic_xchg_reduce_types(oop new_value, HeapWord* addr) {
const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP;
@ -846,9 +890,10 @@ namespace AccessInternal {
}
template <DecoratorSet decorators, typename T>
inline oop load_reduce_types(narrowOop* addr) {
const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP | INTERNAL_RT_USE_COMPRESSED_OOPS;
return PreRuntimeDispatch::load<expanded_decorators, oop>(addr);
inline typename OopOrNarrowOop<T>::type load_reduce_types(narrowOop* addr) {
const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP |
INTERNAL_RT_USE_COMPRESSED_OOPS;
return PreRuntimeDispatch::load<expanded_decorators, typename OopOrNarrowOop<T>::type>(addr);
}
template <DecoratorSet decorators, typename T>

View File

@ -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
@ -28,6 +28,7 @@
#include "metaprogramming/conditional.hpp"
#include "metaprogramming/enableIf.hpp"
#include "metaprogramming/integralConstant.hpp"
#include "metaprogramming/isSame.hpp"
#include "utilities/debug.hpp"
#include "utilities/globalDefinitions.hpp"
@ -54,11 +55,11 @@ namespace AccessInternal {
BARRIER_CLONE
};
template <DecoratorSet decorators>
template <DecoratorSet decorators, typename T>
struct MustConvertCompressedOop: public IntegralConstant<bool,
HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value &&
HasDecorator<decorators, INTERNAL_CONVERT_COMPRESSED_OOP>::value &&
HasDecorator<decorators, INTERNAL_RT_USE_COMPRESSED_OOPS>::value> {};
IsSame<typename HeapOopType<decorators>::type, narrowOop>::value &&
IsSame<T, oop>::value> {};
// This metafunction returns an appropriate oop type if the value is oop-like
// and otherwise returns the same type T.
@ -172,13 +173,13 @@ protected:
// Only encode if INTERNAL_VALUE_IS_OOP
template <DecoratorSet idecorators, typename T>
static inline typename EnableIf<
AccessInternal::MustConvertCompressedOop<idecorators>::value,
AccessInternal::MustConvertCompressedOop<idecorators, T>::value,
typename HeapOopType<idecorators>::type>::type
encode_internal(T value);
template <DecoratorSet idecorators, typename T>
static inline typename EnableIf<
!AccessInternal::MustConvertCompressedOop<idecorators>::value, T>::type
!AccessInternal::MustConvertCompressedOop<idecorators, T>::value, T>::type
encode_internal(T value) {
return value;
}
@ -192,12 +193,12 @@ protected:
// Only decode if INTERNAL_VALUE_IS_OOP
template <DecoratorSet idecorators, typename T>
static inline typename EnableIf<
AccessInternal::MustConvertCompressedOop<idecorators>::value, T>::type
AccessInternal::MustConvertCompressedOop<idecorators, T>::value, T>::type
decode_internal(typename HeapOopType<idecorators>::type value);
template <DecoratorSet idecorators, typename T>
static inline typename EnableIf<
!AccessInternal::MustConvertCompressedOop<idecorators>::value, T>::type
!AccessInternal::MustConvertCompressedOop<idecorators, T>::value, T>::type
decode_internal(T value) {
return value;
}

View File

@ -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
@ -32,7 +32,7 @@
template <DecoratorSet decorators>
template <DecoratorSet idecorators, typename T>
inline typename EnableIf<
AccessInternal::MustConvertCompressedOop<idecorators>::value, T>::type
AccessInternal::MustConvertCompressedOop<idecorators, T>::value, T>::type
RawAccessBarrier<decorators>::decode_internal(typename HeapOopType<idecorators>::type value) {
if (HasDecorator<decorators, OOP_NOT_NULL>::value) {
return oopDesc::decode_heap_oop_not_null(value);
@ -44,7 +44,7 @@ RawAccessBarrier<decorators>::decode_internal(typename HeapOopType<idecorators>:
template <DecoratorSet decorators>
template <DecoratorSet idecorators, typename T>
inline typename EnableIf<
AccessInternal::MustConvertCompressedOop<idecorators>::value,
AccessInternal::MustConvertCompressedOop<idecorators, T>::value,
typename HeapOopType<idecorators>::type>::type
RawAccessBarrier<decorators>::encode_internal(T value) {
if (HasDecorator<decorators, OOP_NOT_NULL>::value) {

View File

@ -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
@ -2265,7 +2265,8 @@ void InstanceKlass::set_source_debug_extension(const char* array, int length) {
}
address InstanceKlass::static_field_addr(int offset) {
return (address)(offset + InstanceMirrorKlass::offset_of_static_fields() + cast_from_oop<intptr_t>(java_mirror()));
assert(offset >= InstanceMirrorKlass::offset_of_static_fields(), "has already been adjusted");
return (address)(offset + cast_from_oop<intptr_t>(java_mirror()));
}
@ -3421,6 +3422,15 @@ void JNIid::verify(Klass* holder) {
}
}
oop InstanceKlass::klass_holder_phantom() {
oop* addr;
if (is_anonymous()) {
addr = _java_mirror.ptr_raw();
} else {
addr = &class_loader_data()->_class_loader;
}
return RootAccess<IN_CONCURRENT_ROOT | ON_PHANTOM_OOP_REF>::oop_load(addr);
}
#ifdef ASSERT
void InstanceKlass::set_init_state(ClassState state) {

View File

@ -645,6 +645,11 @@ class InstanceKlass: public Klass {
return is_anonymous() ? java_mirror() : class_loader();
}
// Load the klass_holder as a phantom. This is useful when a weak Klass
// pointer has been "peeked" and then must be kept alive before it may
// be used safely.
oop klass_holder_phantom();
bool is_contended() const {
return (_misc_flags & _misc_is_contended) != 0;
}

View File

@ -28,6 +28,7 @@
#include "gc/shared/specialized_oop_closures.hpp"
#include "memory/iterator.hpp"
#include "memory/memRegion.hpp"
#include "oops/access.hpp"
#include "oops/metadata.hpp"
#include "utilities/macros.hpp"
@ -178,6 +179,8 @@ class oopDesc {
static inline void encode_store_heap_oop(oop* p, oop v);
// Access to fields in a instanceOop through these methods.
template <DecoratorSet decorator>
oop obj_field_access(int offset) const;
oop obj_field(int offset) const;
void obj_field_put(int offset, oop value);
void obj_field_put_raw(int offset, oop value);

View File

@ -326,7 +326,10 @@ void oopDesc::encode_store_heap_oop(narrowOop* p, oop v) {
*p = encode_heap_oop(v);
}
template <DecoratorSet decorators>
inline oop oopDesc::obj_field_access(int offset) const { return HeapAccess<decorators>::oop_load_at(as_oop(), offset); }
inline oop oopDesc::obj_field(int offset) const { return HeapAccess<>::oop_load_at(as_oop(), offset); }
inline void oopDesc::obj_field_put(int offset, oop value) { HeapAccess<>::oop_store_at(as_oop(), offset, value); }
inline jbyte oopDesc::byte_field(int offset) const { return HeapAccess<>::load_at(as_oop(), offset); }

View File

@ -30,6 +30,7 @@
#include "code/codeCache.hpp"
#include "jvmtifiles/jvmtiEnv.hpp"
#include "memory/resourceArea.hpp"
#include "oops/access.inline.hpp"
#include "oops/instanceMirrorKlass.hpp"
#include "oops/objArrayKlass.hpp"
#include "oops/objArrayOop.inline.hpp"
@ -52,10 +53,6 @@
#include "runtime/vm_operations.hpp"
#include "services/serviceUtil.hpp"
#include "utilities/macros.hpp"
#if INCLUDE_ALL_GCS
#include "gc/g1/g1SATBCardTableModRefBS.hpp"
#include "gc/parallel/parallelScavengeHeap.hpp"
#endif // INCLUDE_ALL_GCS
// JvmtiTagHashmapEntry
//
@ -78,22 +75,31 @@ class JvmtiTagHashmapEntry : public CHeapObj<mtInternal> {
}
// constructor
JvmtiTagHashmapEntry(oop object, jlong tag) { init(object, tag); }
JvmtiTagHashmapEntry(oop object, jlong tag) { init(object, tag); }
public:
// accessor methods
inline oop object() const { return _object; }
inline oop* object_addr() { return &_object; }
inline jlong tag() const { return _tag; }
inline oop* object_addr() { return &_object; }
inline oop object() { return RootAccess<ON_PHANTOM_OOP_REF>::oop_load(object_addr()); }
// Peek at the object without keeping it alive. The returned object must be
// kept alive using a normal access if it leaks out of a thread transition from VM.
inline oop object_peek() {
return RootAccess<ON_PHANTOM_OOP_REF | AS_NO_KEEPALIVE>::oop_load(object_addr());
}
inline jlong tag() const { return _tag; }
inline void set_tag(jlong tag) {
assert(tag != 0, "can't be zero");
_tag = tag;
}
inline JvmtiTagHashmapEntry* next() const { return _next; }
inline void set_next(JvmtiTagHashmapEntry* next) { _next = next; }
inline bool equals(oop object) {
return object == object_peek();
}
inline JvmtiTagHashmapEntry* next() const { return _next; }
inline void set_next(JvmtiTagHashmapEntry* next) { _next = next; }
};
@ -211,7 +217,7 @@ class JvmtiTagHashmap : public CHeapObj<mtInternal> {
JvmtiTagHashmapEntry* entry = _table[i];
while (entry != NULL) {
JvmtiTagHashmapEntry* next = entry->next();
oop key = entry->object();
oop key = entry->object_peek();
assert(key != NULL, "jni weak reference cleared!!");
unsigned int h = hash(key, new_size);
JvmtiTagHashmapEntry* anchor = new_table[h];
@ -304,7 +310,7 @@ class JvmtiTagHashmap : public CHeapObj<mtInternal> {
unsigned int h = hash(key);
JvmtiTagHashmapEntry* entry = _table[h];
while (entry != NULL) {
if (entry->object() == key) {
if (entry->equals(key)) {
return entry;
}
entry = entry->next();
@ -345,7 +351,7 @@ class JvmtiTagHashmap : public CHeapObj<mtInternal> {
JvmtiTagHashmapEntry* entry = _table[h];
JvmtiTagHashmapEntry* prev = NULL;
while (entry != NULL) {
if (key == entry->object()) {
if (entry->equals(key)) {
break;
}
prev = entry;
@ -1535,16 +1541,12 @@ class TagObjectCollector : public JvmtiTagHashmapEntryClosure {
void do_entry(JvmtiTagHashmapEntry* entry) {
for (int i=0; i<_tag_count; i++) {
if (_tags[i] == entry->tag()) {
// The reference in this tag map could be the only (implicitly weak)
// reference to that object. If we hand it out, we need to keep it live wrt
// SATB marking similar to other j.l.ref.Reference referents. This is
// achieved by using a phantom load in the object() accessor.
oop o = entry->object();
assert(o != NULL && Universe::heap()->is_in_reserved(o), "sanity check");
#if INCLUDE_ALL_GCS
if (UseG1GC) {
// The reference in this tag map could be the only (implicitly weak)
// reference to that object. If we hand it out, we need to keep it live wrt
// SATB marking similar to other j.l.ref.Reference referents.
G1SATBCardTableModRefBS::enqueue(o);
}
#endif
jobject ref = JNIHandles::make_local(JavaThread::current(), o);
_object_results->append(ref);
_tag_results->append((uint64_t)entry->tag());
@ -3363,10 +3365,8 @@ void JvmtiTagMap::do_weak_oops(BoolObjectClosure* is_alive, OopClosure* f) {
while (entry != NULL) {
JvmtiTagHashmapEntry* next = entry->next();
oop* obj = entry->object_addr();
// has object been GC'ed
if (!is_alive->do_object_b(entry->object())) {
if (!is_alive->do_object_b(entry->object_peek())) {
// grab the tag
jlong tag = entry->tag();
guarantee(tag != 0, "checking");
@ -3384,7 +3384,7 @@ void JvmtiTagMap::do_weak_oops(BoolObjectClosure* is_alive, OopClosure* f) {
++freed;
} else {
f->do_oop(entry->object_addr());
oop new_oop = entry->object();
oop new_oop = entry->object_peek();
// if the object has moved then re-hash it and move its
// entry to its new location.
@ -3418,7 +3418,7 @@ void JvmtiTagMap::do_weak_oops(BoolObjectClosure* is_alive, OopClosure* f) {
// Re-add all the entries which were kept aside
while (delayed_add != NULL) {
JvmtiTagHashmapEntry* next = delayed_add->next();
unsigned int pos = JvmtiTagHashmap::hash(delayed_add->object(), size);
unsigned int pos = JvmtiTagHashmap::hash(delayed_add->object_peek(), size);
delayed_add->set_next(table[pos]);
table[pos] = delayed_add;
delayed_add = next;

View File

@ -25,6 +25,7 @@
#include "precompiled.hpp"
#include "gc/shared/gcLocker.hpp"
#include "memory/allocation.hpp"
#include "oops/access.inline.hpp"
#include "oops/oop.inline.hpp"
#include "oops/method.hpp"
#include "oops/symbol.hpp"
@ -33,24 +34,39 @@
#include "runtime/mutexLocker.hpp"
#include "utilities/hashtable.inline.hpp"
#include "utilities/macros.hpp"
#if INCLUDE_ALL_GCS
#include "gc/g1/g1SATBCardTableModRefBS.hpp"
#endif
oop ResolvedMethodEntry::object() {
return RootAccess<ON_PHANTOM_OOP_REF>::oop_load(literal_addr());
}
oop ResolvedMethodEntry::object_no_keepalive() {
// The AS_NO_KEEPALIVE peeks at the oop without keeping it alive.
// This is dangerous in general but is okay if the loaded oop does
// not leak out past a thread transition where a safepoint can happen.
// A subsequent oop_load without AS_NO_KEEPALIVE (the object() accessor)
// keeps the oop alive before doing so.
return RootAccess<ON_PHANTOM_OOP_REF | AS_NO_KEEPALIVE>::oop_load(literal_addr());
}
ResolvedMethodTable::ResolvedMethodTable()
: Hashtable<oop, mtClass>(_table_size, sizeof(ResolvedMethodEntry)) { }
oop ResolvedMethodTable::lookup(int index, unsigned int hash, Method* method) {
for (ResolvedMethodEntry* p = bucket(index); p != NULL; p = p->next()) {
if (p->hash() == hash) {
oop target = p->literal();
// Peek the object to check if it is the right target.
oop target = p->object_no_keepalive();
// The method is in the table as a target already
if (java_lang_invoke_ResolvedMethodName::vmtarget(target) == method) {
ResourceMark rm;
log_debug(membername, table) ("ResolvedMethod entry found for %s index %d",
method->name_and_sig_as_C_string(), index);
return target;
// The object() accessor makes sure the target object is kept alive before
// leaking out.
return p->object();
}
}
}
@ -70,18 +86,6 @@ oop ResolvedMethodTable::lookup(Method* method) {
return lookup(index, hash, method);
}
// Tell the GC that this oop was looked up in the table
static void ensure_oop_alive(oop mname) {
// A lookup in the ResolvedMethodTable could return an object that was previously
// considered dead. The SATB part of G1 needs to get notified about this
// potential resurrection, otherwise the marking might not find the object.
#if INCLUDE_ALL_GCS
if (UseG1GC && mname != NULL) {
G1SATBCardTableModRefBS::enqueue(mname);
}
#endif
}
oop ResolvedMethodTable::basic_add(Method* method, oop rmethod_name) {
assert_locked_or_safepoint(ResolvedMethodTable_lock);
@ -91,7 +95,6 @@ oop ResolvedMethodTable::basic_add(Method* method, oop rmethod_name) {
// One was added while aquiring the lock
oop entry = lookup(index, hash, method);
if (entry != NULL) {
ensure_oop_alive(entry);
return entry;
}
@ -100,14 +103,13 @@ oop ResolvedMethodTable::basic_add(Method* method, oop rmethod_name) {
ResourceMark rm;
log_debug(membername, table) ("ResolvedMethod entry added for %s index %d",
method->name_and_sig_as_C_string(), index);
return p->literal();
return rmethod_name;
}
ResolvedMethodTable* ResolvedMethodTable::_the_table = NULL;
oop ResolvedMethodTable::find_method(Method* method) {
oop entry = _the_table->lookup(method);
ensure_oop_alive(entry);
return entry;
}
@ -147,12 +149,12 @@ void ResolvedMethodTable::unlink(BoolObjectClosure* is_alive) {
ResolvedMethodEntry* entry = _the_table->bucket(i);
while (entry != NULL) {
_oops_counted++;
if (is_alive->do_object_b(entry->literal())) {
if (is_alive->do_object_b(entry->object_no_keepalive())) {
p = entry->next_addr();
} else {
_oops_removed++;
if (log_is_enabled(Debug, membername, table)) {
Method* m = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(entry->literal());
Method* m = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(entry->object_no_keepalive());
ResourceMark rm;
log_debug(membername, table) ("ResolvedMethod entry removed for %s index %d",
m->name_and_sig_as_C_string(), i);
@ -185,7 +187,7 @@ void ResolvedMethodTable::print() {
ResolvedMethodEntry* entry = bucket(i);
while (entry != NULL) {
tty->print("%d : ", i);
oop rmethod_name = entry->literal();
oop rmethod_name = entry->object_no_keepalive();
rmethod_name->print();
Method* m = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(rmethod_name);
m->print();
@ -203,8 +205,7 @@ void ResolvedMethodTable::adjust_method_entries(bool * trace_name_printed) {
for (int i = 0; i < _the_table->table_size(); ++i) {
ResolvedMethodEntry* entry = _the_table->bucket(i);
while (entry != NULL) {
oop mem_name = entry->literal();
oop mem_name = entry->object_no_keepalive();
Method* old_method = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(mem_name);
if (old_method->is_old()) {

View File

@ -44,6 +44,9 @@ class ResolvedMethodEntry : public HashtableEntry<oop, mtClass> {
return (ResolvedMethodEntry**)HashtableEntry<oop, mtClass>::next_addr();
}
oop object();
oop object_no_keepalive();
void print_on(outputStream* st) const;
};

View File

@ -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
@ -527,6 +527,7 @@ static SpecialFlag const special_jvm_flags[] = {
{ "ConvertSleepToYield", JDK_Version::jdk(9), JDK_Version::jdk(10), JDK_Version::jdk(11) },
{ "ConvertYieldToSleep", JDK_Version::jdk(9), JDK_Version::jdk(10), JDK_Version::jdk(11) },
{ "MinSleepInterval", JDK_Version::jdk(9), JDK_Version::jdk(10), JDK_Version::jdk(11) },
{ "CheckAssertionStatusDirectives",JDK_Version::undefined(), JDK_Version::jdk(11), JDK_Version::jdk(12) },
{ "PermSize", JDK_Version::undefined(), JDK_Version::jdk(8), JDK_Version::undefined() },
{ "MaxPermSize", JDK_Version::undefined(), JDK_Version::jdk(8), JDK_Version::undefined() },
{ "SharedReadWriteSize", JDK_Version::undefined(), JDK_Version::jdk(10), JDK_Version::undefined() },

View File

@ -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
@ -893,9 +893,6 @@ public:
develop(bool, TraceJavaAssertions, false, \
"Trace java language assertions") \
\
notproduct(bool, CheckAssertionStatusDirectives, false, \
"Temporary - see javaClasses.cpp") \
\
notproduct(bool, PrintMallocFree, false, \
"Trace calls to C heap malloc/free allocation") \
\

View File

@ -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
@ -131,6 +131,7 @@ jint init_globals() {
InterfaceSupport_init();
SharedRuntime::generate_stubs();
universe2_init(); // dependent on codeCache_init and stubRoutines_init1
javaClasses_init();// must happen after vtable initialization, before referenceProcessor_init
referenceProcessor_init();
jni_handles_init();
#if INCLUDE_VM_STRUCTS
@ -150,7 +151,6 @@ jint init_globals() {
if (!universe_post_init()) {
return JNI_ERR;
}
javaClasses_init(); // must happen after vtable initialization
stubRoutines_init2(); // note: StubRoutines need 2-phase init
MethodHandles::generate_adapters();

View File

@ -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
@ -778,7 +778,6 @@ class os: AllStatic {
static void* signal(int signal_number, void* handler);
static void signal_raise(int signal_number);
static int signal_wait();
static int signal_lookup();
static void* user_handler();
static void terminate_signal_thread();
static int sigexitnum_pd();

View File

@ -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
@ -67,9 +67,8 @@
template(CGC_Operation) \
template(CMS_Initial_Mark) \
template(CMS_Final_Remark) \
template(G1CollectFull) \
template(G1CollectForAllocation) \
template(G1IncCollectionPause) \
template(G1CollectFull) \
template(HandshakeOneThread) \
template(HandshakeAllThreads) \
template(HandshakeFallback) \

View File

@ -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
@ -243,11 +243,12 @@ void VMError::print_native_stack(outputStream* st, frame fr, Thread* t, char* bu
RegisterMap map((JavaThread*)t, false); // No update
fr = fr.sender(&map);
} else {
// is_first_C_frame() does only simple checks for frame pointer,
// it will pass if java compiled code has a pointer in EBP.
if (os::is_first_C_frame(&fr)) break;
fr = os::get_sender_for_C_frame(&fr);
}
} else {
// is_first_C_frame() does only simple checks for frame pointer,
// it will pass if java compiled code has a pointer in EBP.
if (os::is_first_C_frame(&fr)) break;
fr = os::get_sender_for_C_frame(&fr);
}

View File

@ -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
@ -86,6 +86,10 @@ public abstract class HotSpotVirtualMachine extends VirtualMachine {
private void loadAgentLibrary(String agentLibrary, boolean isAbsolute, String options)
throws AgentLoadException, AgentInitializationException, IOException
{
if (agentLibrary == null) {
throw new NullPointerException("agentLibrary cannot be null");
}
String msgPrefix = "return code: ";
InputStream in = execute("load",
agentLibrary,
@ -131,6 +135,10 @@ public abstract class HotSpotVirtualMachine extends VirtualMachine {
public void loadAgent(String agent, String options)
throws AgentLoadException, AgentInitializationException, IOException
{
if (agent == null) {
throw new NullPointerException("agent cannot be null");
}
String args = agent;
if (options != null) {
args = args + "=" + options;

View File

@ -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
@ -1607,7 +1607,9 @@ public class CommandProcessor {
if (!all) return;
}
}
out.println("Couldn't find thread " + name);
if (!all) {
out.println("Couldn't find thread " + name);
}
}
}
},

View File

@ -104,6 +104,11 @@ public class CallSite {
*/
private List<UncommonTrap> traps;
/**
* The name of the intrinsic at this call site.
*/
private String intrinsicName;
/**
* Default constructor: used to create an instance that represents the top
* scope of a compilation.
@ -179,6 +184,7 @@ public class CallSite {
} else {
stream.print(" @ " + getBci() + " " + m + " " + getReason());
}
stream.print(getIntrinsicOrEmptyString());
stream.printf(" (end time: %6.4f", getTimeStamp());
if (getEndNodes() > 0) {
stream.printf(" nodes: %d live: %d", getEndNodes(), getEndLiveNodes());
@ -368,4 +374,19 @@ public class CallSite {
public void setInlineId(long inlineId) {
this.inlineId = inlineId;
}
public String getIntrinsicName() {
return intrinsicName;
}
public void setIntrinsicName(String name) {
this.intrinsicName = name;
}
public String getIntrinsicOrEmptyString() {
if (intrinsicName != null) {
return " (intrinsic: " + getIntrinsicName() + ")";
}
return "";
}
}

View File

@ -975,6 +975,12 @@ public class LogParser extends DefaultHandler implements ErrorHandler {
// track of it but don't add it to the list yet.
methodHandleSite = site;
}
} else if (qname.equals("intrinsic")) {
String id = atts.getValue("id");
assert id != null : "intrinsic id is null";
CallSite cs = (site != null) ? site : scopes.peek();
assert cs != null : "no CallSite?";
cs.setIntrinsicName(id);
} else if (qname.equals("regalloc")) {
compile.setAttempts(Integer.parseInt(search(atts, "attempts")));
} else if (qname.equals("inline_fail")) {

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 1995, 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,13 +66,15 @@ ifndef CONCURRENCY_FACTOR
CONCURRENCY_FACTOR = 1
endif
# Concurrency based on min(cores / 2, 12)
CONCURRENCY := $(shell awk 'BEGIN { printf "%.0f", $(NUM_CORES) / 2 * $(CONCURRENCY_FACTOR) }')
ifeq ($(CONCURRENCY), 0)
CONCURRENCY := 1
else ifeq ($(shell expr $(CONCURRENCY) \> 12), 1)
CONCURRENCY := 12
endif
# Concurrency based on min(cores / 2, 12) * CONCURRENCY_FACTOR
CONCURRENCY := $(shell awk \
'BEGIN { \
c = $(NUM_CORES) / 2; \
if (c > 12) c = 12; \
c = c * $(CONCURRENCY_FACTOR); \
if (c < 1) c = 1; \
printf "%.0f", c; \
}')
# Make sure MaxRAMPercentage is high enough to not cause OOM or swapping since we may end up with a lot of JVM's
JTREG_BASIC_OPTIONS += -vmoption:-XX:MaxRAMPercentage=$(shell expr 25 / $(CONCURRENCY))

View File

@ -71,6 +71,7 @@ gc/g1/TestVerifyGCType.java 8193067 generic-all
gc/stress/gclocker/TestGCLockerWithParallel.java 8180622 generic-all
gc/stress/gclocker/TestGCLockerWithG1.java 8179226 generic-all
gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java 8177765 generic-all
gc/stress/TestJNIBlockFullGC/TestJNIBlockFullGC.java 8192647 generic-all
#############################################################################

View File

@ -0,0 +1,181 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, SAP SE 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 TestJNIBlockFullGC
* @summary Check that in G1 a Full GC to reclaim space can not be blocked out by the GC locker.
* @key gc
* @requires vm.gc.G1
* @run main/othervm/native -Xmx64m -XX:+UseG1GC -Xlog:gc=info,gc+alloc=trace -XX:MaxGCPauseMillis=10 TestJNIBlockFullGC 10 10000 10000 10000 30000 10000 0.7
*/
import java.lang.ref.SoftReference;
public class TestJNIBlockFullGC {
static {
System.loadLibrary("TestJNIBlockFullGC");
}
public static volatile Object tmp;
public static volatile boolean hadError = false;
private static native int TestCriticalArray0(int[] x);
public static class Node {
public SoftReference<Node> next;
long payload1;
long payload2;
long payload3;
long payload4;
public Node(int load) {
payload1 = payload2 = payload3 = payload4 = load;
}
}
public static void warmUp(long warmupEndTime, int size) {
// First let the GC assume most of our objects will die.
Node[] roots = new Node[size];
while (System.currentTimeMillis() < warmupEndTime) {
int index = (int) (Math.random() * roots.length);
roots[index] = new Node(1);
}
// Make sure the young generation is empty.
for (int i = 0; i < roots.length; ++i) {
roots[i] = null;
}
}
public static void runTest(long endTime, int size, double alive) {
final int length = 10000;
int[] array1 = new int[length];
for (int x = 1; x < length; x++) {
array1[x] = x;
}
Node[] roots = new Node[size];
try {
int index = 0;
roots[0] = new Node(0);
while (!hadError && (System.currentTimeMillis() < endTime)) {
int test_val1 = TestCriticalArray0(array1);
if (Math.random() > alive) {
tmp = new Node(test_val1);
} else {
index = (int) (Math.random() * roots.length);
if (roots[index] != null) {
Node node = new Node(test_val1);
node.next = new SoftReference<Node>(roots[index]);
roots[index] = node;
} else {
roots[index] = new Node(test_val1);
}
}
}
} catch (OutOfMemoryError e) {
hadError = true;
e.printStackTrace();
}
}
private static void joinThreads(Thread[] threads) throws Exception {
for (int i = 0; i < threads.length; i++) {
try {
if (threads[i] != null) {
threads[i].join();
}
} catch (InterruptedException e) {
e.printStackTrace();
throw e;
}
}
}
public static void main(String[] args) throws Exception {
if (args.length < 7){
System.out.println("Usage: java TestJNIBlockFullGC <warmupThreads> <warmup-time-in-millis> <warmup iterations> <threads> <time-in-millis> <iterations> <aliveFrac>");
System.exit(0);
}
int warmupThreads = Integer.parseInt(args[0]);
System.out.println("# Warmup Threads = " + warmupThreads);
int warmupDuration = Integer.parseInt(args[1]);
System.out.println("WarmUp Duration = " + warmupDuration);
int warmupIterations = Integer.parseInt(args[2]);
System.out.println("# Warmup Iterations = "+ warmupIterations);
int mainThreads = Integer.parseInt(args[3]);
System.out.println("# Main Threads = " + mainThreads);
int mainDuration = Integer.parseInt(args[4]);
System.out.println("Main Duration = " + mainDuration);
int mainIterations = Integer.parseInt(args[5]);
System.out.println("# Main Iterations = " + mainIterations);
double liveFrac = Double.parseDouble(args[6]);
System.out.println("Live Fraction = " + liveFrac);
Thread threads[] = new Thread[Math.max(warmupThreads, mainThreads)];
System.out.println("Start warm-up threads!");
long warmupStartTime = System.currentTimeMillis();
for (int i = 0; i < warmupThreads; i++) {
threads[i] = new Thread() {
public void run() {
warmUp(warmupStartTime + warmupDuration, warmupIterations);
};
};
threads[i].start();
}
joinThreads(threads);
System.gc();
System.out.println("Keep alive a lot");
long startTime = System.currentTimeMillis();
for (int i = 0; i < mainThreads; i++) {
threads[i] = new Thread() {
public void run() {
runTest(startTime + mainDuration, mainIterations, liveFrac);
};
};
threads[i].start();
}
System.out.println("All threads started");
joinThreads(threads);
if (hadError) {
throw new RuntimeException("Experienced an OoME during execution.");
}
}
}

View File

@ -0,0 +1,48 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, SAP SE 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.
*/
#include "jni.h"
JNIEXPORT jint JNICALL
Java_TestJNIBlockFullGC_TestCriticalArray0(JNIEnv *env, jclass jCls, jintArray jIn) {
jint *bufIn = NULL;
jint jInLen = (*env)->GetArrayLength(env, jIn);
jint result = 0;
jint i;
if (jInLen != 0) {
bufIn = (jint*)(*env)->GetPrimitiveArrayCritical(env, jIn, 0);
}
for (i = 0; i < jInLen; ++i) {
result += bufIn[i]; // result = sum of all array elements
}
if (bufIn != NULL) {
(*env)->ReleasePrimitiveArrayCritical(env, jIn, bufIn, 0);
}
return result;
}

View File

@ -0,0 +1,103 @@
/*
* 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 TestReclaimStringsLeaksMemory
* @bug 8180048
* @summary Ensure that during a Full GC interned string memory is reclaimed completely.
* @requires vm.gc=="null"
* @requires !vm.debug
* @key gc
* @library /test/lib
* @modules java.base/jdk.internal.misc
* @run main/othervm TestReclaimStringsLeaksMemory
* @run main/othervm TestReclaimStringsLeaksMemory -XX:+UseSerialGC
* @run main/othervm TestReclaimStringsLeaksMemory -XX:+UseParallelGC
* @run main/othervm TestReclaimStringsLeaksMemory -XX:+UseParallelGC -XX:-UseParallelOldGC
* @run main/othervm TestReclaimStringsLeaksMemory -XX:+UseConcMarkSweepGC
* @run main/othervm TestReclaimStringsLeaksMemory -XX:+UseG1GC
*/
import java.util.Arrays;
import java.util.ArrayList;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import jdk.test.lib.Asserts;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
public class TestReclaimStringsLeaksMemory {
// The amount of memory in kB reserved in the "Symbol" category that indicates a memory leak for
// this test.
public static final int ReservedThreshold = 70000;
public static void main(String[] args) throws Exception {
ArrayList<String> baseargs = new ArrayList(Arrays.asList( "-Xms256M",
"-Xmx256M",
"-Xlog:gc*",
"-XX:NativeMemoryTracking=summary",
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+PrintNMTStatistics" ));
baseargs.addAll(Arrays.asList(args));
baseargs.add(GCTest.class.getName());
ProcessBuilder pb_default =
ProcessTools.createJavaProcessBuilder(baseargs.toArray(new String[] {}));
verifySymbolMemoryUsageNotTooHigh(new OutputAnalyzer(pb_default.start()));
}
private static void verifySymbolMemoryUsageNotTooHigh(OutputAnalyzer output) throws Exception {
String stdout = output.getStdout();
System.out.println(stdout);
Pattern p = Pattern.compile("Symbol \\(reserved=(\\d*)");
Matcher m = p.matcher(stdout);
if (!m.find()) {
throw new RuntimeException("Could not find Symbol memory usage in NMT output");
}
int reserved = Integer.parseInt(m.group(1));
Asserts.assertLT(reserved, ReservedThreshold, "Reserved memory size is " + reserved + "KB which is greater than or equal to " + ReservedThreshold + "KB indicating a memory leak");
output.shouldHaveExitValue(0);
}
static class GCTest {
public static final String BaseName = "SomeRandomBaseString";
public static volatile String lastString;
public static void main(String [] args) {
for (int iterations = 0; iterations < 20;) {
for (int i = 0; i < 1000000; i++) {
lastString = (BaseName + i).intern();
}
if (++iterations % 5 == 0) {
System.gc();
}
}
}
}
}

View File

@ -0,0 +1,104 @@
/*
* 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.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.regex.Pattern;
import jdk.test.lib.Platform;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
/*
* @test
* @bug 8194652
* @summary Printing native stack shows an "error occurred during error reporting".
* @modules java.base/jdk.internal.misc
* @library /test/lib
*/
// This test was adapted from SafeFetchInErrorHandlingTest.java.
public class BadNativeStackInErrorHandlingTest {
public static void main(String[] args) throws Exception {
if (!Platform.isDebugBuild() || Platform.isZero()) {
return;
}
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
"-XX:+UnlockDiagnosticVMOptions",
"-Xmx100M",
"-XX:ErrorHandlerTest=14",
"-XX:-CreateCoredumpOnCrash",
"-version");
OutputAnalyzer output_detail = new OutputAnalyzer(pb.start());
// we should have crashed with a SIGSEGV
output_detail.shouldMatch("# A fatal error has been detected by the Java Runtime Environment:.*");
output_detail.shouldMatch("# +(?:SIGSEGV|EXCEPTION_ACCESS_VIOLATION).*");
// extract hs-err file
String hs_err_file = output_detail.firstMatch("# *(\\S*hs_err_pid\\d+\\.log)", 1);
if (hs_err_file == null) {
throw new RuntimeException("Did not find hs-err file in output.\n");
}
File f = new File(hs_err_file);
if (!f.exists()) {
throw new RuntimeException("hs-err file missing at " +
f.getAbsolutePath() + ".\n");
}
System.out.println("Found hs_err file. Scanning...");
FileInputStream fis = new FileInputStream(f);
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
String line = null;
// The failing line looks like this:
// [error occurred during error reporting (printing native stack), id 0xb]
Pattern pattern =
Pattern.compile("\\[error occurred during error reporting \\(printing native stack\\), id .*\\]");
String lastLine = null;
while ((line = br.readLine()) != null) {
if (pattern.matcher(line).matches()) {
System.out.println("Found: " + line + ".");
throw new RuntimeException("hs-err file should not contain: '" +
pattern + "'");
}
lastLine = line;
}
br.close();
if (!lastLine.equals("END.")) {
throw new RuntimeException("hs-err file incomplete (missing END marker.)");
} else {
System.out.println("End marker found.");
}
System.out.println("OK.");
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 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
@ -46,7 +46,6 @@ public class PrintNMTStatistics {
OutputAnalyzer output_detail = new OutputAnalyzer(pb.start());
output_detail.shouldContain("Virtual memory map:");
output_detail.shouldContain("Details:");
output_detail.shouldNotContain("error");
output_detail.shouldHaveExitValue(0);
// Make sure memory reserved for Module processing is recorded.
@ -62,7 +61,6 @@ public class PrintNMTStatistics {
output_summary.shouldContain("Java Heap (reserved=");
output_summary.shouldNotContain("Virtual memory map:");
output_summary.shouldNotContain("Details:");
output_summary.shouldNotContain("error");
output_summary.shouldHaveExitValue(0);
}
}

View File

@ -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
@ -33,8 +33,13 @@
import jdk.test.lib.Platform;
import jdk.test.lib.process.OutputAnalyzer;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
public class DirClasspathTest {
private static final int MAX_PATH = 260;
public static void main(String[] args) throws Exception {
File dir = new File(System.getProperty("user.dir"));
File emptydir = new File(dir, "emptydir");
@ -42,15 +47,36 @@ public class DirClasspathTest {
// Empty dir in -cp: should be OK
OutputAnalyzer output;
if (!Platform.isWindows()) {
// This block fails on Windows because of JDK-8192927
output = TestCommon.dump(emptydir.getPath(), TestCommon.list("DoesntMatter"), "-Xlog:class+path=info");
TestCommon.checkDump(output);
String classList[] = {"java/lang/Object"};
output = TestCommon.dump(emptydir.getPath(), classList, "-Xlog:class+path=info");
TestCommon.checkDump(output);
// Long path to empty dir in -cp: should be OK
Path classDir = Paths.get(System.getProperty("test.classes"));
Path destDir = classDir;
int subDirLen = MAX_PATH - classDir.toString().length() - 2;
if (subDirLen > 0) {
char[] chars = new char[subDirLen];
Arrays.fill(chars, 'x');
String subPath = new String(chars);
destDir = Paths.get(System.getProperty("test.classes"), subPath);
}
File longDir = destDir.toFile();
longDir.mkdir();
File subDir = new File(longDir, "subdir");
subDir.mkdir();
output = TestCommon.dump(subDir.getPath(), classList, "-Xlog:class+path=info");
TestCommon.checkDump(output);
// Non-empty dir in -cp: should fail
// <dir> is not empty because it has at least one subdirectory, i.e., <emptydir>
output = TestCommon.dump(dir.getPath(), TestCommon.list("DoesntMatter"), "-Xlog:class+path=info");
output = TestCommon.dump(dir.getPath(), classList, "-Xlog:class+path=info");
output.shouldNotHaveExitValue(0);
output.shouldContain("CDS allows only empty directories in archived classpaths");
// Long path to non-empty dir in -cp: should fail
// <dir> is not empty because it has at least one subdirectory, i.e., <emptydir>
output = TestCommon.dump(longDir.getPath(), classList, "-Xlog:class+path=info");
output.shouldNotHaveExitValue(0);
output.shouldContain("CDS allows only empty directories in archived classpaths");
}

View File

@ -0,0 +1,118 @@
/*
* 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 8193352
* @summary Test clhsdb 'thread' and 'threads' commands
* @library /test/lib
* @run main/othervm ClhsdbThread
*/
public class ClhsdbThread {
public static void main(String[] args) throws Exception {
System.out.println("Starting ClhsdbThread test");
LingeredApp theApp = null;
try {
ClhsdbLauncher test = new ClhsdbLauncher();
theApp = LingeredApp.startApp();
System.out.println("Started LingeredApp with pid " + theApp.getPid());
List<String> cmds = List.of("thread", "thread -a", "threads");
Map<String, List<String>> expStrMap = new HashMap<>();
// Check for the presence of the usage string
expStrMap.put("thread", List.of( "Usage: thread { -a | id }"));
expStrMap.put("thread -a", List.of(
"State: BLOCKED",
"Stack in use by Java",
"Base of Stack",
"Last_Java_SP:",
"Address"));
expStrMap.put("threads", List.of(
"Finalizer",
"Signal Dispatcher",
"Common-Cleaner",
"Stack in use by Java:",
"State:",
"Base of Stack:",
"main"));
Map<String, List<String>> unExpStrMap = new HashMap<>();
unExpStrMap.put(
"thread -a",
List.of("Couldn't find thread -a"));
String consolidatedOutput = test.run(
theApp.getPid(),
cmds,
expStrMap,
unExpStrMap);
if (consolidatedOutput == null) {
// Output could be null due to attach permission issues.
System.out.println(
"Output is empty. Probably due to attach permission issues.");
LingeredApp.stopApp(theApp);
return;
}
// Test the thread <id> command now. Obtain <id> from the
// output of the previous 'threads' command. The word before
// the token 'Finalizer' should denote the thread id of the
// 'Finalizer' thread.
String[] snippets = consolidatedOutput.split("Finalizer");
String[] wordTokens = snippets[0].split(" ");
String threadIdObtained = wordTokens[wordTokens.length - 1];
// Weed out newlines and blurb before that.
if (threadIdObtained.contains("\n")) {
String[] threadIdTokens = threadIdObtained.split("\n");
threadIdObtained = threadIdTokens[threadIdTokens.length - 1];
}
expStrMap = new HashMap<>();
System.out.println("Thread Id obtained is: " + threadIdObtained);
String cmd = "thread " + threadIdObtained;
expStrMap.put(cmd, List.of(
"Base of Stack:",
"State:",
"Last_Java_SP"));
cmds = List.of(cmd);
test.run(theApp.getPid(), cmds, expStrMap, null);
} catch (Exception ex) {
throw new RuntimeException("Test ERROR " + ex, ex);
} finally {
LingeredApp.stopApp(theApp);
}
System.out.println("Test PASSED");
}
}